diff options
-rw-r--r-- | al/source.cpp | 9 | ||||
-rw-r--r-- | alc/alc.cpp | 26 |
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; |