aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/source.cpp9
-rw-r--r--alc/alc.cpp26
2 files changed, 34 insertions, 1 deletions
diff --git a/al/source.cpp b/al/source.cpp
index dd79a1b6..229a6d66 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -510,9 +510,18 @@ void SendVoiceChanges(ALCcontext *ctx, VoiceChange *tail)
oldhead = next;
oldhead->mNext.store(tail, std::memory_order_release);
+ const bool connected{device->Connected.load(std::memory_order_acquire)};
ALuint refcount;
while(((refcount=device->MixCount.load(std::memory_order_acquire))&1))
std::this_thread::yield();
+ if UNLIKELY(!connected)
+ {
+ /* If the device is disconnected, just ignore all pending changes. */
+ VoiceChange *cur{ctx->mCurrentVoiceChange.load(std::memory_order_acquire)};
+ while(VoiceChange *next{cur->mNext.load(std::memory_order_acquire)})
+ cur = next;
+ ctx->mCurrentVoiceChange.store(cur, std::memory_order_release);
+ }
}
diff --git a/alc/alc.cpp b/alc/alc.cpp
index 85d6ae30..72ae1b1c 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -4362,7 +4362,31 @@ START_API_FUNC
if(dev->Flags.get<DeviceRunning>())
dev->Backend->stop();
dev->Flags.unset<DeviceRunning>();
- device->Connected.store(true);
+ if(!dev->Connected.load(std::memory_order_relaxed))
+ {
+ /* Make sure disconnection is finished before continuing on. */
+ ALuint refcount;
+ while(((refcount=dev->MixCount.load(std::memory_order_acquire))&1))
+ std::this_thread::yield();
+
+ for(ALCcontext *ctx : *dev->mContexts.load(std::memory_order_acquire))
+ {
+ /* Clear any pending voice changes and reallocate voices to get a
+ * clean restart.
+ */
+ std::lock_guard<std::mutex> __{ctx->mSourceLock};
+ auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire);
+ while(auto *next = vchg->mNext.load(std::memory_order_acquire))
+ vchg = next;
+ ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
+
+ ctx->mVoiceClusters.clear();
+ ctx->allocVoices(std::max<size_t>(256,
+ ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
+ }
+
+ dev->Connected.store(true);
+ }
ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
if LIKELY(err == ALC_NO_ERROR) return ALC_TRUE;