1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

CoreAudio: Forward errors to callback during device initialisation

This commit is contained in:
attila 2022-08-18 18:38:10 +02:00
parent 5b355f6373
commit 5ec536f13f
2 changed files with 70 additions and 4 deletions

View file

@ -720,6 +720,12 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
currentDeviceType = currentAudioDevice->getTypeName(); currentDeviceType = currentAudioDevice->getTypeName();
currentAudioDevice->start (callbackHandler.get()); currentAudioDevice->start (callbackHandler.get());
error = currentAudioDevice->getLastError();
}
if (error.isEmpty())
{
updateCurrentSetup(); updateCurrentSetup();
for (int i = 0; i < availableDeviceTypes.size(); ++i) for (int i = 0; i < availableDeviceTypes.size(); ++i)

View file

@ -1605,11 +1605,17 @@ public:
stop(); stop();
fifos.clear(); fifos.clear();
{
ScopedErrorForwarder forwarder (*this, newCallback);
for (auto* d : devices) for (auto* d : devices)
d->start(); d->start();
if (newCallback != nullptr) if (! forwarder.encounteredError() && newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this); newCallback->audioDeviceAboutToStart (this);
else if (lastError.isEmpty())
lastError = TRANS("Failed to initialise all requested devices.");
}
const ScopedLock sl (callbackLock); const ScopedLock sl (callbackLock);
previousCallback = callback = newCallback; previousCallback = callback = newCallback;
@ -2079,6 +2085,60 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper)
}; };
/* If the current AudioIODeviceCombiner::callback is nullptr, it sets itself as the callback
and forwards error related callbacks to the provided callback
*/
class ScopedErrorForwarder : public AudioIODeviceCallback
{
public:
ScopedErrorForwarder (AudioIODeviceCombiner& ownerIn, AudioIODeviceCallback* cb)
: owner (ownerIn),
target (cb)
{
const ScopedLock sl (owner.callbackLock);
if (owner.callback == nullptr)
owner.callback = this;
}
~ScopedErrorForwarder() override
{
const ScopedLock sl (owner.callbackLock);
if (owner.callback == this)
owner.callback = nullptr;
}
// We only want to be notified about error conditions when the owner's callback is nullptr.
// This class shouldn't be relied on for forwarding this call.
void audioDeviceAboutToStart (AudioIODevice*) override {}
void audioDeviceStopped() override
{
if (target != nullptr)
target->audioDeviceStopped();
error = true;
}
void audioDeviceError (const String& errorMessage) override
{
owner.lastError = errorMessage;
if (target != nullptr)
target->audioDeviceError (errorMessage);
error = true;
}
bool encounteredError() const { return error; }
private:
AudioIODeviceCombiner& owner;
AudioIODeviceCallback* target;
bool error = false;
};
OwnedArray<DeviceWrapper> devices; OwnedArray<DeviceWrapper> devices;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioIODeviceCombiner) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioIODeviceCombiner)