From 0c89469ab63afd209748417683e4fb2a2837b873 Mon Sep 17 00:00:00 2001 From: ed Date: Tue, 29 Jun 2021 16:14:48 +0100 Subject: [PATCH] CoreAudio: Call AudioDeviceStop() on IO thread when stopping audio devices When AudioDeviceStop() is called from a thread other than the IO thread there are no guarantees about the IOProc being called before the thread actually terminates. Moving this call to the audioCallback() method ensures that the device will be stopped immediately and we can remove a check that was taking a few seconds to close devices. --- .../native/juce_mac_CoreAudio.cpp | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp b/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp index 402400b0b0..332dbaa139 100644 --- a/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp +++ b/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp @@ -671,6 +671,8 @@ public: bool start() { + const ScopedLock sl (callbackLock); + if (! started) { callback = nullptr; @@ -703,41 +705,27 @@ public: void stop (bool leaveInterruptRunning) { - { - const ScopedLock sl (callbackLock); - callback = nullptr; - } + const ScopedLock sl (callbackLock); + + callback = nullptr; if (started && (deviceID != 0) && ! leaveInterruptRunning) { - OK (AudioDeviceStop (deviceID, audioProcID)); - OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); - audioProcID = {}; + audioDeviceStopPending = true; - started = false; - - { const ScopedLock sl (callbackLock); } - - // wait until it's definitely stopped calling back.. + // wait until AudioDeviceStop() has been called on the IO thread for (int i = 40; --i >= 0;) { - Thread::sleep (50); - - UInt32 running = 0; - UInt32 size = sizeof (running); - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDeviceIsRunning; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = juceAudioObjectPropertyElementMain; - - OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &running)); - - if (running == 0) + if (audioDeviceStopPending == false) break; + + const ScopedUnlock ul (callbackLock); + Thread::sleep (50); } - const ScopedLock sl (callbackLock); + OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); + audioProcID = {}; + started = false; } } @@ -749,6 +737,14 @@ public: { const ScopedLock sl (callbackLock); + if (audioDeviceStopPending) + { + if (OK (AudioDeviceStop (deviceID, audioProcID))) + audioDeviceStopPending = false; + + return; + } + if (callback != nullptr) { for (int i = numInputChans; --i >= 0;) @@ -836,7 +832,7 @@ public: private: CriticalSection callbackLock; AudioDeviceID deviceID; - bool started = false; + bool started = false, audioDeviceStopPending = false; double sampleRate = 0; int bufferSize = 512; HeapBlock audioBuffer;