From 250a69ee82821f9d2d11325ab15e72b39632df1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= Date: Fri, 19 Mar 2021 21:42:55 +0100 Subject: Fix T86728: Blender freezes when playhead is dragged in this .blend Porting the deadlock bugfix in WASAPI from upstream Audaspace. --- extern/audaspace/plugins/wasapi/WASAPIDevice.cpp | 60 +++++++++++++++++++----- extern/audaspace/plugins/wasapi/WASAPIDevice.h | 5 ++ 2 files changed, 53 insertions(+), 12 deletions(-) (limited to 'extern') diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp index 241f694feb5..4f213dc8468 100644 --- a/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp +++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.cpp @@ -35,7 +35,11 @@ void WASAPIDevice::start() { lock(); - if(!m_playing) + // thread is still running, we can abort stopping it + if(m_stop) + m_stop = false; + // thread is not running, let's start it + else if(!m_playing) { if(m_thread.joinable()) m_thread.join(); @@ -53,20 +57,35 @@ void WASAPIDevice::updateStream() UINT32 buffer_size; data_t* buffer; + lock(); + if(FAILED(m_audio_client->GetBufferSize(&buffer_size))) + { + m_playing = false; + m_stop = false; + unlock(); return; + } IAudioRenderClient* render_client = nullptr; const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast(&render_client)))) + { + m_playing = false; + m_stop = false; + unlock(); return; + } UINT32 padding; if(FAILED(m_audio_client->GetCurrentPadding(&padding))) { SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } @@ -75,31 +94,40 @@ void WASAPIDevice::updateStream() if(FAILED(render_client->GetBuffer(length, &buffer))) { SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } - lock(); - mix((data_t*)buffer, length); - unlock(); - if(FAILED(render_client->ReleaseBuffer(length, 0))) { SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } + unlock(); + m_audio_client->Start(); auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2); for(;;) { + lock(); + if(FAILED(m_audio_client->GetCurrentPadding(&padding))) { m_audio_client->Stop(); SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } @@ -109,44 +137,52 @@ void WASAPIDevice::updateStream() { m_audio_client->Stop(); SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } - lock(); - mix((data_t*)buffer, length); - unlock(); - if(FAILED(render_client->ReleaseBuffer(length, 0))) { m_audio_client->Stop(); SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } // stop thread - if(!m_playing) + if(m_stop) { m_audio_client->Stop(); SafeRelease(&render_client); + m_playing = false; + m_stop = false; + unlock(); return; } + unlock(); + std::this_thread::sleep_for(sleepDuration); } } void WASAPIDevice::playing(bool playing) { - if(!m_playing && playing) + if((!m_playing || m_stop) && playing) start(); else - m_playing = playing; + m_stop = true; } WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) : m_playing(false), + m_stop(false), m_imm_device_enumerator(nullptr), m_imm_device(nullptr), diff --git a/extern/audaspace/plugins/wasapi/WASAPIDevice.h b/extern/audaspace/plugins/wasapi/WASAPIDevice.h index b7b520e802c..ae25a09c432 100644 --- a/extern/audaspace/plugins/wasapi/WASAPIDevice.h +++ b/extern/audaspace/plugins/wasapi/WASAPIDevice.h @@ -48,6 +48,11 @@ private: */ bool m_playing; + /** + * Whether the current playback should stop. + */ + bool m_stop; + IMMDeviceEnumerator* m_imm_device_enumerator; IMMDevice* m_imm_device; IAudioClient* m_audio_client; -- cgit v1.2.3