Updates to WASAPI API to support MinGW compile.
authorGary Scavone <gary@music.mcgill.ca>
Wed, 16 Apr 2014 00:40:51 +0000 (20:40 -0400)
committerGary Scavone <gary@music.mcgill.ca>
Wed, 16 Apr 2014 00:40:51 +0000 (20:40 -0400)
CMakeLists.txt
RtAudio.cpp
RtAudio.h
configure.ac
doc/release.txt
install

index b96b769888ca4448223e08ce0ebb911246156215..136ab8d89102071f1d9a27818d642f13e9bdd257 100644 (file)
@@ -87,7 +87,7 @@ endif (UNIX)
 
 if (WIN32)
     if (NOT AUDIO_WINDOWS_DS AND NOT AUDIO_WINDOWS_ASIO AND NOT AUDIO_WINDOWS_WASAPI)
-        set(AUDIO_WINDOWS_DS ON)
+        set(AUDIO_WINDOWS_WASAPI ON)
     endif()
 
     include_directories(include)
index eb3eadc411236243eded55af91ee744ff31b8048..dd06b52ba1263023b1fb2db74f3c4ee2a6b449ba 100644 (file)
@@ -38,7 +38,7 @@
 */\r
 /************************************************************************/\r
 \r
-// RtAudio: Version 4.1.0\r
+// RtAudio: Version 4.1.1pre\r
 \r
 #include "RtAudio.h"\r
 #include <iostream>\r
@@ -3578,21 +3578,16 @@ static const char* getAsioErrorString( ASIOError result )
 \r
 #if defined(__WINDOWS_WASAPI__) // Windows WASAPI API\r
 \r
+#ifndef INITGUID\r
+  #define INITGUID\r
+#endif\r
 #include <audioclient.h>\r
 #include <avrt.h>\r
-#include <functiondiscoverykeys.h>\r
 #include <mmdeviceapi.h>\r
+#include <functiondiscoverykeys_devpkey.h>\r
 \r
 //=============================================================================\r
 \r
-#define EXIT_ON_ERROR( hr, errorType, errorText )\\r
-if ( FAILED( hr ) )\\r
-{\\r
-  errorText_ = __FUNCTION__ ": " errorText;\\r
-  error( errorType );\\r
-  goto Exit;\\r
-}\r
-\r
 #define SAFE_RELEASE( objectPtr )\\r
 if ( objectPtr )\\r
 {\\r
@@ -3783,7 +3778,7 @@ void convertBufferWasapi( char* outBuffer,
   float sampleRatio = ( float ) outSampleRate / inSampleRate;\r
   float sampleStep = 1.0f / sampleRatio;\r
   float inSampleFraction = 0.0f;\r
-  unsigned int commonChannelCount = min( inChannelCount, outChannelCount );\r
+  unsigned int commonChannelCount = std::min( inChannelCount, outChannelCount );\r
 \r
   outSampleCount = ( unsigned int ) ( inSampleCount * sampleRatio );\r
 \r
@@ -3851,7 +3846,7 @@ RtApiWasapi::RtApiWasapi()
   if ( !FAILED( hr ) )\r
     coInitialized_ = true;\r
 \r
-  // instantiate device enumerator\r
+  // Instantiate device enumerator\r
   hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL,\r
                          CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ),\r
                          ( void** ) &deviceEnumerator_ );\r
@@ -3888,26 +3883,43 @@ unsigned int RtApiWasapi::getDeviceCount( void )
   IMMDeviceCollection* captureDevices = NULL;\r
   IMMDeviceCollection* renderDevices = NULL;\r
 \r
-  // count capture devices\r
+  // Count capture devices\r
+  errorText_.clear();\r
   HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = captureDevices->GetCount( &captureDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count.";\r
+    goto Exit;\r
+  }\r
 \r
-  // count render devices\r
+  // Count render devices\r
   hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = renderDevices->GetCount( &renderDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count.";\r
+    goto Exit;\r
+  }\r
 \r
 Exit:\r
   // release all references\r
   SAFE_RELEASE( captureDevices );\r
   SAFE_RELEASE( renderDevices );\r
 \r
-  return captureDeviceCount + renderDeviceCount;\r
+  if ( errorText_.empty() )\r
+    return captureDeviceCount + renderDeviceCount;\r
+\r
+  error( RtAudioError::DRIVER_ERROR );\r
+  return 0;\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -3938,67 +3950,105 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
   // probed\r
   info.probed = false;\r
 \r
-  // count capture devices\r
+  // Count capture devices\r
+  errorText_.clear();\r
+  RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;\r
   HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = captureDevices->GetCount( &captureDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count.";\r
+    goto Exit;\r
+  }\r
 \r
-  // count render devices\r
+  // Count render devices\r
   hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = renderDevices->GetCount( &renderDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count.";\r
+    goto Exit;\r
+  }\r
 \r
   // validate device index\r
-  if ( device >= captureDeviceCount + renderDeviceCount )\r
-    EXIT_ON_ERROR( -1, RtAudioError::INVALID_USE, "Invalid device index" );\r
+  if ( device >= captureDeviceCount + renderDeviceCount ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index.";\r
+    errorType = RtAudioError::INVALID_USE;\r
+    goto Exit;\r
+  }\r
 \r
   // determine whether index falls within capture or render devices\r
   if ( device >= renderDeviceCount ) {\r
     hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device handle" );\r
-\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle.";\r
+      goto Exit;\r
+    }\r
     isCaptureDevice = true;\r
   }\r
   else {\r
     hr = renderDevices->Item( device, &devicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device handle" );\r
-\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle.";\r
+      goto Exit;\r
+    }\r
     isCaptureDevice = false;\r
   }\r
 \r
   // get default device name\r
   if ( isCaptureDevice ) {\r
     hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve default render device handle" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle.";\r
+      goto Exit;\r
+    }\r
   }\r
   else {\r
     hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve default capture device handle" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle.";\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to open default device property store" );\r
-\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store.";\r
+    goto Exit;\r
+  }\r
   PropVariantInit( &defaultDeviceNameProp );\r
 \r
   hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve default device property: PKEY_Device_FriendlyName" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName.";\r
+    goto Exit;\r
+  }\r
 \r
   deviceName = defaultDeviceNameProp.pwszVal;\r
   defaultDeviceName = std::string( deviceName.begin(), deviceName.end() );\r
 \r
   // name\r
   hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to open device property store" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store.";\r
+    goto Exit;\r
+  }\r
 \r
   PropVariantInit( &deviceNameProp );\r
 \r
   hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device property: PKEY_Device_FriendlyName" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName.";\r
+    goto Exit;\r
+  }\r
 \r
   deviceName = deviceNameProp.pwszVal;\r
   info.name = std::string( deviceName.begin(), deviceName.end() );\r
@@ -4015,10 +4065,16 @@ RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
 \r
   // channel count\r
   hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device audio client" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = audioClient->GetMixFormat( &deviceFormat );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device mix format" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format.";\r
+    goto Exit;\r
+  }\r
 \r
   if ( isCaptureDevice ) {\r
     info.inputChannels = deviceFormat->nChannels;\r
@@ -4099,6 +4155,8 @@ Exit:
   CoTaskMemFree( deviceFormat );\r
   CoTaskMemFree( closestMatchFormat );\r
 \r
+  if ( !errorText_.empty() )\r
+    error( errorType );\r
   return info;\r
 }\r
 \r
@@ -4133,7 +4191,7 @@ unsigned int RtApiWasapi::getDefaultInputDevice( void )
 void RtApiWasapi::closeStream( void )\r
 {\r
   if ( stream_.state == STREAM_CLOSED ) {\r
-    errorText_ = "RtApiWasapi::closeStream: No open stream to close";\r
+    errorText_ = "RtApiWasapi::closeStream: No open stream to close.";\r
     error( RtAudioError::WARNING );\r
     return;\r
   }\r
@@ -4154,7 +4212,7 @@ void RtApiWasapi::closeStream( void )
   if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent )\r
     CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent );\r
 \r
-  delete stream_.apiHandle;\r
+  delete ( WasapiHandle* ) stream_.apiHandle;\r
   stream_.apiHandle = NULL;\r
 \r
   for ( int i = 0; i < 2; i++ ) {\r
@@ -4180,7 +4238,7 @@ void RtApiWasapi::startStream( void )
   verifyStream();\r
 \r
   if ( stream_.state == STREAM_RUNNING ) {\r
-    errorText_ = "RtApiWasapi::startStream: The stream is already running";\r
+    errorText_ = "RtApiWasapi::startStream: The stream is already running.";\r
     error( RtAudioError::WARNING );\r
     return;\r
   }\r
@@ -4189,10 +4247,10 @@ void RtApiWasapi::startStream( void )
   stream_.state = STREAM_RUNNING;\r
 \r
   // create WASAPI stream thread\r
-  stream_.callbackInfo.thread = ( unsigned int ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL );\r
+  stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL );\r
 \r
   if ( !stream_.callbackInfo.thread ) {\r
-    errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread";\r
+    errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread.";\r
     error( RtAudioError::THREAD_ERROR );\r
   }\r
   else {\r
@@ -4208,7 +4266,7 @@ void RtApiWasapi::stopStream( void )
   verifyStream();\r
 \r
   if ( stream_.state == STREAM_STOPPED ) {\r
-    errorText_ = "RtApiWasapi::stopStream: The stream is already stopped";\r
+    errorText_ = "RtApiWasapi::stopStream: The stream is already stopped.";\r
     error( RtAudioError::WARNING );\r
     return;\r
   }\r
@@ -4228,8 +4286,9 @@ void RtApiWasapi::stopStream( void )
   if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) {\r
     HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();\r
     if ( FAILED( hr ) ) {\r
-      errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream";\r
+      errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream.";\r
       error( RtAudioError::DRIVER_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
@@ -4237,18 +4296,20 @@ void RtApiWasapi::stopStream( void )
   if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) {\r
     HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();\r
     if ( FAILED( hr ) ) {\r
-      errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream";\r
+      errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream.";\r
       error( RtAudioError::DRIVER_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
   // close thread handle\r
   if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {\r
-    errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread";\r
+    errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread.";\r
     error( RtAudioError::THREAD_ERROR );\r
+    return;\r
   }\r
 \r
-  stream_.callbackInfo.thread = NULL;\r
+  stream_.callbackInfo.thread = (ThreadHandle) NULL;\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -4258,7 +4319,7 @@ void RtApiWasapi::abortStream( void )
   verifyStream();\r
 \r
   if ( stream_.state == STREAM_STOPPED ) {\r
-    errorText_ = "RtApiWasapi::abortStream: The stream is already stopped";\r
+    errorText_ = "RtApiWasapi::abortStream: The stream is already stopped.";\r
     error( RtAudioError::WARNING );\r
     return;\r
   }\r
@@ -4275,8 +4336,9 @@ void RtApiWasapi::abortStream( void )
   if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) {\r
     HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();\r
     if ( FAILED( hr ) ) {\r
-      errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream";\r
+      errorText_ = "RtApiWasapi::abortStream: Unable to stop capture stream.";\r
       error( RtAudioError::DRIVER_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
@@ -4284,18 +4346,20 @@ void RtApiWasapi::abortStream( void )
   if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) {\r
     HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();\r
     if ( FAILED( hr ) ) {\r
-      errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream";\r
+      errorText_ = "RtApiWasapi::abortStream: Unable to stop render stream.";\r
       error( RtAudioError::DRIVER_ERROR );\r
+      return;\r
     }\r
   }\r
 \r
   // close thread handle\r
   if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {\r
-    errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread";\r
+    errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread.";\r
     error( RtAudioError::THREAD_ERROR );\r
+    return;\r
   }\r
 \r
-  stream_.callbackInfo.thread = NULL;\r
+  stream_.callbackInfo.thread = (ThreadHandle) NULL;\r
 }\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -4313,66 +4377,109 @@ bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   IMMDeviceCollection* renderDevices = NULL;\r
   IMMDevice* devicePtr = NULL;\r
   WAVEFORMATEX* deviceFormat = NULL;\r
+  unsigned int bufferBytes;\r
+  stream_.state = STREAM_STOPPED;\r
 \r
   // create API Handle if not already created\r
   if ( !stream_.apiHandle )\r
     stream_.apiHandle = ( void* ) new WasapiHandle();\r
 \r
-  // count capture devices\r
+  // Count capture devices\r
+  errorText_.clear();\r
+  RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;\r
   HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = captureDevices->GetCount( &captureDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count.";\r
+    goto Exit;\r
+  }\r
 \r
-  // count render devices\r
+  // Count render devices\r
   hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device collection" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection.";\r
+    goto Exit;\r
+  }\r
 \r
   hr = renderDevices->GetCount( &renderDeviceCount );\r
-  EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device count" );\r
+  if ( FAILED( hr ) ) {\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count.";\r
+    goto Exit;\r
+  }\r
 \r
   // validate device index\r
-  if ( device >= captureDeviceCount + renderDeviceCount )\r
-    EXIT_ON_ERROR( -1, RtAudioError::INVALID_USE, "Invalid device index" );\r
+  if ( device >= captureDeviceCount + renderDeviceCount ) {\r
+    errorType = RtAudioError::INVALID_USE;\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index.";\r
+    goto Exit;\r
+  }\r
 \r
   // determine whether index falls within capture or render devices\r
   if ( device >= renderDeviceCount ) {\r
-    if ( mode != INPUT )\r
-      EXIT_ON_ERROR( -1, RtAudioError::INVALID_USE, "Capture device selected as output device" );\r
+    if ( mode != INPUT ) {\r
+      errorType = RtAudioError::INVALID_USE;\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device.";\r
+      goto Exit;\r
+    }\r
 \r
     // retrieve captureAudioClient from devicePtr\r
     IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;\r
 \r
     hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture device handle" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle.";\r
+      goto Exit;\r
+    }\r
 \r
     hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,\r
                               NULL, ( void** ) &captureAudioClient );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device audio client" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client.";\r
+      goto Exit;\r
+    }\r
 \r
     hr = captureAudioClient->GetMixFormat( &deviceFormat );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device mix format" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format.";\r
+      goto Exit;\r
+    }\r
 \r
     stream_.nDeviceChannels[mode] = deviceFormat->nChannels;\r
     captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );\r
   }\r
   else {\r
-    if ( mode != OUTPUT )\r
-      EXIT_ON_ERROR( -1, RtAudioError::INVALID_USE, "Render device selected as input device" );\r
+    if ( mode != OUTPUT ) {\r
+      errorType = RtAudioError::INVALID_USE;\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Render device selected as input device.";\r
+      goto Exit;\r
+    }\r
 \r
     // retrieve renderAudioClient from devicePtr\r
     IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;\r
 \r
     hr = renderDevices->Item( device, &devicePtr );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render device handle" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle.";\r
+      goto Exit;\r
+    }\r
 \r
     hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,\r
                               NULL, ( void** ) &renderAudioClient );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device audio client" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device audio client.";\r
+      goto Exit;\r
+    }\r
 \r
     hr = renderAudioClient->GetMixFormat( &deviceFormat );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device mix format" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve device mix format.";\r
+      goto Exit;\r
+    }\r
 \r
     stream_.nDeviceChannels[mode] = deviceFormat->nChannels;\r
     renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );\r
@@ -4388,7 +4495,6 @@ bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
   }\r
 \r
   stream_.device[mode] = device;\r
-  stream_.state = STREAM_STOPPED;\r
   stream_.doByteSwap[mode] = false;\r
   stream_.sampleRate = sampleRate;\r
   stream_.bufferSize = *bufferSize;\r
@@ -4416,11 +4522,14 @@ bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
     setConvertInfo( mode, 0 );\r
 \r
   // Allocate necessary internal buffers\r
-  unsigned int bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat );\r
+  bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat );\r
 \r
   stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 );\r
-  if ( !stream_.userBuffer[mode] )\r
-    EXIT_ON_ERROR( -1, RtAudioError::MEMORY_ERROR, "Error allocating user buffer memory" );\r
+  if ( !stream_.userBuffer[mode] ) {\r
+    errorType = RtAudioError::MEMORY_ERROR;\r
+    errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory.";\r
+    goto Exit;\r
+  }\r
 \r
   if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME )\r
     stream_.callbackInfo.priority = 15;\r
@@ -4434,17 +4543,17 @@ bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
 \r
 Exit:\r
   //clean up\r
-\r
   SAFE_RELEASE( captureDevices );\r
   SAFE_RELEASE( renderDevices );\r
   SAFE_RELEASE( devicePtr );\r
-\r
   CoTaskMemFree( deviceFormat );\r
 \r
   // if method failed, close the stream\r
   if ( methodResult == FAILURE )\r
     closeStream();\r
 \r
+  if ( !errorText_.empty() )\r
+    error( errorType );\r
   return methodResult;\r
 }\r
 \r
@@ -4497,6 +4606,25 @@ void RtApiWasapi::wasapiThread()
   WasapiBuffer captureBuffer;\r
   WasapiBuffer renderBuffer;\r
 \r
+  // declare local stream variables\r
+  RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback;\r
+  BYTE* streamBuffer = NULL;\r
+  unsigned long captureFlags = 0;\r
+  unsigned int bufferFrameCount = 0;\r
+  unsigned int numFramesPadding = 0;\r
+  unsigned int convBufferSize = 0;\r
+  bool callbackPushed = false;\r
+  bool callbackPulled = false;\r
+  bool callbackStopped = false;\r
+  int callbackResult = 0;\r
+\r
+  // convBuffer is used to store converted buffers between WASAPI and the user\r
+  char* convBuffer = NULL;\r
+  unsigned int deviceBufferSize = 0;\r
+\r
+  errorText_.clear();\r
+  RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;\r
+\r
   // Attempt to assign "Pro Audio" characteristic to thread\r
   HMODULE AvrtDll = LoadLibrary( "AVRT.dll" );\r
   if ( AvrtDll ) {\r
@@ -4509,7 +4637,10 @@ void RtApiWasapi::wasapiThread()
   // start capture stream if applicable\r
   if ( captureAudioClient ) {\r
     hr = captureAudioClient->GetMixFormat( &captureFormat );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device mix format" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";\r
+      goto Exit;\r
+    }\r
 \r
     captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate );\r
 \r
@@ -4524,19 +4655,31 @@ void RtApiWasapi::wasapiThread()
                                            desiredBufferPeriod,\r
                                            captureFormat,\r
                                            NULL );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to initialize capture audio client" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client.";\r
+        goto Exit;\r
+      }\r
 \r
       hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ),\r
                                            ( void** ) &captureClient );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture client handle" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle.";\r
+        goto Exit;\r
+      }\r
 \r
       // configure captureEvent to trigger on every available capture buffer\r
       captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
-      if ( !captureEvent )\r
-        EXIT_ON_ERROR( -1, RtAudioError::SYSTEM_ERROR, "Unable to create capture event" );\r
+      if ( !captureEvent ) {\r
+        errorType = RtAudioError::SYSTEM_ERROR;\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to create capture event.";\r
+        goto Exit;\r
+      }\r
 \r
       hr = captureAudioClient->SetEventHandle( captureEvent );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to set capture event handle" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to set capture event handle.";\r
+        goto Exit;\r
+      }\r
 \r
       ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient;\r
       ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent;\r
@@ -4544,7 +4687,10 @@ void RtApiWasapi::wasapiThread()
 \r
     unsigned int inBufferSize = 0;\r
     hr = captureAudioClient->GetBufferSize( &inBufferSize );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to get capture buffer size" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to get capture buffer size.";\r
+      goto Exit;\r
+    }\r
 \r
     // scale outBufferSize according to stream->user sample rate ratio\r
     unsigned int outBufferSize = ( unsigned int ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT];\r
@@ -4555,17 +4701,26 @@ void RtApiWasapi::wasapiThread()
 \r
     // reset the capture stream\r
     hr = captureAudioClient->Reset();\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to reset capture stream" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to reset capture stream.";\r
+      goto Exit;\r
+    }\r
 \r
     // start the capture stream\r
     hr = captureAudioClient->Start();\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to start capture stream" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to start capture stream.";\r
+      goto Exit;\r
+    }\r
   }\r
 \r
   // start render stream if applicable\r
   if ( renderAudioClient ) {\r
     hr = renderAudioClient->GetMixFormat( &renderFormat );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve device mix format" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";\r
+      goto Exit;\r
+    }\r
 \r
     renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate );\r
 \r
@@ -4580,19 +4735,31 @@ void RtApiWasapi::wasapiThread()
                                           desiredBufferPeriod,\r
                                           renderFormat,\r
                                           NULL );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to initialize render audio client" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to initialize render audio client.";\r
+        goto Exit;\r
+      }\r
 \r
       hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ),\r
                                           ( void** ) &renderClient );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render client handle" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle.";\r
+        goto Exit;\r
+      }\r
 \r
       // configure renderEvent to trigger on every available render buffer\r
       renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
-      if ( !renderEvent )\r
-        EXIT_ON_ERROR( -1, RtAudioError::SYSTEM_ERROR, "Unable to create render event" );\r
+      if ( !renderEvent ) {\r
+        errorType = RtAudioError::SYSTEM_ERROR;\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to create render event.";\r
+        goto Exit;\r
+      }\r
 \r
       hr = renderAudioClient->SetEventHandle( renderEvent );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to set render event handle" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to set render event handle.";\r
+        goto Exit;\r
+      }\r
 \r
       ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient;\r
       ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent;\r
@@ -4600,7 +4767,10 @@ void RtApiWasapi::wasapiThread()
 \r
     unsigned int outBufferSize = 0;\r
     hr = renderAudioClient->GetBufferSize( &outBufferSize );\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to get render buffer size" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to get render buffer size.";\r
+      goto Exit;\r
+    }\r
 \r
     // scale inBufferSize according to user->stream sample rate ratio\r
     unsigned int inBufferSize = ( unsigned int ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT];\r
@@ -4611,31 +4781,19 @@ void RtApiWasapi::wasapiThread()
 \r
     // reset the render stream\r
     hr = renderAudioClient->Reset();\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to reset render stream" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to reset render stream.";\r
+      goto Exit;\r
+    }\r
 \r
     // start the render stream\r
     hr = renderAudioClient->Start();\r
-    EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to start render stream" );\r
+    if ( FAILED( hr ) ) {\r
+      errorText_ = "RtApiWasapi::wasapiThread: Unable to start render stream.";\r
+      goto Exit;\r
+    }\r
   }\r
 \r
-  // declare local stream variables\r
-  RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback;\r
-\r
-  BYTE* streamBuffer = NULL;\r
-  unsigned long captureFlags = 0;\r
-\r
-  unsigned int bufferFrameCount = 0;\r
-  unsigned int numFramesPadding = 0;\r
-  unsigned int convBufferSize = 0;\r
-\r
-  bool callbackPushed = false;\r
-  bool callbackPulled = false;\r
-  bool callbackStopped = false;\r
-\r
-  int callbackResult = 0;\r
-\r
-  // convBuffer is used to store converted buffers between WASAPI and the user\r
-  unsigned int deviceBufferSize = 0;\r
   if ( stream_.mode == INPUT ) {\r
     deviceBufferSize = ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );\r
   }\r
@@ -4643,14 +4801,17 @@ void RtApiWasapi::wasapiThread()
     deviceBufferSize = ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] );\r
   }\r
   else if ( stream_.mode == DUPLEX ) {\r
-    deviceBufferSize = max( ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),\r
+    deviceBufferSize = std::max( ( size_t ) ( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),\r
                             ( size_t ) ( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) );\r
   }\r
 \r
-  char* convBuffer = ( char* ) malloc( deviceBufferSize );\r
+  convBuffer = ( char* ) malloc( deviceBufferSize );\r
   stream_.deviceBuffer = ( char* ) malloc( deviceBufferSize );\r
-  if ( !convBuffer || !stream_.deviceBuffer )\r
-      EXIT_ON_ERROR( -1, RtAudioError::MEMORY_ERROR, "Error allocating device buffer memory" );\r
+  if ( !convBuffer || !stream_.deviceBuffer ) {\r
+    errorType = RtAudioError::MEMORY_ERROR;\r
+    errorText_ = "RtApiWasapi::wasapiThread: Error allocating device buffer memory.";\r
+    goto Exit;\r
+  }\r
 \r
   // stream process loop\r
   while ( stream_.state != STREAM_STOPPING ) {\r
@@ -4716,26 +4877,32 @@ void RtApiWasapi::wasapiThread()
         // Handle return value from callback\r
         if ( callbackResult == 1 ) {\r
           // instantiate a thread to stop this thread\r
-          HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, NULL, NULL );\r
-\r
+          HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL );\r
           if ( !threadHandle ) {\r
-            EXIT_ON_ERROR( -1, RtAudioError::THREAD_ERROR, "Unable to instantiate stream stop thread" );\r
+            errorType = RtAudioError::THREAD_ERROR;\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread.";\r
+            goto Exit;\r
           }\r
           else if ( !CloseHandle( threadHandle ) ) {\r
-            EXIT_ON_ERROR( -1, RtAudioError::THREAD_ERROR, "Unable to close stream stop thread handle" );\r
+            errorType = RtAudioError::THREAD_ERROR;\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle.";\r
+            goto Exit;\r
           }\r
 \r
           callbackStopped = true;\r
         }\r
         else if ( callbackResult == 2 ) {\r
           // instantiate a thread to stop this thread\r
-          HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, NULL, NULL );\r
-\r
+          HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL );\r
           if ( !threadHandle ) {\r
-            EXIT_ON_ERROR( -1, RtAudioError::THREAD_ERROR, "Unable to instantiate stream abort thread" );\r
+            errorType = RtAudioError::THREAD_ERROR;\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread.";\r
+            goto Exit;\r
           }\r
           else if ( !CloseHandle( threadHandle ) ) {\r
-            EXIT_ON_ERROR( -1, RtAudioError::THREAD_ERROR, "Unable to close stream abort thread handle" );\r
+            errorType = RtAudioError::THREAD_ERROR;\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle.";\r
+            goto Exit;\r
           }\r
 \r
           callbackStopped = true;\r
@@ -4802,7 +4969,10 @@ void RtApiWasapi::wasapiThread()
       hr = captureClient->GetBuffer( &streamBuffer,\r
                                      &bufferFrameCount,\r
                                      &captureFlags, NULL, NULL );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve capture buffer" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer.";\r
+        goto Exit;\r
+      }\r
 \r
       if ( bufferFrameCount != 0 ) {\r
         // Push capture buffer into inputBuffer\r
@@ -4812,20 +4982,29 @@ void RtApiWasapi::wasapiThread()
         {\r
           // Release capture buffer\r
           hr = captureClient->ReleaseBuffer( bufferFrameCount );\r
-          EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release capture buffer" );\r
+          if ( FAILED( hr ) ) {\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";\r
+            goto Exit;\r
+          }\r
         }\r
         else\r
         {\r
           // Inform WASAPI that capture was unsuccessful\r
           hr = captureClient->ReleaseBuffer( 0 );\r
-          EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release capture buffer" );\r
+          if ( FAILED( hr ) ) {\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";\r
+            goto Exit;\r
+          }\r
         }\r
       }\r
       else\r
       {\r
         // Inform WASAPI that capture was unsuccessful\r
         hr = captureClient->ReleaseBuffer( 0 );\r
-        EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release capture buffer" );\r
+        if ( FAILED( hr ) ) {\r
+          errorText_ = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";\r
+          goto Exit;\r
+        }\r
       }\r
     }\r
 \r
@@ -4844,16 +5023,25 @@ void RtApiWasapi::wasapiThread()
 \r
       // Get render buffer from stream\r
       hr = renderAudioClient->GetBufferSize( &bufferFrameCount );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render buffer size" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size.";\r
+        goto Exit;\r
+      }\r
 \r
       hr = renderAudioClient->GetCurrentPadding( &numFramesPadding );\r
-      EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render buffer padding" );\r
+      if ( FAILED( hr ) ) {\r
+        errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding.";\r
+        goto Exit;\r
+      }\r
 \r
       bufferFrameCount -= numFramesPadding;\r
 \r
       if ( bufferFrameCount != 0 ) {\r
         hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer );\r
-        EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to retrieve render buffer" );\r
+        if ( FAILED( hr ) ) {\r
+          errorText_ = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer.";\r
+          goto Exit;\r
+        }\r
 \r
         // Pull next buffer from outputBuffer\r
         // Fill render buffer with next buffer\r
@@ -4863,20 +5051,29 @@ void RtApiWasapi::wasapiThread()
         {\r
           // Release render buffer\r
           hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 );\r
-          EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release render buffer" );\r
+          if ( FAILED( hr ) ) {\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";\r
+            goto Exit;\r
+          }\r
         }\r
         else\r
         {\r
           // Inform WASAPI that render was unsuccessful\r
           hr = renderClient->ReleaseBuffer( 0, 0 );\r
-          EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release render buffer" );\r
+          if ( FAILED( hr ) ) {\r
+            errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";\r
+            goto Exit;\r
+          }\r
         }\r
       }\r
       else\r
       {\r
         // Inform WASAPI that render was unsuccessful\r
         hr = renderClient->ReleaseBuffer( 0, 0 );\r
-        EXIT_ON_ERROR( hr, RtAudioError::DRIVER_ERROR, "Unable to release render buffer" );\r
+        if ( FAILED( hr ) ) {\r
+          errorText_ = "RtApiWasapi::wasapiThread: Unable to release render buffer.";\r
+          goto Exit;\r
+        }\r
       }\r
     }\r
 \r
@@ -4901,6 +5098,11 @@ Exit:
 \r
   // update stream state\r
   stream_.state = STREAM_STOPPED;\r
+\r
+  if ( errorText_.empty() )\r
+    return;\r
+  else\r
+    error( errorType );\r
 }\r
 \r
 //******************** End of __WINDOWS_WASAPI__ *********************//\r
index bc99bd934e23ed027709369a0ea48ab7559b357b..52f361a75f20924b9bf7881a23af93dc9746eedf 100644 (file)
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -45,7 +45,7 @@
 #ifndef __RTAUDIO_H
 #define __RTAUDIO_H
 
-#define RTAUDIO_VERSION "4.1.0"
+#define RTAUDIO_VERSION "4.1.1pre"
 
 #include <string>
 #include <vector>
@@ -567,11 +567,11 @@ class RtAudio
 };
 
 // Operating system dependent thread functionality.
-#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) ||  defined(__WINDOWS_WASAPI__)
+#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__)
   #include <windows.h>
   #include <process.h>
 
-  typedef ULONG_PTR ThreadHandle;
+  typedef uintptr_t ThreadHandle;
   typedef CRITICAL_SECTION StreamMutex;
 
 #elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
index 6d6474d24979c9f558ebd9d488c9537f530e7eec..6c169b6f307402b3a1f7eb2446264269795f57b0 100644 (file)
@@ -168,7 +168,13 @@ case $host in
     AC_MSG_RESULT(using DirectSound)
     LIBS="-ldsound -lwinmm $LIBS" ], )
 
-  # If no audio api flags specified, use DirectSound
+  # Look for WASAPI flag
+  AC_ARG_WITH(wasapi, [  --with-wasapi = choose Windows Audio Session API support (windoze only)], [
+    api="$api -D__WINDOWS_WASAPI__"
+    AC_MSG_RESULT(using WASAPI)
+    LIBS="-lwinmm -luuid -lksuser $LIBS" ], )
+
+  # If no audio api flags specified, use DS
   if [test "$api" == "";] then
     AC_SUBST( api, [-D__WINDOWS_DS__] )
     AC_MSG_RESULT(using DirectSound)
index 91807fbb6374edf25db39ed1028c0b65ed125be0..d43f697c3fd30a7a1488d0a5f44d414866b33e4a 100644 (file)
@@ -2,6 +2,9 @@ RtAudio - a set of C++ classes that provide a common API for realtime audio inpu
 
 By Gary P. Scavone, 2001-2014.
 
+v4.1.1pre: (??)
+- updates to WASAPI API for MinGW compiling
+
 v4.1.0: (10 April 2014)
 - RtError class renamed RtAudioError and embedded in RtAudio.h (RtError.h deleted)
 - new support for the Windows WASAPI API (thanks to Marcus Tomlinson)
diff --git a/install b/install
index fd2b4c62f74d781d57698cfbb54d4def4350e2d0..b2e8987e87359743b92c70f33f75f5b5679e9705 100644 (file)
--- a/install
+++ b/install
@@ -25,6 +25,7 @@ A few options can be passed to configure, including:
   --with-jack = choose JACK server support (linux or Macintosh OS-X)
   --with-core = choose CoreAudio API support (Macintosh OS-X only)
   --with-asio = choose ASIO API support (windows only)
+  --with-wasapi = choose Windows Audio System API support (windows only)
   --with-ds = choose DirectSound API support (windows only)
 
 Typing "./configure --help" will display all the available options.  Note that you can provide more than one "--with-" flag to the configure script to enable multiple API support.
@@ -45,7 +46,7 @@ cmake <path to CMakeLists.txt usually two dots> <options> e.g. cmake .. -DAUDIO_
 
 WINDOWS:
 
-The DirectSound and ASIO APIs in RtAudio compile with either the MinGW compiler or MS Visual Studio.  The WASAPI API currently only compiles in MS Visual Studio.
+All Windows audio APIs in RtAudio compile with either the MinGW compiler (tested with latest tdm64-gcc-4.8.1) or MS Visual Studio.
 
 Visual C++ 6.0 project files (very old) are included for the test programs in the /tests/Windows/ directory.  These projects compile API support for ASIO, WASAPI and DirectSound.