Merge pull request #210 from f1xpl/master
authorgaryscavone <garyscavone@users.noreply.github.com>
Wed, 28 Aug 2019 14:11:03 +0000 (10:11 -0400)
committerGitHub <noreply@github.com>
Wed, 28 Aug 2019 14:11:03 +0000 (10:11 -0400)
Fix high CPU usage by PulseAudio backend when stream is stopped

1  2 
RtAudio.cpp

diff --combined RtAudio.cpp
index 1108c7482b945a8bb89cb8c674e1392e3a092d00,1df152b7ec96d8dfe206a9542037ff49b5528f2b..dce61fe9af0598a2d3c586ceb6c7fa847e0fbeaf
@@@ -1478,17 -1478,15 +1478,17 @@@ void RtApiCore :: closeStream( void 
          errorText_ = "RtApiCore::closeStream(): error removing property listener!";
          error( RtAudioError::WARNING );
        }
 -    }
 -    if ( stream_.state == STREAM_RUNNING )
 -      AudioDeviceStop( handle->id[0], callbackHandler );
 +
  #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 -    AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] );
 -#else
 -    // deprecated in favor of AudioDeviceDestroyIOProcID()
 -    AudioDeviceRemoveIOProc( handle->id[0], callbackHandler );
 +      if ( stream_.state == STREAM_RUNNING )
 +        AudioDeviceStop( handle->id[0], handle->procId[0] );
 +      AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] );
 +#else // deprecated behaviour
 +      if ( stream_.state == STREAM_RUNNING )
 +        AudioDeviceStop( handle->id[0], callbackHandler );
 +      AudioDeviceRemoveIOProc( handle->id[0], callbackHandler );
  #endif
 +    }
    }
  
    if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
          errorText_ = "RtApiCore::closeStream(): error removing property listener!";
          error( RtAudioError::WARNING );
        }
 -    }
 -    if ( stream_.state == STREAM_RUNNING )
 -      AudioDeviceStop( handle->id[1], callbackHandler );
 +
  #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 -    AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] );
 -#else
 -    // deprecated in favor of AudioDeviceDestroyIOProcID()
 -    AudioDeviceRemoveIOProc( handle->id[1], callbackHandler );
 +      if ( stream_.state == STREAM_RUNNING )
 +        AudioDeviceStop( handle->id[1], handle->procId[1] );
 +      AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] );
 +#else // deprecated behaviour
 +      if ( stream_.state == STREAM_RUNNING )
 +        AudioDeviceStop( handle->id[1], callbackHandler );
 +      AudioDeviceRemoveIOProc( handle->id[1], callbackHandler );
  #endif
 +    }
    }
  
    for ( int i=0; i<2; i++ ) {
@@@ -1546,19 -1542,15 +1546,19 @@@ void RtApiCore :: startStream( void 
      return;
    }
  
 -  #if defined( HAVE_GETTIMEOFDAY )
 +#if defined( HAVE_GETTIMEOFDAY )
    gettimeofday( &stream_.lastTickTimestamp, NULL );
 -  #endif
 +#endif
  
    OSStatus result = noErr;
    CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
    if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  
 +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 +    result = AudioDeviceStart( handle->id[0], handle->procId[0] );
 +#else // deprecated behaviour
      result = AudioDeviceStart( handle->id[0], callbackHandler );
 +#endif
      if ( result != noErr ) {
        errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ").";
        errorText_ = errorStream_.str();
    if ( stream_.mode == INPUT ||
         ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
  
 +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 +    result = AudioDeviceStart( handle->id[1], handle->procId[1] );
 +#else // deprecated behaviour
      result = AudioDeviceStart( handle->id[1], callbackHandler );
 +#endif
      if ( result != noErr ) {
        errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ").";
        errorText_ = errorStream_.str();
@@@ -1608,11 -1596,7 +1608,11 @@@ void RtApiCore :: stopStream( void 
        pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled
      }
  
 +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 +    result = AudioDeviceStop( handle->id[0], handle->procId[0] );
 +#else // deprecated behaviour
      result = AudioDeviceStop( handle->id[0], callbackHandler );
 +#endif
      if ( result != noErr ) {
        errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ").";
        errorText_ = errorStream_.str();
  
    if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
  
 +#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
 +    result = AudioDeviceStop( handle->id[0], handle->procId[1] );
 +#else  // deprecated behaviour
      result = AudioDeviceStop( handle->id[1], callbackHandler );
 +#endif
      if ( result != noErr ) {
        errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ").";
        errorText_ = errorStream_.str();
@@@ -8699,15 -8679,18 +8699,18 @@@ void RtApiPulse::stopStream( void 
    stream_.state = STREAM_STOPPED;
    MUTEX_LOCK( &stream_.mutex );
  
-   if ( pah && pah->s_play ) {
-     int pa_error;
-     if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) {
-       errorStream_ << "RtApiPulse::stopStream: error draining output device, " <<
-         pa_strerror( pa_error ) << ".";
-       errorText_ = errorStream_.str();
-       MUTEX_UNLOCK( &stream_.mutex );
-       error( RtAudioError::SYSTEM_ERROR );
-       return;
+   if ( pah ) {
+     pah->runnable = false;
+     if ( pah->s_play ) {
+       int pa_error;
+       if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) {
+         errorStream_ << "RtApiPulse::stopStream: error draining output device, " <<
+           pa_strerror( pa_error ) << ".";
+         errorText_ = errorStream_.str();
+         MUTEX_UNLOCK( &stream_.mutex );
+         error( RtAudioError::SYSTEM_ERROR );
+         return;
+       }
      }
    }
  
@@@ -8733,15 -8716,18 +8736,18 @@@ void RtApiPulse::abortStream( void 
    stream_.state = STREAM_STOPPED;
    MUTEX_LOCK( &stream_.mutex );
  
-   if ( pah && pah->s_play ) {
-     int pa_error;
-     if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) {
-       errorStream_ << "RtApiPulse::abortStream: error flushing output device, " <<
-         pa_strerror( pa_error ) << ".";
-       errorText_ = errorStream_.str();
-       MUTEX_UNLOCK( &stream_.mutex );
-       error( RtAudioError::SYSTEM_ERROR );
-       return;
+   if ( pah ) {
+     pah->runnable = false;
+     if ( pah->s_play ) {
+       int pa_error;
+       if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) {
+         errorStream_ << "RtApiPulse::abortStream: error flushing output device, " <<
+           pa_strerror( pa_error ) << ".";
+         errorText_ = errorStream_.str();
+         MUTEX_UNLOCK( &stream_.mutex );
+         error( RtAudioError::SYSTEM_ERROR );
+         return;
+       }
      }
    }