aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/pa_mac_core/pa_mac_core_utilities.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/pa_mac_core/pa_mac_core_utilities.c')
-rw-r--r--pd/portaudio/pa_mac_core/pa_mac_core_utilities.c466
1 files changed, 0 insertions, 466 deletions
diff --git a/pd/portaudio/pa_mac_core/pa_mac_core_utilities.c b/pd/portaudio/pa_mac_core/pa_mac_core_utilities.c
deleted file mode 100644
index f2cbd29c..00000000
--- a/pd/portaudio/pa_mac_core/pa_mac_core_utilities.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- *
- * pa_mac_core_utilities.c
- *
- * utilitiy functions for pa_mac_core.c
- *
- * This functions are more like helper functions than part of the core,
- * so I moved them to a separate file so the core code would be cleaner.
- *
- * by Bjorn Roche.
- */
-
-/*
- * Translates MacOS generated errors into PaErrors
- */
-static PaError PaMacCore_SetError(OSStatus error, int line, int isError)
-{
- /*FIXME: still need to handle possible ComponentResult values.*/
- /* unfortunately, they don't seem to be documented anywhere.*/
- PaError result;
- const char *errorType;
- const char *errorText;
-
- switch (error) {
- case kAudioHardwareNoError:
- return paNoError;
- case kAudioHardwareNotRunningError:
- errorText = "Audio Hardware Not Running";
- result = paInternalError; break;
- case kAudioHardwareUnspecifiedError:
- errorText = "Unspecified Audio Hardware Error";
- result = paInternalError; break;
- case kAudioHardwareUnknownPropertyError:
- errorText = "Audio Hardware: Unknown Property";
- result = paInternalError; break;
- case kAudioHardwareBadPropertySizeError:
- errorText = "Audio Hardware: Bad Property Size";
- result = paInternalError; break;
- case kAudioHardwareIllegalOperationError:
- errorText = "Audio Hardware: Illegal Operation";
- result = paInternalError; break;
- case kAudioHardwareBadDeviceError:
- errorText = "Audio Hardware: Bad Device";
- result = paInvalidDevice; break;
- case kAudioHardwareBadStreamError:
- errorText = "Audio Hardware: BadStream";
- result = paBadStreamPtr; break;
- case kAudioHardwareUnsupportedOperationError:
- errorText = "Audio Hardware: Unsupported Operation";
- result = paInternalError; break;
- case kAudioDeviceUnsupportedFormatError:
- errorText = "Audio Device: Unsupported Format";
- result = paSampleFormatNotSupported; break;
- case kAudioDevicePermissionsError:
- errorText = "Audio Device: Permissions Error";
- result = paDeviceUnavailable; break;
- /* Audio Unit Errors: http://developer.apple.com/documentation/MusicAudio/Reference/CoreAudio/audio_units/chapter_5_section_3.html */
- case kAudioUnitErr_InvalidProperty:
- errorText = "Audio Unit: Invalid Property";
- result = paInternalError; break;
- case kAudioUnitErr_InvalidParameter:
- errorText = "Audio Unit: Invalid Parameter";
- result = paInternalError; break;
- case kAudioUnitErr_NoConnection:
- errorText = "Audio Unit: No Connection";
- result = paInternalError; break;
- case kAudioUnitErr_FailedInitialization:
- errorText = "Audio Unit: Initialization Failed";
- result = paInternalError; break;
- case kAudioUnitErr_TooManyFramesToProcess:
- errorText = "Audio Unit: Too Many Frames";
- result = paInternalError; break;
- case kAudioUnitErr_IllegalInstrument:
- errorText = "Audio Unit: Illegal Instrument";
- result = paInternalError; break;
- case kAudioUnitErr_InstrumentTypeNotFound:
- errorText = "Audio Unit: Instrument Type Not Found";
- result = paInternalError; break;
- case kAudioUnitErr_InvalidFile:
- errorText = "Audio Unit: Invalid File";
- result = paInternalError; break;
- case kAudioUnitErr_UnknownFileType:
- errorText = "Audio Unit: Unknown File Type";
- result = paInternalError; break;
- case kAudioUnitErr_FileNotSpecified:
- errorText = "Audio Unit: File Not Specified";
- result = paInternalError; break;
- case kAudioUnitErr_FormatNotSupported:
- errorText = "Audio Unit: Format Not Supported";
- result = paInternalError; break;
- case kAudioUnitErr_Uninitialized:
- errorText = "Audio Unit: Unitialized";
- result = paInternalError; break;
- case kAudioUnitErr_InvalidScope:
- errorText = "Audio Unit: Invalid Scope";
- result = paInternalError; break;
- case kAudioUnitErr_PropertyNotWritable:
- errorText = "Audio Unit: PropertyNotWritable";
- result = paInternalError; break;
- case kAudioUnitErr_InvalidPropertyValue:
- errorText = "Audio Unit: Invalid Property Value";
- result = paInternalError; break;
- case kAudioUnitErr_PropertyNotInUse:
- errorText = "Audio Unit: Property Not In Use";
- result = paInternalError; break;
- case kAudioUnitErr_Initialized:
- errorText = "Audio Unit: Initialized";
- result = paInternalError; break;
- case kAudioUnitErr_InvalidOfflineRender:
- errorText = "Audio Unit: Invalid Offline Render";
- result = paInternalError; break;
- case kAudioUnitErr_Unauthorized:
- errorText = "Audio Unit: Unauthorized";
- result = paInternalError; break;
- case kAudioUnitErr_CannotDoInCurrentContext:
- errorText = "Audio Unit: cannot do in current context";
- result = paInternalError; break;
- default:
- errorText = "Unknown Error";
- result = paInternalError;
- }
-
- if (isError)
- errorType = "Error";
- else
- errorType = "Warning";
-
- if ((int)error < -99999 || (int)error > 99999)
- DBUG(("%s on line %d: err='%4s', msg='%s'\n", errorType, line, (const char *)&error, errorText));
- else
- DBUG(("%s on line %d: err=%d, 0x%x, msg='%s'\n", errorType, line, (int)error, (unsigned)error, errorText));
-
- PaUtil_SetLastHostErrorInfo( paCoreAudio, error, errorText );
-
- return result;
-}
-
-
-
-
-/*
- * Durring testing of core audio, I found that serious crashes could occur
- * if properties such as sample rate were changed multiple times in rapid
- * succession. The function below has some fancy logic to make sure that changes
- * are acknowledged before another is requested. That seems to help a lot.
- */
-
-#include <pthread.h>
-typedef struct {
- bool once; /* I didn't end up using this. bdr */
- pthread_mutex_t mutex;
-} MutexAndBool ;
-
-static OSStatus propertyProc(
- AudioDeviceID inDevice,
- UInt32 inChannel,
- Boolean isInput,
- AudioDevicePropertyID inPropertyID,
- void* inClientData )
-{
- MutexAndBool *mab = (MutexAndBool *) inClientData;
- mab->once = TRUE;
- pthread_mutex_unlock( &(mab->mutex) );
- return noErr;
-}
-
-/* sets the value of the given property and waits for the change to
- be acknowledged, and returns the final value, which is not guaranteed
- by this function to be the same as the desired value. Obviously, this
- function can only be used for data whose input and output are the
- same size and format, and their size and format are known in advance.*/
-PaError AudioDeviceSetPropertyNowAndWaitForChange(
- AudioDeviceID inDevice,
- UInt32 inChannel,
- Boolean isInput,
- AudioDevicePropertyID inPropertyID,
- UInt32 inPropertyDataSize,
- const void *inPropertyData,
- void *outPropertyData )
-{
- OSStatus macErr;
- int unixErr;
- MutexAndBool mab;
- UInt32 outPropertyDataSize = inPropertyDataSize;
-
- /* First, see if it already has that value. If so, return. */
- macErr = AudioDeviceGetProperty( inDevice, inChannel,
- isInput, inPropertyID,
- &outPropertyDataSize, outPropertyData );
- if( macErr )
- goto failMac2;
- if( inPropertyDataSize!=outPropertyDataSize )
- return paInternalError;
- if( 0==memcmp( outPropertyData, inPropertyData, outPropertyDataSize ) )
- return paNoError;
-
- /* setup and lock mutex */
- mab.once = FALSE;
- unixErr = pthread_mutex_init( &mab.mutex, NULL );
- if( unixErr )
- goto failUnix2;
- unixErr = pthread_mutex_lock( &mab.mutex );
- if( unixErr )
- goto failUnix;
-
- /* add property listener */
- macErr = AudioDeviceAddPropertyListener( inDevice, inChannel, isInput,
- inPropertyID, propertyProc,
- &mab );
- if( macErr )
- goto failMac;
- /* set property */
- macErr = AudioDeviceSetProperty( inDevice, NULL, inChannel,
- isInput, inPropertyID,
- inPropertyDataSize, inPropertyData );
- if( macErr ) {
- /* we couldn't set the property, so we'll just unlock the mutex
- and move on. */
- pthread_mutex_unlock( &mab.mutex );
- }
-
- /* wait for property to change */
- unixErr = pthread_mutex_lock( &mab.mutex );
- if( unixErr )
- goto failUnix;
-
- /* now read the property back out */
- macErr = AudioDeviceGetProperty( inDevice, inChannel,
- isInput, inPropertyID,
- &outPropertyDataSize, outPropertyData );
- if( macErr )
- goto failMac;
- /* cleanup */
- AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
- inPropertyID, propertyProc );
- unixErr = pthread_mutex_unlock( &mab.mutex );
- if( unixErr )
- goto failUnix2;
- unixErr = pthread_mutex_destroy( &mab.mutex );
- if( unixErr )
- goto failUnix2;
-
- return paNoError;
-
- failUnix:
- pthread_mutex_destroy( &mab.mutex );
- AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
- inPropertyID, propertyProc );
-
- failUnix2:
- DBUG( ("Error #%d while setting a device property: %s\n", unixErr, strerror( unixErr ) ) );
- return paUnanticipatedHostError;
-
- failMac:
- pthread_mutex_destroy( &mab.mutex );
- AudioDeviceRemovePropertyListener( inDevice, inChannel, isInput,
- inPropertyID, propertyProc );
- failMac2:
- return ERR( macErr );
-}
-
-/*
- * Sets the sample rate the HAL device.
- * if requireExact: set the sample rate or fail.
- *
- * otherwise : set the exact sample rate.
- * If that fails, check for available sample rates, and choose one
- * higher than the requested rate. If there isn't a higher one,
- * just use the highest available.
- */
-static PaError setBestSampleRateForDevice( const AudioDeviceID device,
- const bool isOutput,
- const bool requireExact,
- const Float64 desiredSrate )
-{
- /*FIXME: changing the sample rate is disruptive to other programs using the
- device, so it might be good to offer a custom flag to not change the
- sample rate and just do conversion. (in my casual tests, there is
- no disruption unless the sample rate really does need to change) */
- const bool isInput = isOutput ? 0 : 1;
- Float64 srate;
- UInt32 propsize = sizeof( Float64 );
- OSErr err;
- AudioValueRange *ranges;
- int i=0;
- Float64 max = -1; /*the maximum rate available*/
- Float64 best = -1; /*the lowest sample rate still greater than desired rate*/
- VDBUG(("Setting sample rate for device %ld to %g.\n",device,(float)desiredSrate));
-
- /* -- try setting the sample rate -- */
- err = AudioDeviceSetPropertyNowAndWaitForChange(
- device, 0, isInput,
- kAudioDevicePropertyNominalSampleRate,
- propsize, &desiredSrate, &srate );
- if( err )
- return err;
-
- /* -- if the rate agrees, and we got no errors, we are done -- */
- if( !err && srate == desiredSrate )
- return paNoError;
- /* -- we've failed if the rates disagree and we are setting input -- */
- if( requireExact )
- return paInvalidSampleRate;
-
- /* -- generate a list of available sample rates -- */
- err = AudioDeviceGetPropertyInfo( device, 0, isInput,
- kAudioDevicePropertyAvailableNominalSampleRates,
- &propsize, NULL );
- if( err )
- return ERR( err );
- ranges = (AudioValueRange *)calloc( 1, propsize );
- if( !ranges )
- return paInsufficientMemory;
- err = AudioDeviceGetProperty( device, 0, isInput,
- kAudioDevicePropertyAvailableNominalSampleRates,
- &propsize, ranges );
- if( err )
- {
- free( ranges );
- return ERR( err );
- }
- VDBUG(("Requested sample rate of %g was not available.\n", (float)desiredSrate));
- VDBUG(("%lu Available Sample Rates are:\n",propsize/sizeof(AudioValueRange)));
-#ifdef MAC_CORE_VERBOSE_DEBUG
- for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
- VDBUG( ("\t%g-%g\n",
- (float) ranges[i].mMinimum,
- (float) ranges[i].mMaximum ) );
-#endif
- VDBUG(("-----\n"));
-
- /* -- now pick the best available sample rate -- */
- for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
- {
- if( ranges[i].mMaximum > max ) max = ranges[i].mMaximum;
- if( ranges[i].mMinimum > desiredSrate ) {
- if( best < 0 )
- best = ranges[i].mMinimum;
- else if( ranges[i].mMinimum < best )
- best = ranges[i].mMinimum;
- }
- }
- if( best < 0 )
- best = max;
- VDBUG( ("Maximum Rate %g. best is %g.\n", max, best ) );
- free( ranges );
-
- /* -- set the sample rate -- */
- propsize = sizeof( best );
- err = AudioDeviceSetPropertyNowAndWaitForChange(
- device, 0, isInput,
- kAudioDevicePropertyNominalSampleRate,
- propsize, &best, &srate );
- if( err )
- return err;
-
- if( err )
- return ERR( err );
- /* -- if the set rate matches, we are done -- */
- if( srate == best )
- return paNoError;
-
- /* -- otherwise, something wierd happened: we didn't set the rate, and we got no errors. Just bail. */
- return paInternalError;
-}
-
-
-/*
- Attempts to set the requestedFramesPerBuffer. If it can't set the exact
- value, it settles for something smaller if available. If nothing smaller
- is available, it uses the smallest available size.
- actualFramesPerBuffer will be set to the actual value on successful return.
- OK to pass NULL to actualFramesPerBuffer.
- The logic is very simmilar too setBestSampleRate only failure here is
- not usually catastrophic.
-*/
-static PaError setBestFramesPerBuffer( const AudioDeviceID device,
- const bool isOutput,
- unsigned long requestedFramesPerBuffer,
- unsigned long *actualFramesPerBuffer )
-{
- UInt32 afpb;
- const bool isInput = !isOutput;
- UInt32 propsize = sizeof(UInt32);
- OSErr err;
- Float64 min = -1; /*the min blocksize*/
- Float64 best = -1; /*the best blocksize*/
- int i=0;
- AudioValueRange *ranges;
-
- if( actualFramesPerBuffer == NULL )
- actualFramesPerBuffer = &afpb;
-
-
- /* -- try and set exact FPB -- */
- err = AudioDeviceSetProperty( device, NULL, 0, isInput,
- kAudioDevicePropertyBufferFrameSize,
- propsize, &requestedFramesPerBuffer);
- err = AudioDeviceGetProperty( device, 0, isInput,
- kAudioDevicePropertyBufferFrameSize,
- &propsize, actualFramesPerBuffer);
- if( err )
- return ERR( err );
- if( *actualFramesPerBuffer == requestedFramesPerBuffer )
- return paNoError; /* we are done */
-
- /* -- fetch available block sizes -- */
- err = AudioDeviceGetPropertyInfo( device, 0, isInput,
- kAudioDevicePropertyBufferSizeRange,
- &propsize, NULL );
- if( err )
- return ERR( err );
- ranges = (AudioValueRange *)calloc( 1, propsize );
- if( !ranges )
- return paInsufficientMemory;
- err = AudioDeviceGetProperty( device, 0, isInput,
- kAudioDevicePropertyBufferSizeRange,
- &propsize, ranges );
- if( err )
- {
- free( ranges );
- return ERR( err );
- }
- VDBUG(("Requested block size of %lu was not available.\n",
- requestedFramesPerBuffer ));
- VDBUG(("%lu Available block sizes are:\n",propsize/sizeof(AudioValueRange)));
-#ifdef MAC_CORE_VERBOSE_DEBUG
- for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
- VDBUG( ("\t%g-%g\n",
- (float) ranges[i].mMinimum,
- (float) ranges[i].mMaximum ) );
-#endif
- VDBUG(("-----\n"));
-
- /* --- now pick the best available framesPerBuffer -- */
- for( i=0; i<propsize/sizeof(AudioValueRange); ++i )
- {
- if( min == -1 || ranges[i].mMinimum < min ) min = ranges[i].mMinimum;
- if( ranges[i].mMaximum < requestedFramesPerBuffer ) {
- if( best < 0 )
- best = ranges[i].mMaximum;
- else if( ranges[i].mMaximum > best )
- best = ranges[i].mMaximum;
- }
- }
- if( best == -1 )
- best = min;
- VDBUG( ("Minimum FPB %g. best is %g.\n", min, best ) );
- free( ranges );
-
- /* --- set the buffer size (ignore errors) -- */
- requestedFramesPerBuffer = (UInt32) best ;
- propsize = sizeof( UInt32 );
- err = AudioDeviceSetProperty( device, NULL, 0, isInput,
- kAudioDevicePropertyBufferSize,
- propsize, &requestedFramesPerBuffer );
- /* --- read the property to check that it was set -- */
- err = AudioDeviceGetProperty( device, 0, isInput,
- kAudioDevicePropertyBufferSize,
- &propsize, actualFramesPerBuffer );
-
- if( err )
- return ERR( err );
-
- return paNoError;
-}