Browse Source

CoreAudio: Fixed some issues handling background device changes

tags/2021-05-28
Tom Poole 7 years ago
parent
commit
f24045053d
1 changed files with 88 additions and 15 deletions
  1. +88
    -15
      modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp

+ 88
- 15
modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp View File

@@ -167,6 +167,10 @@ public:
jassert (deviceID != 0); jassert (deviceID != 0);
updateDetailsFromDevice(); updateDetailsFromDevice();
JUCE_COREAUDIOLOG ("Creating CoreAudioInternal\n"
<< (isInputDevice ? (" inputDeviceId " + String (deviceID) + "\n") : "")
<< (isOutputDevice ? (" outputDeviceId " + String (deviceID) + "\n") : "")
<< getDeviceDetails().joinIntoString ("\n "));
AudioObjectPropertyAddress pa; AudioObjectPropertyAddress pa;
pa.mSelector = kAudioObjectPropertySelectorWildcard; pa.mSelector = kAudioObjectPropertySelectorWildcard;
@@ -463,6 +467,33 @@ public:
return true; return true;
} }
StringArray getDeviceDetails()
{
StringArray result;
String availableSampleRates ("Available sample rates:");
for (auto& s : sampleRates)
availableSampleRates << " " << s;
result.add (availableSampleRates);
result.add ("Sample rate: " + String (sampleRate));
String availableBufferSizes ("Available buffer sizes:");
for (auto& b : bufferSizes)
availableBufferSizes << " " << b;
result.add (availableBufferSizes);
result.add ("Buffer size: " + String (bufferSize));
result.add ("Bit depth: " + String (bitDepth));
result.add ("Input latency: " + String (inputLatency));
result.add ("Output latency: " + String (outputLatency));
result.add ("Input channel names: " + inChanNames.joinIntoString (" "));
result.add ("Output channel names: " + outChanNames.joinIntoString (" "));
return result;
}
//============================================================================== //==============================================================================
StringArray getSources (bool input) StringArray getSources (bool input)
{ {
@@ -676,9 +707,7 @@ public:
callback = nullptr; callback = nullptr;
} }
if (started
&& (deviceID != 0)
&& ! leaveInterruptRunning)
if (started && (deviceID != 0) && ! leaveInterruptRunning)
{ {
OK (AudioDeviceStop (deviceID, audioIOProc)); OK (AudioDeviceStop (deviceID, audioIOProc));
OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));
@@ -772,7 +801,7 @@ public:
// called by callbacks // called by callbacks
void deviceDetailsChanged() void deviceDetailsChanged()
{ {
if (callbacksAllowed)
if (callbacksAllowed.get() == 1)
startTimer (100); startTimer (100);
} }
@@ -812,7 +841,7 @@ private:
HeapBlock<float> audioBuffer; HeapBlock<float> audioBuffer;
int numInputChans = 0; int numInputChans = 0;
int numOutputChans = 0; int numOutputChans = 0;
bool callbacksAllowed = true;
Atomic<int> callbacksAllowed { 1 };
const bool isInputDevice, isOutputDevice; const bool isInputDevice, isOutputDevice;
Array<CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo; Array<CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo;
@@ -850,7 +879,7 @@ private:
break; break;
case kAudioObjectPropertyOwnedObjects: case kAudioObjectPropertyOwnedObjects:
intern->stop (false);
intern->owner.restart();
intern->owner.deviceType.triggerAsyncAudioDeviceListChange(); intern->owner.deviceType.triggerAsyncAudioDeviceListChange();
break; break;
@@ -921,6 +950,7 @@ public:
isStarted (false) isStarted (false)
{ {
CoreAudioInternal* device = nullptr; CoreAudioInternal* device = nullptr;
if (outputDeviceId == 0 || outputDeviceId == inputDeviceId) if (outputDeviceId == 0 || outputDeviceId == inputDeviceId)
{ {
jassert (inputDeviceId != 0); jassert (inputDeviceId != 0);
@@ -930,8 +960,8 @@ public:
{ {
device = new CoreAudioInternal (*this, outputDeviceId, false, true); device = new CoreAudioInternal (*this, outputDeviceId, false, true);
} }
jassert (device != nullptr);
jassert (device != nullptr);
internal = device; internal = device;
AudioObjectPropertyAddress pa; AudioObjectPropertyAddress pa;
@@ -985,17 +1015,16 @@ public:
double sampleRate, int bufferSizeSamples) override double sampleRate, int bufferSizeSamples) override
{ {
isOpen_ = true; isOpen_ = true;
internal->xruns = 0; internal->xruns = 0;
if (bufferSizeSamples <= 0) if (bufferSizeSamples <= 0)
bufferSizeSamples = getDefaultBufferSize(); bufferSizeSamples = getDefaultBufferSize();
lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples);
JUCE_COREAUDIOLOG ("Opened: " << getName()); JUCE_COREAUDIOLOG ("Opened: " << getName());
JUCE_COREAUDIOLOG ("Latencies: " << getInputLatencyInSamples() << ' ' << getOutputLatencyInSamples());
isOpen_ = lastError.isEmpty(); isOpen_ = lastError.isEmpty();
return lastError; return lastError;
} }
@@ -1069,10 +1098,16 @@ public:
void restart() void restart()
{ {
JUCE_COREAUDIOLOG ("Restarting");
AudioIODeviceCallback* oldCallback = internal->callback;
stop();
start (oldCallback);
if (deviceWrapperRestartCallback != nullptr)
{
deviceWrapperRestartCallback();
}
else
{
AudioIODeviceCallback* oldCallback = internal->callback;
stop();
start (oldCallback);
}
} }
bool setCurrentSampleRate (double newSampleRate) bool setCurrentSampleRate (double newSampleRate)
@@ -1080,6 +1115,11 @@ public:
return internal->setNominalSampleRate (newSampleRate); return internal->setNominalSampleRate (newSampleRate);
} }
void setDeviceWrapperRestartCallback (const std::function<void()>& cb)
{
deviceWrapperRestartCallback = cb;
}
CoreAudioIODeviceType& deviceType; CoreAudioIODeviceType& deviceType;
int inputIndex, outputIndex; int inputIndex, outputIndex;
@@ -1087,6 +1127,7 @@ private:
ScopedPointer<CoreAudioInternal> internal; ScopedPointer<CoreAudioInternal> internal;
bool isOpen_, isStarted; bool isOpen_, isStarted;
String lastError; String lastError;
std::function<void()> deviceWrapperRestartCallback = nullptr;
static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData) static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData)
{ {
@@ -1110,7 +1151,8 @@ private:
//============================================================================== //==============================================================================
class AudioIODeviceCombiner : public AudioIODevice, class AudioIODeviceCombiner : public AudioIODevice,
private Thread
private Thread,
private Timer
{ {
public: public:
AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType& deviceType) AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType& deviceType)
@@ -1247,6 +1289,11 @@ public:
const BigInteger& outputChannels, const BigInteger& outputChannels,
double sampleRate, int bufferSize) override double sampleRate, int bufferSize) override
{ {
inputChannelsRequested = inputChannels;
outputChannelsRequested = outputChannels;
sampleRateRequested = sampleRate;
bufferSizeRequested = bufferSize;
close(); close();
active = true; active = true;
@@ -1313,6 +1360,21 @@ public:
d->close(); d->close();
} }
void restart()
{
auto* oldCallback = callback;
close();
open (inputChannelsRequested, outputChannelsRequested,
sampleRateRequested, bufferSizeRequested);
start (oldCallback);
}
void restartAsync()
{
startTimer (100);
}
BigInteger getActiveOutputChannels() const override BigInteger getActiveOutputChannels() const override
{ {
BigInteger chans; BigInteger chans;
@@ -1409,6 +1471,10 @@ private:
float** fifoWritePointers = nullptr; float** fifoWritePointers = nullptr;
WaitableEvent threadInitialised; WaitableEvent threadInitialised;
BigInteger inputChannelsRequested, outputChannelsRequested;
double sampleRateRequested = 44100;
int bufferSizeRequested = 512;
void run() override void run() override
{ {
auto numSamples = currentBufferSize; auto numSamples = currentBufferSize;
@@ -1467,6 +1533,12 @@ private:
} }
} }
void timerCallback() override
{
stopTimer();
restart();
}
void shutdown (const String& error) void shutdown (const String& error)
{ {
AudioIODeviceCallback* lastCallback = nullptr; AudioIODeviceCallback* lastCallback = nullptr;
@@ -1623,6 +1695,7 @@ private:
: owner (cd), device (d), : owner (cd), device (d),
useInputs (useIns), useOutputs (useOuts) useInputs (useIns), useOutputs (useOuts)
{ {
d->setDeviceWrapperRestartCallback ([this]() { owner.restartAsync(); });
} }
~DeviceWrapper() ~DeviceWrapper()


Loading…
Cancel
Save