Updates to RtAudio.cpp,h to fix deadlock in stopping stream (Core API). Other file...
authorGary Scavone <gary@music.mcgill.ca>
Thu, 31 May 2012 20:21:04 +0000 (20:21 +0000)
committerStephen Sinclair <sinclair@music.mcgill.ca>
Thu, 10 Oct 2013 23:38:30 +0000 (01:38 +0200)
Makefile.in
RtAudio.cpp
RtAudio.h
doc/doxygen/tutorial.txt
doc/release.txt
install
readme

index b627531c826954cfc2adaf0a35a0c8091dc55e78..c2cdcb1ac458a7a0ea1be5446f53aae77287f6aa 100644 (file)
@@ -8,7 +8,7 @@ OBJECTS = RtAudio.o @objects@
 
 STATIC = librtaudio.a
 SHARED = @sharedlib@
-RELEASE = 4.0.10
+RELEASE = 4.0.11
 MAJOR = 4
 LIBRARIES = $(STATIC) $(SHARED)
 
index 656be061fa7b869a3e3789f1bc960a992504dd68..47e58048bfa373ff9a1da27a7c2f4a2172567371 100644 (file)
@@ -10,7 +10,7 @@
     RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/\r
 \r
     RtAudio: realtime audio i/o C++ classes\r
-    Copyright (c) 2001-2011 Gary P. Scavone\r
+    Copyright (c) 2001-2012 Gary P. Scavone\r
 \r
     Permission is hereby granted, free of charge, to any person\r
     obtaining a copy of this software and associated documentation files\r
@@ -38,7 +38,7 @@
 */\r
 /************************************************************************/\r
 \r
-// RtAudio: Version 4.0.10\r
+// RtAudio: Version 4.0.11\r
 \r
 #include "RtAudio.h"\r
 #include <iostream>\r
@@ -416,6 +416,8 @@ struct CoreHandle {
     :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }\r
 };\r
 \r
+ThreadHandle threadId;\r
+\r
 RtApiCore:: RtApiCore()\r
 {\r
 #if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER )\r
@@ -1355,7 +1357,7 @@ void RtApiCore :: startStream( void )
     return;\r
   }\r
 \r
-  MUTEX_LOCK( &stream_.mutex );\r
+  //MUTEX_LOCK( &stream_.mutex );\r
 \r
   OSStatus result = noErr;\r
   CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r
@@ -1385,7 +1387,7 @@ void RtApiCore :: startStream( void )
   stream_.state = STREAM_RUNNING;\r
 \r
  unlock:\r
-  MUTEX_UNLOCK( &stream_.mutex );\r
+  //MUTEX_UNLOCK( &stream_.mutex );\r
 \r
   if ( result == noErr ) return;\r
   error( RtError::SYSTEM_ERROR );\r
@@ -1400,12 +1402,14 @@ void RtApiCore :: stopStream( void )
     return;\r
   }\r
 \r
+  /*\r
   MUTEX_LOCK( &stream_.mutex );\r
 \r
   if ( stream_.state == STREAM_STOPPED ) {\r
     MUTEX_UNLOCK( &stream_.mutex );\r
     return;\r
   }\r
+  */\r
 \r
   OSStatus result = noErr;\r
   CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r
@@ -1416,9 +1420,9 @@ void RtApiCore :: stopStream( void )
       pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled\r
     }\r
 \r
-    MUTEX_UNLOCK( &stream_.mutex );\r
+    //MUTEX_UNLOCK( &stream_.mutex );\r
     result = AudioDeviceStop( handle->id[0], callbackHandler );\r
-    MUTEX_LOCK( &stream_.mutex );\r
+    //MUTEX_LOCK( &stream_.mutex );\r
     if ( result != noErr ) {\r
       errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ").";\r
       errorText_ = errorStream_.str();\r
@@ -1428,9 +1432,9 @@ void RtApiCore :: stopStream( void )
 \r
   if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {\r
 \r
-    MUTEX_UNLOCK( &stream_.mutex );\r
+    //MUTEX_UNLOCK( &stream_.mutex );\r
     result = AudioDeviceStop( handle->id[1], callbackHandler );\r
-    MUTEX_LOCK( &stream_.mutex );\r
+    //MUTEX_LOCK( &stream_.mutex );\r
     if ( result != noErr ) {\r
       errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ").";\r
       errorText_ = errorStream_.str();\r
@@ -1441,7 +1445,7 @@ void RtApiCore :: stopStream( void )
   stream_.state = STREAM_STOPPED;\r
 \r
  unlock:\r
-  MUTEX_UNLOCK( &stream_.mutex );\r
+  //MUTEX_UNLOCK( &stream_.mutex );\r
 \r
   if ( result == noErr ) return;\r
   error( RtError::SYSTEM_ERROR );\r
@@ -1462,11 +1466,26 @@ void RtApiCore :: abortStream( void )
   stopStream();\r
 }\r
 \r
+// This function will be called by a spawned thread when the user\r
+// callback function signals that the stream should be stopped or\r
+// aborted.  It is better to handle it this way because the\r
+// callbackEvent() function probably should return before the AudioDeviceStop()\r
+// function is called.\r
+extern "C" void *coreStopStream( void *ptr )\r
+{\r
+  CallbackInfo *info = (CallbackInfo *) ptr;\r
+  RtApiCore *object = (RtApiCore *) info->object;\r
+\r
+  object->stopStream();\r
+\r
+  pthread_exit( NULL );\r
+}\r
+\r
 bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,\r
                                  const AudioBufferList *inBufferList,\r
                                  const AudioBufferList *outBufferList )\r
 {\r
-  if ( stream_.state == STREAM_STOPPED ) return SUCCESS;\r
+  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;\r
   if ( stream_.state == STREAM_CLOSED ) {\r
     errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";\r
     error( RtError::WARNING );\r
@@ -1478,13 +1497,18 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
 \r
   // Check if we were draining the stream and signal is finished.\r
   if ( handle->drainCounter > 3 ) {\r
-    if ( handle->internalDrain == true )\r
-      stopStream();\r
+\r
+    if ( handle->internalDrain == true ) {\r
+      stream_.state = STREAM_STOPPING;\r
+      pthread_create( &threadId, NULL, coreStopStream, info );\r
+      //stopStream();\r
+    }\r
     else // external call to stopStream()\r
       pthread_cond_signal( &handle->condition );\r
     return SUCCESS;\r
   }\r
 \r
+  /*\r
   MUTEX_LOCK( &stream_.mutex );\r
 \r
   // The state might change while waiting on a mutex.\r
@@ -1492,6 +1516,7 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
     MUTEX_UNLOCK( &stream_.mutex );\r
     return SUCCESS;\r
   }\r
+  */\r
 \r
   AudioDeviceID outputDevice = handle->id[0];\r
 \r
@@ -1514,14 +1539,15 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
     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
+      //MUTEX_UNLOCK( &stream_.mutex );\r
       handle->drainCounter = 2;\r
       abortStream();\r
       return SUCCESS;\r
     }\r
-    else if ( cbReturnValue == 1 )\r
+    else if ( cbReturnValue == 1 ) {\r
       handle->drainCounter = 1;\r
       handle->internalDrain = true;\r
+    }\r
   }\r
 \r
   if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) {\r
@@ -1719,7 +1745,7 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
   }\r
 \r
  unlock:\r
-  MUTEX_UNLOCK( &stream_.mutex );\r
+  //MUTEX_UNLOCK( &stream_.mutex );\r
 \r
   RtApi::tickStreamTime();\r
   return SUCCESS;\r
@@ -2487,9 +2513,10 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
       pthread_create( &id, NULL, jackStopStream, info );\r
       return SUCCESS;\r
     }\r
-    else if ( cbReturnValue == 1 )\r
+    else if ( cbReturnValue == 1 ) {\r
       handle->drainCounter = 1;\r
       handle->internalDrain = true;\r
+    }\r
   }\r
 \r
   jack_default_audio_sample_t *jackbuffer;\r
@@ -3321,9 +3348,10 @@ bool RtApiAsio :: callbackEvent( long bufferIndex )
                                                     &stream_.callbackInfo, 0, &threadId );\r
       return SUCCESS;\r
     }\r
-    else if ( cbReturnValue == 1 )\r
+    else if ( cbReturnValue == 1 ) {\r
       handle->drainCounter = 1;\r
       handle->internalDrain = true;\r
+    }\r
   }\r
 \r
   unsigned int nChannels, bufferBytes, i, j;\r
@@ -4653,9 +4681,10 @@ void RtApiDs :: callbackEvent()
       abortStream();\r
       return;\r
     }\r
-    else if ( cbReturnValue == 1 )\r
+    else if ( cbReturnValue == 1 ) {\r
       handle->drainCounter = 1;\r
       handle->internalDrain = true;\r
+    }\r
   }\r
 \r
   HRESULT result;\r
index 368fda3268bd6ec4e4b2919fa43222e7f0e11b81..d59e6bc06ce00d695b56fd3272a305c7b2e9907c 100644 (file)
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -10,7 +10,7 @@
     RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
 
     RtAudio: realtime audio i/o C++ classes
-    Copyright (c) 2001-2011 Gary P. Scavone
+    Copyright (c) 2001-2012 Gary P. Scavone
 
     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation files
@@ -42,7 +42,7 @@
   \file RtAudio.h
  */
 
-// RtAudio: Version 4.0.10
+// RtAudio: Version 4.0.11
 
 #ifndef __RTAUDIO_H
 #define __RTAUDIO_H
@@ -599,6 +599,7 @@ protected:
 
   enum StreamState {
     STREAM_STOPPED,
+    STREAM_STOPPING,
     STREAM_RUNNING,
     STREAM_CLOSED = -50
   };
index 39cb76a853275be083a560ce0811fe1334e662f6..e33ceecf2d836191c86d8a098e4b4829bc6e0011 100644 (file)
@@ -32,7 +32,7 @@ Devices are now re-enumerated every time the RtAudio::getDeviceCount(), RtAudio:
 
 \section download Download
 
-Latest Release (30 August 2011): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.10.tar.gz">Version 4.0.10</A>
+Latest Release (?? June 2012): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.11.tar.gz">Version 4.0.11</A>
 
 \section documentation Documentation Links
 
index a3dab357b7afe16a68e3b41b35e7174f4a24e9cc..e36c3e71687a59f14096aa571dec9186088aec11 100644 (file)
@@ -1,6 +1,11 @@
 RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.
 
-By Gary P. Scavone, 2001-2011.
+By Gary P. Scavone, 2001-2012.
+
+v4.0.11: (?? June 2012)
+- fixes for memory leaks in ALSA (thanks to Martin Koegler)
+- bitwise format flag fixes in OS-X (Benjamin Schroeder and Stefan Arisona)
+- changes to stopStream / drain flag to avoid hung state in ASIO, DS, OS-X, and Jack APIs (Rasmus Ekman and Carlos Luna)
 
 v4.0.10: (30 August 2011)
 - fix for compile bug in Windows DS (counting devices)
diff --git a/install b/install
index 365a527b4e1b0fb6aad190321d7c54dbf20856ce..0e01d12cd9a094123fbf5f0976c0d4d12b64b572 100644 (file)
--- a/install
+++ b/install
@@ -1,6 +1,6 @@
 RtAudio - a set of C++ classes which provide a common API for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.
 
-By Gary P. Scavone, 2001-2011.
+By Gary P. Scavone, 2001-2012.
 
 To configure and compile (on Unix systems and MinGW):
 
diff --git a/readme b/readme
index 58052f46a39682f720a3a0b6d4381ef485ef36b4..ae73eb24de6651068ceccaba0bee08ab297292a1 100644 (file)
--- a/readme
+++ b/readme
@@ -1,6 +1,6 @@
 RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.
 
-By Gary P. Scavone, 2001-2011.
+By Gary P. Scavone, 2001-2012.
 
 This distribution of RtAudio contains the following:
 
@@ -34,7 +34,7 @@ LEGAL AND ETHICAL:
 The RtAudio license is similar to the MIT License.
 
     RtAudio: a set of realtime audio i/o C++ classes
-    Copyright (c) 2001-2011 Gary P. Scavone
+    Copyright (c) 2001-2012 Gary P. Scavone
 
     Permission is hereby granted, free of charge, to any person
     obtaining a copy of this software and associated documentation files