Updates regarding leaks in ALSA, bitwise format flags in OS-X, and changes to stopStr...
authorGary Scavone <gary@music.mcgill.ca>
Thu, 31 May 2012 17:23:37 +0000 (17:23 +0000)
committerStephen Sinclair <sinclair@music.mcgill.ca>
Thu, 10 Oct 2013 23:38:30 +0000 (01:38 +0200)
RtAudio.cpp

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