2
* $Id: pa_jack.c,v 1.3 2006/09/29 00:09:54 llucius Exp $
2
* $Id: pa_jack.c,v 1.6 2007/08/16 20:45:36 richardash1981 Exp $
3
3
* PortAudio Portable Real-Time Audio Library
4
4
* Latest Version at: http://www.portaudio.com
5
5
* JACK Implementation by Joshua Haberman
35
* The text above constitutes the entire PortAudio license; however,
35
* The text above constitutes the entire PortAudio license; however,
36
36
* the PortAudio community also makes the following non-binding requests:
38
38
* Any person wishing to distribute modifications to the Software is
39
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
40
* they can be incorporated into the canonical version. It is also
41
* requested that these non-binding requests be included along with the
50
50
#include <string.h>
68
68
#include "pa_process.h"
69
69
#include "pa_allocation.h"
70
70
#include "pa_cpuload.h"
71
#include "../pablio/ringbuffer.c"
71
#include "pa_ringbuffer.h"
72
#include "pa_debugprint.h"
74
75
static PaError paErr_; /* For use with ENSURE_PA */
75
76
static pthread_t mainThread_;
76
77
static char *jackErr_ = NULL;
78
static const char* clientName_ = "PortAudio";
78
80
#define STRINGIZE_HELPER(expr) #expr
79
81
#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
86
88
if( (paErr_) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
90
if (! jackErr_ ) jackErr_ = "unknown error";\
89
91
PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
91
93
PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
101
103
if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
103
assert( jackErr_ ); \
105
if (!jackErr_) jackErr_ = "unknown error";\
104
106
PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
106
108
PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
246
248
/* ---- blocking emulation layer ---- */
248
250
/* Allocate buffer. */
249
static PaError BlockingInitFIFO( RingBuffer *rbuf, long numFrames, long bytesPerFrame )
251
static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long bytesPerFrame )
251
253
long numBytes = numFrames * bytesPerFrame;
252
254
char *buffer = (char *) malloc( numBytes );
253
255
if( buffer == NULL ) return paInsufficientMemory;
254
256
memset( buffer, 0, numBytes );
255
return (PaError) RingBuffer_Init( rbuf, numBytes, buffer );
257
return (PaError) PaUtil_InitializeRingBuffer( rbuf, numBytes, buffer );
258
260
/* Free buffer. */
259
static PaError BlockingTermFIFO( RingBuffer *rbuf )
261
static PaError BlockingTermFIFO( PaUtilRingBuffer *rbuf )
261
263
if( rbuf->buffer ) free( rbuf->buffer );
262
264
rbuf->buffer = NULL;
277
279
/* This may get called with NULL inputBuffer during initial setup. */
278
280
if( inputBuffer != NULL )
280
RingBuffer_Write( &stream->inFIFO, inputBuffer, numBytes );
282
PaUtil_WriteRingBuffer( &stream->inFIFO, inputBuffer, numBytes );
282
284
if( outputBuffer != NULL )
284
int numRead = RingBuffer_Read( &stream->outFIFO, outputBuffer, numBytes );
286
int numRead = PaUtil_ReadRingBuffer( &stream->outFIFO, outputBuffer, numBytes );
285
287
/* Zero out remainder of buffer if we run out of data. */
286
288
memset( (char *)outputBuffer + numRead, 0, numBytes - numRead );
323
325
ENSURE_PA( BlockingInitFIFO( &stream->outFIFO, numFrames, stream->bytesPerFrame ) );
325
327
/* Make Write FIFO appear full initially. */
326
numBytes = RingBuffer_GetWriteAvailable( &stream->outFIFO );
327
RingBuffer_AdvanceWriteIndex( &stream->outFIFO, numBytes );
328
numBytes = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
329
PaUtil_AdvanceRingBufferWriteIndex( &stream->outFIFO, numBytes );
330
332
stream->data_available = 0;
353
355
long numBytes = stream->bytesPerFrame * numFrames;
354
356
while( numBytes > 0 )
356
bytesRead = RingBuffer_Read( &stream->inFIFO, p, numBytes );
358
bytesRead = PaUtil_ReadRingBuffer( &stream->inFIFO, p, numBytes );
357
359
numBytes -= bytesRead;
359
361
if( numBytes > 0 )
378
380
long numBytes = stream->bytesPerFrame * numFrames;
379
381
while( numBytes > 0 )
381
bytesWritten = RingBuffer_Write( &stream->outFIFO, p, numBytes );
383
bytesWritten = PaUtil_WriteRingBuffer( &stream->outFIFO, p, numBytes );
382
384
numBytes -= bytesWritten;
383
385
p += bytesWritten;
386
/* we use the following algorithm:
388
/* we use the following algorithm:
388
390
* (2) if some data didn't fit into the ringbuffer, set data_available to 0
389
391
* to indicate to the audio that if space becomes available, we want to know
413
415
PaJackStream *stream = (PaJackStream *)s;
415
int bytesFull = RingBuffer_GetReadAvailable( &stream->inFIFO );
417
int bytesFull = PaUtil_GetRingBufferReadAvailable( &stream->inFIFO );
416
418
return bytesFull / stream->bytesPerFrame;
422
424
PaJackStream *stream = (PaJackStream *)s;
424
int bytesEmpty = RingBuffer_GetWriteAvailable( &stream->outFIFO );
426
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
425
427
return bytesEmpty / stream->bytesPerFrame;
431
433
PaJackStream *stream = (PaJackStream *)s;
433
while( RingBuffer_GetReadAvailable( &stream->outFIFO ) > 0 )
435
while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
435
437
stream->data_available = 0;
436
438
sem_wait( &stream->data_semaphore );
452
454
/* Utility macros for the repetitive process of allocating memory */
454
/* ... MALLOC: allocate memory as part of the device list
455
* allocation group */
456
#define MALLOC(size) \
457
(PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, (size) ))
459
456
/* JACK has no concept of a device. To JACK, there are clients
460
457
* which have an arbitrary number of ports. To make this
461
458
* intelligible to PortAudio clients, we will group each JACK client
484
481
* associated with the previous list */
485
482
PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
487
regex_pattern = MALLOC( jack_client_name_size() + 3 );
488
tmp_client_name = MALLOC( jack_client_name_size() );
484
regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
485
tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
490
487
/* We can only retrieve the list of clients indirectly, by first
491
488
* asking for a list of all ports, then parsing the port names
497
494
while( jack_ports[numPorts] )
499
496
/* At least there will be one port per client :) */
500
UNLESS( client_names = MALLOC( numPorts * sizeof (char *) ), paInsufficientMemory );
497
UNLESS( client_names = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, numPorts *
498
sizeof (char *) ), paInsufficientMemory );
502
500
/* Build a list of clients from the list of ports */
503
501
for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
525
523
continue; /* A: Nothing to see here, move along */
527
UNLESS( client_names[numClients] = (char*)MALLOC(strlen(tmp_client_name) + 1), paInsufficientMemory );
525
UNLESS( client_names[numClients] = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
526
strlen(tmp_client_name) + 1), paInsufficientMemory );
529
528
/* The alsa_pcm client should go in spot 0. If this
530
529
* is the alsa_pcm client AND we are NOT about to put
550
549
/* there is one global sample rate all clients must conform to */
552
551
globalSampleRate = jack_get_sample_rate( jackApi->jack_client );
553
UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)MALLOC( sizeof(PaDeviceInfo*) *
554
numClients ), paInsufficientMemory );
552
UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
553
sizeof(PaDeviceInfo*) * numClients ), paInsufficientMemory );
556
555
assert( commonApi->info.deviceCount == 0 );
561
560
PaDeviceInfo *curDevInfo;
562
561
const char **clientPorts = NULL;
564
UNLESS( curDevInfo = (PaDeviceInfo*)MALLOC( sizeof(PaDeviceInfo) ), paInsufficientMemory );
565
UNLESS( curDevInfo->name = (char*)MALLOC( strlen(client_names[client_index]) + 1 ), paInsufficientMemory );
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 );
566
567
strcpy( (char *)curDevInfo->name, client_names[client_index] );
568
569
curDevInfo->structVersion = 2;
647
647
if( pthread_self() == mainThread_ )
651
jackErr_ = malloc( strlen( msg ) );
652
sprintf( jackErr_, msg );
650
jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
651
strcpy( jackErr_, msg );
706
705
PaError result = paNoError;
707
706
PaJackHostApiRepresentation *jackHostApi;
708
707
int activated = 0;
708
jack_status_t jackStatus = 0;
711
709
*hostApi = NULL; /* Initialize to NULL */
713
711
UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
721
719
/* Try to become a client of the JACK server. If we cannot do
722
720
* this, then this API cannot be used. */
724
clientName = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_client_name_size() );
725
written = snprintf( clientName, jack_client_name_size(), "PortAudio-%d", getpid() );
726
assert( written < jack_client_name_size() );
727
jackHostApi->jack_client = jack_client_new( clientName );
728
if( jackHostApi->jack_client == NULL )
722
jackHostApi->jack_client = jack_client_open( clientName_, 0, &jackStatus );
723
if( !jackHostApi->jack_client )
730
/* the V19 development docs say that if an implementation
731
* detects that it cannot be used, it should return a NULL
732
* interface and paNoError */
725
/* the V19 development docs say that if an implementation
726
* detects that it cannot be used, it should return a NULL
727
* interface and paNoError */
737
732
jackHostApi->hostApiIndex = hostApiIndex;
775
770
jack_on_shutdown( jackHostApi->jack_client, JackOnShutdown, jackHostApi );
776
771
jack_set_error_function( JackErrorCallback );
777
772
jackHostApi->jack_buffer_size = jack_get_buffer_size ( jackHostApi->jack_client );
778
UNLESS( !jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi ), paUnanticipatedHostError );
773
/* Don't check for error, may not be supported (deprecated in at least jackdmp) */
774
jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi );
779
775
UNLESS( !jack_set_xrun_callback( jackHostApi->jack_client, JackXRunCb, jackHostApi ), paUnanticipatedHostError );
780
776
UNLESS( !jack_set_process_callback( jackHostApi->jack_client, JackCallback, jackHostApi ), paUnanticipatedHostError );
781
777
UNLESS( !jack_activate( jackHostApi->jack_client ), paUnanticipatedHostError );
894
890
Because the buffer adapter handles conversion between all standard
895
891
sample formats, the following checks are only required if paCustomFormat
896
892
is implemented, or under some other unusual conditions.
898
894
- check that input device can support inputSampleFormat, or that
899
895
we have the capability to convert from outputSampleFormat to
907
903
/* check that the device supports sampleRate */
909
905
#define ABS(x) ( (x) > 0 ? (x) : -(x) )
910
906
if( ABS(sampleRate - jack_get_sample_rate(((PaJackHostApiRepresentation *) hostApi)->jack_client )) > 1 )
911
907
return paInvalidSampleRate;
1058
/* Add stream to processing queue */
1054
/* Add stream to JACK callback processing queue */
1059
1055
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
1061
1057
const PaStreamParameters *inputParameters,
1227
1223
if( inputChannelCount > 0 )
1231
/* ... remote output ports (that we input from) */
1227
/* Get output ports of our capture device */
1232
1228
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
1233
1229
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1234
1230
NULL, JackPortIsOutput ), paUnanticipatedHostError );
1235
1231
for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
1237
1233
if( (stream->remote_output_ports[i] = jack_port_by_name(
1238
jackHostApi->jack_client, jack_ports[i] )) == NULL )
1234
jackHostApi->jack_client, jack_ports[i] )) == NULL )
1255
/* ... remote input ports (that we output to) */
1251
/* Get input ports of our playback device */
1256
1252
snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
1257
1253
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1258
1254
NULL, JackPortIsInput ), paUnanticipatedHostError );
1301
1297
stream->streamRepresentation.streamInfo.sampleRate = jackSr;
1302
1298
stream->t0 = jack_frame_time( jackHostApi->jack_client ); /* A: Time should run from Pa_OpenStream */
1304
ENSURE_PA( AddStream( stream ) ); /* Add to queue over opened streams */
1300
/* Add to queue of opened streams */
1301
ENSURE_PA( AddStream( stream ) );
1306
1303
*s = (PaStream*)stream;
1436
1433
node->next = hostApi->toAdd;
1437
/* The only queue entry. */
1439
1438
hostApi->processQueue = (PaJackStream *)hostApi->toAdd;
1441
1441
/* If necessary, update stream state */
1442
1442
if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr )
1586
1587
/* Ready the processor */
1587
1588
PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
1589
/* connect the ports */
1590
/* Connect the ports. Note that the ports may already have been connected by someone else in
1591
* the meantime, in which case JACK returns EEXIST. */
1591
/* NOTE: I would rather use jack_port_connect which uses jack_port_t's
1592
* instead of port names, but it is not implemented yet. */
1593
1593
if( stream->num_incoming_connections > 0 )
1595
1595
for( i = 0; i < stream->num_incoming_connections; i++ )
1596
UNLESS( jack_connect( stream->jack_client,
1597
jack_port_name( stream->remote_output_ports[i] ),
1598
jack_port_name( stream->local_input_ports[i] ) ) == 0, paUnanticipatedHostError );
1597
int r = jack_connect( stream->jack_client, jack_port_name( stream->remote_output_ports[i] ),
1598
jack_port_name( stream->local_input_ports[i] ) );
1599
UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
1601
1603
if( stream->num_outgoing_connections > 0 )
1603
1605
for( i = 0; i < stream->num_outgoing_connections; i++ )
1604
UNLESS( jack_connect( stream->jack_client,
1605
jack_port_name( stream->local_output_ports[i] ),
1606
jack_port_name( stream->remote_input_ports[i] ) ) == 0, paUnanticipatedHostError );
1607
int r = jack_connect( stream->jack_client, jack_port_name( stream->local_output_ports[i] ),
1608
jack_port_name( stream->remote_input_ports[i] ) );
1609
UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
1609
1613
stream->xrun = FALSE;
1670
1674
for( i = 0; i < stream->num_incoming_connections; i++ )
1672
UNLESS( !jack_port_lock( stream->jack_client, stream->local_input_ports[i] ),
1673
paUnanticipatedHostError );
1674
1676
if( jack_port_connected( stream->local_input_ports[i] ) )
1676
1678
UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ),
1677
1679
paUnanticipatedHostError );
1679
UNLESS( !jack_port_unlock( stream->jack_client, stream->local_input_ports[i] ),
1680
paUnanticipatedHostError );
1682
1682
for( i = 0; i < stream->num_outgoing_connections; i++ )
1684
UNLESS( !jack_port_lock( stream->jack_client, stream->local_output_ports[i] ),
1685
paUnanticipatedHostError );
1686
1684
if( jack_port_connected( stream->local_output_ports[i] ) )
1688
1686
UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ),
1689
1687
paUnanticipatedHostError );
1691
UNLESS( !jack_port_unlock( stream->jack_client, stream->local_output_ports[i] ),
1692
paUnanticipatedHostError );
1736
1732
PaJackStream *stream = (PaJackStream*)s;
1737
1733
return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
1736
PaError PaJack_SetClientName( const char* name )
1738
if( strlen( name ) > jack_client_name_size() )
1740
/* OK, I don't know any better error code */
1741
return paInvalidFlag;
1747
PaError PaJack_GetClientName(const char** clientName)
1749
PaError result = paNoError;
1750
PaJackHostApiRepresentation* jackHostApi = NULL;
1751
ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)&jackHostApi, paJACK ) );
1752
*clientName = jack_get_client_name( jackHostApi->jack_client );