📄 pa_jack.c
字号:
PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor, chn, channel_buf ); } framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &stream->callbackResult ); /* We've specified a host buffer size mode where every frame should be consumed by the buffer processor */ assert( framesProcessed == frames ); PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );end: return result;}/* Alter the processing queue if necessary */static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi ){ PaError result = paNoError; int queueModified = 0; const double jackSr = jack_get_sample_rate( hostApi->jack_client ); int err; if( (err = pthread_mutex_trylock( &hostApi->mtx )) != 0 ) { assert( err == EBUSY ); return paNoError; } if( hostApi->toAdd ) { if( hostApi->processQueue ) { PaJackStream *node = hostApi->processQueue; /* Advance to end of queue */ while( node->next ) node = node->next; node->next = hostApi->toAdd; } else hostApi->processQueue = (PaJackStream *)hostApi->toAdd; /* If necessary, update stream state */ if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr ) UpdateSampleRate( hostApi->toAdd, jackSr ); hostApi->toAdd = NULL; queueModified = 1; } if( hostApi->toRemove ) { int removed = 0; PaJackStream *node = hostApi->processQueue, *prev = NULL; assert( hostApi->processQueue ); while( node ) { if( node == hostApi->toRemove ) { if( prev ) prev->next = node->next; else hostApi->processQueue = (PaJackStream *)node->next; removed = 1; break; } prev = node; node = node->next; } UNLESS( removed, paInternalError ); hostApi->toRemove = NULL; PA_DEBUG(( "%s: Removed stream from processing queue\n", __FUNCTION__ )); queueModified = 1; } if( queueModified ) { /* Signal that we've done what was asked of us */ ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 ); }error: ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 ); return result;}static int JackCallback( jack_nframes_t frames, void *userData ){ PaError result = paNoError; PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)userData; PaJackStream *stream = NULL; int xrun = hostApi->xrun; hostApi->xrun = 0; assert( hostApi ); ENSURE_PA( UpdateQueue( hostApi ) ); /* Process each stream */ stream = hostApi->processQueue; for( ; stream; stream = stream->next ) { if( xrun ) /* Don't override if already set */ stream->xrun = 1; /* See if this stream is to be started */ if( stream->doStart ) { /* If we can't obtain a lock, we'll try next time */ int err = pthread_mutex_trylock( &stream->hostApi->mtx ); if( !err ) { if( stream->doStart ) /* Could potentially change before obtaining the lock */ { stream->is_active = 1; stream->doStart = 0; PA_DEBUG(( "%s: Starting stream\n", __FUNCTION__ )); ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 ); stream->callbackResult = paContinue; stream->isSilenced = 0; } ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 ); } else assert( err == EBUSY ); } else if( stream->doStop || stream->doAbort ) /* Should we stop/abort stream? */ { if( stream->callbackResult == paContinue ) /* Ok, make it stop */ { PA_DEBUG(( "%s: Stopping stream\n", __FUNCTION__ )); stream->callbackResult = stream->doStop ? paComplete : paAbort; } } if( stream->is_active ) ENSURE_PA( RealProcess( stream, frames ) ); /* If we have just entered inactive state, silence output */ if( !stream->is_active && !stream->isSilenced ) { int i; /* Silence buffer after entering inactive state */ PA_DEBUG(( "Silencing the output\n" )); for( i = 0; i < stream->num_outgoing_connections; ++i ) { jack_default_audio_sample_t *buffer = jack_port_get_buffer( stream->local_output_ports[i], frames ); memset( buffer, 0, sizeof (jack_default_audio_sample_t) * frames ); } stream->isSilenced = 1; } if( stream->doStop || stream->doAbort ) { /* See if RealProcess has acted on the request */ if( !stream->is_active ) /* Ok, signal to the main thread that we've carried out the operation */ { /* If we can't obtain a lock, we'll try next time */ int err = pthread_mutex_trylock( &stream->hostApi->mtx ); if( !err ) { stream->doStop = stream->doAbort = 0; ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 ); ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 ); } else assert( err == EBUSY ); } } } return 0;error: return -1;}static PaError StartStream( PaStream *s ){ PaError result = paNoError; PaJackStream *stream = (PaJackStream*)s; int i; /* Ready the processor */ PaUtil_ResetBufferProcessor( &stream->bufferProcessor ); /* connect the ports */ /* NOTE: I would rather use jack_port_connect which uses jack_port_t's * instead of port names, but it is not implemented yet. */ if( stream->num_incoming_connections > 0 ) { for( i = 0; i < stream->num_incoming_connections; i++ ) UNLESS( jack_connect( stream->jack_client, jack_port_name( stream->remote_output_ports[i] ), jack_port_name( stream->local_input_ports[i] ) ) == 0, paUnanticipatedHostError ); } if( stream->num_outgoing_connections > 0 ) { for( i = 0; i < stream->num_outgoing_connections; i++ ) UNLESS( jack_connect( stream->jack_client, jack_port_name( stream->local_output_ports[i] ), jack_port_name( stream->remote_input_ports[i] ) ) == 0, paUnanticipatedHostError ); } stream->xrun = FALSE; /* Enable processing */ ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 ); stream->doStart = 1; /* Wait for stream to be started */ result = WaitCondition( stream->hostApi ); /* do { err = pthread_cond_timedwait( &stream->hostApi->cond, &stream->hostApi->mtx, &ts ); } while( !stream->is_active && !err ); */ if( result != paNoError ) /* Something went wrong, call off the stream start */ { stream->doStart = 0; stream->is_active = 0; /* Cancel any processing */ } ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 ); ENSURE_PA( result ); stream->is_running = TRUE; PA_DEBUG(( "%s: Stream started\n", __FUNCTION__ ));error: return result;}static PaError RealStop( PaJackStream *stream, int abort ){ PaError result = paNoError; int i; if( stream->isBlockingStream ) BlockingWaitEmpty ( stream ); ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 ); if( abort ) stream->doAbort = 1; else stream->doStop = 1; /* Wait for stream to be stopped */ result = WaitCondition( stream->hostApi ); ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 ); ENSURE_PA( result ); UNLESS( !stream->is_active, paInternalError ); PA_DEBUG(( "%s: Stream stopped\n", __FUNCTION__ ));error: stream->is_running = FALSE; /* Disconnect ports belonging to this stream */ if( !stream->hostApi->jackIsDown ) /* XXX: Well? */ { for( i = 0; i < stream->num_incoming_connections; i++ ) { UNLESS( !jack_port_lock( stream->jack_client, stream->local_input_ports[i] ), paUnanticipatedHostError ); if( jack_port_connected( stream->local_input_ports[i] ) ) { UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ), paUnanticipatedHostError ); } UNLESS( !jack_port_unlock( stream->jack_client, stream->local_input_ports[i] ), paUnanticipatedHostError ); } for( i = 0; i < stream->num_outgoing_connections; i++ ) { UNLESS( !jack_port_lock( stream->jack_client, stream->local_output_ports[i] ), paUnanticipatedHostError ); if( jack_port_connected( stream->local_output_ports[i] ) ) { UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ), paUnanticipatedHostError ); } UNLESS( !jack_port_unlock( stream->jack_client, stream->local_output_ports[i] ), paUnanticipatedHostError ); } } return result;}static PaError StopStream( PaStream *s ){ assert(s); return RealStop( (PaJackStream *)s, 0 );}static PaError AbortStream( PaStream *s ){ assert(s); return RealStop( (PaJackStream *)s, 1 );}static PaError IsStreamStopped( PaStream *s ){ PaJackStream *stream = (PaJackStream*)s; return !stream->is_running;}static PaError IsStreamActive( PaStream *s ){ PaJackStream *stream = (PaJackStream*)s; return stream->is_active;}static PaTime GetStreamTime( PaStream *s ){ PaJackStream *stream = (PaJackStream*)s; /* A: Is this relevant?? --> TODO: what if we're recording-only? */ return (jack_frame_time( stream->jack_client ) - stream->t0) / (PaTime)jack_get_sample_rate( stream->jack_client );}static double GetStreamCpuLoad( PaStream* s ){ PaJackStream *stream = (PaJackStream*)s; return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -