From 2e416ee0095f1bf608f849f156d564e0f45fb8ab Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 2 Feb 2004 12:18:59 +0000 Subject: merged in version_0_37_1test6 svn path=/trunk/; revision=1305 --- pd/portaudio/pa_jack/pa_jack.c | 864 ----------------------------------------- 1 file changed, 864 deletions(-) delete mode 100644 pd/portaudio/pa_jack/pa_jack.c (limited to 'pd/portaudio/pa_jack/pa_jack.c') diff --git a/pd/portaudio/pa_jack/pa_jack.c b/pd/portaudio/pa_jack/pa_jack.c deleted file mode 100644 index 4efeff81..00000000 --- a/pd/portaudio/pa_jack/pa_jack.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * $Id: pa_jack.c,v 1.1.2.1 2002/07/31 04:22:56 joshua Exp $ - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com - * JACK Implementation by Joshua Haberman - * - * Copyright (c) 2002 Joshua Haberman - * - * Based on the Open Source API proposed by Ross Bencina - * Copyright (c) 1999-2002 Ross Bencina, Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include -#include - -#include "pa_util.h" -#include "pa_hostapi.h" -#include "pa_stream.h" -#include "pa_process.h" -#include "pa_allocation.h" -#include "pa_cpuload.h" - -PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, - PaHostApiIndex hostApiIndex ); - -/* - * Functions that directly map to the PortAudio stream interface - */ - -static void Terminate( struct PaUtilHostApiRepresentation *hostApi ); -static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, - PaStream** s, - PaDeviceIndex inputDevice, - int numInputChannels, - PaSampleFormat inputSampleFormat, - unsigned long inputLatency, - PaHostApiSpecificStreamInfo *inputStreamInfo, - PaDeviceIndex outputDevice, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - unsigned long outputLatency, - PaHostApiSpecificStreamInfo *outputStreamInfo, - double sampleRate, - unsigned long framesPerCallback, - PaStreamFlags streamFlags, - PortAudioCallback *callback, - void *userData ); -static PaError CloseStream( PaStream* stream ); -static PaError StartStream( PaStream *stream ); -static PaError StopStream( PaStream *stream ); -static PaError AbortStream( PaStream *stream ); -static PaError IsStreamStopped( PaStream *s ); -static PaError IsStreamActive( PaStream *stream ); -static PaTimestamp GetStreamTime( PaStream *stream ); -static double GetStreamCpuLoad( PaStream* stream ); - -/* - * Data specific to this API - */ - -typedef struct -{ - PaUtilHostApiRepresentation commonHostApiRep; - PaUtilStreamInterface callbackStreamInterface; - - PaUtilAllocationGroup *deviceInfoMemory; - - jack_client_t *jack_client; - PaHostApiIndex hostApiIndex; -} -PaJackHostApiRepresentation; - -#define MAX_CLIENTS 100 -#define TRUE 1 -#define FALSE 0 - -/* - * Functions specific to this API - */ - -static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi ); -static int JackCallback( jack_nframes_t frames, void *userData ); - - - -/* - * - * Implementation - * - */ - - -/* BuildDeviceList(): - * - * The process of determining a list of PortAudio "devices" from - * JACK's client/port system is fairly involved, so it is separated - * into its own routine. - */ - -static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi ) -{ - /* Utility macros for the repetitive process of allocating memory */ - - /* ... MALLOC: allocate memory as part of the device list - * allocation group */ -#define MALLOC(size) \ - (PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, (size) )) - - /* ... MEMVERIFY: make sure we didn't get NULL */ -#define MEMVERIFY(ptr) \ - if( (ptr) == NULL ) return paInsufficientMemory; - - /* JACK has no concept of a device. To JACK, there are clients - * which have an arbitrary number of ports. To make this - * intelligible to PortAudio clients, we will group each JACK client - * into a device, and make each port of that client a channel */ - - PaUtilHostApiRepresentation *commonApi = &jackApi->commonHostApiRep; - - const char **jack_ports; - char *client_names[MAX_CLIENTS]; - int num_clients = 0; - int port_index, client_index, i; - double *globalSampleRate; - regex_t port_regex; - - /* since we are rebuilding the list of devices, free all memory - * associated with the previous list */ - PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory ); - - /* We can only retrieve the list of clients indirectly, by first - * asking for a list of all ports, then parsing the port names - * according to the client_name:port_name convention (which is - * enforced by jackd) */ - jack_ports = jack_get_ports( jackApi->jack_client, "", "", 0 ); - - if( jack_ports == NULL ) - return paHostError; - - /* Parse the list of ports, using a regex to grab the client names */ - regcomp( &port_regex, "^[^:]*", REG_EXTENDED ); - - /* Build a list of clients from the list of ports */ - for( port_index = 0; jack_ports[port_index] != NULL; port_index++ ) - { - int client_seen; - regmatch_t match_info; - char tmp_client_name[100]; - - /* extract the client name from the port name, using a regex - * that parses the clientname:portname syntax */ - regexec( &port_regex, jack_ports[port_index], 1, &match_info, 0 ); - memcpy( tmp_client_name, &jack_ports[port_index][match_info.rm_so], - match_info.rm_eo - match_info.rm_so ); - tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0'; - - /* do we know about this port's client yet? */ - client_seen = FALSE; - - for( i = 0; i < num_clients; i++ ) - if( strcmp( tmp_client_name, client_names[i] ) == 0 ) - client_seen = TRUE; - - if( client_seen == FALSE ) - { - client_names[num_clients] = (char*)MALLOC(strlen(tmp_client_name) + 1); - MEMVERIFY( client_names[num_clients] ); - - /* The alsa_pcm client should go in spot 0. If this - * is the alsa_pcm client AND we are NOT about to put - * it in spot 0 put it in spot 0 and move whatever - * was already in spot 0 to the end. */ - if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 ) - { - /* alsa_pcm goes in spot 0 */ - strcpy( client_names[ num_clients ], client_names[0] ); - strcpy( client_names[0], "alsa_pcm" ); - num_clients++; - } - else - { - /* put the new client at the end of the client list */ - strcpy( client_names[ num_clients ], tmp_client_name ); - num_clients++; - } - } - } - free( jack_ports ); - - /* Now we have a list of clients, which will become the list of - * PortAudio devices. */ - - commonApi->deviceCount = num_clients; - commonApi->defaultInputDeviceIndex = 0; - commonApi->defaultOutputDeviceIndex = 0; - - /* there is one global sample rate all clients must conform to */ - - globalSampleRate = (double*)MALLOC( sizeof(double) ); - MEMVERIFY( globalSampleRate ); - *globalSampleRate = jack_get_sample_rate( jackApi->jack_client ); - - commonApi->deviceInfos = (PaDeviceInfo**)MALLOC( sizeof(PaDeviceInfo*) * - num_clients ); - MEMVERIFY(commonApi->deviceInfos); - - /* Create a PaDeviceInfo structure for every client */ - for( client_index = 0; client_index < num_clients; client_index++ ) - { - char regex_pattern[100]; - PaDeviceInfo *curDevInfo; - - curDevInfo = (PaDeviceInfo*)MALLOC( sizeof(PaDeviceInfo) ); - MEMVERIFY( curDevInfo ); - - curDevInfo->name = (char*)MALLOC( strlen(client_names[client_index]) + 1 ); - MEMVERIFY( curDevInfo->name ); - strcpy( (char*)curDevInfo->name, client_names[client_index] ); - - curDevInfo->structVersion = 2; - curDevInfo->hostApi = jackApi->hostApiIndex; - - /* JACK is very inflexible: there is one sample rate the whole - * system must run at, and all clients must speak IEEE float. */ - curDevInfo->numSampleRates = 1; - curDevInfo->sampleRates = globalSampleRate; - curDevInfo->nativeSampleFormats = paFloat32|paNonInterleaved; - - /* To determine how many input and output channels are available, - * we re-query jackd with more specific parameters. */ - - sprintf( regex_pattern, "%s:.*", client_names[client_index] ); - - /* ... what are your output ports (that we could input to)? */ - jack_ports = jack_get_ports( jackApi->jack_client, regex_pattern, - NULL, JackPortIsOutput); - curDevInfo->maxInputChannels = 0; - for( i = 0; jack_ports[i] != NULL ; i++) - { - /* The number of ports returned is the number of output channels. - * We don't care what they are, we just care how many */ - curDevInfo->maxInputChannels++; - } - free(jack_ports); - - /* ... what are your input ports (that we could output to)? */ - jack_ports = jack_get_ports( jackApi->jack_client, regex_pattern, - NULL, JackPortIsInput); - curDevInfo->maxOutputChannels = 0; - for( i = 0; jack_ports[i] != NULL ; i++) - { - /* The number of ports returned is the number of input channels. - * We don't care what they are, we just care how many */ - curDevInfo->maxOutputChannels++; - } - free(jack_ports); - - /* Add this client to the list of devices */ - commonApi->deviceInfos[client_index] = curDevInfo; - } - -#undef MALLOC -#undef MEMVERIFY - return paNoError; -} - -PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, - PaHostApiIndex hostApiIndex ) -{ - PaError result = paNoError; - PaJackHostApiRepresentation *jackHostApi; - - jackHostApi = (PaJackHostApiRepresentation*) - PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ); - if( !jackHostApi ) - { - result = paInsufficientMemory; - goto error; - } - - /* Try to become a client of the JACK server. If we cannot do - * this, than this API cannot be used. */ - - jackHostApi->jack_client = jack_client_new( "PortAudio client" ); - if( jackHostApi->jack_client == 0 ) - { - /* the V19 development docs say that if an implementation - * detects that it cannot be used, it should return a NULL - * interface and paNoError */ - result = paNoError; - *hostApi = NULL; - goto error; - } - - jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(); - if( !jackHostApi->deviceInfoMemory ) - { - result = paInsufficientMemory; - goto error; - } - - jackHostApi->hostApiIndex = hostApiIndex; - - *hostApi = &jackHostApi->commonHostApiRep; - (*hostApi)->info.structVersion = 1; - (*hostApi)->info.type = paInDevelopment; - (*hostApi)->info.name = "JACK Audio Connection Kit"; - - /* Build a device list by querying the JACK server */ - - result = BuildDeviceList( jackHostApi ); - if( result != paNoError ) - goto error; - - /* Register functions */ - - (*hostApi)->Terminate = Terminate; - (*hostApi)->OpenStream = OpenStream; - - PaUtil_InitializeStreamInterface( &jackHostApi->callbackStreamInterface, - CloseStream, StartStream, - StopStream, AbortStream, - IsStreamStopped, IsStreamActive, - GetStreamTime, GetStreamCpuLoad, - PaUtil_DummyReadWrite, PaUtil_DummyReadWrite, - PaUtil_DummyGetAvailable, - PaUtil_DummyGetAvailable ); - - return result; - -error: - if( jackHostApi ) - { - if( jackHostApi->deviceInfoMemory ) - { - PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory ); - PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory ); - } - - PaUtil_FreeMemory( jackHostApi ); - } - return result; -} - - -static void Terminate( struct PaUtilHostApiRepresentation *hostApi ) -{ - PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi; - - jack_client_close( jackHostApi->jack_client ); - - if( jackHostApi->deviceInfoMemory ) - { - PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory ); - PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory ); - } - - PaUtil_FreeMemory( jackHostApi ); -} - - -/* PaJackStream - a stream data structure specifically for this implementation */ - -typedef struct PaJackStream -{ - PaUtilStreamRepresentation streamRepresentation; - PaUtilBufferProcessor bufferProcessor; - PaUtilCpuLoadMeasurer cpuLoadMeasurer; - - /* our input and output ports */ - jack_port_t **local_input_ports; - jack_port_t **local_output_ports; - - /* the input and output ports of the client we are connecting to */ - jack_port_t **remote_input_ports; - jack_port_t **remote_output_ports; - - int num_incoming_connections; - int num_outgoing_connections; - - jack_client_t *jack_client; - - /* The stream is running if it's still producing samples. - * The stream is active if samples it produced are still being heard. - */ - int is_running; - int is_active; - - jack_nframes_t t0; - unsigned long total_frames_sent; - - PaUtilAllocationGroup *stream_memory; -} -PaJackStream; - -static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, - PaStream** s, - PaDeviceIndex inputDevice, - int numInputChannels, - PaSampleFormat inputSampleFormat, - unsigned long inputLatency, - PaHostApiSpecificStreamInfo *inputStreamInfo, - PaDeviceIndex outputDevice, - int numOutputChannels, - PaSampleFormat outputSampleFormat, - unsigned long outputLatency, - PaHostApiSpecificStreamInfo *outputStreamInfo, - double sampleRate, - unsigned long framesPerCallback, - PaStreamFlags streamFlags, - PortAudioCallback *callback, - void *userData ) -{ - PaError result = paNoError; - PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi; - PaJackStream *stream = 0; - char port_string[100]; - char regex_pattern[100]; - const char **jack_ports; - int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); - int i; - - /* the client has no say over the frames per callback */ - - (void)framesPerCallback; - - /* Preliminary checks */ - - /* ... check that input device can support numInputChannels */ - - if( inputDevice != paNoDevice && - numInputChannels > hostApi->deviceInfos[ inputDevice ]->maxInputChannels ) - return paInvalidChannelCount; - - /* ... check that output device can support numOutputChannels */ - - if( outputDevice != paNoDevice && - numOutputChannels > hostApi->deviceInfos[ outputDevice ]->maxOutputChannels) - return paInvalidChannelCount; - - /* ... check that the sample rate exactly matches the ONE acceptable rate */ - -#define ABS(x) ( (x) > 0 ? (x) : -(x) ) - if( ABS(sampleRate - hostApi->deviceInfos[0]->sampleRates[0]) > 1 ) - return paInvalidSampleRate; -#undef ABS - - /* ... this implementation doesn't use custom stream info */ - - if( inputStreamInfo ) - return paIncompatibleStreamInfo; - - /* ... this implementation doesn't use custom stream info */ - - if( outputStreamInfo ) - return paIncompatibleStreamInfo; - - /* ... this implementation doesn't use platform-specific flags */ - if( (streamFlags & paPlatformSpecificFlags) != 0 ) - return paInvalidFlag; - - /* Allocate memory for structuures */ - -#define MALLOC(size) \ - (PaUtil_GroupAllocateMemory( stream->stream_memory, (size) )) - -#define MEMVERIFY(ptr) \ - if( (ptr) == NULL ) \ - { \ - result = paInsufficientMemory; \ - goto error; \ - } - - stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ); - MEMVERIFY( stream ); - - stream->stream_memory = PaUtil_CreateAllocationGroup(); - stream->jack_client = jackHostApi->jack_client; - PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); - - stream->local_input_ports = - (jack_port_t**) MALLOC(sizeof(jack_port_t*) * numInputChannels ); - stream->local_output_ports = - (jack_port_t**) MALLOC( sizeof(jack_port_t*) * numOutputChannels ); - stream->remote_output_ports = - (jack_port_t**) MALLOC( sizeof(jack_port_t*) * numInputChannels ); - stream->remote_input_ports = - (jack_port_t**) MALLOC( sizeof(jack_port_t*) * numOutputChannels ); - - MEMVERIFY( stream->local_input_ports ); - MEMVERIFY( stream->local_output_ports ); - MEMVERIFY( stream->remote_input_ports ); - MEMVERIFY( stream->remote_output_ports ); - - stream->num_incoming_connections = numInputChannels; - stream->num_outgoing_connections = numOutputChannels; - - if( callback ) - { - PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, - &jackHostApi->callbackStreamInterface, callback, userData ); - } - else - { - /* we do not support blocking I/O */ - return paBadIODeviceCombination; - } - - /* create the JACK ports. We cannot connect them until audio - * processing begins */ - - for( i = 0; i < numInputChannels; i++ ) - { - sprintf( port_string, "in_%d", i ); - stream->local_input_ports[i] = jack_port_register( - jackHostApi->jack_client, port_string, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); - } - - for( i = 0; i < numOutputChannels; i++ ) - { - sprintf( port_string, "out_%d", i ); - stream->local_output_ports[i] = jack_port_register( - jackHostApi->jack_client, port_string, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); - } - - /* look up the jack_port_t's for the remote ports. We could do - * this at stream start time, but doing it here ensures the - * name lookup only happens once. */ - - if( numInputChannels > 0 ) - { - /* ... remote output ports (that we input from) */ - sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ inputDevice ]->name ); - jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern, - NULL, JackPortIsOutput); - for( i = 0; i < numInputChannels && jack_ports[i]; i++ ) - { - stream->remote_output_ports[i] = jack_port_by_name( - jackHostApi->jack_client, jack_ports[i] ); - } - if( i < numInputChannels ) - { - /* we found fewer ports than we expected */ - return paInternalError; - } - free( jack_ports ); // XXX: this doesn't happen if we exit prematurely - } - - - if( numOutputChannels > 0 ) - { - /* ... remote input ports (that we output to) */ - sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ outputDevice ]->name ); - jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern, - NULL, JackPortIsInput); - for( i = 0; i < numOutputChannels && jack_ports[i]; i++ ) - { - stream->remote_input_ports[i] = jack_port_by_name( - jackHostApi->jack_client, jack_ports[i] ); - } - if( i < numOutputChannels ) - { - /* we found fewer ports than we expected */ - return paInternalError; - } - free( jack_ports ); // XXX: this doesn't happen if we exit prematurely - } - - result = PaUtil_InitializeBufferProcessor( - &stream->bufferProcessor, - numInputChannels, - inputSampleFormat, - paFloat32, /* hostInputSampleFormat */ - numOutputChannels, - outputSampleFormat, - paFloat32, /* hostOutputSampleFormat */ - sampleRate, - streamFlags, - framesPerCallback, - jack_max_buffer_size, - paUtilFixedHostBufferSize, - callback, - userData ); - - if( result != paNoError ) - goto error; - - stream->is_running = FALSE; - stream->t0 = -1;/* set the first time through the callback*/ - stream->total_frames_sent = 0; - - jack_set_process_callback( jackHostApi->jack_client, JackCallback, stream ); - - *s = (PaStream*)stream; - - return result; - -error: - if( stream ) - { - if( stream->stream_memory ) - { - PaUtil_FreeAllAllocations( stream->stream_memory ); - PaUtil_DestroyAllocationGroup( stream->stream_memory ); - } - - PaUtil_FreeMemory( stream ); - } - - return result; - -#undef MALLOC -#undef MEMVERIFY -} - - -static int JackCallback( jack_nframes_t frames, void *userData ) -{ - PaJackStream *stream = (PaJackStream*)userData; - PaTimestamp outTime = 0; /* IMPLEMENT ME */ - int callbackResult; - int chn; - int framesProcessed; - - if( stream->t0 == -1 ) - { - if( stream->num_outgoing_connections == 0 ) - { - /* TODO: how to handle stream time for capture-only operation? */ - } - else - { - /* the beginning time needs to be initialized */ - stream->t0 = jack_frame_time( stream->jack_client ) - - jack_frames_since_cycle_start( stream->jack_client) + - jack_port_get_total_latency( stream->jack_client, - stream->local_output_ports[0] ); - } - } - - PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer ); - - PaUtil_BeginBufferProcessing( &stream->bufferProcessor, outTime ); - - for( chn = 0; chn < stream->num_incoming_connections; chn++ ) - { - jack_default_audio_sample_t *channel_buf; - channel_buf = (jack_default_audio_sample_t*) - jack_port_get_buffer( stream->local_input_ports[chn], - frames ); - - PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor, - chn, - channel_buf ); - } - - for( chn = 0; chn < stream->num_outgoing_connections; chn++ ) - { - jack_default_audio_sample_t *channel_buf; - channel_buf = (jack_default_audio_sample_t*) - jack_port_get_buffer( stream->local_output_ports[chn], - frames ); - - PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor, - chn, - channel_buf ); - } - - if( stream->num_incoming_connections > 0 ) - PaUtil_SetInputFrameCount( &stream->bufferProcessor, frames ); - - if( stream->num_outgoing_connections > 0 ) - PaUtil_SetOutputFrameCount( &stream->bufferProcessor, frames ); - - framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, - &callbackResult ); - - PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed ); - stream->total_frames_sent += frames; - - - if( callbackResult == paContinue ) - { - /* nothing special */ - } - else if( callbackResult == paAbort ) - { - /* finish playback immediately */ - - /* TODO: memset 0 the outgoing samples to "cancel" them */ - - stream->is_active = FALSE; - - /* return nonzero so we get deactivated (and the callback won't - * get called again) */ - return 1; - } - else - { - /* User callback has asked us to stop with paComplete or other non-zero value. */ - - stream->is_active = FALSE; - - /* return nonzero so we get deactivated (and the callback won't - * get called again) */ - return 1; - } - return 0; -} - - -/* - When CloseStream() is called, the multi-api layer ensures that - the stream has already been stopped or aborted. -*/ -static PaError CloseStream( PaStream* s ) -{ - PaError result = paNoError; - PaJackStream *stream = (PaJackStream*)s; - - PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation ); - PaUtil_FreeMemory( stream ); - - return result; -} - - -static PaError StartStream( PaStream *s ) -{ - PaError result = paNoError; - PaJackStream *stream = (PaJackStream*)s; - int i; - - /* start the audio thread */ - - jack_activate( stream->jack_client ); - - /* 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++ ) - jack_connect( stream->jack_client, - jack_port_name(stream->remote_output_ports[i]), - jack_port_name(stream->local_input_ports[i] ) ); - } - - if( stream->num_outgoing_connections > 0 ) - { - for( i = 0; i < stream->num_outgoing_connections; i++ ) - jack_connect( stream->jack_client, - jack_port_name(stream->local_output_ports[i]), - jack_port_name(stream->remote_input_ports[i]) ); - } - - stream->is_running = TRUE; - - return result; -} - - -static PaError StopStream( PaStream *s ) -{ - PaError result = paNoError; - PaJackStream *stream = (PaJackStream*)s; - - /* note: this automatically disconnects all ports, since a deactivated - * client is not allowed to have any ports connected */ - jack_deactivate( stream->jack_client ); - - stream->is_running = FALSE; - - /* TODO: block until playback complete */ - - stream->is_active = FALSE; - - return result; -} - - -static PaError AbortStream( PaStream *s ) -{ - PaError result = paNoError; - PaJackStream *stream = (PaJackStream*)s; - - /* There's no way to cancel samples already submitted, but we can - * return immediately */ - - /* note: this automatically disconnects all ports, since a deactivated - * client is not allowed to have any ports connected */ - jack_deactivate( stream->jack_client ); - - stream->is_running = FALSE; - stream->is_active = FALSE; - - return result; -} - - -static PaError IsStreamStopped( PaStream *s ) -{ - PaJackStream *stream = (PaJackStream*)s; - - return stream->is_running == FALSE; -} - - -static PaError IsStreamActive( PaStream *s ) -{ - PaJackStream *stream = (PaJackStream*)s; - - return stream->is_active == TRUE; -} - - -static PaTimestamp GetStreamTime( PaStream *s ) -{ - PaJackStream *stream = (PaJackStream*)s; - - /* TODO: what if we're recording-only? */ - return jack_frame_time( stream->jack_client ) - stream->t0; -} - - -static double GetStreamCpuLoad( PaStream* s ) -{ - PaJackStream *stream = (PaJackStream*)s; - - return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer ); -} - - -- cgit v1.2.1