From 98ea697d33ad8d21d2fd7a720a565d73c9855635 Mon Sep 17 00:00:00 2001 From: John Melas Date: Thu, 26 Nov 2020 14:28:17 +0200 Subject: [PATCH] new hal --- src/hostapi/coreaudio/pa_mac_core.c | 241 +++++++++++++----- src/hostapi/coreaudio/pa_mac_core_utilities.c | 212 +++++++++++++-- src/hostapi/coreaudio/pa_mac_core_utilities.h | 75 +++++- 3 files changed, 448 insertions(+), 80 deletions(-) diff --git a/src/hostapi/coreaudio/pa_mac_core.c b/src/hostapi/coreaudio/pa_mac_core.c index 4f66f8c..155c6ba 100644 --- a/src/hostapi/coreaudio/pa_mac_core.c +++ b/src/hostapi/coreaudio/pa_mac_core.c @@ -138,7 +138,7 @@ const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input ) /* First try with CFString */ UInt32 size = sizeof(nameRef); - error = AudioDeviceGetProperty( hostApiDevice, + error = pa_AudioDeviceGetProperty( hostApiDevice, channelIndex + 1, input, kAudioDevicePropertyChannelNameCFString, @@ -148,18 +148,17 @@ const char *PaMacCore_GetChannelName( int device, int channelIndex, bool input ) { /* try the C String */ size = 0; - error = AudioDeviceGetPropertyInfo( hostApiDevice, + error = pa_AudioDeviceGetPropertySize( hostApiDevice, channelIndex + 1, input, kAudioDevicePropertyChannelName, - &size, - NULL); + &size); if( !error ) { if( !ensureChannelNameSize( size ) ) return NULL; - - error = AudioDeviceGetProperty( hostApiDevice, + + error = pa_AudioDeviceGetProperty( hostApiDevice, channelIndex + 1, input, kAudioDevicePropertyChannelName, @@ -223,8 +222,8 @@ PaError PaMacCore_GetBufferSizeRange( PaDeviceIndex device, Boolean isInput = 0; if( macCoreHostApi->inheritedHostApiRep.deviceInfos[hostApiDeviceIndex]->maxOutputChannels == 0 ) isInput = 1; - - result = WARNING(AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) ); + + result = WARNING(pa_AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) ); *minBufferSizeFrames = audioRange.mMinimum; *maxBufferSizeFrames = audioRange.mMaximum; @@ -353,9 +352,8 @@ static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi) auhalHostApi->devIds = NULL; /* -- figure out how many devices there are -- */ - AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices, - &propsize, - NULL ); + pa_AudioHardwareGetPropertySize( kAudioHardwarePropertyDevices, + &propsize); auhalHostApi->devCount = propsize / sizeof( AudioDeviceID ); VDBUG( ( "Found %ld device(s).\n", auhalHostApi->devCount ) ); @@ -366,7 +364,7 @@ static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi) propsize ); if( !auhalHostApi->devIds ) return paInsufficientMemory; - AudioHardwareGetProperty( kAudioHardwarePropertyDevices, + pa_AudioHardwareGetProperty( kAudioHardwarePropertyDevices, &propsize, auhalHostApi->devIds ); #ifdef MAC_CORE_VERBOSE_DEBUG @@ -385,7 +383,7 @@ static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi) /* I am not sure how these calls to AudioHardwareGetProperty() could fail, but in case they do, we use the first available device as the default. */ - if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, + if( 0 != pa_AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size, &auhalHostApi->defaultIn) ) { int i; @@ -401,8 +399,8 @@ static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi) break; } } - } - if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + } + if( 0 != pa_AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &auhalHostApi->defaultOut) ) { int i; @@ -437,7 +435,7 @@ static PaError ClipToDeviceBufferSize( AudioDeviceID macCoreDeviceId, UInt32 resultSize = desiredSize; AudioValueRange audioRange; UInt32 propSize = sizeof( audioRange ); - PaError err = WARNING(AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) ); + PaError err = WARNING(pa_AudioDeviceGetProperty( macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &audioRange ) ); resultSize = MAX( resultSize, audioRange.mMinimum ); resultSize = MIN( resultSize, audioRange.mMaximum ); *allowedSize = resultSize; @@ -487,7 +485,7 @@ static void DumpDeviceProperties( AudioDeviceID macCoreDeviceId, printf("Stream #%d = %d---------------------- \n", i, streamIDs[i] ); propSize = sizeof(UInt32); - err = WARNING(AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &propSize, &streamLatency)); + err = WARNING(p_AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &propSize, &streamLatency)); printf(" kAudioStreamPropertyLatency: err = %d, propSize = %d, value = %d\n", err, propSize, streamLatency ); } } @@ -517,20 +515,20 @@ static PaError CalculateFixedDeviceLatency( AudioDeviceID macCoreDeviceId, int i // To get stream latency we have to get a streamID from the device. // We are only going to look at the first stream so only fetch one stream. propSize = sizeof(streamIDs); - err = WARNING(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreams, &propSize, &streamIDs[0])); + err = WARNING(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreams, &propSize, &streamIDs[0])); if( err != paNoError ) goto error; if( propSize == sizeof(AudioStreamID) ) { propSize = sizeof(UInt32); - err = WARNING(AudioStreamGetProperty(streamIDs[0], 0, kAudioStreamPropertyLatency, &propSize, &streamLatency)); + err = WARNING(pa_AudioStreamGetProperty(streamIDs[0], 0, kAudioStreamPropertyLatency, &propSize, &streamLatency)); } propSize = sizeof(UInt32); - err = WARNING(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertySafetyOffset, &propSize, &safetyOffset)); + err = WARNING(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertySafetyOffset, &propSize, &safetyOffset)); if( err != paNoError ) goto error; propSize = sizeof(UInt32); - err = WARNING(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyLatency, &propSize, &deviceLatency)); + err = WARNING(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyLatency, &propSize, &deviceLatency)); if( err != paNoError ) goto error; *fixedLatencyPtr = deviceLatency + streamLatency + safetyOffset; @@ -560,7 +558,7 @@ static PaError CalculateDefaultDeviceLatencies( AudioDeviceID macCoreDeviceId, // For high latency use the default device buffer size. propSize = sizeof(UInt32); - err = WARNING(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSize, &propSize, &bufferFrames)); + err = WARNING(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyBufferFrameSize, &propSize, &bufferFrames)); if( err != paNoError ) goto error; *lowLatencyFramesPtr = fixedLatency + clippedMinBufferSize; @@ -589,14 +587,14 @@ static PaError GetChannelInfo( PaMacAUHAL *auhalHostApi, /* Get the number of channels from the stream configuration. Fail if we can't get this. */ - err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL)); + err = ERR(pa_AudioDeviceGetPropertySize(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize)); if (err) return err; buflist = PaUtil_AllocateMemory(propSize); if( !buflist ) return paInsufficientMemory; - err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist)); + err = ERR(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist)); if (err) goto error; @@ -664,18 +662,18 @@ static PaError InitializeDeviceInfo( PaMacAUHAL *auhalHostApi, /* Get the device name using CFString */ propSize = sizeof(nameRef); - err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceNameCFString, &propSize, &nameRef)); + err = ERR(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceNameCFString, &propSize, &nameRef)); if (err) { /* Get the device name using c string. Fail if we can't get it. */ - err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL)); + err = ERR(pa_AudioDeviceGetPropertySize(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize)); if (err) return err; name = PaUtil_GroupAllocateMemory(auhalHostApi->allocations,propSize+1); if ( !name ) return paInsufficientMemory; - err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name)); + err = ERR(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name)); if (err) return err; } @@ -696,7 +694,7 @@ static PaError InitializeDeviceInfo( PaMacAUHAL *auhalHostApi, /* Try to get the default sample rate. Don't fail if we can't get this. */ propSize = sizeof(Float64); - err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &sampleRate)); + err = ERR(pa_AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &sampleRate)); if (err) deviceInfo->defaultSampleRate = 0.0; else @@ -1045,7 +1043,7 @@ static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, Aud Float64 sampleRate = 0.0; UInt32 propSize = sizeof(Float64); - OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, sampleRatePropertyID, &propSize, &sampleRate); + OSStatus osErr = pa_AudioDeviceGetProperty( deviceID, 0, isInput, sampleRatePropertyID, &propSize, &sampleRate); if( (osErr == noErr) && (sampleRate > 1000.0) ) /* avoid divide by zero if there's an error */ { deviceProperties->sampleRate = sampleRate; @@ -1054,6 +1052,23 @@ static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, Aud return osErr; } +#if PA_NEW_HAL +static OSStatus AudioDevicePropertyActualSampleRateListenerProc(AudioObjectID inDevice, UInt32 inNumberAddresses, const AudioObjectPropertyAddress * inAddresses, void * inClientData) +{ + PaMacCoreStream * stream = (PaMacCoreStream *) inClientData; + bool isInput = inAddresses->mScope == kAudioDevicePropertyScopeInput; + + // Make sure the callback is operating on a stream that is still valid! + assert(stream->streamRepresentation.magic == PA_STREAM_MAGIC); + + OSStatus osErr = UpdateSampleRateFromDeviceProperty(stream, inDevice, isInput, kAudioDevicePropertyActualSampleRate); + if (osErr == noErr) + { + UpdateTimeStampOffsets(stream); + } + return osErr; +} +#else static OSStatus AudioDevicePropertyActualSampleRateListenerProc( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void *inClientData ) { PaMacCoreStream *stream = (PaMacCoreStream*)inClientData; @@ -1068,13 +1083,13 @@ static OSStatus AudioDevicePropertyActualSampleRateListenerProc( AudioDeviceID i } return osErr; } - +#endif /* ================================================================================= */ static OSStatus QueryUInt32DeviceProperty( AudioDeviceID deviceID, Boolean isInput, AudioDevicePropertyID propertyID, UInt32 *outValue ) { UInt32 propertyValue = 0; UInt32 propertySize = sizeof(UInt32); - OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, propertyID, &propertySize, &propertyValue); + OSStatus osErr = pa_AudioDeviceGetProperty( deviceID, 0, isInput, propertyID, &propertySize, &propertyValue); if( osErr == noErr ) { *outValue = propertyValue; @@ -1082,6 +1097,44 @@ static OSStatus QueryUInt32DeviceProperty( AudioDeviceID deviceID, Boolean isInp return osErr; } +#if PA_NEW_HAL +static OSStatus AudioDevicePropertyGenericListenerProc(AudioObjectID inDevice, UInt32 inNumberAddresses, const AudioObjectPropertyAddress * inAddresses, void * inClientData) +{ + OSStatus osErr = noErr; + PaMacCoreStream * stream = (PaMacCoreStream *) inClientData; + bool isInput = inAddresses->mScope == kAudioDevicePropertyScopeInput; + AudioDevicePropertyID inPropertyID = inAddresses->mSelector; + + // Make sure the callback is operating on a stream that is still valid! + assert(stream->streamRepresentation.magic == PA_STREAM_MAGIC); + + PaMacCoreDeviceProperties * deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties; + UInt32 * valuePtr = NULL; + switch (inPropertyID) + { + case kAudioDevicePropertySafetyOffset: + valuePtr = &deviceProperties->safetyOffset; + break; + + case kAudioDevicePropertyLatency: + valuePtr = &deviceProperties->deviceLatency; + break; + + case kAudioDevicePropertyBufferFrameSize: + valuePtr = &deviceProperties->bufferFrameSize; + break; + } + if (valuePtr != NULL) + { + osErr = QueryUInt32DeviceProperty(inDevice, isInput, inPropertyID, valuePtr); + if (osErr == noErr) + { + UpdateTimeStampOffsets(stream); + } + } + return osErr; +} +#else static OSStatus AudioDevicePropertyGenericListenerProc( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void *inClientData ) { OSStatus osErr = noErr; @@ -1116,6 +1169,7 @@ static OSStatus AudioDevicePropertyGenericListenerProc( AudioDeviceID inDevice, } return osErr; } +#endif /* ================================================================================= */ /* @@ -1131,31 +1185,31 @@ static OSStatus SetupDevicePropertyListeners( PaMacCoreStream *stream, AudioDevi kAudioDevicePropertyBufferFrameSize, &deviceProperties->bufferFrameSize )) != noErr ) return osErr; if( (osErr = QueryUInt32DeviceProperty( deviceID, isInput, kAudioDevicePropertySafetyOffset, &deviceProperties->safetyOffset )) != noErr ) return osErr; - - AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, + + pa_AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, AudioDevicePropertyActualSampleRateListenerProc, stream ); - - AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioStreamPropertyLatency, - AudioDevicePropertyGenericListenerProc, stream ); - AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertyBufferFrameSize, - AudioDevicePropertyGenericListenerProc, stream ); - AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertySafetyOffset, - AudioDevicePropertyGenericListenerProc, stream ); - + + pa_AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioStreamPropertyLatency, + AudioDevicePropertyGenericListenerProc, stream ); + pa_AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertyBufferFrameSize, + AudioDevicePropertyGenericListenerProc, stream ); + pa_AudioDeviceAddPropertyListener( deviceID, 0, isInput, kAudioDevicePropertySafetyOffset, + AudioDevicePropertyGenericListenerProc, stream ); + return osErr; } static void CleanupDevicePropertyListeners( PaMacCoreStream *stream, AudioDeviceID deviceID, Boolean isInput ) -{ - AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, - AudioDevicePropertyActualSampleRateListenerProc ); - - AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyLatency, - AudioDevicePropertyGenericListenerProc ); - AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyBufferFrameSize, - AudioDevicePropertyGenericListenerProc ); - AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertySafetyOffset, - AudioDevicePropertyGenericListenerProc ); +{ + pa_AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, + AudioDevicePropertyActualSampleRateListenerProc, stream ); + + pa_AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyLatency, + AudioDevicePropertyGenericListenerProc, stream ); + pa_AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertyBufferFrameSize, + AudioDevicePropertyGenericListenerProc, stream ); + pa_AudioDeviceRemovePropertyListener( deviceID, 0, isInput, kAudioDevicePropertySafetyOffset, + AudioDevicePropertyGenericListenerProc, stream ); } /* ================================================================================= */ @@ -1329,7 +1383,7 @@ static PaError OpenAndSetupOneAudioUnit( sizeof(AudioDeviceID) ) ); } /* -- add listener for dropouts -- */ - result = AudioDeviceAddPropertyListener( *audioDevice, + result = pa_AudioDeviceAddPropertyListener( *audioDevice, 0, outStreamParams ? false : true, kAudioDeviceProcessorOverload, @@ -2128,9 +2182,43 @@ PaTime GetStreamTime( PaStream *s ) #define RING_BUFFER_EMPTY (1000) -static OSStatus ringBufferIOProc( AudioConverterRef inAudioConverter, - UInt32*ioDataSize, - void** outData, +#if PA_NEW_HAL +static OSStatus ringBufferIOProc( + AudioConverterRef inAudioConverter, + UInt32* ioNumberDataPackets, + AudioBufferList* ioData, + AudioStreamPacketDescription** outDataPacketDescription, + void* inUserData) +{ + UInt32 * ioDataSize = &ioData->mBuffers[0].mDataByteSize; + void ** outData = &ioData->mBuffers[0].mData; + + void *dummyData; + ring_buffer_size_t dummySize; + PaUtilRingBuffer *rb = (PaUtilRingBuffer *) inUserData; + + VVDBUG(("ringBufferIOProc()\n")); + + if( PaUtil_GetRingBufferReadAvailable( rb ) == 0 ) { + *outData = NULL; + *ioDataSize = 0; + return RING_BUFFER_EMPTY; + } + assert(sizeof(UInt32) == sizeof(ring_buffer_size_t)); + assert( ( (*ioDataSize) / rb->elementSizeBytes ) * rb->elementSizeBytes == (*ioDataSize) ) ; + (*ioDataSize) /= rb->elementSizeBytes ; + PaUtil_GetRingBufferReadRegions( rb, *ioDataSize, + outData, (ring_buffer_size_t *)ioDataSize, + &dummyData, &dummySize ); + assert( *ioDataSize ); + PaUtil_AdvanceRingBufferReadIndex( rb, *ioDataSize ); + (*ioDataSize) *= rb->elementSizeBytes ; + return noErr; +} +#else +static OSStatus ringBufferIOProc( AudioConverterRef inAudioConverter, + UInt32*ioDataSize, + void** outData, void*inUserData ) { void *dummyData; @@ -2156,6 +2244,7 @@ static OSStatus ringBufferIOProc( AudioConverterRef inAudioConverter, return noErr; } +#endif /* * Called by the AudioUnit API to process audio from the sound card. @@ -2377,12 +2466,27 @@ static OSStatus AudioIOProc( void *inRefCon, UInt32 size; float data[ inChan * frames ]; size = sizeof( data ); - err = AudioConverterFillBuffer( +#if PA_NEW_HAL + AudioBufferList bufferList; + bufferList.mNumberBuffers = 1; + bufferList.mBuffers[0].mNumberChannels = inChan; + bufferList.mBuffers[0].mDataByteSize = size; + bufferList.mBuffers[0].mData = data; + err = AudioConverterFillComplexBuffer( + stream->inputSRConverter, + ringBufferIOProc, + &stream->inputRingBuffer, + &size, + &bufferList, + NULL); +#else + err = AudioConverterFillBuffer( stream->inputSRConverter, ringBufferIOProc, &stream->inputRingBuffer, &size, (void *)&data ); +#endif if( err == RING_BUFFER_EMPTY ) { /* the ring buffer callback underflowed */ err = 0; @@ -2562,12 +2666,27 @@ static OSStatus AudioIOProc( void *inRefCon, long f; size = sizeof( data ); - err = AudioConverterFillBuffer( +#if PA_NEW_HAL + AudioBufferList bufferList; + bufferList.mNumberBuffers = 1; + bufferList.mBuffers[0].mNumberChannels = chan; + bufferList.mBuffers[0].mDataByteSize = size; + bufferList.mBuffers[0].mData = data; + err = AudioConverterFillComplexBuffer( + stream->inputSRConverter, + ringBufferIOProc, + &stream->inputRingBuffer, + &size, + &bufferList, + NULL); +#else + err = AudioConverterFillBuffer( stream->inputSRConverter, ringBufferIOProc, &stream->inputRingBuffer, &size, (void *)data ); +#endif if( err != RING_BUFFER_EMPTY ) ERR( err ); if( err != noErr && err != RING_BUFFER_EMPTY ) @@ -2646,20 +2765,20 @@ static PaError CloseStream( PaStream* s ) if( stream->outputUnit ) { int count = removeFromXRunListenerList( stream ); if( count == 0 ) - AudioDeviceRemovePropertyListener( stream->outputDevice, + pa_AudioDeviceRemovePropertyListener( stream->outputDevice, 0, false, kAudioDeviceProcessorOverload, - xrunCallback ); + xrunCallback, NULL ); //todo: do we need to pass actual node? } if( stream->inputUnit && stream->outputUnit != stream->inputUnit ) { int count = removeFromXRunListenerList( stream ); if( count == 0 ) - AudioDeviceRemovePropertyListener( stream->inputDevice, + pa_AudioDeviceRemovePropertyListener( stream->inputDevice, 0, true, kAudioDeviceProcessorOverload, - xrunCallback ); + xrunCallback, NULL ); //todo: do we need to pass actual node? } if( stream->outputUnit && stream->outputUnit != stream->inputUnit ) { AudioUnitUninitialize( stream->outputUnit ); diff --git a/src/hostapi/coreaudio/pa_mac_core_utilities.c b/src/hostapi/coreaudio/pa_mac_core_utilities.c index 73c7f8c..4563a93 100644 --- a/src/hostapi/coreaudio/pa_mac_core_utilities.c +++ b/src/hostapi/coreaudio/pa_mac_core_utilities.c @@ -63,6 +63,131 @@ #include #include +OSStatus pa_AudioHardwareGetProperty( + AudioHardwarePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData) +{ +#if PA_NEW_HAL + AudioObjectPropertyAddress address = { inPropertyID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + return AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, ioPropertyDataSize, outPropertyData); +#else + macErr = AudioHardwareGetProperty(inPropertyID, ioPropertyDataSize, outPropertyData); +#endif +} + +OSStatus pa_AudioHardwareGetPropertySize( + AudioHardwarePropertyID inPropertyID, + UInt32* outSize) +{ +#if PA_NEW_HAL + AudioObjectPropertyAddress address = { inPropertyID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + return AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &address, 0, NULL, outSize); +#else + macErr = AudioHardwareGetPropertyInfo(inPropertyID, outSize, NULL); +#endif +} + +OSStatus pa_AudioDeviceGetProperty( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData) +{ +#if PA_NEW_HAL + AudioObjectPropertyScope scope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + AudioObjectPropertyAddress address = { inPropertyID, scope, inChannel }; + return AudioObjectGetPropertyData(inDevice, &address, 0, NULL, ioPropertyDataSize, outPropertyData); +#else + macErr = AudioDeviceGetProperty(inDevice, inChannel, isInput, inPropertyID, ioPropertyDataSize, outPropertyData); +#endif +} + +OSStatus pa_AudioDeviceSetProperty( + AudioDeviceID inDevice, + const AudioTimeStamp* inWhen, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32 inPropertyDataSize, + const void* inPropertyData) +{ +#if PA_NEW_HAL + AudioObjectPropertyScope scope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + AudioObjectPropertyAddress address = { inPropertyID, scope, inChannel }; + return AudioObjectSetPropertyData(inDevice, &address, 0, NULL, inPropertyDataSize, inPropertyData); +#else + return AudioDeviceSetProperty(inDevice, inWhen, inChannel, isInput, inPropertyID, inPropertyDataSize, inPropertyData); +#endif +} + +OSStatus pa_AudioDeviceGetPropertySize( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32* outSize) +{ +#if PA_NEW_HAL + AudioObjectPropertyScope scope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + AudioObjectPropertyAddress address = { inPropertyID, scope, inChannel }; + return AudioObjectGetPropertyDataSize(inDevice, &address, 0, NULL, outSize); +#else + return AudioDeviceGetPropertyInfo(inDevice, inChannel, isInput, inPropertyID, outSize, NULL); +#endif +} + +OSStatus pa_AudioDeviceAddPropertyListener( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + pa_AudioDevicePropertyListenerProc inProc, + void* inClientData) +{ +#if PA_NEW_HAL + AudioObjectPropertyScope scope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + AudioObjectPropertyAddress address = { inPropertyID, scope, inChannel }; + return AudioObjectAddPropertyListener(inDevice, &address, inProc, inClientData); +#else + return AudioDeviceAddPropertyListener(inDevice, inChannel, isInput, inPropertyID, inProc, inClientData); +#endif +} + +OSStatus pa_AudioDeviceRemovePropertyListener( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + pa_AudioDevicePropertyListenerProc inProc, + void* inClientData) +{ +#if PA_NEW_HAL + AudioObjectPropertyScope scope = isInput ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + AudioObjectPropertyAddress address = { inPropertyID, scope, inChannel }; + return AudioObjectRemovePropertyListener(inDevice, &address, inProc, inClientData); +#else + return AudioDeviceRemovePropertyListener(inDevice, inChannel, isInput, inPropertyID, inProc); +#endif +} + +OSStatus pa_AudioStreamGetProperty( + AudioStreamID inStream, + UInt32 inChannel, + AudioDevicePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData) +{ +#if PA_NEW_HAL + AudioObjectPropertyAddress address = { inPropertyID, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + return AudioObjectGetPropertyData(inStream, &address, 0, NULL, ioPropertyDataSize, outPropertyData); +#else + return AudioStreamGetProperty(inStream, inChannel, inPropertyID, ioPropertyDataSize, outPropertyData); +#endif +} + PaError PaMacCore_SetUnixError( int err, int line ) { PaError ret; @@ -149,12 +274,14 @@ PaError PaMacCore_SetError(OSStatus error, int line, int isError) case kAudioUnitErr_TooManyFramesToProcess: errorText = "Audio Unit: Too Many Frames"; result = paInternalError; break; +#if ! PA_NEW_HAL case kAudioUnitErr_IllegalInstrument: errorText = "Audio Unit: Illegal Instrument"; result = paInternalError; break; case kAudioUnitErr_InstrumentTypeNotFound: errorText = "Audio Unit: Instrument Type Not Found"; result = paInternalError; break; +#endif case kAudioUnitErr_InvalidFile: errorText = "Audio Unit: Invalid File"; result = paInternalError; break; @@ -307,6 +434,17 @@ long computeRingBufferSize( const PaStreamParameters *inputParameters, * since it represents a theoretically better implementation. */ +#if PA_NEW_HAL +OSStatus propertyProc( + AudioObjectID inObjectID, + UInt32 inNumberAddresses, + const AudioObjectPropertyAddress* inAddresses, + void* inClientData) +{ + // this is where we would set the condition variable + return noErr; +} +#else OSStatus propertyProc( AudioDeviceID inDevice, UInt32 inChannel, @@ -317,6 +455,7 @@ OSStatus propertyProc( // this is where we would set the condition variable return noErr; } +#endif /* sets the value of the given property and waits for the change to be acknowledged, and returns the final value, which is not guaranteed @@ -340,8 +479,8 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( UInt32 outPropertyDataSize = inPropertyDataSize; /* First, see if it already has that value. If so, return. */ - macErr = AudioDeviceGetProperty( inDevice, inChannel, - isInput, inPropertyID, + macErr = pa_AudioDeviceGetProperty( inDevice, inChannel, + isInput, inPropertyID, &outPropertyDataSize, outPropertyData ); if( macErr ) { memset( outPropertyData, 0, inPropertyDataSize ); @@ -357,7 +496,7 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( /* If we were using a cond variable, we'd do something useful here, but for now, this is just to make 10.6 happy. */ - macErr = AudioDeviceAddPropertyListener( inDevice, inChannel, isInput, + macErr = pa_AudioDeviceAddPropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc, NULL ); if( macErr ) @@ -365,7 +504,7 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( goto failMac; /* set property */ - macErr = AudioDeviceSetProperty( inDevice, NULL, inChannel, + macErr = pa_AudioDeviceSetProperty( inDevice, NULL, inChannel, isInput, inPropertyID, inPropertyDataSize, inPropertyData ); if( macErr ) @@ -380,8 +519,8 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( memcpy( &tv2, &tv1, sizeof( struct timeval ) ); while( tv2.tv_sec - tv1.tv_sec < 30 ) { /* now read the property back out */ - macErr = AudioDeviceGetProperty( inDevice, inChannel, - isInput, inPropertyID, + macErr = pa_AudioDeviceGetProperty( inDevice, inChannel, + isInput, inPropertyID, &outPropertyDataSize, outPropertyData ); if( macErr ) { memset( outPropertyData, 0, inPropertyDataSize ); @@ -389,7 +528,7 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( } /* and compare... */ if( 0==memcmp( outPropertyData, inPropertyData, outPropertyDataSize ) ) { - AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc ); + pa_AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc, NULL); return paNoError; } /* No match yet, so let's sleep and try again. */ @@ -397,12 +536,12 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange( gettimeofday( &tv2, NULL ); } DBUG( ("Timeout waiting for device setting.\n" ) ); - - AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc ); + + pa_AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc, NULL ); return paNoError; failMac: - AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc ); + pa_AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput, inPropertyID, propertyProc, NULL ); return ERR( macErr ); } @@ -448,15 +587,15 @@ PaError setBestSampleRateForDevice( const AudioDeviceID device, return paInvalidSampleRate; /* -- generate a list of available sample rates -- */ - err = AudioDeviceGetPropertyInfo( device, 0, isInput, + err = pa_AudioDeviceGetPropertySize( device, 0, isInput, kAudioDevicePropertyAvailableNominalSampleRates, - &propsize, NULL ); + &propsize ); if( err ) return ERR( err ); ranges = (AudioValueRange *)calloc( 1, propsize ); if( !ranges ) return paInsufficientMemory; - err = AudioDeviceGetProperty( device, 0, isInput, + err = pa_AudioDeviceGetProperty( device, 0, isInput, kAudioDevicePropertyAvailableNominalSampleRates, &propsize, ranges ); if( err ) @@ -536,10 +675,10 @@ PaError setBestFramesPerBuffer( const AudioDeviceID device, } /* -- try and set exact FPB -- */ - err = AudioDeviceSetProperty( device, NULL, 0, isInput, + err = pa_AudioDeviceSetProperty( device, NULL, 0, isInput, kAudioDevicePropertyBufferFrameSize, propsize, &requestedFramesPerBuffer); - err = AudioDeviceGetProperty( device, 0, isInput, + err = pa_AudioDeviceGetProperty( device, 0, isInput, kAudioDevicePropertyBufferFrameSize, &propsize, actualFramesPerBuffer); if( err ) @@ -554,7 +693,7 @@ PaError setBestFramesPerBuffer( const AudioDeviceID device, // Clip requested value against legal range for the device. propsize = sizeof(AudioValueRange); - err = AudioDeviceGetProperty( device, 0, isInput, + err = pa_AudioDeviceGetProperty( device, 0, isInput, kAudioDevicePropertyBufferFrameSizeRange, &propsize, &range ); if( err ) @@ -572,11 +711,11 @@ PaError setBestFramesPerBuffer( const AudioDeviceID device, /* --- set the buffer size (ignore errors) -- */ propsize = sizeof( UInt32 ); - err = AudioDeviceSetProperty( device, NULL, 0, isInput, + err = pa_AudioDeviceSetProperty( device, NULL, 0, isInput, kAudioDevicePropertyBufferFrameSize, propsize, &requestedFramesPerBuffer ); /* --- read the property to check that it was set -- */ - err = AudioDeviceGetProperty( device, 0, isInput, + err = pa_AudioDeviceGetProperty( device, 0, isInput, kAudioDevicePropertyBufferFrameSize, &propsize, actualFramesPerBuffer ); @@ -605,6 +744,42 @@ static PaMacXRunListNode firstXRunListNode; static int xRunListSize; static pthread_mutex_t xrunMutex; +#if PA_NEW_HAL +OSStatus xrunCallback( + AudioObjectID inDevice, + UInt32 inNumberAddresses, + const AudioObjectPropertyAddress* inAddresses, + void * inClientData) +{ + PaMacXRunListNode *node = (PaMacXRunListNode *) inClientData; + bool isInput = inAddresses->mScope == kAudioDevicePropertyScopeInput; + + int ret = pthread_mutex_trylock( &xrunMutex ) ; + + if( ret == 0 ) { + node = node->next ; //skip the first node + + for( ; node; node=node->next ) { + PaMacCoreStream *stream = node->stream; + + if( stream->state != ACTIVE ) + continue; //if the stream isn't active, we don't care if the device is dropping + + if( isInput ) { + if( stream->inputDevice == inDevice ) + OSAtomicOr32( paInputOverflow, &stream->xrunFlags ); + } else { + if( stream->outputDevice == inDevice ) + OSAtomicOr32( paOutputUnderflow, &stream->xrunFlags ); + } + } + + pthread_mutex_unlock( &xrunMutex ); + } + + return 0; +} +#else OSStatus xrunCallback( AudioDeviceID inDevice, UInt32 inChannel, @@ -640,6 +815,7 @@ OSStatus xrunCallback( return 0; } +#endif int initializeXRunListenerList( void ) { diff --git a/src/hostapi/coreaudio/pa_mac_core_utilities.h b/src/hostapi/coreaudio/pa_mac_core_utilities.h index e63b3cb..e6e0c6e 100644 --- a/src/hostapi/coreaudio/pa_mac_core_utilities.h +++ b/src/hostapi/coreaudio/pa_mac_core_utilities.h @@ -111,9 +111,66 @@ # define VVDBUG(MSG) #endif +#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) +#define PA_NEW_HAL 1 +#else +#define PA_NEW_HAL 0 +#endif +#if PA_NEW_HAL +typedef AudioObjectPropertyListenerProc pa_AudioDevicePropertyListenerProc; +#else +typedef AudioDevicePropertyListenerProc pa_AudioDevicePropertyListenerProc; +#endif - +OSStatus pa_AudioHardwareGetProperty( + AudioHardwarePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData); +OSStatus pa_AudioHardwareGetPropertySize( + AudioHardwarePropertyID inPropertyID, + UInt32* outSize); +OSStatus pa_AudioDeviceGetProperty( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData); +OSStatus pa_AudioDeviceSetProperty( + AudioDeviceID inDevice, + const AudioTimeStamp* inWhen, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32 inPropertyDataSize, + const void* inPropertyData); +OSStatus pa_AudioDeviceGetPropertySize( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + UInt32* outSize); +OSStatus pa_AudioDeviceAddPropertyListener( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + pa_AudioDevicePropertyListenerProc inProc, + void* inClientData); +OSStatus pa_AudioDeviceRemovePropertyListener( + AudioDeviceID inDevice, + UInt32 inChannel, + Boolean isInput, + AudioDevicePropertyID inPropertyID, + pa_AudioDevicePropertyListenerProc inProc, + void* inClientData); +OSStatus pa_AudioStreamGetProperty( + AudioStreamID inStream, + UInt32 inChannel, + AudioDevicePropertyID inPropertyID, + UInt32* ioPropertyDataSize, + void* outPropertyData); #define UNIX_ERR(err) PaMacCore_SetUnixError( err, __LINE__ ) @@ -143,12 +200,20 @@ long computeRingBufferSize( const PaStreamParameters *inputParameters, long outputFramesPerBuffer, double sampleRate ); +#if PA_NEW_HAL +OSStatus propertyProc( + AudioObjectID inObjectID, + UInt32 inNumberAddresses, + const AudioObjectPropertyAddress* inAddresses, + void* inClientData); +#else OSStatus propertyProc( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void* inClientData ); +#endif /* sets the value of the given property and waits for the change to be acknowledged, and returns the final value, which is not guaranteed @@ -198,12 +263,20 @@ PaError setBestFramesPerBuffer( const AudioDeviceID device, * *********************/ +#if PA_NEW_HAL +OSStatus xrunCallback( + AudioObjectID inObjectID, + UInt32 inNumberAddresses, + const AudioObjectPropertyAddress* inAddresses, + void * inClientData ); +#else OSStatus xrunCallback( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void* inClientData ) ; +#endif /** returns zero on success or a unix style error code. */ int initializeXRunListenerList( void ); -- 2.43.0