mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-30 02:50:05 +00:00
Improved CoreAudio handling of USB audio devices being unplugged
This commit is contained in:
parent
783d892359
commit
076896d33b
1 changed files with 61 additions and 41 deletions
|
|
@ -388,65 +388,84 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
void updateDetailsFromDevice()
|
||||
int getFrameSizeFromDevice() const
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
if (deviceID == 0)
|
||||
return;
|
||||
|
||||
// this collects all the new details from the device without any locking, then
|
||||
// locks + swaps them afterwards.
|
||||
AudioObjectPropertyAddress pa;
|
||||
pa.mScope = kAudioObjectPropertyScopeWildcard;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
UInt32 isAlive;
|
||||
UInt32 size = sizeof (isAlive);
|
||||
pa.mSelector = kAudioDevicePropertyDeviceIsAlive;
|
||||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive)) && isAlive == 0)
|
||||
return;
|
||||
|
||||
const double currentRate = getNominalSampleRate();
|
||||
if (currentRate > 0)
|
||||
sampleRate = currentRate;
|
||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize;
|
||||
|
||||
UInt32 framesPerBuf = (UInt32) bufferSize;
|
||||
size = sizeof (framesPerBuf);
|
||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize;
|
||||
UInt32 size = sizeof (framesPerBuf);
|
||||
AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf);
|
||||
return (int) framesPerBuf;
|
||||
}
|
||||
|
||||
Array<int> newBufferSizes (getBufferSizesFromDevice());
|
||||
Array<double> newSampleRates (getSampleRatesFromDevice());
|
||||
bool isDeviceAlive() const
|
||||
{
|
||||
AudioObjectPropertyAddress pa;
|
||||
pa.mScope = kAudioObjectPropertyScopeWildcard;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
pa.mSelector = kAudioDevicePropertyDeviceIsAlive;
|
||||
|
||||
inputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeInput);
|
||||
outputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeOutput);
|
||||
UInt32 isAlive = 0;
|
||||
UInt32 size = sizeof (isAlive);
|
||||
return deviceID != 0
|
||||
&& OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive))
|
||||
&& isAlive != 0;
|
||||
}
|
||||
|
||||
bool updateDetailsFromDevice()
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
if (! isDeviceAlive())
|
||||
return false;
|
||||
|
||||
// this collects all the new details from the device without any locking, then
|
||||
// locks + swaps them afterwards.
|
||||
|
||||
const double newSampleRate = getNominalSampleRate();
|
||||
const int newBufferSize = getFrameSizeFromDevice();
|
||||
|
||||
Array<int> newBufferSizes = getBufferSizesFromDevice();
|
||||
Array<double> newSampleRates = getSampleRatesFromDevice();
|
||||
|
||||
const int newInputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeInput);
|
||||
const int newOutputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeOutput);
|
||||
|
||||
Array<CallbackDetailsForChannel> newInChans, newOutChans;
|
||||
StringArray newInNames (getChannelInfo (true, newInChans));
|
||||
StringArray newOutNames (getChannelInfo (false, newOutChans));
|
||||
|
||||
const int inputBitDepth = getBitDepthFromDevice (kAudioDevicePropertyScopeInput);
|
||||
const int outputBitDepth = getBitDepthFromDevice (kAudioDevicePropertyScopeOutput);
|
||||
const int newBitDepth = jmax (getBitDepthFromDevice (kAudioDevicePropertyScopeInput),
|
||||
getBitDepthFromDevice (kAudioDevicePropertyScopeOutput));
|
||||
|
||||
bitDepth = jmax (inputBitDepth, outputBitDepth);
|
||||
if (bitDepth <= 0)
|
||||
bitDepth = 32;
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
||||
// after getting the new values, lock + apply them
|
||||
const ScopedLock sl (callbackLock);
|
||||
bitDepth = newBitDepth > 0 ? newBitDepth : 32;
|
||||
|
||||
bufferSize = (int) framesPerBuf;
|
||||
allocateTempBuffers();
|
||||
if (newSampleRate > 0)
|
||||
sampleRate = newSampleRate;
|
||||
|
||||
sampleRates.swapWith (newSampleRates);
|
||||
bufferSizes.swapWith (newBufferSizes);
|
||||
inputLatency = newInputLatency;
|
||||
outputLatency = newOutputLatency;
|
||||
bufferSize = newBufferSize;
|
||||
|
||||
inChanNames.swapWith (newInNames);
|
||||
outChanNames.swapWith (newOutNames);
|
||||
sampleRates.swapWith (newSampleRates);
|
||||
bufferSizes.swapWith (newBufferSizes);
|
||||
|
||||
inputChannelInfo.swapWith (newInChans);
|
||||
outputChannelInfo.swapWith (newOutChans);
|
||||
inChanNames.swapWith (newInNames);
|
||||
outChanNames.swapWith (newOutNames);
|
||||
|
||||
inputChannelInfo.swapWith (newInChans);
|
||||
outputChannelInfo.swapWith (newOutChans);
|
||||
|
||||
allocateTempBuffers();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -769,9 +788,10 @@ public:
|
|||
stopTimer();
|
||||
const double oldSampleRate = sampleRate;
|
||||
const int oldBufferSize = bufferSize;
|
||||
updateDetailsFromDevice();
|
||||
|
||||
if (oldBufferSize != bufferSize || oldSampleRate != sampleRate)
|
||||
if (! updateDetailsFromDevice())
|
||||
owner.stop();
|
||||
else if (oldBufferSize != bufferSize || oldSampleRate != sampleRate)
|
||||
owner.restart();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue