Commit 5fd12677 authored by bjornroche's avatar bjornroche

fixes for hardware samplerate changes

git-svn-id: https://subversion.assembla.com/svn/portaudio/portaudio/trunk@1423 0f58301d-fd10-0410-b4af-bbb618454e57
parent 53b1182c
......@@ -84,6 +84,7 @@ TESTS = \
bin/patest_sine_channelmaps \
bin/patest_sine_formats \
bin/patest_sine_time \
bin/patest_sine_srate \
bin/patest_start_stop \
bin/patest_stop \
bin/patest_stop_playout \
......
......@@ -61,6 +61,7 @@
#include <libkern/OSAtomic.h>
#include <strings.h>
#include <pthread.h>
#include <sys/time.h>
PaError PaMacCore_SetUnixError( int err, int line )
{
......@@ -305,8 +306,13 @@ long computeRingBufferSize( const PaStreamParameters *inputParameters,
/*
* 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.
* succession. The function below could be used to with a condition variable.
* to prevent propertychanges from happening until the last property
* change is acknowledged. Instead, I implemented a busy-wait, which is simpler
* to implement b/c in second round of testing (nov '09) property changes occured
* quickly and so there was no real way to test the condition variable implementation.
* therefore, this function is not used, but it is aluded to in commented code below,
* since it represents a theoretically better implementation.
*/
OSStatus propertyProc(
......@@ -316,9 +322,7 @@ OSStatus propertyProc(
AudioDevicePropertyID inPropertyID,
void* inClientData )
{
MutexAndBool *mab = (MutexAndBool *) inClientData;
mab->once = TRUE;
pthread_mutex_unlock( &(mab->mutex) );
// this is where we would set the condition variable
return noErr;
}
......@@ -337,8 +341,6 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange(
void *outPropertyData )
{
OSStatus macErr;
int unixErr;
MutexAndBool mab;
UInt32 outPropertyDataSize = inPropertyDataSize;
/* First, see if it already has that value. If so, return. */
......@@ -346,74 +348,63 @@ PaError AudioDeviceSetPropertyNowAndWaitForChange(
isInput, inPropertyID,
&outPropertyDataSize, outPropertyData );
if( macErr )
goto failMac2;
goto failMac;
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;
/* Ideally, we'd use a condition variable to determine changes.
we could set that up here. */
/* If we were using a cond variable, we'd add a property listener here.
No more notes on that, but don't forget to remove the listener as well! */
//macErr = AudioDeviceAddPropertyListener( inDevice, inChannel, isInput,
// inPropertyID, propertyProc,
// NULL );
//if( macErr )
// /* we couldn't add a listener. */
// 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 );
}
if( macErr )
goto failMac;
/* wait for property to change */
unixErr = pthread_mutex_lock( &mab.mutex );
if( unixErr )
goto failUnix;
/* busy-wait up to 30 seconds for the property to change */
/* busy-wait is justified here only because the correct alternative (condition variable)
was hard to test, since most of the waiting ended up being for setting rather than
getting in OS X 10.5. This was not the case in earlier OS versions. */
struct timeval tv1, tv2;
gettimeofday( &tv1, NULL );
memcpy( &tv2, &tv1, sizeof( struct timeval ) );
while( tv2.tv_sec - tv1.tv_sec < 30 ) {
macErr = AudioDeviceGetProperty( inDevice, inChannel,
isInput, inPropertyID,
&outPropertyDataSize, outPropertyData );
if( macErr )
goto failMac;
if( 0==memcmp( outPropertyData, inPropertyData, outPropertyDataSize ) ) {
return paNoError;
}
Pa_Sleep( 100 );
gettimeofday( &tv2, NULL );
}
DBUG( ("Timeout waiting for device setting." ) );
/* now read the property back out */
///* 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 );
}
......
......@@ -143,18 +143,6 @@ long computeRingBufferSize( const PaStreamParameters *inputParameters,
long outputFramesPerBuffer,
double sampleRate );
/*
* 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.
*/
typedef struct {
bool once; /* I didn't end up using this. bdr */
pthread_mutex_t mutex;
} MutexAndBool ;
OSStatus propertyProc(
AudioDeviceID inDevice,
UInt32 inChannel,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment