Various updates for pulse audio, preparation for release 4.0.12, error callback addit...
authorGary Scavone <gary@music.mcgill.ca>
Mon, 15 Apr 2013 15:30:29 +0000 (15:30 +0000)
committerStephen Sinclair <sinclair@music.mcgill.ca>
Thu, 10 Oct 2013 23:38:32 +0000 (01:38 +0200)
Makefile.in
RtAudio.cpp
RtAudio.h
doc/doxygen/compiling.txt
doc/doxygen/tutorial.txt
doc/release.txt
librtaudio.pc.in

index af5c9573f8657c75e35e77e64045322c40383a56..41685e5ffab731118a1851244f25d5b961e19644 100644 (file)
@@ -8,7 +8,7 @@ OBJECTS = RtAudio.o @objects@
 
 STATIC = librtaudio.a
 SHARED = @sharedlib@
-RELEASE = 4.0.11
+RELEASE = 4.0.12
 MAJOR = 4
 LIBRARIES = $(STATIC) $(SHARED)
 
index 70414a68297577db58426f2ab46b9c3c5d9860e0..356315102b80d0a802209e233e7bcb448575d740 100644 (file)
@@ -38,7 +38,7 @@
 */\r
 /************************************************************************/\r
 \r
-// RtAudio: Version 4.0.11\r
+// RtAudio: Version 4.0.12\r
 \r
 #include "RtAudio.h"\r
 #include <iostream>\r
@@ -189,11 +189,12 @@ void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
                             RtAudioFormat format, unsigned int sampleRate,\r
                             unsigned int *bufferFrames,\r
                             RtAudioCallback callback, void *userData,\r
-                            RtAudio::StreamOptions *options )\r
+                            RtAudio::StreamOptions *options,\r
+                            RtAudioErrorCallback errorCallback )\r
 {\r
   return rtapi_->openStream( outputParameters, inputParameters, format,\r
                              sampleRate, bufferFrames, callback,\r
-                             userData, options );\r
+                             userData, options, errorCallback );\r
 }\r
 \r
 // *************************************************** //\r
@@ -224,31 +225,37 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
                           RtAudioFormat format, unsigned int sampleRate,\r
                           unsigned int *bufferFrames,\r
                           RtAudioCallback callback, void *userData,\r
-                          RtAudio::StreamOptions *options )\r
+                          RtAudio::StreamOptions *options,\r
+                          RtAudioErrorCallback errorCallback )\r
 {\r
   if ( stream_.state != STREAM_CLOSED ) {\r
     errorText_ = "RtApi::openStream: a stream is already open!";\r
     error( RtError::INVALID_USE );\r
+    return;\r
   }\r
 \r
   if ( oParams && oParams->nChannels < 1 ) {\r
     errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one.";\r
     error( RtError::INVALID_USE );\r
+    return;\r
   }\r
 \r
   if ( iParams && iParams->nChannels < 1 ) {\r
     errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one.";\r
     error( RtError::INVALID_USE );\r
+    return;\r
   }\r
 \r
   if ( oParams == NULL && iParams == NULL ) {\r
     errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!";\r
     error( RtError::INVALID_USE );\r
+    return;\r
   }\r
 \r
   if ( formatBytes(format) == 0 ) {\r
     errorText_ = "RtApi::openStream: 'format' parameter value is undefined.";\r
     error( RtError::INVALID_USE );\r
+    return;\r
   }\r
 \r
   unsigned int nDevices = getDeviceCount();\r
@@ -258,6 +265,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
     if ( oParams->deviceId >= nDevices ) {\r
       errorText_ = "RtApi::openStream: output device parameter value is invalid.";\r
       error( RtError::INVALID_USE );\r
+      return;\r
     }\r
   }\r
 \r
@@ -267,6 +275,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
     if ( iParams->deviceId >= nDevices ) {\r
       errorText_ = "RtApi::openStream: input device parameter value is invalid.";\r
       error( RtError::INVALID_USE );\r
+      return;\r
     }\r
   }\r
 \r
@@ -277,7 +286,10 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
 \r
     result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel,\r
                               sampleRate, format, bufferFrames, options );\r
-    if ( result == false ) error( RtError::SYSTEM_ERROR );\r
+    if ( result == false ) {\r
+      error( RtError::SYSTEM_ERROR );\r
+      return;\r
+    }\r
   }\r
 \r
   if ( iChannels > 0 ) {\r
@@ -287,11 +299,13 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
     if ( result == false ) {\r
       if ( oChannels > 0 ) closeStream();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
   stream_.callbackInfo.callback = (void *) callback;\r
   stream_.callbackInfo.userData = userData;\r
+  stream_.callbackInfo.errorCallback = (void *) errorCallback;\r
 \r
   if ( options ) options->numberOfBuffers = stream_.nBuffers;\r
   stream_.state = STREAM_STOPPED;\r
@@ -315,10 +329,10 @@ void RtApi :: closeStream( void )
   return;\r
 }\r
 \r
-bool RtApi :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r
-                               unsigned int firstChannel, unsigned int sampleRate,\r
-                               RtAudioFormat format, unsigned int *bufferSize,\r
-                               RtAudio::StreamOptions *options )\r
+bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/,\r
+                               unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,\r
+                               RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,\r
+                               RtAudio::StreamOptions * /*options*/ )\r
 {\r
   // MUST be implemented in subclasses!\r
   return FAILURE;\r
@@ -423,8 +437,6 @@ 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
@@ -543,11 +555,13 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
   if ( nDevices == 0 ) {\r
     errorText_ = "RtApiCore::getDeviceInfo: no devices found!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   if ( device >= nDevices ) {\r
     errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   AudioDeviceID deviceList[ nDevices ];\r
@@ -736,13 +750,13 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
   return info;\r
 }\r
 \r
-OSStatus callbackHandler( AudioDeviceID inDevice,\r
-                          const AudioTimeStamp* inNow,\r
-                          const AudioBufferList* inInputData,\r
-                          const AudioTimeStamp* inInputTime,\r
-                          AudioBufferList* outOutputData,\r
-                          const AudioTimeStamp* inOutputTime, \r
-                          void* infoPointer )\r
+static OSStatus callbackHandler( AudioDeviceID inDevice,\r
+                                 const AudioTimeStamp* /*inNow*/,\r
+                                 const AudioBufferList* inInputData,\r
+                                 const AudioTimeStamp* /*inInputTime*/,\r
+                                 AudioBufferList* outOutputData,\r
+                                 const AudioTimeStamp* /*inOutputTime*/,\r
+                                 void* infoPointer )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) infoPointer;\r
 \r
@@ -753,10 +767,10 @@ OSStatus callbackHandler( AudioDeviceID inDevice,
     return kAudioHardwareNoError;\r
 }\r
 \r
-OSStatus xrunListener( AudioObjectID inDevice,\r
-                         UInt32 nAddresses,\r
-                         const AudioObjectPropertyAddress properties[],\r
-                         void* handlePointer )\r
+static OSStatus xrunListener( AudioObjectID /*inDevice*/,\r
+                              UInt32 nAddresses,\r
+                              const AudioObjectPropertyAddress properties[],\r
+                              void* handlePointer )\r
 {\r
   CoreHandle *handle = (CoreHandle *) handlePointer;\r
   for ( UInt32 i=0; i<nAddresses; i++ ) {\r
@@ -771,10 +785,10 @@ OSStatus xrunListener( AudioObjectID inDevice,
   return kAudioHardwareNoError;\r
 }\r
 \r
-OSStatus rateListener( AudioObjectID inDevice,\r
-                       UInt32 nAddresses,\r
-                       const AudioObjectPropertyAddress properties[],\r
-                       void* ratePointer )\r
+static OSStatus rateListener( AudioObjectID inDevice,\r
+                              UInt32 /*nAddresses*/,\r
+                              const AudioObjectPropertyAddress /*properties*/[],\r
+                              void* ratePointer )\r
 {\r
 \r
   Float64 *rate = (Float64 *) ratePointer;\r
@@ -1300,6 +1314,7 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     stream_.deviceBuffer = 0;\r
   }\r
 \r
+  stream_.state = STREAM_CLOSED;\r
   return FAILURE;\r
 }\r
 \r
@@ -1459,7 +1474,7 @@ void RtApiCore :: abortStream( void )
 // 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
+static void *coreStopStream( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiCore *object = (RtApiCore *) info->object;\r
@@ -1484,6 +1499,7 @@ bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
 \r
   // Check if we were draining the stream and signal is finished.\r
   if ( handle->drainCounter > 3 ) {\r
+    ThreadHandle threadId;\r
 \r
     stream_.state = STREAM_STOPPING;\r
     if ( handle->internalDrain == true )\r
@@ -1821,8 +1837,7 @@ struct JackHandle {
     :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; }\r
 };\r
 \r
-ThreadHandle threadId;\r
-void jackSilentError( const char * ) {};\r
+static void jackSilentError( const char * ) {};\r
 \r
 RtApiJack :: RtApiJack()\r
 {\r
@@ -1911,6 +1926,7 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
     jack_client_close( client );\r
     errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   // Get the current jack server sample rate.\r
@@ -1961,7 +1977,7 @@ RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
   return info;\r
 }\r
 \r
-int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )\r
+static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) infoPointer;\r
 \r
@@ -1975,7 +1991,7 @@ int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
 // server signals that it is shutting down.  It is necessary to handle\r
 // it this way because the jackShutdown() function must return before\r
 // the jack_deactivate() function (in closeStream()) will return.\r
-extern "C" void *jackCloseStream( void *ptr )\r
+static void *jackCloseStream( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiJack *object = (RtApiJack *) info->object;\r
@@ -1984,7 +2000,7 @@ extern "C" void *jackCloseStream( void *ptr )
 \r
   pthread_exit( NULL );\r
 }\r
-void jackShutdown( void *infoPointer )\r
+static void jackShutdown( void *infoPointer )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) infoPointer;\r
   RtApiJack *object = (RtApiJack *) info->object;\r
@@ -1996,11 +2012,12 @@ void jackShutdown( void *infoPointer )
   // other problem occurred and we should close the stream.\r
   if ( object->isStreamRunning() == false ) return;\r
 \r
+  ThreadHandle threadId;\r
   pthread_create( &threadId, NULL, jackCloseStream, info );\r
   std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl;\r
 }\r
 \r
-int jackXrun( void *infoPointer )\r
+static int jackXrun( void *infoPointer )\r
 {\r
   JackHandle *handle = (JackHandle *) infoPointer;\r
 \r
@@ -2418,7 +2435,7 @@ void RtApiJack :: abortStream( void )
 // aborted.  It is necessary to handle it this way because the\r
 // callbackEvent() function must return before the jack_deactivate()\r
 // function will return.\r
-extern "C" void *jackStopStream( void *ptr )\r
+static void *jackStopStream( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiJack *object = (RtApiJack *) info->object;\r
@@ -2446,6 +2463,7 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
 \r
   // Check if we were draining the stream and signal is finished.\r
   if ( handle->drainCounter > 3 ) {\r
+    ThreadHandle threadId;\r
 \r
     stream_.state = STREAM_STOPPING;\r
     if ( handle->internalDrain == true )\r
@@ -2565,11 +2583,11 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
 #include "asiodrivers.h"\r
 #include <cmath>\r
 \r
-AsioDrivers drivers;\r
-ASIOCallbacks asioCallbacks;\r
-ASIODriverInfo driverInfo;\r
-CallbackInfo *asioCallbackInfo;\r
-bool asioXRun;\r
+static AsioDrivers drivers;\r
+static ASIOCallbacks asioCallbacks;\r
+static ASIODriverInfo driverInfo;\r
+static CallbackInfo *asioCallbackInfo;\r
+static bool asioXRun;\r
 \r
 struct AsioHandle {\r
   int drainCounter;       // Tracks callback counts when draining\r
@@ -2583,8 +2601,8 @@ struct AsioHandle {
 \r
 // Function declarations (definitions at end of section)\r
 static const char* getAsioErrorString( ASIOError result );\r
-void sampleRateChanged( ASIOSampleRate sRate );\r
-long asioMessages( long selector, long value, void* message, double* opt );\r
+static void sampleRateChanged( ASIOSampleRate sRate );\r
+static long asioMessages( long selector, long value, void* message, double* opt );\r
 \r
 RtApiAsio :: RtApiAsio()\r
 {\r
@@ -2627,11 +2645,13 @@ RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )
   if ( nDevices == 0 ) {\r
     errorText_ = "RtApiAsio::getDeviceInfo: no devices found!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   if ( device >= nDevices ) {\r
     errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   // If a stream is already open, we cannot probe other devices.  Thus, use the saved results.\r
@@ -2730,7 +2750,7 @@ RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )
   return info;\r
 }\r
 \r
-void bufferSwitch( long index, ASIOBool processNow )\r
+static void bufferSwitch( long index, ASIOBool processNow )\r
 {\r
   RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object;\r
   object->callbackEvent( index );\r
@@ -3230,7 +3250,7 @@ void RtApiAsio :: abortStream()
 // aborted.  It is necessary to handle it this way because the\r
 // callbackEvent() function must return before the ASIOStop()\r
 // function will return.\r
-extern "C" unsigned __stdcall asioStopStream( void *ptr )\r
+static unsigned __stdcall asioStopStream( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiAsio *object = (RtApiAsio *) info->object;\r
@@ -3393,7 +3413,7 @@ bool RtApiAsio :: callbackEvent( long bufferIndex )
   return SUCCESS;\r
 }\r
 \r
-void sampleRateChanged( ASIOSampleRate sRate )\r
+static void sampleRateChanged( ASIOSampleRate sRate )\r
 {\r
   // The ASIO documentation says that this usually only happens during\r
   // external sync.  Audio processing is not stopped by the driver,\r
@@ -3413,7 +3433,7 @@ void sampleRateChanged( ASIOSampleRate sRate )
   std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl;\r
 }\r
 \r
-long asioMessages( long selector, long value, void* message, double* opt )\r
+static long asioMessages( long selector, long value, void* message, double* opt )\r
 {\r
   long ret = 0;\r
 \r
@@ -3491,7 +3511,7 @@ static const char* getAsioErrorString( ASIOError result )
     const char*message;\r
   };\r
 \r
-  static Messages m[] = \r
+  static const Messages m[] = \r
     {\r
       {   ASE_NotPresent,    "Hardware input or output is not present or available." },\r
       {   ASE_HWMalfunction,  "Hardware is malfunctioning." },\r
@@ -3572,7 +3592,7 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
 \r
 static const char* getErrorString( int code );\r
 \r
-extern "C" unsigned __stdcall callbackHandler( void *ptr );\r
+static unsigned __stdcall callbackHandler( void *ptr );\r
 \r
 struct DsDevice {\r
   LPGUID id[2];\r
@@ -3584,7 +3604,10 @@ struct DsDevice {
   : found(false) { validId[0] = false; validId[1] = false; }\r
 };\r
 \r
-std::vector< DsDevice > dsDevices;\r
+struct DsProbeData {\r
+  bool isInput;\r
+  std::vector<struct DsDevice>* dsDevices;\r
+};\r
 \r
 RtApiDs :: RtApiDs()\r
 {\r
@@ -3622,8 +3645,10 @@ unsigned int RtApiDs :: getDeviceCount( void )
     dsDevices[i].found = false;\r
 \r
   // Query DirectSound devices.\r
-  bool isInput = false;\r
-  HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &isInput );\r
+  struct DsProbeData probeInfo;\r
+  probeInfo.isInput = false;\r
+  probeInfo.dsDevices = &dsDevices;\r
+  HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );\r
   if ( FAILED( result ) ) {\r
     errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating output devices!";\r
     errorText_ = errorStream_.str();\r
@@ -3631,8 +3656,8 @@ unsigned int RtApiDs :: getDeviceCount( void )
   }\r
 \r
   // Query DirectSoundCapture devices.\r
-  isInput = true;\r
-  result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &isInput );\r
+  probeInfo.isInput = true;\r
+  result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );\r
   if ( FAILED( result ) ) {\r
     errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating input devices!";\r
     errorText_ = errorStream_.str();\r
@@ -3661,12 +3686,14 @@ RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device )
     if ( dsDevices.size() == 0 ) {\r
       errorText_ = "RtApiDs::getDeviceInfo: no devices found!";\r
       error( RtError::INVALID_USE );\r
+      return info;\r
     }\r
   }\r
 \r
   if ( device >= dsDevices.size() ) {\r
     errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   HRESULT result;\r
@@ -4321,6 +4348,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned
     stream_.deviceBuffer = 0;\r
   }\r
 \r
+  stream_.state = STREAM_CLOSED;\r
   return FAILURE;\r
 }\r
 \r
@@ -4642,12 +4670,14 @@ void RtApiDs :: callbackEvent()
         errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";\r
         errorText_ = errorStream_.str();\r
         error( RtError::SYSTEM_ERROR );\r
+        return;\r
       }\r
       result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer );\r
       if ( FAILED( result ) ) {\r
         errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";\r
         errorText_ = errorStream_.str();\r
         error( RtError::SYSTEM_ERROR );\r
+        return;\r
       }\r
       while ( true ) {\r
         result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer );\r
@@ -4655,12 +4685,14 @@ void RtApiDs :: callbackEvent()
           errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";\r
           errorText_ = errorStream_.str();\r
           error( RtError::SYSTEM_ERROR );\r
+          return;\r
         }\r
         result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer );\r
         if ( FAILED( result ) ) {\r
           errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";\r
           errorText_ = errorStream_.str();\r
           error( RtError::SYSTEM_ERROR );\r
+          return;\r
         }\r
         if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break;\r
         Sleep( 1 );\r
@@ -4681,6 +4713,7 @@ void RtApiDs :: callbackEvent()
         errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";\r
         errorText_ = errorStream_.str();\r
         error( RtError::SYSTEM_ERROR );\r
+        return;\r
       }\r
       handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];\r
       if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];\r
@@ -4731,6 +4764,7 @@ void RtApiDs :: callbackEvent()
         errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";\r
         errorText_ = errorStream_.str();\r
         error( RtError::SYSTEM_ERROR );\r
+        return;\r
       }\r
 \r
       // We will copy our output buffer into the region between\r
@@ -4771,6 +4805,7 @@ void RtApiDs :: callbackEvent()
       errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!";\r
       errorText_ = errorStream_.str();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
 \r
     // Copy our buffer into the DS buffer\r
@@ -4783,6 +4818,7 @@ void RtApiDs :: callbackEvent()
       errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!";\r
       errorText_ = errorStream_.str();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
     nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize;\r
     handle->bufferPointer[0] = nextWritePointer;\r
@@ -4817,6 +4853,7 @@ void RtApiDs :: callbackEvent()
       errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";\r
       errorText_ = errorStream_.str();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
 \r
     if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset\r
@@ -4877,6 +4914,7 @@ void RtApiDs :: callbackEvent()
           errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";\r
           errorText_ = errorStream_.str();\r
           error( RtError::SYSTEM_ERROR );\r
+          return;\r
         }\r
       \r
         if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset\r
@@ -4890,6 +4928,7 @@ void RtApiDs :: callbackEvent()
       errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!";\r
       errorText_ = errorStream_.str();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
 \r
     if ( duplexPrerollBytes <= 0 ) {\r
@@ -4910,6 +4949,7 @@ void RtApiDs :: callbackEvent()
       errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!";\r
       errorText_ = errorStream_.str();\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
     handle->bufferPointer[1] = nextReadPointer;\r
 \r
@@ -4931,7 +4971,7 @@ void RtApiDs :: callbackEvent()
 // Definitions for utility functions and callbacks\r
 // specific to the DirectSound implementation.\r
 \r
-extern "C" unsigned __stdcall callbackHandler( void *ptr )\r
+static unsigned __stdcall callbackHandler( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiDs *object = (RtApiDs *) info->object;\r
@@ -4947,7 +4987,7 @@ extern "C" unsigned __stdcall callbackHandler( void *ptr )
 \r
 #include "tchar.h"\r
 \r
-std::string convertTChar( LPCTSTR name )\r
+static std::string convertTChar( LPCTSTR name )\r
 {\r
 #if defined( UNICODE ) || defined( _UNICODE )\r
   int length = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);\r
@@ -4965,11 +5005,12 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
                                           LPCTSTR module,\r
                                           LPVOID lpContext )\r
 {\r
-  bool *isInput = (bool *) lpContext;\r
+  struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext;\r
+  std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;\r
 \r
   HRESULT hr;\r
   bool validDevice = false;\r
-  if ( *isInput == true ) {\r
+  if ( probeInfo.isInput == true ) {\r
     DSCCAPS caps;\r
     LPDIRECTSOUNDCAPTURE object;\r
 \r
@@ -5001,13 +5042,14 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
 \r
   // If good device, then save its name and guid.\r
   std::string name = convertTChar( description );\r
-  if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" )\r
+  //if ( name == "Primary Sound Driver" || name == "Primary Sound Capture Driver" )\r
+  if ( lpguid == NULL )\r
     name = "Default Device";\r
   if ( validDevice ) {\r
     for ( unsigned int i=0; i<dsDevices.size(); i++ ) {\r
       if ( dsDevices[i].name == name ) {\r
         dsDevices[i].found = true;\r
-        if ( *isInput ) {\r
+        if ( probeInfo.isInput ) {\r
           dsDevices[i].id[1] = lpguid;\r
           dsDevices[i].validId[1] = true;\r
         }\r
@@ -5022,7 +5064,7 @@ static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
     DsDevice device;\r
     device.name = name;\r
     device.found = true;\r
-    if ( *isInput ) {\r
+    if ( probeInfo.isInput ) {\r
       device.id[1] = lpguid;\r
       device.validId[1] = true;\r
     }\r
@@ -5111,7 +5153,7 @@ struct AlsaHandle {
     :synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; }\r
 };\r
 \r
-extern "C" void *alsaCallbackHandler( void * ptr );\r
+static void *alsaCallbackHandler( void * ptr );\r
 \r
 RtApiAlsa :: RtApiAlsa()\r
 {\r
@@ -5224,11 +5266,13 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )
   if ( nDevices == 0 ) {\r
     errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   if ( device >= nDevices ) {\r
     errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
  foundDevice:\r
@@ -5961,6 +6005,7 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     stream_.deviceBuffer = 0;\r
   }\r
 \r
+  stream_.state = STREAM_CLOSED;\r
   return FAILURE;\r
 }\r
 \r
@@ -6335,7 +6380,7 @@ void RtApiAlsa :: callbackEvent()
   if ( doStopStream == 1 ) this->stopStream();\r
 }\r
 \r
-extern "C" void *alsaCallbackHandler( void *ptr )\r
+static void *alsaCallbackHandler( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiAlsa *object = (RtApiAlsa *) info->object;\r
@@ -6369,9 +6414,8 @@ extern "C" void *alsaCallbackHandler( void *ptr )
 #include <pulse/simple.h>\r
 #include <cstdio>\r
 \r
-namespace {\r
-const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000,\r
-                                               44100, 48000, 96000, 0}; }\r
+static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000,\r
+                                                      44100, 48000, 96000, 0};\r
 \r
 struct rtaudio_pa_format_mapping_t {\r
   RtAudioFormat rtaudio_format;\r
@@ -6423,7 +6467,7 @@ RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int device )
   return info;\r
 }\r
 \r
-extern "C" void *pulseaudio_callback( void * user )\r
+static void *pulseaudio_callback( void * user )\r
 {\r
   CallbackInfo *cbi = static_cast<CallbackInfo *>( user );\r
   RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object );\r
@@ -6618,6 +6662,7 @@ void RtApiPulse::stopStream( void )
       errorText_ = errorStream_.str();\r
       MUTEX_UNLOCK( &stream_.mutex );\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
@@ -6651,6 +6696,7 @@ void RtApiPulse::abortStream( void )
       errorText_ = errorStream_.str();\r
       MUTEX_UNLOCK( &stream_.mutex );\r
       error( RtError::SYSTEM_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
@@ -6748,9 +6794,8 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
       }\r
     }\r
   }\r
-  \r
+\r
   stream_.device[mode] = device;\r
-  stream_.state = STREAM_STOPPED;\r
 \r
   // Setup the buffer conversion information structure.\r
   if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );\r
@@ -6797,8 +6842,6 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
   else\r
     stream_.mode = DUPLEX;\r
 \r
-  stream_.state = STREAM_STOPPED;\r
-\r
   if ( !stream_.callbackInfo.isRunning ) {\r
     stream_.callbackInfo.object = this;\r
     stream_.callbackInfo.isRunning = true;\r
@@ -6807,11 +6850,30 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
       goto error;\r
     }\r
   }\r
+\r
+  stream_.state = STREAM_STOPPED;\r
   return true;\r
  \r
  error:\r
-  closeStream();\r
-  return false;\r
+  if ( pah && stream_.callbackInfo.isRunning ) {\r
+    pthread_cond_destroy( &pah->runnable_cv );\r
+    delete pah;\r
+    stream_.apiHandle = 0;\r
+  }\r
+\r
+  for ( int i=0; i<2; i++ ) {\r
+    if ( stream_.userBuffer[i] ) {\r
+      free( stream_.userBuffer[i] );\r
+      stream_.userBuffer[i] = 0;\r
+    }\r
+  }\r
+\r
+  if ( stream_.deviceBuffer ) {\r
+    free( stream_.deviceBuffer );\r
+    stream_.deviceBuffer = 0;\r
+  }\r
+\r
+  return FAILURE;\r
 }\r
 \r
 //******************** End of __LINUX_PULSE__ *********************//\r
@@ -6827,7 +6889,7 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
 #include <errno.h>\r
 #include <math.h>\r
 \r
-extern "C" void *ossCallbackHandler(void * ptr);\r
+static void *ossCallbackHandler(void * ptr);\r
 \r
 // A structure to hold various information related to the OSS API\r
 // implementation.\r
@@ -6898,12 +6960,14 @@ RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
     close( mixerfd );\r
     errorText_ = "RtApiOss::getDeviceInfo: no devices found!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   if ( device >= nDevices ) {\r
     close( mixerfd );\r
     errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!";\r
     error( RtError::INVALID_USE );\r
+    return info;\r
   }\r
 \r
   oss_audioinfo ainfo;\r
@@ -7734,7 +7798,7 @@ void RtApiOss :: callbackEvent()
   if ( doStopStream == 1 ) this->stopStream();\r
 }\r
 \r
-extern "C" void *ossCallbackHandler( void *ptr )\r
+static void *ossCallbackHandler( void *ptr )\r
 {\r
   CallbackInfo *info = (CallbackInfo *) ptr;\r
   RtApiOss *object = (RtApiOss *) info->object;\r
@@ -7763,6 +7827,28 @@ extern "C" void *ossCallbackHandler( void *ptr )
 void RtApi :: error( RtError::Type type )\r
 {\r
   errorStream_.str(""); // clear the ostringstream\r
+\r
+  RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback;\r
+  if ( errorCallback ) {\r
+    // abortStream() can generate new error messages. Ignore them. Just keep original one.\r
+    static bool firstErrorOccured = false;\r
+\r
+    if ( firstErrorOccured )\r
+      return;\r
+\r
+    firstErrorOccured = true;\r
+    const std::string errorMessage = errorText_;\r
+\r
+    if ( type != RtError::WARNING && stream_.state != STREAM_STOPPED) {\r
+      stream_.callbackInfo.isRunning = false; // exit from the thread\r
+      abortStream();\r
+    }\r
+\r
+    errorCallback( type, errorMessage );\r
+    firstErrorOccured = false;\r
+    return;\r
+  }\r
+\r
   if ( type == RtError::WARNING && showWarnings_ == true )\r
     std::cerr << '\n' << errorText_ << "\n\n";\r
   else if ( type != RtError::WARNING )\r
@@ -7792,6 +7878,7 @@ void RtApi :: clearStreamInfo()
   stream_.callbackInfo.callback = 0;\r
   stream_.callbackInfo.userData = 0;\r
   stream_.callbackInfo.isRunning = false;\r
+  stream_.callbackInfo.errorCallback = 0;\r
   for ( int i=0; i<2; i++ ) {\r
     stream_.device[i] = 11111;\r
     stream_.doConvertBuffer[i] = false;\r
index 4a0b9f330260111d14b83f5ef497c628e1d94298..8d827e3ada84270a178a043c47f819b30cca9132 100644 (file)
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -42,7 +42,7 @@
   \file RtAudio.h
  */
 
-// RtAudio: Version 4.0.11
+// RtAudio: Version 4.0.12
 
 #ifndef __RTAUDIO_H
 #define __RTAUDIO_H
     internal routines will automatically take care of any necessary
     byte-swapping between the host format and the soundcard.  Thus,
     endian-ness is not a concern in the following format definitions.
-    Note that 24-bit data is expected to be encapsulated in a 32-bit
-    format.
 
     - \e RTAUDIO_SINT8:   8-bit signed integer.
     - \e RTAUDIO_SINT16:  16-bit signed integer.
-    - \e RTAUDIO_SINT24:  Lower 3 bytes of 32-bit signed integer.
+    - \e RTAUDIO_SINT24:  24-bit signed integer.
     - \e RTAUDIO_SINT32:  32-bit signed integer.
     - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0.
     - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0.
@@ -72,7 +70,7 @@
 typedef unsigned long RtAudioFormat;
 static const RtAudioFormat RTAUDIO_SINT8 = 0x1;    // 8-bit signed integer.
 static const RtAudioFormat RTAUDIO_SINT16 = 0x2;   // 16-bit signed integer.
-static const RtAudioFormat RTAUDIO_SINT24 = 0x4;   // Lower 3 bytes of 32-bit signed integer.
+static const RtAudioFormat RTAUDIO_SINT24 = 0x4;   // 24-bit signed integer.
 static const RtAudioFormat RTAUDIO_SINT32 = 0x8;   // 32-bit signed integer.
 static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0.
 static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0.
@@ -186,6 +184,12 @@ typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer,
                                 RtAudioStreamStatus status,
                                 void *userData );
 
+//! RtAudio error callback function prototype.
+/*!
+    \param type Type of error.
+    \param errorText Error description.
+ */
+typedef void (*RtAudioErrorCallback)( RtError::Type type, const std::string &errorText );
 
 // **************************************************************** //
 //
@@ -423,12 +427,14 @@ class RtAudio
            chosen.  If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the
            lowest allowable value is used.  The actual value used is
            returned via the structure argument.  The parameter is API dependent.
+    \param errorCallback A client-defined function that will be invoked
+           when an error has occured.
   */
   void openStream( RtAudio::StreamParameters *outputParameters,
                    RtAudio::StreamParameters *inputParameters,
                    RtAudioFormat format, unsigned int sampleRate,
                    unsigned int *bufferFrames, RtAudioCallback callback,
-                   void *userData = NULL, RtAudio::StreamOptions *options = NULL );
+                   void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );
 
   //! A function that closes a stream and frees any associated stream memory.
   /*!
@@ -535,6 +541,7 @@ struct CallbackInfo {
   ThreadHandle thread;
   void *callback;
   void *userData;
+  void *errorCallback;
   void *apiInfo;   // void pointer for API specific callback information
   bool isRunning;
   bool doRealtime;
@@ -542,7 +549,7 @@ struct CallbackInfo {
 
   // Default constructor.
   CallbackInfo()
-  :object(0), callback(0), userData(0), apiInfo(0), isRunning(false), doRealtime(false) {}
+  :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {}
 };
 
 // **************************************************************** //
@@ -610,7 +617,8 @@ public:
                    RtAudio::StreamParameters *inputParameters,
                    RtAudioFormat format, unsigned int sampleRate,
                    unsigned int *bufferFrames, RtAudioCallback callback,
-                   void *userData, RtAudio::StreamOptions *options );
+                   void *userData, RtAudio::StreamOptions *options,
+                   RtAudioErrorCallback errorCallback );
   virtual void closeStream( void );
   virtual void startStream( void ) = 0;
   virtual void stopStream( void ) = 0;
@@ -618,9 +626,9 @@ public:
   long getStreamLatency( void );
   unsigned int getStreamSampleRate( void );
   virtual double getStreamTime( void );
-  bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; };
-  bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; };
-  void showWarnings( bool value ) { showWarnings_ = value; };
+  bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; }
+  bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; }
+  void showWarnings( bool value ) { showWarnings_ = value; }
 
 
 protected:
@@ -759,7 +767,7 @@ inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }
 inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); }
 inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); }
 inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }
-inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); };
+inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); }
 inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }
 inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }
 
@@ -775,7 +783,7 @@ public:
 
   RtApiCore();
   ~RtApiCore();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; };
+  RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   unsigned int getDefaultOutputDevice( void );
@@ -813,7 +821,7 @@ public:
 
   RtApiJack();
   ~RtApiJack();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; };
+  RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -846,7 +854,7 @@ public:
 
   RtApiAsio();
   ~RtApiAsio();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; };
+  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -882,7 +890,7 @@ public:
 
   RtApiDs();
   ~RtApiDs();
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; };
+  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }
   unsigned int getDeviceCount( void );
   unsigned int getDefaultOutputDevice( void );
   unsigned int getDefaultInputDevice( void );
@@ -904,6 +912,7 @@ public:
   bool coInitialized_;
   bool buffersRolling;
   long duplexPrerollBytes;
+  std::vector<struct DsDevice> dsDevices;
   bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 
                         unsigned int firstChannel, unsigned int sampleRate,
                         RtAudioFormat format, unsigned int *bufferSize,
@@ -920,7 +929,7 @@ public:
 
   RtApiAlsa();
   ~RtApiAlsa();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; };
+  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -952,7 +961,7 @@ class RtApiPulse: public RtApi
 {
 public:
   ~RtApiPulse();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; };
+  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -986,7 +995,7 @@ public:
 
   RtApiOss();
   ~RtApiOss();
-  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; };
+  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }
   unsigned int getDeviceCount( void );
   RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
   void closeStream( void );
@@ -1016,21 +1025,21 @@ class RtApiDummy: public RtApi
 {
 public:
 
-  RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); };
-  RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; };
-  unsigned int getDeviceCount( void ) { return 0; };
-  RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) { RtAudio::DeviceInfo info; return info; };
-  void closeStream( void ) {};
-  void startStream( void ) {};
-  void stopStream( void ) {};
-  void abortStream( void ) {};
+  RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); }
+  RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }
+  unsigned int getDeviceCount( void ) { return 0; }
+  RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; }
+  void closeStream( void ) {}
+  void startStream( void ) {}
+  void stopStream( void ) {}
+  void abortStream( void ) {}
 
   private:
 
-  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels
-                        unsigned int firstChannel, unsigned int sampleRate,
-                        RtAudioFormat format, unsigned int *bufferSize,
-                        RtAudio::StreamOptions *options ) { return false; };
+  bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/
+                        unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,
+                        RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,
+                        RtAudio::StreamOptions * /*options*/ ) { return false; }
 };
 
 #endif
index d9884d009ea2ac32857e870976c79a53a0245d30..c1f83e4fae9bccac024107562c29486c23fbb371 100644 (file)
@@ -32,7 +32,7 @@ In order to compile RtAudio for a specific OS and audio API, it is necessary to
   <TD>RtApiPulse</TD>
   <TD>__LINUX_PULSE__</TD>
   <TD><TT>pthread</TT></TD>
-  <TD><TT>g++ -Wall -D__LINUX_PULSE__ -o audioprobe audioprobe.cpp RtAudio.cpp -lpthread</TT></TD>
+  <TD><TT>g++ -Wall -D__LINUX_PULSE__ -o audioprobe audioprobe.cpp RtAudio.cpp -lpthread -lpulse-simple -lpulse</TT></TD>
 </TR>
 <TR>
   <TD>Linux</TD>
index 19ed170f5410d88e0e726ad6094e485b7bcff547..cbd4e21bd5016b59016b2a84d70f3a617e5acbe7 100644 (file)
@@ -32,7 +32,7 @@ Devices are now re-enumerated every time the RtAudio::getDeviceCount(), RtAudio:
 
 \section download Download
 
-Latest Release (14 June 2012): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.11.tar.gz">Version 4.0.11</A>
+Latest Release (?? December 2012): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.12.tar.gz">Version 4.0.12</A>
 
 \section documentation Documentation Links
 
index a29a36ce3f350a9e55d6745c2aa50216a8e03be8..3b09e890e3906ed93d0272c729572754cb92537a 100644 (file)
@@ -2,6 +2,14 @@ RtAudio - a set of C++ classes that provide a common API for realtime audio inpu
 
 By Gary P. Scavone, 2001-2012.
 
+v4.0.12: (?? December 2012)
+- updates to PulseAudio API support (thanks to Peter Meerwald and Tristan Matthews)
+- updates for pkg-config support in configure script
+- 24-bit format changed to true 24-bit format, not sub-bytes of 32-bits (thanks to Marc Britton)
+- bug fixes to make sure stream status is closed if error during probeDeviceOpen
+- updates / fixes to SCHED_RR code in ALSA (thanks to Marc Lindahl)
+- various changes to avoid global variables (thanks to Martin Koegler)
+
 v4.0.11: (14 June 2012)
 - fixes for memory leaks in ALSA (thanks to Martin Koegler)
 - PulseAudio API support added (thanks to Peter Meerwald and Tristan Matthews)
index e80da3cc8e5f5e16f09a0938e264e4a8574701d6..d7591a78890b6dd2bee0a3432e9d6e03674b497e 100644 (file)
@@ -5,7 +5,7 @@ includedir=${prefix}/include
 
 Name: librtaudio
 Description: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output
-Version: 4.0.11
+Version: 4.0.12
 Requires: @req@ 
 Libs: -L${libdir} -lrtaudio
 Libs.private: -lpthread