diff --git a/extern/audaspace/include/devices/OpenCloseDevice.h b/extern/audaspace/include/devices/OpenCloseDevice.h index 5d127ea295a..a7208e637ba 100644 --- a/extern/audaspace/include/devices/OpenCloseDevice.h +++ b/extern/audaspace/include/devices/OpenCloseDevice.h @@ -22,8 +22,9 @@ * The OpenCloseDevice class. */ -#include #include +#include +#include #include "devices/SoftwareDevice.h" @@ -48,17 +49,27 @@ private: /** * Whether thread released the device. */ - bool m_delayed_close_finished{false}; + bool m_delayed_close_running{false}; /** * Thread used to release the device after time delay. */ std::thread m_delayed_close_thread; + /** + * Mutex to protect members accessed by multiple threads. + */ + std::mutex m_delayed_close_mutex; + + /** + * Condition to close immediately. Used when object is destructed. + */ + std::condition_variable m_immediate_close_condition; + /** * How long to wait until closing the device.. */ - std::chrono::milliseconds m_device_close_delay{std::chrono::milliseconds(10000)}; + std::chrono::milliseconds m_device_close_delay{10000}; /** * Time when playback has stopped. @@ -97,6 +108,8 @@ private: protected: OpenCloseDevice() = default; + void closeNow(); + virtual void playing(bool playing); }; diff --git a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp index 340b22ba8fb..ce8fdd73409 100644 --- a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp +++ b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp @@ -171,8 +171,8 @@ m_audio_unit(nullptr) CoreAudioDevice::~CoreAudioDevice() { - close(); destroy(); + closeNow(); } ISynchronizer* CoreAudioDevice::getSynchronizer() diff --git a/extern/audaspace/src/devices/OpenCloseDevice.cpp b/extern/audaspace/src/devices/OpenCloseDevice.cpp index f1dd83bbdc5..43645005779 100644 --- a/extern/audaspace/src/devices/OpenCloseDevice.cpp +++ b/extern/audaspace/src/devices/OpenCloseDevice.cpp @@ -21,45 +21,59 @@ AUD_NAMESPACE_BEGIN void OpenCloseDevice::closeAfterDelay() { - for(;;) - { - std::this_thread::sleep_for(m_device_close_delay / 10); - if(m_playing || m_playback_stopped_time.time_since_epoch().count() == 0) - m_playback_stopped_time = std::chrono::steady_clock::now(); - if(std::chrono::steady_clock::now() < m_playback_stopped_time + m_device_close_delay) - continue; + std::unique_lock lock(m_delayed_close_mutex); + + m_immediate_close_condition.wait_until(lock, m_playback_stopped_time + m_device_close_delay); + + m_delayed_close_running = false; + + if(m_playing) + return; - break; - } close(); - m_delayed_close_finished = true; m_device_opened = false; } +void OpenCloseDevice::closeNow() +{ + if(m_delayed_close_thread.joinable()) + { + m_immediate_close_condition.notify_all(); + m_delayed_close_thread.join(); + } +} + void OpenCloseDevice::playing(bool playing) { + std::lock_guard lock(m_delayed_close_mutex); + if(m_playing != playing) { m_playing = playing; if(playing) { if(!m_device_opened) + { open(); - m_device_opened = true; + m_device_opened = true; + } + start(); } else { stop(); - m_playback_stopped_time = std::chrono::steady_clock::now(); - if(m_delayed_close_thread.joinable() && m_delayed_close_finished) - { - m_delayed_close_thread.join(); - m_delayed_close_finished = false; - } - if(m_device_opened && !m_delayed_close_thread.joinable()) + m_playback_stopped_time = std::chrono::steady_clock::now(); + + if(m_device_opened && !m_delayed_close_running) + { + if(m_delayed_close_thread.joinable()) + m_delayed_close_thread.join(); + + m_delayed_close_running = true; m_delayed_close_thread = std::thread(&OpenCloseDevice::closeAfterDelay, this); + } } } } diff --git a/extern/audaspace/src/devices/SoftwareDevice.cpp b/extern/audaspace/src/devices/SoftwareDevice.cpp index f9ad6f767d3..cf44965deea 100644 --- a/extern/audaspace/src/devices/SoftwareDevice.cpp +++ b/extern/audaspace/src/devices/SoftwareDevice.cpp @@ -726,11 +726,7 @@ void SoftwareDevice::destroy() if(m_playback) playing(m_playback = false); - while(!m_playingSounds.empty()) - m_playingSounds.front()->stop(); - - while(!m_pausedSounds.empty()) - m_pausedSounds.front()->stop(); + stopAll(); } void SoftwareDevice::mix(data_t* buffer, int length)