aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/pa_jack
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/pa_jack')
-rw-r--r--pd/portaudio/pa_jack/pa_jack.c864
1 files changed, 0 insertions, 864 deletions
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 <joshua@haberman.com>
- *
- * 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 <string.h>
-#include <regex.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <jack/types.h>
-#include <jack/jack.h>
-
-#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 );
-}
-
-