Ports Portaudio WMME device timeout system to MacOsX CoreAudio in order to
avoid deadlock when a device is unplugged. Vincent Lucas committed on Jan 10, 2013 2a20693 from https://github.com/jitsi/libsrc/commits/master/portaudio.zip
This commit is contained in:
parent
ab8b64023c
commit
66bda13f84
3 changed files with 69 additions and 4 deletions
|
|
@ -2460,15 +2460,32 @@ static PaError StartStream( PaStream *s )
|
|||
|
||||
// it's not clear from appl's docs that this really waits
|
||||
// until all data is flushed.
|
||||
static ComponentResult BlockWhileAudioUnitIsRunning( AudioUnit audioUnit, AudioUnitElement element )
|
||||
static ComponentResult BlockWhileAudioUnitIsRunning(
|
||||
AudioUnit audioUnit,
|
||||
AudioUnitElement element)
|
||||
{
|
||||
long waitTime = 100;
|
||||
// If PaUtil_GetRingBufferWriteAvailable starts repetitively and
|
||||
// consecutively returning that there is no data available, do eventually
|
||||
// give up in order to allow the caller to handle such cases.
|
||||
long totalTimeout = 0;
|
||||
Boolean isRunning = 1;
|
||||
while( isRunning ) {
|
||||
UInt32 s = sizeof( isRunning );
|
||||
ComponentResult err = AudioUnitGetProperty( audioUnit, kAudioOutputUnitProperty_IsRunning, kAudioUnitScope_Global, element, &isRunning, &s );
|
||||
if( err )
|
||||
return err;
|
||||
Pa_Sleep( 100 );
|
||||
Pa_Sleep( waitTime );
|
||||
|
||||
// If a timeout is encountered, continue. However, testing has
|
||||
// shown that it is possible to unplug a device and to wait here
|
||||
// forever. In order to allow the caller to handle such cases of
|
||||
// repeated timeouts, do eventually given up.
|
||||
totalTimeout += waitTime;
|
||||
if( PA_COREAUDIO_MIN_TIMEOUT_MSEC_ <= totalTimeout)
|
||||
{
|
||||
return paTimedOut;
|
||||
}
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
|
@ -2481,7 +2498,7 @@ static PaError StopStream( PaStream *s )
|
|||
VVDBUG(("StopStream()\n"));
|
||||
|
||||
VDBUG( ("Waiting for BLIO.\n") );
|
||||
waitUntilBlioWriteBufferIsFlushed( &stream->blio );
|
||||
waitUntilBlioWriteBufferIsFlushed( &stream->blio);
|
||||
VDBUG( ( "Stopping stream.\n" ) );
|
||||
|
||||
stream->state = STOPPING;
|
||||
|
|
@ -2507,7 +2524,7 @@ static PaError StopStream( PaStream *s )
|
|||
if( stream->outputUnit )
|
||||
{
|
||||
ERR_WRAP(AudioOutputUnitStop(stream->outputUnit));
|
||||
ERR_WRAP( BlockWhileAudioUnitIsRunning(stream->outputUnit,0) );
|
||||
ERR_WRAP( BlockWhileAudioUnitIsRunning(stream->outputUnit,0));
|
||||
ERR_WRAP(AudioUnitReset(stream->outputUnit,kAudioUnitScope_Global,0));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -415,6 +415,10 @@ PaError ReadStream( PaStream* stream,
|
|||
while( frames > 0 ) {
|
||||
long avail;
|
||||
long toRead;
|
||||
// If PaUtil_GetRingBufferReadAvailable starts repetitively and
|
||||
// consecutively returning that there is no data available, do eventually
|
||||
// give up in order to allow the caller to handle such cases.
|
||||
long totalTimeout = 0;
|
||||
do {
|
||||
avail = PaUtil_GetRingBufferReadAvailable( &blio->inputRingBuffer );
|
||||
/*
|
||||
|
|
@ -438,6 +442,16 @@ PaError ReadStream( PaStream* stream,
|
|||
return ret;
|
||||
#else
|
||||
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
|
||||
|
||||
// If a timeout is encountered, continue. However, testing has
|
||||
// shown that it is possible to unplug a device and to wait here
|
||||
// forever. In order to allow the caller to handle such cases of
|
||||
// repeated timeouts, do eventually given up.
|
||||
totalTimeout += PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL;
|
||||
if( PA_COREAUDIO_MAX_TIMEOUT_MSEC_ <= totalTimeout)
|
||||
{
|
||||
return paTimedOut;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} while( avail == 0 );
|
||||
|
|
@ -491,6 +505,10 @@ PaError WriteStream( PaStream* stream,
|
|||
while( frames > 0 ) {
|
||||
long avail = 0;
|
||||
long toWrite;
|
||||
// If PaUtil_GetRingBufferWriteAvailable starts repetitively and
|
||||
// consecutively returning that there is no data available, do eventually
|
||||
// give up in order to allow the caller to handle such cases.
|
||||
long totalTimeout = 0;
|
||||
|
||||
do {
|
||||
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
|
||||
|
|
@ -515,6 +533,16 @@ PaError WriteStream( PaStream* stream,
|
|||
return ret;
|
||||
#else
|
||||
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
|
||||
|
||||
// If a timeout is encountered, continue. However, testing has
|
||||
// shown that it is possible to unplug a device and to wait here
|
||||
// forever. In order to allow the caller to handle such cases of
|
||||
// repeated timeouts, do eventually given up.
|
||||
totalTimeout += PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL;
|
||||
if( PA_COREAUDIO_MAX_TIMEOUT_MSEC_ <= totalTimeout)
|
||||
{
|
||||
return paTimedOut;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} while( avail == 0 );
|
||||
|
|
@ -561,13 +589,30 @@ PaError WriteStream( PaStream* stream,
|
|||
void waitUntilBlioWriteBufferIsFlushed( PaMacBlio *blio )
|
||||
{
|
||||
if( blio->outputRingBuffer.buffer ) {
|
||||
// If PaUtil_GetRingBufferWriteAvailable starts repetitively and
|
||||
// consecutively returning that there is no data available, do eventually
|
||||
// give up in order to allow the caller to handle such cases.
|
||||
long totalTimeout = 0;
|
||||
long avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
|
||||
while( avail != blio->outputRingBuffer.bufferSize ) {
|
||||
if( avail == 0 )
|
||||
{
|
||||
Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
|
||||
|
||||
// If a timeout is encountered, continue. However, testing has
|
||||
// shown that it is possible to unplug a device and to wait here
|
||||
// forever. In order to allow the caller to handle such cases of
|
||||
// repeated timeouts, do eventually given up.
|
||||
totalTimeout += PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL;
|
||||
if( PA_COREAUDIO_MIN_TIMEOUT_MSEC_ <= totalTimeout)
|
||||
{
|
||||
return paTimedOut;
|
||||
}
|
||||
}
|
||||
avail = PaUtil_GetRingBufferWriteAvailable( &blio->outputRingBuffer );
|
||||
}
|
||||
}
|
||||
return paNoError;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@
|
|||
#define PA_MAC_BLIO_MUTEX
|
||||
*/
|
||||
|
||||
#define PA_COREAUDIO_MIN_TIMEOUT_MSEC_ (1000)
|
||||
#define PA_COREAUDIO_MAX_TIMEOUT_MSEC_ (2000)
|
||||
|
||||
typedef struct {
|
||||
PaUtilRingBuffer inputRingBuffer;
|
||||
PaUtilRingBuffer outputRingBuffer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue