|
@@ -280,10 +280,12 @@ bool Source::update()
|
|
switch (type)
|
|
switch (type)
|
|
{
|
|
{
|
|
case TYPE_STATIC:
|
|
case TYPE_STATIC:
|
|
|
|
+ {
|
|
// Looping mode could have changed.
|
|
// Looping mode could have changed.
|
|
- // FIXME: make looping mode not change without you noticing so that this is not needed
|
|
|
|
|
|
+ // FIXME: make looping mode change atomically so this is not needed
|
|
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
|
|
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 +403,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 +458,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 +745,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 +768,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 +780,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 +837,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 +883,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 +967,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);
|