I have noticed a concurrency issue in juce_ios_audio.cpp.
Using AudioDeviceSettingPannel, I was messing changing Sample Rate few times in a row very quick. After few iteration an error occurs (in AudioDeviceManager::setAudioDEviceSetup()) and the device is deleted.
(the reason why open() return an error (“Could not open the device”) is not the issue here, I am going to investigate on that afterwards).
“MessageThread” calls “~iOSAudioIODevice()” to unsubscribe the device from the session holder and then delete it. At the same time “AV Notify Thread” is still processing device->handleRouteChange().
The exact “device” that is beeing deleted from “MessageThread”.
I added a critical section in AudioSessionHolder to fix the issue.
juce_ios_Audio.cpp:
struct AudioSessionHolder
{
AudioSessionHolder();
~AudioSessionHolder();
void handleStatusChange (bool enabled, const char* reason) const;
void handleRouteChange (const char* reason) const;
CriticalSection devicesLock; //ADD
Array<iOSAudioIODevice*> activeDevices;
id nativeSession;
};
[…]
void AudioSessionHolder::handleRouteChange (const char* reason) const
{
ScopedLock lock(devicesLock); //ADD
for (auto device: activeDevices)
device->handleRouteChange (reason);
}
[…]
iOSAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, iOSAudioDeviceName)
{
ScopedLock lock(sessionHolder->devicesLock); //ADD
sessionHolder->activeDevices.add (this);
updateSampleRateAndAudioInput();
}
~iOSAudioIODevice()
{
ScopedLock lock(sessionHolder->devicesLock); //ADD
sessionHolder->activeDevices.removeFirstMatchingValue (this);
close();
}