Browse Source

consistified seeking to invalid location behavior

removed few redundant operations and checks
moved sound start seeking from prepare to play
fixed potential bug with sources that failed to play not releasing AL source
back into the pool
sources now stop if seeked to invalid location
looped sources play from 0 if seeked to invalid location while playing

--HG--
branch : minor
rcoaxil 8 years ago
parent
commit
b337e0ff6f
1 changed files with 42 additions and 21 deletions
  1. 42 21
      src/modules/audio/openal/Source.cpp

+ 42 - 21
src/modules/audio/openal/Source.cpp

@@ -280,9 +280,6 @@ bool Source::update()
 	switch (type)
 	switch (type)
 	{
 	{
 		case TYPE_STATIC:
 		case TYPE_STATIC:
-			// Looping mode could have changed.
-			// FIXME: make looping mode not change without you noticing so that this is not needed
-			alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
 			return !isFinished();
 			return !isFinished();
 		case TYPE_STREAM:
 		case TYPE_STREAM:
 			if (!isFinished())
 			if (!isFinished())
@@ -401,24 +398,26 @@ void Source::seekAtomic(float offset, void *unit)
 		break;
 		break;
 	}
 	}
 
 
+	bool wasPlaying = isPlaying();
 	switch (type)
 	switch (type)
 	{
 	{
 		case TYPE_STATIC:
 		case TYPE_STATIC:
-			alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
-			offsetSamples = offsetSeconds = 0;
+			if (valid)
+			{
+				alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
+				offsetSamples = offsetSeconds = 0;
+			}
 			break;
 			break;
 		case TYPE_STREAM:
 		case TYPE_STREAM:
 		{
 		{
-			bool wasPlaying = isPlaying();
-
 			// To drain all buffers
 			// To drain all buffers
 			if (valid)
 			if (valid)
-				stopAtomic();
+				stop();
 
 
 			decoder->seek(offsetSeconds);
 			decoder->seek(offsetSeconds);
 
 
 			if (wasPlaying)
 			if (wasPlaying)
-				playAtomic(source);
+				play();
 
 
 			break;
 			break;
 		}
 		}
@@ -454,6 +453,13 @@ void Source::seekAtomic(float offset, void *unit)
 		case TYPE_MAX_ENUM:
 		case TYPE_MAX_ENUM:
 			break;
 			break;
 	}
 	}
+	if (wasPlaying && (alGetError() == AL_INVALID_VALUE || (type == TYPE_STREAM && !isPlaying())))
+	{
+		stop();
+		if (isLooping())
+			play();
+		return;
+	}
 	this->offsetSamples = offsetSamples;
 	this->offsetSamples = offsetSamples;
 	this->offsetSeconds = offsetSeconds;
 	this->offsetSeconds = offsetSeconds;
 }
 }
@@ -734,9 +740,6 @@ void Source::prepareAtomic()
 	{
 	{
 		case TYPE_STATIC:
 		case TYPE_STATIC:
 			alSourcei(source, AL_BUFFER, staticBuffer->getBuffer());
 			alSourcei(source, AL_BUFFER, staticBuffer->getBuffer());
-			//source can be seeked while not valid
-			if (offsetSamples >= 0) 
-				alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
 			break;
 			break;
 		case TYPE_STREAM:
 		case TYPE_STREAM:
 			while (unusedBufferPeek() != AL_NONE)
 			while (unusedBufferPeek() != AL_NONE)
@@ -760,8 +763,6 @@ void Source::prepareAtomic()
 			for (unsigned int i = top + 1; i < MAX_BUFFERS; i++)
 			for (unsigned int i = top + 1; i < MAX_BUFFERS; i++)
 				unusedBufferPush(unusedBuffers[i]);
 				unusedBufferPush(unusedBuffers[i]);
 
 
-			if (offsetSamples >= 0) 
-				alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
 			break;
 			break;
 		}
 		}
 		case TYPE_MAX_ENUM:
 		case TYPE_MAX_ENUM:
@@ -774,7 +775,6 @@ void Source::teardownAtomic()
 	switch (type)
 	switch (type)
 	{
 	{
 		case TYPE_STATIC:
 		case TYPE_STATIC:
-			alSourcef(source, AL_SAMPLE_OFFSET, 0);
 			break;
 			break;
 		case TYPE_STREAM:
 		case TYPE_STREAM:
 		{
 		{
@@ -832,16 +832,32 @@ bool Source::playAtomic(ALuint source)
 
 
 	alSourcePlay(source);
 	alSourcePlay(source);
 
 
-	// alSourcePlay may fail if the system has reached its limit of simultaneous
-	// playing sources.
 	bool success = alGetError() == AL_NO_ERROR;
 	bool success = alGetError() == AL_NO_ERROR;
 
 
-	valid = true; //if it fails it will be set to false again
-	//but this prevents a horrible, horrible bug
+	if (type == TYPE_STREAM)
+	{
+		valid = true; //isPlaying() needs source to be valid
+		if (!isPlaying())
+			success = false;
+	}
+	else if (success)
+	{
+		alSourcef(source, AL_SAMPLE_OFFSET, offsetSamples);
+		success = alGetError() == AL_NO_ERROR;
+	}
 
 
-	if (type != TYPE_STREAM)
+	if (!success)
+	{
+		valid = true; //stop() needs source to be valid
+		stop();
+	}
+	else if (type != TYPE_STREAM)
 		offsetSamples = offsetSeconds = 0;
 		offsetSamples = offsetSeconds = 0;
 
 
+	//this is set to success state afterwards anyway, but setting it here
+	//to true preemptively avoids race condition with update bug
+	valid = true; 
+
 	return success;
 	return success;
 }
 }
 
 
@@ -862,7 +878,12 @@ void Source::pauseAtomic()
 void Source::resumeAtomic()
 void Source::resumeAtomic()
 {
 {
 	if (valid && !isPlaying())
 	if (valid && !isPlaying())
+	{
 		alSourcePlay(source);
 		alSourcePlay(source);
+
+		if (alGetError() == AL_INVALID_VALUE || (type == TYPE_STREAM && unusedBufferTop == MAX_BUFFERS - 1))
+			stop();
+	}
 }
 }
 
 
 bool Source::playAtomic(const std::vector<love::audio::Source*> &sources, const std::vector<ALuint> &ids, const std::vector<char> &wasPlaying)
 bool Source::playAtomic(const std::vector<love::audio::Source*> &sources, const std::vector<ALuint> &ids, const std::vector<char> &wasPlaying)
@@ -941,7 +962,7 @@ void Source::pauseAtomic(const std::vector<love::audio::Source*> &sources)
 
 
 void Source::reset()
 void Source::reset()
 {
 {
-	alSourcei(source, AL_BUFFER, 0);
+	alSourcei(source, AL_BUFFER, AL_NONE);
 	alSourcefv(source, AL_POSITION, position);
 	alSourcefv(source, AL_POSITION, position);
 	alSourcefv(source, AL_VELOCITY, velocity);
 	alSourcefv(source, AL_VELOCITY, velocity);
 	alSourcefv(source, AL_DIRECTION, direction);
 	alSourcefv(source, AL_DIRECTION, direction);