Skip to content

Commit

Permalink
CoreAudio: Call AudioDeviceStop() on IO thread when stopping audio de…
Browse files Browse the repository at this point in the history
…vices

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.
  • Loading branch information
ed95 committed Jun 29, 2021
1 parent e1f855a commit 0c89469
Showing 1 changed file with 23 additions and 27 deletions.
50 changes: 23 additions & 27 deletions modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
Expand Up @@ -671,6 +671,8 @@ class CoreAudioInternal : private Timer

bool start()
{
const ScopedLock sl (callbackLock);

if (! started)
{
callback = nullptr;
Expand Down Expand Up @@ -703,41 +705,27 @@ class CoreAudioInternal : private Timer

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 = {};

started = false;
audioDeviceStopPending = true;

{ 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;
}
}

Expand All @@ -749,6 +737,14 @@ class CoreAudioInternal : private Timer
{
const ScopedLock sl (callbackLock);

if (audioDeviceStopPending)
{
if (OK (AudioDeviceStop (deviceID, audioProcID)))
audioDeviceStopPending = false;

return;
}

if (callback != nullptr)
{
for (int i = numInputChans; --i >= 0;)
Expand Down Expand Up @@ -836,7 +832,7 @@ class CoreAudioInternal : private Timer
private:
CriticalSection callbackLock;
AudioDeviceID deviceID;
bool started = false;
bool started = false, audioDeviceStopPending = false;
double sampleRate = 0;
int bufferSize = 512;
HeapBlock<float> audioBuffer;
Expand Down

0 comments on commit 0c89469

Please sign in to comment.