2
* $Id: pa_jack.c 1346 2008-02-20 10:09:20Z rossb $
3
* PortAudio Portable Real-Time Audio Library
4
* Latest Version at: http://www.portaudio.com
5
* JACK Implementation by Joshua Haberman
7
* Copyright (c) 2004 Stefan Westerfeld <stefan@space.twc.de>
8
* Copyright (c) 2004 Arve Knudsen <aknuds-1@broadpark.no>
9
* Copyright (c) 2002 Joshua Haberman <joshua@haberman.com>
11
* Based on the Open Source API proposed by Ross Bencina
12
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
14
* Permission is hereby granted, free of charge, to any person obtaining
15
* a copy of this software and associated documentation files
16
* (the "Software"), to deal in the Software without restriction,
17
* including without limitation the rights to use, copy, modify, merge,
18
* publish, distribute, sublicense, and/or sell copies of the Software,
19
* and to permit persons to whom the Software is furnished to do so,
20
* subject to the following conditions:
22
* The above copyright notice and this permission notice shall be
23
* included in all copies or substantial portions of the Software.
25
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
29
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
30
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
* The text above constitutes the entire PortAudio license; however,
36
* the PortAudio community also makes the following non-binding requests:
38
* Any person wishing to distribute modifications to the Software is
39
* requested to send the modifications to the original developer so that
40
* they can be incorporated into the canonical version. It is also
41
* requested that these non-binding requests be included along with the
55
#include <sys/types.h>
57
#include <errno.h> /* EBUSY */
58
#include <signal.h> /* sig_atomic_t */
60
#include <semaphore.h>
62
#include <jack/types.h>
63
#include <jack/jack.h>
66
#include "pa_hostapi.h"
67
#include "pa_stream.h"
68
#include "pa_process.h"
69
#include "pa_allocation.h"
70
#include "pa_cpuload.h"
71
#include "pa_ringbuffer.h"
72
#include "pa_debugprint.h"
75
static PaError paErr_; /* For use with ENSURE_PA */
76
static pthread_t mainThread_;
77
static char *jackErr_ = NULL;
78
static const char* clientName_ = "PortAudio";
80
#define STRINGIZE_HELPER(expr) #expr
81
#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
84
#define ENSURE_PA(expr) \
86
if( (paErr_ = (expr)) < paNoError ) \
88
if( (paErr_) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
90
if (! jackErr_ ) jackErr_ = "unknown error";\
91
PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
93
PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
99
#define UNLESS(expr, code) \
103
if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
105
if (!jackErr_) jackErr_ = "unknown error";\
106
PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
108
PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
114
#define ASSERT_CALL(expr, success) \
116
assert( aErr_ == success );
119
* Functions that directly map to the PortAudio stream interface
122
static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
123
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
124
const PaStreamParameters *inputParameters,
125
const PaStreamParameters *outputParameters,
127
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
129
const PaStreamParameters *inputParameters,
130
const PaStreamParameters *outputParameters,
132
unsigned long framesPerBuffer,
133
PaStreamFlags streamFlags,
134
PaStreamCallback *streamCallback,
136
static PaError CloseStream( PaStream* stream );
137
static PaError StartStream( PaStream *stream );
138
static PaError StopStream( PaStream *stream );
139
static PaError AbortStream( PaStream *stream );
140
static PaError IsStreamStopped( PaStream *s );
141
static PaError IsStreamActive( PaStream *stream );
142
/*static PaTime GetStreamInputLatency( PaStream *stream );*/
143
/*static PaTime GetStreamOutputLatency( PaStream *stream );*/
144
static PaTime GetStreamTime( PaStream *stream );
145
static double GetStreamCpuLoad( PaStream* stream );
149
* Data specific to this API
156
PaUtilHostApiRepresentation commonHostApiRep;
157
PaUtilStreamInterface callbackStreamInterface;
158
PaUtilStreamInterface blockingStreamInterface;
160
PaUtilAllocationGroup *deviceInfoMemory;
162
jack_client_t *jack_client;
163
int jack_buffer_size;
164
PaHostApiIndex hostApiIndex;
168
unsigned long inputBase, outputBase;
170
/* For dealing with the process thread */
171
volatile int xrun; /* Received xrun notification from JACK? */
172
struct PaJackStream * volatile toAdd, * volatile toRemove;
173
struct PaJackStream *processQueue;
174
volatile sig_atomic_t jackIsDown;
176
PaJackHostApiRepresentation;
178
/* PaJackStream - a stream data structure specifically for this implementation */
180
typedef struct PaJackStream
182
PaUtilStreamRepresentation streamRepresentation;
183
PaUtilBufferProcessor bufferProcessor;
184
PaUtilCpuLoadMeasurer cpuLoadMeasurer;
185
PaJackHostApiRepresentation *hostApi;
187
/* our input and output ports */
188
jack_port_t **local_input_ports;
189
jack_port_t **local_output_ports;
191
/* the input and output ports of the client we are connecting to */
192
jack_port_t **remote_input_ports;
193
jack_port_t **remote_output_ports;
195
int num_incoming_connections;
196
int num_outgoing_connections;
198
jack_client_t *jack_client;
200
/* The stream is running if it's still producing samples.
201
* The stream is active if samples it produced are still being heard.
203
volatile sig_atomic_t is_running;
204
volatile sig_atomic_t is_active;
205
/* Used to signal processing thread that stream should start or stop, respectively */
206
volatile sig_atomic_t doStart, doStop, doAbort;
210
PaUtilAllocationGroup *stream_memory;
212
/* These are useful in the process callback */
218
/* These are useful for the blocking API */
220
int isBlockingStream;
221
PaUtilRingBuffer inFIFO;
222
PaUtilRingBuffer outFIFO;
223
volatile sig_atomic_t data_available;
224
sem_t data_semaphore;
228
struct PaJackStream *next;
236
* Functions specific to this API
239
static int JackCallback( jack_nframes_t frames, void *userData );
248
/* ---- blocking emulation layer ---- */
250
/* Allocate buffer. */
251
static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long bytesPerFrame )
253
long numBytes = numFrames * bytesPerFrame;
254
char *buffer = (char *) malloc( numBytes );
255
if( buffer == NULL ) return paInsufficientMemory;
256
memset( buffer, 0, numBytes );
257
return (PaError) PaUtil_InitializeRingBuffer( rbuf, 1, numBytes, buffer );
261
static PaError BlockingTermFIFO( PaUtilRingBuffer *rbuf )
263
if( rbuf->buffer ) free( rbuf->buffer );
269
BlockingCallback( const void *inputBuffer,
271
unsigned long framesPerBuffer,
272
const PaStreamCallbackTimeInfo* timeInfo,
273
PaStreamCallbackFlags statusFlags,
276
struct PaJackStream *stream = (PaJackStream *)userData;
277
long numBytes = stream->bytesPerFrame * framesPerBuffer;
279
/* This may get called with NULL inputBuffer during initial setup. */
280
if( inputBuffer != NULL )
282
PaUtil_WriteRingBuffer( &stream->inFIFO, inputBuffer, numBytes );
284
if( outputBuffer != NULL )
286
int numRead = PaUtil_ReadRingBuffer( &stream->outFIFO, outputBuffer, numBytes );
287
/* Zero out remainder of buffer if we run out of data. */
288
memset( (char *)outputBuffer + numRead, 0, numBytes - numRead );
291
if( !stream->data_available )
293
stream->data_available = 1;
294
sem_post( &stream->data_semaphore );
300
BlockingBegin( PaJackStream *stream, int minimum_buffer_size )
304
PaError result = paNoError;
307
doRead = stream->local_input_ports != NULL;
308
doWrite = stream->local_output_ports != NULL;
310
stream->samplesPerFrame = 2;
311
stream->bytesPerFrame = sizeof(float) * stream->samplesPerFrame;
314
while (numFrames < minimum_buffer_size)
319
ENSURE_PA( BlockingInitFIFO( &stream->inFIFO, numFrames, stream->bytesPerFrame ) );
325
ENSURE_PA( BlockingInitFIFO( &stream->outFIFO, numFrames, stream->bytesPerFrame ) );
327
/* Make Write FIFO appear full initially. */
328
numBytes = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
329
PaUtil_AdvanceRingBufferWriteIndex( &stream->outFIFO, numBytes );
332
stream->data_available = 0;
333
sem_init( &stream->data_semaphore, 0, 0 );
340
BlockingEnd( PaJackStream *stream )
342
BlockingTermFIFO( &stream->inFIFO );
343
BlockingTermFIFO( &stream->outFIFO );
345
sem_destroy( &stream->data_semaphore );
348
static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames )
350
PaError result = paNoError;
351
PaJackStream *stream = (PaJackStream *)s;
354
char *p = (char *) data;
355
long numBytes = stream->bytesPerFrame * numFrames;
356
while( numBytes > 0 )
358
bytesRead = PaUtil_ReadRingBuffer( &stream->inFIFO, p, numBytes );
359
numBytes -= bytesRead;
363
/* see write for an explanation */
364
if( stream->data_available )
365
stream->data_available = 0;
367
sem_wait( &stream->data_semaphore );
374
static PaError BlockingWriteStream( PaStream* s, const void *data, unsigned long numFrames )
376
PaError result = paNoError;
377
PaJackStream *stream = (PaJackStream *)s;
379
char *p = (char *) data;
380
long numBytes = stream->bytesPerFrame * numFrames;
381
while( numBytes > 0 )
383
bytesWritten = PaUtil_WriteRingBuffer( &stream->outFIFO, p, numBytes );
384
numBytes -= bytesWritten;
388
/* we use the following algorithm:
390
* (2) if some data didn't fit into the ringbuffer, set data_available to 0
391
* to indicate to the audio that if space becomes available, we want to know
392
* (3) retry to write data (because it might be that between (1) and (2)
393
* new space in the buffer became available)
394
* (4) if this failed, we are sure that the buffer is really empty and
395
* we will definitely receive a notification when it becomes available
396
* thus we can safely sleep
398
* if the algorithm bailed out in step (3) before, it leaks a count of 1
399
* on the semaphore; however, it doesn't matter, because if we block in (4),
400
* we also do it in a loop
402
if( stream->data_available )
403
stream->data_available = 0;
405
sem_wait( &stream->data_semaphore );
413
BlockingGetStreamReadAvailable( PaStream* s )
415
PaJackStream *stream = (PaJackStream *)s;
417
int bytesFull = PaUtil_GetRingBufferReadAvailable( &stream->inFIFO );
418
return bytesFull / stream->bytesPerFrame;
422
BlockingGetStreamWriteAvailable( PaStream* s )
424
PaJackStream *stream = (PaJackStream *)s;
426
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
427
return bytesEmpty / stream->bytesPerFrame;
431
BlockingWaitEmpty( PaStream *s )
433
PaJackStream *stream = (PaJackStream *)s;
435
while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
437
stream->data_available = 0;
438
sem_wait( &stream->data_semaphore );
443
/* ---- jack driver ---- */
445
/* BuildDeviceList():
447
* The process of determining a list of PortAudio "devices" from
448
* JACK's client/port system is fairly involved, so it is separated
449
* into its own routine.
452
static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
454
/* Utility macros for the repetitive process of allocating memory */
456
/* JACK has no concept of a device. To JACK, there are clients
457
* which have an arbitrary number of ports. To make this
458
* intelligible to PortAudio clients, we will group each JACK client
459
* into a device, and make each port of that client a channel */
461
PaError result = paNoError;
462
PaUtilHostApiRepresentation *commonApi = &jackApi->commonHostApiRep;
464
const char **jack_ports = NULL;
465
char **client_names = NULL;
466
char *regex_pattern = NULL;
467
int port_index, client_index, i;
468
double globalSampleRate;
470
unsigned long numClients = 0, numPorts = 0;
471
char *tmp_client_name = NULL;
473
commonApi->info.defaultInputDevice = paNoDevice;
474
commonApi->info.defaultOutputDevice = paNoDevice;
475
commonApi->info.deviceCount = 0;
477
/* Parse the list of ports, using a regex to grab the client names */
478
ASSERT_CALL( regcomp( &port_regex, "^[^:]*", REG_EXTENDED ), 0 );
480
/* since we are rebuilding the list of devices, free all memory
481
* associated with the previous list */
482
PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
484
regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
485
tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
487
/* We can only retrieve the list of clients indirectly, by first
488
* asking for a list of all ports, then parsing the port names
489
* according to the client_name:port_name convention (which is
491
* A: If jack_get_ports returns NULL, there's nothing for us to do */
492
UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", "", 0 )) && jack_ports[0], paNoError );
493
/* Find number of ports */
494
while( jack_ports[numPorts] )
496
/* At least there will be one port per client :) */
497
UNLESS( client_names = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, numPorts *
498
sizeof (char *) ), paInsufficientMemory );
500
/* Build a list of clients from the list of ports */
501
for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
503
int client_seen = FALSE;
504
regmatch_t match_info;
505
const char *port = jack_ports[port_index];
507
/* extract the client name from the port name, using a regex
508
* that parses the clientname:portname syntax */
509
UNLESS( !regexec( &port_regex, port, 1, &match_info, 0 ), paInternalError );
510
assert(match_info.rm_eo - match_info.rm_so < jack_client_name_size());
511
memcpy( tmp_client_name, port + match_info.rm_so,
512
match_info.rm_eo - match_info.rm_so );
513
tmp_client_name[match_info.rm_eo - match_info.rm_so] = '\0';
515
/* do we know about this port's client yet? */
516
for( i = 0; i < numClients; i++ )
518
if( strcmp( tmp_client_name, client_names[i] ) == 0 )
523
continue; /* A: Nothing to see here, move along */
525
UNLESS( client_names[numClients] = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
526
strlen(tmp_client_name) + 1), paInsufficientMemory );
528
/* The alsa_pcm client should go in spot 0. If this
529
* is the alsa_pcm client AND we are NOT about to put
530
* it in spot 0 put it in spot 0 and move whatever
531
* was already in spot 0 to the end. */
532
if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && numClients > 0 )
534
/* alsa_pcm goes in spot 0 */
535
strcpy( client_names[ numClients ], client_names[0] );
536
strcpy( client_names[0], tmp_client_name );
540
/* put the new client at the end of the client list */
541
strcpy( client_names[ numClients ], tmp_client_name );
546
/* Now we have a list of clients, which will become the list of
547
* PortAudio devices. */
549
/* there is one global sample rate all clients must conform to */
551
globalSampleRate = jack_get_sample_rate( jackApi->jack_client );
552
UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
553
sizeof(PaDeviceInfo*) * numClients ), paInsufficientMemory );
555
assert( commonApi->info.deviceCount == 0 );
557
/* Create a PaDeviceInfo structure for every client */
558
for( client_index = 0; client_index < numClients; client_index++ )
560
PaDeviceInfo *curDevInfo;
561
const char **clientPorts = NULL;
563
UNLESS( curDevInfo = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
564
sizeof(PaDeviceInfo) ), paInsufficientMemory );
565
UNLESS( curDevInfo->name = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
566
strlen(client_names[client_index]) + 1 ), paInsufficientMemory );
567
strcpy( (char *)curDevInfo->name, client_names[client_index] );
569
curDevInfo->structVersion = 2;
570
curDevInfo->hostApi = jackApi->hostApiIndex;
572
/* JACK is very inflexible: there is one sample rate the whole
573
* system must run at, and all clients must speak IEEE float. */
574
curDevInfo->defaultSampleRate = globalSampleRate;
576
/* To determine how many input and output channels are available,
577
* we re-query jackd with more specific parameters. */
579
sprintf( regex_pattern, "%s:.*", client_names[client_index] );
581
/* ... what are your output ports (that we could input from)? */
582
clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
583
NULL, JackPortIsOutput);
584
curDevInfo->maxInputChannels = 0;
585
curDevInfo->defaultLowInputLatency = 0.;
586
curDevInfo->defaultHighInputLatency = 0.;
589
jack_port_t *p = jack_port_by_name( jackApi->jack_client, clientPorts[0] );
590
curDevInfo->defaultLowInputLatency = curDevInfo->defaultHighInputLatency =
591
jack_port_get_latency( p ) / globalSampleRate;
593
for( i = 0; clientPorts[i] != NULL; i++)
595
/* The number of ports returned is the number of output channels.
596
* We don't care what they are, we just care how many */
597
curDevInfo->maxInputChannels++;
602
/* ... what are your input ports (that we could output to)? */
603
clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
604
NULL, JackPortIsInput);
605
curDevInfo->maxOutputChannels = 0;
606
curDevInfo->defaultLowOutputLatency = 0.;
607
curDevInfo->defaultHighOutputLatency = 0.;
610
jack_port_t *p = jack_port_by_name( jackApi->jack_client, clientPorts[0] );
611
curDevInfo->defaultLowOutputLatency = curDevInfo->defaultHighOutputLatency =
612
jack_port_get_latency( p ) / globalSampleRate;
614
for( i = 0; clientPorts[i] != NULL; i++)
616
/* The number of ports returned is the number of input channels.
617
* We don't care what they are, we just care how many */
618
curDevInfo->maxOutputChannels++;
623
/* Add this client to the list of devices */
624
commonApi->deviceInfos[client_index] = curDevInfo;
625
++commonApi->info.deviceCount;
626
if( commonApi->info.defaultInputDevice == paNoDevice && curDevInfo->maxInputChannels > 0 )
627
commonApi->info.defaultInputDevice = client_index;
628
if( commonApi->info.defaultOutputDevice == paNoDevice && curDevInfo->maxOutputChannels > 0 )
629
commonApi->info.defaultOutputDevice = client_index;
633
regfree( &port_regex );
638
static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
640
/* XXX: Maybe not the cleanest way of going about this? */
641
stream->cpuLoadMeasurer.samplingPeriod = stream->bufferProcessor.samplePeriod = 1. / sampleRate;
642
stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
645
static void JackErrorCallback( const char *msg )
647
if( pthread_self() == mainThread_ )
650
jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
651
strcpy( jackErr_, msg );
655
static void JackOnShutdown( void *arg )
657
PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
658
PaJackStream *stream = jackApi->processQueue;
660
PA_DEBUG(( "%s: JACK server is shutting down\n", __FUNCTION__ ));
661
for( ; stream; stream = stream->next )
663
stream->is_active = 0;
666
/* Make sure that the main thread doesn't get stuck waiting on the condition */
667
ASSERT_CALL( pthread_mutex_lock( &jackApi->mtx ), 0 );
668
jackApi->jackIsDown = 1;
669
ASSERT_CALL( pthread_cond_signal( &jackApi->cond ), 0 );
670
ASSERT_CALL( pthread_mutex_unlock( &jackApi->mtx ), 0 );
674
static int JackSrCb( jack_nframes_t nframes, void *arg )
676
PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
677
double sampleRate = (double)nframes;
678
PaJackStream *stream = jackApi->processQueue;
680
/* Update all streams in process queue */
681
PA_DEBUG(( "%s: Acting on change in JACK samplerate: %f\n", __FUNCTION__, sampleRate ));
682
for( ; stream; stream = stream->next )
684
if( stream->streamRepresentation.streamInfo.sampleRate != sampleRate )
686
PA_DEBUG(( "%s: Updating samplerate\n", __FUNCTION__ ));
687
UpdateSampleRate( stream, sampleRate );
694
static int JackXRunCb(void *arg) {
695
PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)arg;
697
hostApi->xrun = TRUE;
698
PA_DEBUG(( "%s: JACK signalled xrun\n", __FUNCTION__ ));
702
PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
703
PaHostApiIndex hostApiIndex )
705
PaError result = paNoError;
706
PaJackHostApiRepresentation *jackHostApi;
708
jack_status_t jackStatus = 0;
709
*hostApi = NULL; /* Initialize to NULL */
711
UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
712
PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ), paInsufficientMemory );
713
UNLESS( jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
715
mainThread_ = pthread_self();
716
ASSERT_CALL( pthread_mutex_init( &jackHostApi->mtx, NULL ), 0 );
717
ASSERT_CALL( pthread_cond_init( &jackHostApi->cond, NULL ), 0 );
719
/* Try to become a client of the JACK server. If we cannot do
720
* this, then this API cannot be used.
722
* Without the JackNoStartServer option, the jackd server is started
723
* automatically which we do not want.
726
jackHostApi->jack_client = jack_client_open( clientName_, JackNoStartServer, &jackStatus );
727
if( !jackHostApi->jack_client )
729
/* the V19 development docs say that if an implementation
730
* detects that it cannot be used, it should return a NULL
731
* interface and paNoError */
732
PA_DEBUG(( "%s: Couldn't connect to JACK, status: %d\n", __FUNCTION__, jackStatus ));
737
jackHostApi->hostApiIndex = hostApiIndex;
739
*hostApi = &jackHostApi->commonHostApiRep;
740
(*hostApi)->info.structVersion = 1;
741
(*hostApi)->info.type = paJACK;
742
(*hostApi)->info.name = "JACK Audio Connection Kit";
744
/* Build a device list by querying the JACK server */
745
ENSURE_PA( BuildDeviceList( jackHostApi ) );
747
/* Register functions */
749
(*hostApi)->Terminate = Terminate;
750
(*hostApi)->OpenStream = OpenStream;
751
(*hostApi)->IsFormatSupported = IsFormatSupported;
753
PaUtil_InitializeStreamInterface( &jackHostApi->callbackStreamInterface,
754
CloseStream, StartStream,
755
StopStream, AbortStream,
756
IsStreamStopped, IsStreamActive,
757
GetStreamTime, GetStreamCpuLoad,
758
PaUtil_DummyRead, PaUtil_DummyWrite,
759
PaUtil_DummyGetReadAvailable,
760
PaUtil_DummyGetWriteAvailable );
762
PaUtil_InitializeStreamInterface( &jackHostApi->blockingStreamInterface, CloseStream, StartStream,
763
StopStream, AbortStream, IsStreamStopped, IsStreamActive,
764
GetStreamTime, PaUtil_DummyGetCpuLoad,
765
BlockingReadStream, BlockingWriteStream,
766
BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable );
768
jackHostApi->inputBase = jackHostApi->outputBase = 0;
769
jackHostApi->xrun = 0;
770
jackHostApi->toAdd = jackHostApi->toRemove = NULL;
771
jackHostApi->processQueue = NULL;
772
jackHostApi->jackIsDown = 0;
774
jack_on_shutdown( jackHostApi->jack_client, JackOnShutdown, jackHostApi );
775
jack_set_error_function( JackErrorCallback );
776
jackHostApi->jack_buffer_size = jack_get_buffer_size ( jackHostApi->jack_client );
777
/* Don't check for error, may not be supported (deprecated in at least jackdmp) */
778
jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi );
779
UNLESS( !jack_set_xrun_callback( jackHostApi->jack_client, JackXRunCb, jackHostApi ), paUnanticipatedHostError );
780
UNLESS( !jack_set_process_callback( jackHostApi->jack_client, JackCallback, jackHostApi ), paUnanticipatedHostError );
781
UNLESS( !jack_activate( jackHostApi->jack_client ), paUnanticipatedHostError );
788
ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
792
if( jackHostApi->jack_client )
793
ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
795
if( jackHostApi->deviceInfoMemory )
797
PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
798
PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
801
PaUtil_FreeMemory( jackHostApi );
807
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
809
PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
811
/* note: this automatically disconnects all ports, since a deactivated
812
* client is not allowed to have any ports connected */
813
ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
815
ASSERT_CALL( pthread_mutex_destroy( &jackHostApi->mtx ), 0 );
816
ASSERT_CALL( pthread_cond_destroy( &jackHostApi->cond ), 0 );
818
ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
820
if( jackHostApi->deviceInfoMemory )
822
PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
823
PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
826
PaUtil_FreeMemory( jackHostApi );
831
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
832
const PaStreamParameters *inputParameters,
833
const PaStreamParameters *outputParameters,
836
int inputChannelCount = 0, outputChannelCount = 0;
837
PaSampleFormat inputSampleFormat, outputSampleFormat;
839
if( inputParameters )
841
inputChannelCount = inputParameters->channelCount;
842
inputSampleFormat = inputParameters->sampleFormat;
844
/* unless alternate device specification is supported, reject the use of
845
paUseHostApiSpecificDeviceSpecification */
847
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
848
return paInvalidDevice;
850
/* check that input device can support inputChannelCount */
851
if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
852
return paInvalidChannelCount;
854
/* validate inputStreamInfo */
855
if( inputParameters->hostApiSpecificStreamInfo )
856
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
860
inputChannelCount = 0;
863
if( outputParameters )
865
outputChannelCount = outputParameters->channelCount;
866
outputSampleFormat = outputParameters->sampleFormat;
868
/* unless alternate device specification is supported, reject the use of
869
paUseHostApiSpecificDeviceSpecification */
871
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
872
return paInvalidDevice;
874
/* check that output device can support inputChannelCount */
875
if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
876
return paInvalidChannelCount;
878
/* validate outputStreamInfo */
879
if( outputParameters->hostApiSpecificStreamInfo )
880
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
884
outputChannelCount = 0;
888
The following check is not necessary for JACK.
890
- if a full duplex stream is requested, check that the combination
891
of input and output parameters is supported
894
Because the buffer adapter handles conversion between all standard
895
sample formats, the following checks are only required if paCustomFormat
896
is implemented, or under some other unusual conditions.
898
- check that input device can support inputSampleFormat, or that
899
we have the capability to convert from outputSampleFormat to
902
- check that output device can support outputSampleFormat, or that
903
we have the capability to convert from outputSampleFormat to
907
/* check that the device supports sampleRate */
909
#define ABS(x) ( (x) > 0 ? (x) : -(x) )
910
if( ABS(sampleRate - jack_get_sample_rate(((PaJackHostApiRepresentation *) hostApi)->jack_client )) > 1 )
911
return paInvalidSampleRate;
914
return paFormatIsSupported;
917
/* Basic stream initialization */
918
static PaError InitializeStream( PaJackStream *stream, PaJackHostApiRepresentation *hostApi, int numInputChannels,
919
int numOutputChannels )
921
PaError result = paNoError;
924
memset( stream, 0, sizeof (PaJackStream) );
925
UNLESS( stream->stream_memory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
926
stream->jack_client = hostApi->jack_client;
927
stream->hostApi = hostApi;
929
if( numInputChannels > 0 )
931
UNLESS( stream->local_input_ports =
932
(jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numInputChannels ),
933
paInsufficientMemory );
934
memset( stream->local_input_ports, 0, sizeof(jack_port_t*) * numInputChannels );
935
UNLESS( stream->remote_output_ports =
936
(jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numInputChannels ),
937
paInsufficientMemory );
938
memset( stream->remote_output_ports, 0, sizeof(jack_port_t*) * numInputChannels );
940
if( numOutputChannels > 0 )
942
UNLESS( stream->local_output_ports =
943
(jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numOutputChannels ),
944
paInsufficientMemory );
945
memset( stream->local_output_ports, 0, sizeof(jack_port_t*) * numOutputChannels );
946
UNLESS( stream->remote_input_ports =
947
(jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numOutputChannels ),
948
paInsufficientMemory );
949
memset( stream->remote_input_ports, 0, sizeof(jack_port_t*) * numOutputChannels );
952
stream->num_incoming_connections = numInputChannels;
953
stream->num_outgoing_connections = numOutputChannels;
960
* Free resources associated with stream, and eventually stream itself.
962
* Frees allocated memory, and closes opened pcms.
964
static void CleanUpStream( PaJackStream *stream, int terminateStreamRepresentation, int terminateBufferProcessor )
969
if( stream->isBlockingStream )
970
BlockingEnd( stream );
972
for( i = 0; i < stream->num_incoming_connections; ++i )
974
if( stream->local_input_ports[i] )
975
ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_input_ports[i] ), 0 );
977
for( i = 0; i < stream->num_outgoing_connections; ++i )
979
if( stream->local_output_ports[i] )
980
ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_output_ports[i] ), 0 );
983
if( terminateStreamRepresentation )
984
PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
985
if( terminateBufferProcessor )
986
PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
988
if( stream->stream_memory )
990
PaUtil_FreeAllAllocations( stream->stream_memory );
991
PaUtil_DestroyAllocationGroup( stream->stream_memory );
993
PaUtil_FreeMemory( stream );
996
static PaError WaitCondition( PaJackHostApiRepresentation *hostApi )
998
PaError result = paNoError;
1000
PaTime pt = PaUtil_GetTime();
1003
ts.tv_sec = (time_t) floor( pt + 1 );
1004
ts.tv_nsec = (long) ((pt - floor( pt )) * 1000000000);
1005
/* XXX: Best enclose in loop, in case of spurious wakeups? */
1006
err = pthread_cond_timedwait( &hostApi->cond, &hostApi->mtx, &ts );
1008
/* Make sure we didn't time out */
1009
UNLESS( err != ETIMEDOUT, paTimedOut );
1010
UNLESS( !err, paInternalError );
1016
static PaError AddStream( PaJackStream *stream )
1018
PaError result = paNoError;
1019
PaJackHostApiRepresentation *hostApi = stream->hostApi;
1020
/* Add to queue of streams that should be processed */
1021
ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
1022
if( !hostApi->jackIsDown )
1024
hostApi->toAdd = stream;
1025
/* Unlock mutex and await signal from processing thread */
1026
result = WaitCondition( stream->hostApi );
1028
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1029
ENSURE_PA( result );
1031
UNLESS( !hostApi->jackIsDown, paDeviceUnavailable );
1037
/* Remove stream from processing queue */
1038
static PaError RemoveStream( PaJackStream *stream )
1040
PaError result = paNoError;
1041
PaJackHostApiRepresentation *hostApi = stream->hostApi;
1043
/* Add to queue over streams that should be processed */
1044
ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
1045
if( !hostApi->jackIsDown )
1047
hostApi->toRemove = stream;
1048
/* Unlock mutex and await signal from processing thread */
1049
result = WaitCondition( stream->hostApi );
1051
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1052
ENSURE_PA( result );
1058
/* Add stream to JACK callback processing queue */
1059
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
1061
const PaStreamParameters *inputParameters,
1062
const PaStreamParameters *outputParameters,
1064
unsigned long framesPerBuffer,
1065
PaStreamFlags streamFlags,
1066
PaStreamCallback *streamCallback,
1069
PaError result = paNoError;
1070
PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
1071
PaJackStream *stream = NULL;
1072
char *port_string = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_port_name_size() );
1073
unsigned long regexSz = jack_client_name_size() + 3;
1074
char *regex_pattern = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, regexSz );
1075
const char **jack_ports = NULL;
1076
/* int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); */
1078
int inputChannelCount, outputChannelCount;
1079
const double jackSr = jack_get_sample_rate( jackHostApi->jack_client );
1080
PaSampleFormat inputSampleFormat = 0, outputSampleFormat = 0;
1081
int bpInitialized = 0, srInitialized = 0; /* Initialized buffer processor and stream representation? */
1084
/* validate platform specific flags */
1085
if( (streamFlags & paPlatformSpecificFlags) != 0 )
1086
return paInvalidFlag; /* unexpected platform specific flag */
1087
if( (streamFlags & paPrimeOutputBuffersUsingStreamCallback) != 0 )
1089
streamFlags &= ~paPrimeOutputBuffersUsingStreamCallback;
1090
/*return paInvalidFlag;*/ /* This implementation does not support buffer priming */
1093
if( framesPerBuffer != paFramesPerBufferUnspecified )
1095
/* Jack operates with power of two buffers, and we don't support non-integer buffer adaption (yet) */
1096
/*UNLESS( !(framesPerBuffer & (framesPerBuffer - 1)), paBufferTooBig );*/ /* TODO: Add descriptive error code? */
1099
/* Preliminary checks */
1101
if( inputParameters )
1103
inputChannelCount = inputParameters->channelCount;
1104
inputSampleFormat = inputParameters->sampleFormat;
1106
/* unless alternate device specification is supported, reject the use of
1107
paUseHostApiSpecificDeviceSpecification */
1109
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
1110
return paInvalidDevice;
1112
/* check that input device can support inputChannelCount */
1113
if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
1114
return paInvalidChannelCount;
1116
/* validate inputStreamInfo */
1117
if( inputParameters->hostApiSpecificStreamInfo )
1118
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
1122
inputChannelCount = 0;
1125
if( outputParameters )
1127
outputChannelCount = outputParameters->channelCount;
1128
outputSampleFormat = outputParameters->sampleFormat;
1130
/* unless alternate device specification is supported, reject the use of
1131
paUseHostApiSpecificDeviceSpecification */
1133
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
1134
return paInvalidDevice;
1136
/* check that output device can support inputChannelCount */
1137
if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
1138
return paInvalidChannelCount;
1140
/* validate outputStreamInfo */
1141
if( outputParameters->hostApiSpecificStreamInfo )
1142
return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
1146
outputChannelCount = 0;
1149
/* ... check that the sample rate exactly matches the ONE acceptable rate
1150
* A: This rate isn't necessarily constant though? */
1152
#define ABS(x) ( (x) > 0 ? (x) : -(x) )
1153
if( ABS(sampleRate - jackSr) > 1 )
1154
return paInvalidSampleRate;
1157
UNLESS( stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ), paInsufficientMemory );
1158
ENSURE_PA( InitializeStream( stream, jackHostApi, inputChannelCount, outputChannelCount ) );
1160
/* the blocking emulation, if necessary */
1161
stream->isBlockingStream = !streamCallback;
1162
if( stream->isBlockingStream )
1164
float latency = 0.001; /* 1ms is the absolute minimum we support */
1165
int minimum_buffer_frames = 0;
1167
if( inputParameters && inputParameters->suggestedLatency > latency )
1168
latency = inputParameters->suggestedLatency;
1169
else if( outputParameters && outputParameters->suggestedLatency > latency )
1170
latency = outputParameters->suggestedLatency;
1172
/* the latency the user asked for indicates the minimum buffer size in frames */
1173
minimum_buffer_frames = (int) (latency * jack_get_sample_rate( jackHostApi->jack_client ));
1175
/* we also need to be able to store at least three full jack buffers to avoid dropouts */
1176
if( jackHostApi->jack_buffer_size * 3 > minimum_buffer_frames )
1177
minimum_buffer_frames = jackHostApi->jack_buffer_size * 3;
1179
/* setup blocking API data structures (FIXME: can fail) */
1180
BlockingBegin( stream, minimum_buffer_frames );
1182
/* install our own callback for the blocking API */
1183
streamCallback = BlockingCallback;
1186
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
1187
&jackHostApi->blockingStreamInterface, streamCallback, userData );
1191
PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
1192
&jackHostApi->callbackStreamInterface, streamCallback, userData );
1195
PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, jackSr );
1197
/* create the JACK ports. We cannot connect them until audio
1198
* processing begins */
1200
/* Register a unique set of ports for this stream
1201
* TODO: Robust allocation of new port names */
1203
ofs = jackHostApi->inputBase;
1204
for( i = 0; i < inputChannelCount; i++ )
1206
snprintf( port_string, jack_port_name_size(), "in_%lu", ofs + i );
1207
UNLESS( stream->local_input_ports[i] = jack_port_register(
1208
jackHostApi->jack_client, port_string,
1209
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ), paInsufficientMemory );
1211
jackHostApi->inputBase += inputChannelCount;
1213
ofs = jackHostApi->outputBase;
1214
for( i = 0; i < outputChannelCount; i++ )
1216
snprintf( port_string, jack_port_name_size(), "out_%lu", ofs + i );
1217
UNLESS( stream->local_output_ports[i] = jack_port_register(
1218
jackHostApi->jack_client, port_string,
1219
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ), paInsufficientMemory );
1221
jackHostApi->outputBase += outputChannelCount;
1223
/* look up the jack_port_t's for the remote ports. We could do
1224
* this at stream start time, but doing it here ensures the
1225
* name lookup only happens once. */
1227
if( inputChannelCount > 0 )
1231
/* Get output ports of our capture device */
1232
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
1233
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1234
NULL, JackPortIsOutput ), paUnanticipatedHostError );
1235
for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
1237
if( (stream->remote_output_ports[i] = jack_port_by_name(
1238
jackHostApi->jack_client, jack_ports[i] )) == NULL )
1245
UNLESS( !err, paInsufficientMemory );
1247
/* Fewer ports than expected? */
1248
UNLESS( i == inputChannelCount, paInternalError );
1251
if( outputChannelCount > 0 )
1255
/* Get input ports of our playback device */
1256
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
1257
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1258
NULL, JackPortIsInput ), paUnanticipatedHostError );
1259
for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )
1261
if( (stream->remote_input_ports[i] = jack_port_by_name(
1262
jackHostApi->jack_client, jack_ports[i] )) == 0 )
1269
UNLESS( !err , paInsufficientMemory );
1271
/* Fewer ports than expected? */
1272
UNLESS( i == outputChannelCount, paInternalError );
1275
ENSURE_PA( PaUtil_InitializeBufferProcessor(
1276
&stream->bufferProcessor,
1279
paFloat32, /* hostInputSampleFormat */
1282
paFloat32, /* hostOutputSampleFormat */
1287
paUtilUnknownHostBufferSize, /* Buffer size may vary on JACK's discretion */
1292
if( stream->num_incoming_connections > 0 )
1293
stream->streamRepresentation.streamInfo.inputLatency = (jack_port_get_latency( stream->remote_output_ports[0] )
1294
- jack_get_buffer_size( jackHostApi->jack_client ) /* One buffer is not counted as latency */
1295
+ PaUtil_GetBufferProcessorInputLatency( &stream->bufferProcessor )) / sampleRate;
1296
if( stream->num_outgoing_connections > 0 )
1297
stream->streamRepresentation.streamInfo.outputLatency = (jack_port_get_latency( stream->remote_input_ports[0] )
1298
- jack_get_buffer_size( jackHostApi->jack_client ) /* One buffer is not counted as latency */
1299
+ PaUtil_GetBufferProcessorOutputLatency( &stream->bufferProcessor )) / sampleRate;
1301
stream->streamRepresentation.streamInfo.sampleRate = jackSr;
1302
stream->t0 = jack_frame_time( jackHostApi->jack_client ); /* A: Time should run from Pa_OpenStream */
1304
/* Add to queue of opened streams */
1305
ENSURE_PA( AddStream( stream ) );
1307
*s = (PaStream*)stream;
1313
CleanUpStream( stream, srInitialized, bpInitialized );
1319
When CloseStream() is called, the multi-api layer ensures that
1320
the stream has already been stopped or aborted.
1322
static PaError CloseStream( PaStream* s )
1324
PaError result = paNoError;
1325
PaJackStream *stream = (PaJackStream*)s;
1327
/* Remove this stream from the processing queue */
1328
ENSURE_PA( RemoveStream( stream ) );
1331
CleanUpStream( stream, 1, 1 );
1335
static PaError RealProcess( PaJackStream *stream, jack_nframes_t frames )
1337
PaError result = paNoError;
1338
PaStreamCallbackTimeInfo timeInfo = {0,0,0};
1340
int framesProcessed;
1341
const double sr = jack_get_sample_rate( stream->jack_client ); /* Shouldn't change during the process callback */
1342
PaStreamCallbackFlags cbFlags = 0;
1344
/* If the user has returned !paContinue from the callback we'll want to flush the internal buffers,
1345
* when these are empty we can finally mark the stream as inactive */
1346
if( stream->callbackResult != paContinue &&
1347
PaUtil_IsBufferProcessorOutputEmpty( &stream->bufferProcessor ) )
1349
stream->is_active = 0;
1350
if( stream->streamRepresentation.streamFinishedCallback )
1351
stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
1352
PA_DEBUG(( "%s: Callback finished\n", __FUNCTION__ ));
1357
timeInfo.currentTime = (jack_frame_time( stream->jack_client ) - stream->t0) / sr;
1358
if( stream->num_incoming_connections > 0 )
1359
timeInfo.inputBufferAdcTime = timeInfo.currentTime - jack_port_get_latency( stream->remote_output_ports[0] )
1361
if( stream->num_outgoing_connections > 0 )
1362
timeInfo.outputBufferDacTime = timeInfo.currentTime + jack_port_get_latency( stream->remote_input_ports[0] )
1365
PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
1369
/* XXX: Any way to tell which of these occurred? */
1370
cbFlags = paOutputUnderflow | paInputOverflow;
1371
stream->xrun = FALSE;
1373
PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,
1376
if( stream->num_incoming_connections > 0 )
1377
PaUtil_SetInputFrameCount( &stream->bufferProcessor, frames );
1378
if( stream->num_outgoing_connections > 0 )
1379
PaUtil_SetOutputFrameCount( &stream->bufferProcessor, frames );
1381
for( chn = 0; chn < stream->num_incoming_connections; chn++ )
1383
jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
1384
jack_port_get_buffer( stream->local_input_ports[chn],
1387
PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor,
1392
for( chn = 0; chn < stream->num_outgoing_connections; chn++ )
1394
jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
1395
jack_port_get_buffer( stream->local_output_ports[chn],
1398
PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor,
1403
framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,
1404
&stream->callbackResult );
1405
/* We've specified a host buffer size mode where every frame should be consumed by the buffer processor */
1406
assert( framesProcessed == frames );
1408
PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
1414
/* Update the JACK callback's stream processing queue. */
1415
static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
1417
PaError result = paNoError;
1418
int queueModified = 0;
1419
const double jackSr = jack_get_sample_rate( hostApi->jack_client );
1422
if( (err = pthread_mutex_trylock( &hostApi->mtx )) != 0 )
1424
assert( err == EBUSY );
1428
if( hostApi->toAdd )
1430
if( hostApi->processQueue )
1432
PaJackStream *node = hostApi->processQueue;
1433
/* Advance to end of queue */
1437
node->next = hostApi->toAdd;
1441
/* The only queue entry. */
1442
hostApi->processQueue = (PaJackStream *)hostApi->toAdd;
1445
/* If necessary, update stream state */
1446
if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr )
1447
UpdateSampleRate( hostApi->toAdd, jackSr );
1449
hostApi->toAdd = NULL;
1452
if( hostApi->toRemove )
1455
PaJackStream *node = hostApi->processQueue, *prev = NULL;
1456
assert( hostApi->processQueue );
1460
if( node == hostApi->toRemove )
1463
prev->next = node->next;
1465
hostApi->processQueue = (PaJackStream *)node->next;
1474
UNLESS( removed, paInternalError );
1475
hostApi->toRemove = NULL;
1476
PA_DEBUG(( "%s: Removed stream from processing queue\n", __FUNCTION__ ));
1482
/* Signal that we've done what was asked of us */
1483
ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 );
1487
ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1492
/* Audio processing callback invoked periodically from JACK. */
1493
static int JackCallback( jack_nframes_t frames, void *userData )
1495
PaError result = paNoError;
1496
PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)userData;
1497
PaJackStream *stream = NULL;
1498
int xrun = hostApi->xrun;
1503
ENSURE_PA( UpdateQueue( hostApi ) );
1505
/* Process each stream */
1506
stream = hostApi->processQueue;
1507
for( ; stream; stream = stream->next )
1509
if( xrun ) /* Don't override if already set */
1512
/* See if this stream is to be started */
1513
if( stream->doStart )
1515
/* If we can't obtain a lock, we'll try next time */
1516
int err = pthread_mutex_trylock( &stream->hostApi->mtx );
1519
if( stream->doStart ) /* Could potentially change before obtaining the lock */
1521
stream->is_active = 1;
1522
stream->doStart = 0;
1523
PA_DEBUG(( "%s: Starting stream\n", __FUNCTION__ ));
1524
ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
1525
stream->callbackResult = paContinue;
1526
stream->isSilenced = 0;
1529
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1532
assert( err == EBUSY );
1534
else if( stream->doStop || stream->doAbort ) /* Should we stop/abort stream? */
1536
if( stream->callbackResult == paContinue ) /* Ok, make it stop */
1538
PA_DEBUG(( "%s: Stopping stream\n", __FUNCTION__ ));
1539
stream->callbackResult = stream->doStop ? paComplete : paAbort;
1543
if( stream->is_active )
1544
ENSURE_PA( RealProcess( stream, frames ) );
1545
/* If we have just entered inactive state, silence output */
1546
if( !stream->is_active && !stream->isSilenced )
1550
/* Silence buffer after entering inactive state */
1551
PA_DEBUG(( "Silencing the output\n" ));
1552
for( i = 0; i < stream->num_outgoing_connections; ++i )
1554
jack_default_audio_sample_t *buffer = jack_port_get_buffer( stream->local_output_ports[i], frames );
1555
memset( buffer, 0, sizeof (jack_default_audio_sample_t) * frames );
1558
stream->isSilenced = 1;
1561
if( stream->doStop || stream->doAbort )
1563
/* See if RealProcess has acted on the request */
1564
if( !stream->is_active ) /* Ok, signal to the main thread that we've carried out the operation */
1566
/* If we can't obtain a lock, we'll try next time */
1567
int err = pthread_mutex_trylock( &stream->hostApi->mtx );
1570
stream->doStop = stream->doAbort = 0;
1571
ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
1572
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1575
assert( err == EBUSY );
1585
static PaError StartStream( PaStream *s )
1587
PaError result = paNoError;
1588
PaJackStream *stream = (PaJackStream*)s;
1591
/* Ready the processor */
1592
PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
1594
/* Connect the ports. Note that the ports may already have been connected by someone else in
1595
* the meantime, in which case JACK returns EEXIST. */
1597
if( stream->num_incoming_connections > 0 )
1599
for( i = 0; i < stream->num_incoming_connections; i++ )
1601
int r = jack_connect( stream->jack_client, jack_port_name( stream->remote_output_ports[i] ),
1602
jack_port_name( stream->local_input_ports[i] ) );
1603
UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
1607
if( stream->num_outgoing_connections > 0 )
1609
for( i = 0; i < stream->num_outgoing_connections; i++ )
1611
int r = jack_connect( stream->jack_client, jack_port_name( stream->local_output_ports[i] ),
1612
jack_port_name( stream->remote_input_ports[i] ) );
1613
UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
1617
stream->xrun = FALSE;
1619
/* Enable processing */
1621
ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
1622
stream->doStart = 1;
1624
/* Wait for stream to be started */
1625
result = WaitCondition( stream->hostApi );
1629
err = pthread_cond_timedwait( &stream->hostApi->cond, &stream->hostApi->mtx, &ts );
1630
} while( !stream->is_active && !err );
1632
if( result != paNoError ) /* Something went wrong, call off the stream start */
1634
stream->doStart = 0;
1635
stream->is_active = 0; /* Cancel any processing */
1637
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1639
ENSURE_PA( result );
1641
stream->is_running = TRUE;
1642
PA_DEBUG(( "%s: Stream started\n", __FUNCTION__ ));
1648
static PaError RealStop( PaJackStream *stream, int abort )
1650
PaError result = paNoError;
1653
if( stream->isBlockingStream )
1654
BlockingWaitEmpty ( stream );
1656
ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
1658
stream->doAbort = 1;
1662
/* Wait for stream to be stopped */
1663
result = WaitCondition( stream->hostApi );
1664
ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1665
ENSURE_PA( result );
1667
UNLESS( !stream->is_active, paInternalError );
1669
PA_DEBUG(( "%s: Stream stopped\n", __FUNCTION__ ));
1672
stream->is_running = FALSE;
1674
/* Disconnect ports belonging to this stream */
1676
if( !stream->hostApi->jackIsDown ) /* XXX: Well? */
1678
for( i = 0; i < stream->num_incoming_connections; i++ )
1680
if( jack_port_connected( stream->local_input_ports[i] ) )
1682
UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ),
1683
paUnanticipatedHostError );
1686
for( i = 0; i < stream->num_outgoing_connections; i++ )
1688
if( jack_port_connected( stream->local_output_ports[i] ) )
1690
UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ),
1691
paUnanticipatedHostError );
1699
static PaError StopStream( PaStream *s )
1702
return RealStop( (PaJackStream *)s, 0 );
1705
static PaError AbortStream( PaStream *s )
1708
return RealStop( (PaJackStream *)s, 1 );
1711
static PaError IsStreamStopped( PaStream *s )
1713
PaJackStream *stream = (PaJackStream*)s;
1714
return !stream->is_running;
1718
static PaError IsStreamActive( PaStream *s )
1720
PaJackStream *stream = (PaJackStream*)s;
1721
return stream->is_active;
1725
static PaTime GetStreamTime( PaStream *s )
1727
PaJackStream *stream = (PaJackStream*)s;
1729
/* A: Is this relevant?? --> TODO: what if we're recording-only? */
1730
return (jack_frame_time( stream->jack_client ) - stream->t0) / (PaTime)jack_get_sample_rate( stream->jack_client );
1734
static double GetStreamCpuLoad( PaStream* s )
1736
PaJackStream *stream = (PaJackStream*)s;
1737
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
1740
PaError PaJack_SetClientName( const char* name )
1742
if( strlen( name ) > jack_client_name_size() )
1744
/* OK, I don't know any better error code */
1745
return paInvalidFlag;
1751
PaError PaJack_GetClientName(const char** clientName)
1753
PaError result = paNoError;
1754
PaJackHostApiRepresentation* jackHostApi = NULL;
1755
PaJackHostApiRepresentation** ref = &jackHostApi;
1756
ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)ref, paJACK ) );
1757
*clientName = jack_get_client_name( jackHostApi->jack_client );