| @@ -106,6 +106,10 @@ void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw() | |||
| void RtAudio :: openRtApi( RtAudio::Api api ) | |||
| { | |||
| if (rtapi_) | |||
| delete rtapi_; | |||
| rtapi_ = 0; | |||
| #if defined(__UNIX_JACK__) | |||
| if ( api == UNIX_JACK ) | |||
| rtapi_ = new RtApiJack(); | |||
| @@ -1080,7 +1084,7 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne | |||
| // We'll try higher bit rates first and then work our way down. | |||
| std::vector< std::pair<UInt32, UInt32> > physicalFormats; | |||
| formatFlags = description.mFormatFlags | kLinearPCMFormatFlagIsFloat & ~kLinearPCMFormatFlagIsSignedInteger; | |||
| formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger; | |||
| physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) ); | |||
| formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat; | |||
| physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) ); | |||
| @@ -1507,14 +1511,16 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId, | |||
| handle->xrun[1] = false; | |||
| } | |||
| handle->drainCounter = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( handle->drainCounter == 2 ) { | |||
| int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( cbReturnValue == 2 ) { | |||
| MUTEX_UNLOCK( &stream_.mutex ); | |||
| handle->drainCounter = 2; | |||
| abortStream(); | |||
| return SUCCESS; | |||
| } | |||
| else if ( handle->drainCounter == 1 ) | |||
| else if ( cbReturnValue == 1 ) | |||
| handle->drainCounter = 1; | |||
| handle->internalDrain = true; | |||
| } | |||
| @@ -1901,6 +1907,7 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device ) | |||
| } | |||
| if ( device >= nDevices ) { | |||
| jack_client_close( client ); | |||
| errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!"; | |||
| error( RtError::INVALID_USE ); | |||
| } | |||
| @@ -2471,15 +2478,17 @@ bool RtApiJack :: callbackEvent( unsigned long nframes ) | |||
| status |= RTAUDIO_INPUT_OVERFLOW; | |||
| handle->xrun[1] = false; | |||
| } | |||
| handle->drainCounter = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( handle->drainCounter == 2 ) { | |||
| int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( cbReturnValue == 2 ) { | |||
| MUTEX_UNLOCK( &stream_.mutex ); | |||
| ThreadHandle id; | |||
| handle->drainCounter = 2; | |||
| pthread_create( &id, NULL, jackStopStream, info ); | |||
| return SUCCESS; | |||
| } | |||
| else if ( handle->drainCounter == 1 ) | |||
| else if ( cbReturnValue == 1 ) | |||
| handle->drainCounter = 1; | |||
| handle->internalDrain = true; | |||
| } | |||
| @@ -3300,18 +3309,20 @@ bool RtApiAsio :: callbackEvent( long bufferIndex ) | |||
| status |= RTAUDIO_INPUT_OVERFLOW; | |||
| asioXRun = false; | |||
| } | |||
| handle->drainCounter = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( handle->drainCounter == 2 ) { | |||
| if ( cbReturnValue == 2 ) { | |||
| // MUTEX_UNLOCK( &stream_.mutex ); | |||
| // abortStream(); | |||
| unsigned threadId; | |||
| stopThreadCalled = true; | |||
| handle->drainCounter = 2; | |||
| stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream, | |||
| &stream_.callbackInfo, 0, &threadId ); | |||
| return SUCCESS; | |||
| } | |||
| else if ( handle->drainCounter == 1 ) | |||
| else if ( cbReturnValue == 1 ) | |||
| handle->drainCounter = 1; | |||
| handle->internalDrain = true; | |||
| } | |||
| @@ -4634,14 +4645,16 @@ void RtApiDs :: callbackEvent() | |||
| status |= RTAUDIO_INPUT_OVERFLOW; | |||
| handle->xrun[1] = false; | |||
| } | |||
| handle->drainCounter = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( handle->drainCounter == 2 ) { | |||
| int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1], | |||
| stream_.bufferSize, streamTime, status, info->userData ); | |||
| if ( cbReturnValue == 2 ) { | |||
| // MUTEX_UNLOCK( &stream_.mutex ); | |||
| handle->drainCounter = 2; | |||
| abortStream(); | |||
| return; | |||
| } | |||
| else if ( handle->drainCounter == 1 ) | |||
| else if ( cbReturnValue == 1 ) | |||
| handle->drainCounter = 1; | |||
| handle->internalDrain = true; | |||
| } | |||
| @@ -4908,7 +4921,7 @@ void RtApiDs :: callbackEvent() | |||
| } | |||
| } | |||
| else { // mode == INPUT | |||
| while ( safeReadPointer < endRead ) { | |||
| while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) { | |||
| // See comments for playback. | |||
| double millis = (endRead - safeReadPointer) * 1000.0; | |||
| millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate); | |||
| @@ -5268,6 +5281,7 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) | |||
| // Thus, use the saved results. | |||
| if ( stream_.state != STREAM_CLOSED && | |||
| ( stream_.device[0] == device || stream_.device[1] == device ) ) { | |||
| snd_ctl_close( chandle ); | |||
| if ( device >= devices_.size() ) { | |||
| errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened."; | |||
| error( RtError::WARNING ); | |||
| @@ -5672,6 +5686,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne | |||
| } | |||
| // If we get here, no supported format was found. | |||
| snd_pcm_close( phandle ); | |||
| errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio."; | |||
| errorText_ = errorStream_.str(); | |||
| return FAILURE; | |||
| @@ -5769,6 +5784,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne | |||
| // If attempting to setup a duplex stream, the bufferSize parameter | |||
| // MUST be the same in both directions! | |||
| if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { | |||
| snd_pcm_close( phandle ); | |||
| errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ")."; | |||
| errorText_ = errorStream_.str(); | |||
| return FAILURE; | |||
| @@ -5855,6 +5871,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne | |||
| apiInfo = (AlsaHandle *) stream_.apiHandle; | |||
| } | |||
| apiInfo->handles[mode] = phandle; | |||
| phandle = 0; | |||
| // Allocate necessary internal buffers. | |||
| unsigned long bufferBytes; | |||
| @@ -5962,6 +5979,8 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne | |||
| stream_.apiHandle = 0; | |||
| } | |||
| if ( phandle) snd_pcm_close( phandle ); | |||
| for ( int i=0; i<2; i++ ) { | |||
| if ( stream_.userBuffer[i] ) { | |||
| free( stream_.userBuffer[i] ); | |||