if ( handle->id[0] == handle->id[1] ) // same device, only one callback
RtApi::tickStreamTime();
else if ( deviceId == handle->id[0] )
- RtApi::tickStreamTime(); // only tick on the output callback
+ RtApi::tickStreamTime(); // two devices, only tick on the output callback
} else
- RtApi::tickStreamTime();
+ RtApi::tickStreamTime(); // input or output stream only
return SUCCESS;
}
#if defined(__UNIX_JACK__)
// JACK is a low-latency audio server, originally written for the
-// GNU/Linux operating system and now also ported to OS-X. It can
-// connect a number of different applications to an audio device, as
-// well as allowing them to share audio between themselves.
+// GNU/Linux operating system and now also ported to OS-X and
+// Windows. It can connect a number of different applications to an
+// audio device, as well as allowing them to share audio between
+// themselves.
//
// When using JACK with RtAudio, "devices" refer to JACK clients that
// have ports connected to the server. The JACK server is typically
if ( device >= nDevices ) {
jack_client_close( client );
errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";
- error( RtAudioError::INVALID_USE );
+ error( RTAUDIO_INVALID_USE );
return info;
}
if ( info.outputChannels == 0 && info.inputChannels == 0 ) {
jack_client_close(client);
errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!";
- error( RtAudioError::WARNING );
+ error( RTAUDIO_WARNING );
return info;
}
CallbackInfo *info = (CallbackInfo *) ptr;
RtApiJack *object = (RtApiJack *) info->object;
+ info->deviceDisconnected = true;
object->closeStream();
-
pthread_exit( NULL );
}
+
static void jackShutdown( void *infoPointer )
{
CallbackInfo *info = (CallbackInfo *) infoPointer;
ThreadHandle threadId;
pthread_create( &threadId, NULL, jackCloseStream, info );
- std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl;
}
static int jackXrun( void *infoPointer )
client = jack_client_open( "RtApiJack", jackoptions, status );
if ( client == 0 ) {
errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!";
- error( RtAudioError::WARNING );
+ error( RTAUDIO_WARNING );
return FAILURE;
}
}
{
if ( stream_.state == STREAM_CLOSED ) {
errorText_ = "RtApiJack::closeStream(): no open stream to close!";
- error( RtAudioError::WARNING );
+ error( RTAUDIO_WARNING );
return;
}
JackHandle *handle = (JackHandle *) stream_.apiHandle;
if ( handle ) {
-
if ( stream_.state == STREAM_RUNNING )
jack_deactivate( handle->client );
stream_.apiHandle = 0;
}
+ CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
+ if ( info->deviceDisconnected ) {
+ errorText_ = "RtApiJack: the Jack server is shutting down this client ... stream stopped and closed!";
+ error( RTAUDIO_DEVICE_DISCONNECT );
+ }
+
for ( int i=0; i<2; i++ ) {
if ( stream_.userBuffer[i] ) {
free( stream_.userBuffer[i] );
stream_.deviceBuffer = 0;
}
- stream_.mode = UNINITIALIZED;
- stream_.state = STREAM_CLOSED;
+ clearStreamInfo();
+ //stream_.mode = UNINITIALIZED;
+ //stream_.state = STREAM_CLOSED;
}
-void RtApiJack :: startStream( void )
+RtAudioErrorType RtApiJack :: startStream( void )
{
- verifyStream();
- if ( stream_.state == STREAM_RUNNING ) {
- errorText_ = "RtApiJack::startStream(): the stream is already running!";
- error( RtAudioError::WARNING );
- return;
+ if ( stream_.state != STREAM_STOPPED ) {
+ if ( stream_.state == STREAM_RUNNING )
+ errorText_ = "RtApiJack::startStream(): the stream is already running!";
+ else if ( stream_.state == STREAM_STOPPING || stream_.state == STREAM_CLOSED )
+ errorText_ = "RtApiJack::startStream(): the stream is stopping or closed!";
+ return error( RTAUDIO_WARNING );
}
+ /*
#if defined( HAVE_GETTIMEOFDAY )
gettimeofday( &stream_.lastTickTimestamp, NULL );
#endif
+ */
JackHandle *handle = (JackHandle *) stream_.apiHandle;
int result = jack_activate( handle->client );
stream_.state = STREAM_RUNNING;
unlock:
- if ( result == 0 ) return;
- error( RtAudioError::RTAUDIO_SYSTEM_ERROR );
+ if ( result == 0 ) return RTAUDIO_NO_ERROR;
+ return error( RTAUDIO_SYSTEM_ERROR );
}
-void RtApiJack :: stopStream( void )
+RtAudioErrorType RtApiJack :: stopStream( void )
{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiJack::stopStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
+ if ( stream_.state != STREAM_RUNNING && stream_.state != STREAM_STOPPING ) {
+ if ( stream_.state == STREAM_STOPPED )
+ errorText_ = "RtApiJack::stopStream(): the stream is already stopped!";
+ else if ( stream_.state == STREAM_CLOSED )
+ errorText_ = "RtApiJack::stopStream(): the stream is closed!";
+ return error( RTAUDIO_WARNING );
}
JackHandle *handle = (JackHandle *) stream_.apiHandle;
jack_deactivate( handle->client );
stream_.state = STREAM_STOPPED;
+ return RTAUDIO_NO_ERROR;
}
-void RtApiJack :: abortStream( void )
+RtAudioErrorType RtApiJack :: abortStream( void )
{
- verifyStream();
- if ( stream_.state == STREAM_STOPPED ) {
- errorText_ = "RtApiJack::abortStream(): the stream is already stopped!";
- error( RtAudioError::WARNING );
- return;
+ if ( stream_.state != STREAM_RUNNING ) {
+ if ( stream_.state == STREAM_STOPPED )
+ errorText_ = "RtApiJack::abortStream(): the stream is already stopped!";
+ else if ( stream_.state == STREAM_STOPPING || stream_.state == STREAM_CLOSED )
+ errorText_ = "RtApiJack::abortStream(): the stream is stopping or closed!";
+ return error( RTAUDIO_WARNING );
}
JackHandle *handle = (JackHandle *) stream_.apiHandle;
handle->drainCounter = 2;
- stopStream();
+ return stopStream();
}
// This function will be called by a spawned thread when the user
{
if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
if ( stream_.state == STREAM_CLOSED ) {
- errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
- error( RtAudioError::WARNING );
+ errorText_ = "RtApiJack::callbackEvent(): the stream is closed ... this shouldn't happen!";
+ error( RTAUDIO_WARNING );
return FAILURE;
}
if ( stream_.bufferSize != nframes ) {
- errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
- error( RtAudioError::WARNING );
+ errorText_ = "RtApiJack::callbackEvent(): the JACK buffer size has changed ... cannot process!";
+ error( RTAUDIO_WARNING );
return FAILURE;
}
stream_.state = STREAM_STOPPING;
if ( handle->internalDrain == true )
pthread_create( &threadId, NULL, jackStopStream, info );
- else
+ else // external call to stopStream()
pthread_cond_signal( &handle->condition );
return SUCCESS;
}
stream_.callbackInfo.callback = 0;
stream_.callbackInfo.userData = 0;
stream_.callbackInfo.isRunning = false;
+ stream_.callbackInfo.deviceDisconnected = false;
for ( int i=0; i<2; i++ ) {
stream_.device[i] = 11111;
stream_.doConvertBuffer[i] = false;