aboutsummaryrefslogtreecommitdiffstats
path: root/alc/alu.cpp
diff options
context:
space:
mode:
authorChris Robinson <chris.kcat@gmail.com>2020-02-23 21:40:54 -0800
committerChris Robinson <chris.kcat@gmail.com>2020-02-23 21:40:54 -0800
commit90d45984dcaeb0232862cf6fb81af186cd328a63 (patch)
tree86ca49ff693c18451cb2a73603a7735933faa248 /alc/alu.cpp
parent8554e6cde2f3a7014de2f7ce42553b4828b9105d (diff)
Simplify replaying a source
Diffstat (limited to 'alc/alu.cpp')
-rw-r--r--alc/alu.cpp35
1 files changed, 28 insertions, 7 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp
index 08167663..46720cb0 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -1628,35 +1628,56 @@ void ProcessVoiceChanges(ALCcontext *ctx)
do {
cur = next;
- bool success{false};
+ bool sendevt{false};
if(cur->mState == AL_INITIAL || cur->mState == AL_STOPPED)
{
if(ALvoice *voice{cur->mVoice})
{
voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
- voice->mSourceID.exchange(0u, std::memory_order_relaxed);
+ voice->mSourceID.store(0u, std::memory_order_relaxed);
ALvoice::State oldvstate{ALvoice::Playing};
- success = voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping,
+ sendevt = voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping,
std::memory_order_relaxed, std::memory_order_acquire);
voice->mPendingStop.store(false, std::memory_order_release);
}
- success |= (cur->mState == AL_INITIAL);
+ /* AL_INITIAL state change events are always sent, even if the
+ * voice is already stopped or even if there is no voice.
+ */
+ sendevt |= (cur->mState == AL_INITIAL);
}
else if(cur->mState == AL_PAUSED)
{
ALvoice *voice{cur->mVoice};
ALvoice::State oldvstate{ALvoice::Playing};
- success = voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping,
+ sendevt = voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping,
std::memory_order_release, std::memory_order_acquire);
}
else if(cur->mState == AL_PLAYING)
{
+ /* NOTE: When playing a voice, sending a source state change event
+ * depends if there's an old voice to stop and if that stop is
+ * successful. If there is no old voice, a playing event is always
+ * sent. If there is an old voice, an event is sent only if the
+ * voice is already stopped.
+ */
+ if(ALvoice *oldvoice{cur->mOldVoice})
+ {
+ oldvoice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
+ oldvoice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
+ oldvoice->mSourceID.store(0u, std::memory_order_relaxed);
+ ALvoice::State oldvstate{ALvoice::Playing};
+ sendevt = !oldvoice->mPlayState.compare_exchange_strong(oldvstate,
+ ALvoice::Stopping, std::memory_order_relaxed, std::memory_order_acquire);
+ oldvoice->mPendingStop.store(false, std::memory_order_release);
+ }
+ else
+ sendevt = true;
+
ALvoice *voice{cur->mVoice};
voice->mPlayState.store(ALvoice::Playing, std::memory_order_release);
- success = true;
}
- if(success && (enabledevt&EventType_SourceStateChange) && cur->mSourceID != 0)
+ if(sendevt && (enabledevt&EventType_SourceStateChange))
SendSourceStateEvent(ctx, cur->mSourceID, cur->mState);
} while((next=cur->mNext.load(std::memory_order_acquire)));
ctx->mCurrentVoiceChange.store(cur, std::memory_order_release);