/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/portaudio/src/hostapi/jack/pa_jack.c
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/portaudio/src/hostapi/jack/pa_jack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (10 years, 10 months ago) by william
File MIME type: text/plain
File size: 62992 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 /*
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
6 *
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>
10 *
11 * Based on the Open Source API proposed by Ross Bencina
12 * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
13 *
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:
21 *
22 * The above copyright notice and this permission notice shall be
23 * included in all copies or substantial portions of the Software.
24 *
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.
32 */
33
34 /*
35 * The text above constitutes the entire PortAudio license; however,
36 * the PortAudio community also makes the following non-binding requests:
37 *
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
42 * license above.
43 */
44
45 /**
46 @file
47 @ingroup hostapi_src
48 */
49
50 #include <string.h>
51 #include <regex.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <assert.h>
55 #include <sys/types.h>
56 #include <unistd.h>
57 #include <errno.h> /* EBUSY */
58 #include <signal.h> /* sig_atomic_t */
59 #include <math.h>
60 #include <semaphore.h>
61
62 #include <jack/types.h>
63 #include <jack/jack.h>
64
65 #include "pa_util.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"
73
74 static int aErr_;
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";
79
80 #define STRINGIZE_HELPER(expr) #expr
81 #define STRINGIZE(expr) STRINGIZE_HELPER(expr)
82
83 /* Check PaError */
84 #define ENSURE_PA(expr) \
85 do { \
86 if( (paErr_ = (expr)) < paNoError ) \
87 { \
88 if( (paErr_) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
89 { \
90 if (! jackErr_ ) jackErr_ = "unknown error";\
91 PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
92 } \
93 PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
94 result = paErr_; \
95 goto error; \
96 } \
97 } while( 0 )
98
99 #define UNLESS(expr, code) \
100 do { \
101 if( (expr) == 0 ) \
102 { \
103 if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
104 { \
105 if (!jackErr_) jackErr_ = "unknown error";\
106 PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
107 } \
108 PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
109 result = (code); \
110 goto error; \
111 } \
112 } while( 0 )
113
114 #define ASSERT_CALL(expr, success) \
115 aErr_ = (expr); \
116 assert( aErr_ == success );
117
118 /*
119 * Functions that directly map to the PortAudio stream interface
120 */
121
122 static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
123 static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
124 const PaStreamParameters *inputParameters,
125 const PaStreamParameters *outputParameters,
126 double sampleRate );
127 static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
128 PaStream** s,
129 const PaStreamParameters *inputParameters,
130 const PaStreamParameters *outputParameters,
131 double sampleRate,
132 unsigned long framesPerBuffer,
133 PaStreamFlags streamFlags,
134 PaStreamCallback *streamCallback,
135 void *userData );
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 );
146
147
148 /*
149 * Data specific to this API
150 */
151
152 struct PaJackStream;
153
154 typedef struct
155 {
156 PaUtilHostApiRepresentation commonHostApiRep;
157 PaUtilStreamInterface callbackStreamInterface;
158 PaUtilStreamInterface blockingStreamInterface;
159
160 PaUtilAllocationGroup *deviceInfoMemory;
161
162 jack_client_t *jack_client;
163 int jack_buffer_size;
164 PaHostApiIndex hostApiIndex;
165
166 pthread_mutex_t mtx;
167 pthread_cond_t cond;
168 unsigned long inputBase, outputBase;
169
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;
175 }
176 PaJackHostApiRepresentation;
177
178 /* PaJackStream - a stream data structure specifically for this implementation */
179
180 typedef struct PaJackStream
181 {
182 PaUtilStreamRepresentation streamRepresentation;
183 PaUtilBufferProcessor bufferProcessor;
184 PaUtilCpuLoadMeasurer cpuLoadMeasurer;
185 PaJackHostApiRepresentation *hostApi;
186
187 /* our input and output ports */
188 jack_port_t **local_input_ports;
189 jack_port_t **local_output_ports;
190
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;
194
195 int num_incoming_connections;
196 int num_outgoing_connections;
197
198 jack_client_t *jack_client;
199
200 /* The stream is running if it's still producing samples.
201 * The stream is active if samples it produced are still being heard.
202 */
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;
207
208 jack_nframes_t t0;
209
210 PaUtilAllocationGroup *stream_memory;
211
212 /* These are useful in the process callback */
213
214 int callbackResult;
215 int isSilenced;
216 int xrun;
217
218 /* These are useful for the blocking API */
219
220 int isBlockingStream;
221 PaUtilRingBuffer inFIFO;
222 PaUtilRingBuffer outFIFO;
223 volatile sig_atomic_t data_available;
224 sem_t data_semaphore;
225 int bytesPerFrame;
226 int samplesPerFrame;
227
228 struct PaJackStream *next;
229 }
230 PaJackStream;
231
232 #define TRUE 1
233 #define FALSE 0
234
235 /*
236 * Functions specific to this API
237 */
238
239 static int JackCallback( jack_nframes_t frames, void *userData );
240
241
242 /*
243 *
244 * Implementation
245 *
246 */
247
248 /* ---- blocking emulation layer ---- */
249
250 /* Allocate buffer. */
251 static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long bytesPerFrame )
252 {
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 );
258 }
259
260 /* Free buffer. */
261 static PaError BlockingTermFIFO( PaUtilRingBuffer *rbuf )
262 {
263 if( rbuf->buffer ) free( rbuf->buffer );
264 rbuf->buffer = NULL;
265 return paNoError;
266 }
267
268 static int
269 BlockingCallback( const void *inputBuffer,
270 void *outputBuffer,
271 unsigned long framesPerBuffer,
272 const PaStreamCallbackTimeInfo* timeInfo,
273 PaStreamCallbackFlags statusFlags,
274 void *userData )
275 {
276 struct PaJackStream *stream = (PaJackStream *)userData;
277 long numBytes = stream->bytesPerFrame * framesPerBuffer;
278
279 /* This may get called with NULL inputBuffer during initial setup. */
280 if( inputBuffer != NULL )
281 {
282 PaUtil_WriteRingBuffer( &stream->inFIFO, inputBuffer, numBytes );
283 }
284 if( outputBuffer != NULL )
285 {
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 );
289 }
290
291 if( !stream->data_available )
292 {
293 stream->data_available = 1;
294 sem_post( &stream->data_semaphore );
295 }
296 return paContinue;
297 }
298
299 static PaError
300 BlockingBegin( PaJackStream *stream, int minimum_buffer_size )
301 {
302 long doRead = 0;
303 long doWrite = 0;
304 PaError result = paNoError;
305 long numFrames;
306
307 doRead = stream->local_input_ports != NULL;
308 doWrite = stream->local_output_ports != NULL;
309 /* <FIXME> */
310 stream->samplesPerFrame = 2;
311 stream->bytesPerFrame = sizeof(float) * stream->samplesPerFrame;
312 /* </FIXME> */
313 numFrames = 32;
314 while (numFrames < minimum_buffer_size)
315 numFrames *= 2;
316
317 if( doRead )
318 {
319 ENSURE_PA( BlockingInitFIFO( &stream->inFIFO, numFrames, stream->bytesPerFrame ) );
320 }
321 if( doWrite )
322 {
323 long numBytes;
324
325 ENSURE_PA( BlockingInitFIFO( &stream->outFIFO, numFrames, stream->bytesPerFrame ) );
326
327 /* Make Write FIFO appear full initially. */
328 numBytes = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
329 PaUtil_AdvanceRingBufferWriteIndex( &stream->outFIFO, numBytes );
330 }
331
332 stream->data_available = 0;
333 sem_init( &stream->data_semaphore, 0, 0 );
334
335 error:
336 return result;
337 }
338
339 static void
340 BlockingEnd( PaJackStream *stream )
341 {
342 BlockingTermFIFO( &stream->inFIFO );
343 BlockingTermFIFO( &stream->outFIFO );
344
345 sem_destroy( &stream->data_semaphore );
346 }
347
348 static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames )
349 {
350 PaError result = paNoError;
351 PaJackStream *stream = (PaJackStream *)s;
352
353 long bytesRead;
354 char *p = (char *) data;
355 long numBytes = stream->bytesPerFrame * numFrames;
356 while( numBytes > 0 )
357 {
358 bytesRead = PaUtil_ReadRingBuffer( &stream->inFIFO, p, numBytes );
359 numBytes -= bytesRead;
360 p += bytesRead;
361 if( numBytes > 0 )
362 {
363 /* see write for an explanation */
364 if( stream->data_available )
365 stream->data_available = 0;
366 else
367 sem_wait( &stream->data_semaphore );
368 }
369 }
370
371 return result;
372 }
373
374 static PaError BlockingWriteStream( PaStream* s, const void *data, unsigned long numFrames )
375 {
376 PaError result = paNoError;
377 PaJackStream *stream = (PaJackStream *)s;
378 long bytesWritten;
379 char *p = (char *) data;
380 long numBytes = stream->bytesPerFrame * numFrames;
381 while( numBytes > 0 )
382 {
383 bytesWritten = PaUtil_WriteRingBuffer( &stream->outFIFO, p, numBytes );
384 numBytes -= bytesWritten;
385 p += bytesWritten;
386 if( numBytes > 0 )
387 {
388 /* we use the following algorithm:
389 * (1) write data
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
397 *
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
401 */
402 if( stream->data_available )
403 stream->data_available = 0;
404 else
405 sem_wait( &stream->data_semaphore );
406 }
407 }
408
409 return result;
410 }
411
412 static signed long
413 BlockingGetStreamReadAvailable( PaStream* s )
414 {
415 PaJackStream *stream = (PaJackStream *)s;
416
417 int bytesFull = PaUtil_GetRingBufferReadAvailable( &stream->inFIFO );
418 return bytesFull / stream->bytesPerFrame;
419 }
420
421 static signed long
422 BlockingGetStreamWriteAvailable( PaStream* s )
423 {
424 PaJackStream *stream = (PaJackStream *)s;
425
426 int bytesEmpty = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
427 return bytesEmpty / stream->bytesPerFrame;
428 }
429
430 static PaError
431 BlockingWaitEmpty( PaStream *s )
432 {
433 PaJackStream *stream = (PaJackStream *)s;
434
435 while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
436 {
437 stream->data_available = 0;
438 sem_wait( &stream->data_semaphore );
439 }
440 return 0;
441 }
442
443 /* ---- jack driver ---- */
444
445 /* BuildDeviceList():
446 *
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.
450 */
451
452 static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
453 {
454 /* Utility macros for the repetitive process of allocating memory */
455
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 */
460
461 PaError result = paNoError;
462 PaUtilHostApiRepresentation *commonApi = &jackApi->commonHostApiRep;
463
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;
469 regex_t port_regex;
470 unsigned long numClients = 0, numPorts = 0;
471 char *tmp_client_name = NULL;
472
473 commonApi->info.defaultInputDevice = paNoDevice;
474 commonApi->info.defaultOutputDevice = paNoDevice;
475 commonApi->info.deviceCount = 0;
476
477 /* Parse the list of ports, using a regex to grab the client names */
478 ASSERT_CALL( regcomp( &port_regex, "^[^:]*", REG_EXTENDED ), 0 );
479
480 /* since we are rebuilding the list of devices, free all memory
481 * associated with the previous list */
482 PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
483
484 regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
485 tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
486
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
490 * enforced by jackd)
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] )
495 ++numPorts;
496 /* At least there will be one port per client :) */
497 UNLESS( client_names = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, numPorts *
498 sizeof (char *) ), paInsufficientMemory );
499
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++ )
502 {
503 int client_seen = FALSE;
504 regmatch_t match_info;
505 const char *port = jack_ports[port_index];
506
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';
514
515 /* do we know about this port's client yet? */
516 for( i = 0; i < numClients; i++ )
517 {
518 if( strcmp( tmp_client_name, client_names[i] ) == 0 )
519 client_seen = TRUE;
520 }
521
522 if (client_seen)
523 continue; /* A: Nothing to see here, move along */
524
525 UNLESS( client_names[numClients] = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
526 strlen(tmp_client_name) + 1), paInsufficientMemory );
527
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 )
533 {
534 /* alsa_pcm goes in spot 0 */
535 strcpy( client_names[ numClients ], client_names[0] );
536 strcpy( client_names[0], tmp_client_name );
537 }
538 else
539 {
540 /* put the new client at the end of the client list */
541 strcpy( client_names[ numClients ], tmp_client_name );
542 }
543 ++numClients;
544 }
545
546 /* Now we have a list of clients, which will become the list of
547 * PortAudio devices. */
548
549 /* there is one global sample rate all clients must conform to */
550
551 globalSampleRate = jack_get_sample_rate( jackApi->jack_client );
552 UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
553 sizeof(PaDeviceInfo*) * numClients ), paInsufficientMemory );
554
555 assert( commonApi->info.deviceCount == 0 );
556
557 /* Create a PaDeviceInfo structure for every client */
558 for( client_index = 0; client_index < numClients; client_index++ )
559 {
560 PaDeviceInfo *curDevInfo;
561 const char **clientPorts = NULL;
562
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] );
568
569 curDevInfo->structVersion = 2;
570 curDevInfo->hostApi = jackApi->hostApiIndex;
571
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;
575
576 /* To determine how many input and output channels are available,
577 * we re-query jackd with more specific parameters. */
578
579 sprintf( regex_pattern, "%s:.*", client_names[client_index] );
580
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.;
587 if( clientPorts )
588 {
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;
592
593 for( i = 0; clientPorts[i] != NULL; i++)
594 {
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++;
598 }
599 free(clientPorts);
600 }
601
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.;
608 if( clientPorts )
609 {
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;
613
614 for( i = 0; clientPorts[i] != NULL; i++)
615 {
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++;
619 }
620 free(clientPorts);
621 }
622
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;
630 }
631
632 error:
633 regfree( &port_regex );
634 free( jack_ports );
635 return result;
636 }
637
638 static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
639 {
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;
643 }
644
645 static void JackErrorCallback( const char *msg )
646 {
647 if( pthread_self() == mainThread_ )
648 {
649 assert( msg );
650 jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
651 strcpy( jackErr_, msg );
652 }
653 }
654
655 static void JackOnShutdown( void *arg )
656 {
657 PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
658 PaJackStream *stream = jackApi->processQueue;
659
660 PA_DEBUG(( "%s: JACK server is shutting down\n", __FUNCTION__ ));
661 for( ; stream; stream = stream->next )
662 {
663 stream->is_active = 0;
664 }
665
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 );
671
672 }
673
674 static int JackSrCb( jack_nframes_t nframes, void *arg )
675 {
676 PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
677 double sampleRate = (double)nframes;
678 PaJackStream *stream = jackApi->processQueue;
679
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 )
683 {
684 if( stream->streamRepresentation.streamInfo.sampleRate != sampleRate )
685 {
686 PA_DEBUG(( "%s: Updating samplerate\n", __FUNCTION__ ));
687 UpdateSampleRate( stream, sampleRate );
688 }
689 }
690
691 return 0;
692 }
693
694 static int JackXRunCb(void *arg) {
695 PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)arg;
696 assert( hostApi );
697 hostApi->xrun = TRUE;
698 PA_DEBUG(( "%s: JACK signalled xrun\n", __FUNCTION__ ));
699 return 0;
700 }
701
702 PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
703 PaHostApiIndex hostApiIndex )
704 {
705 PaError result = paNoError;
706 PaJackHostApiRepresentation *jackHostApi;
707 int activated = 0;
708 jack_status_t jackStatus = 0;
709 *hostApi = NULL; /* Initialize to NULL */
710
711 UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
712 PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ), paInsufficientMemory );
713 UNLESS( jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
714
715 mainThread_ = pthread_self();
716 ASSERT_CALL( pthread_mutex_init( &jackHostApi->mtx, NULL ), 0 );
717 ASSERT_CALL( pthread_cond_init( &jackHostApi->cond, NULL ), 0 );
718
719 /* Try to become a client of the JACK server. If we cannot do
720 * this, then this API cannot be used.
721 *
722 * Without the JackNoStartServer option, the jackd server is started
723 * automatically which we do not want.
724 */
725
726 jackHostApi->jack_client = jack_client_open( clientName_, JackNoStartServer, &jackStatus );
727 if( !jackHostApi->jack_client )
728 {
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 ));
733 result = paNoError;
734 goto error;
735 }
736
737 jackHostApi->hostApiIndex = hostApiIndex;
738
739 *hostApi = &jackHostApi->commonHostApiRep;
740 (*hostApi)->info.structVersion = 1;
741 (*hostApi)->info.type = paJACK;
742 (*hostApi)->info.name = "JACK Audio Connection Kit";
743
744 /* Build a device list by querying the JACK server */
745 ENSURE_PA( BuildDeviceList( jackHostApi ) );
746
747 /* Register functions */
748
749 (*hostApi)->Terminate = Terminate;
750 (*hostApi)->OpenStream = OpenStream;
751 (*hostApi)->IsFormatSupported = IsFormatSupported;
752
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 );
761
762 PaUtil_InitializeStreamInterface( &jackHostApi->blockingStreamInterface, CloseStream, StartStream,
763 StopStream, AbortStream, IsStreamStopped, IsStreamActive,
764 GetStreamTime, PaUtil_DummyGetCpuLoad,
765 BlockingReadStream, BlockingWriteStream,
766 BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable );
767
768 jackHostApi->inputBase = jackHostApi->outputBase = 0;
769 jackHostApi->xrun = 0;
770 jackHostApi->toAdd = jackHostApi->toRemove = NULL;
771 jackHostApi->processQueue = NULL;
772 jackHostApi->jackIsDown = 0;
773
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 );
782 activated = 1;
783
784 return result;
785
786 error:
787 if( activated )
788 ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
789
790 if( jackHostApi )
791 {
792 if( jackHostApi->jack_client )
793 ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
794
795 if( jackHostApi->deviceInfoMemory )
796 {
797 PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
798 PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
799 }
800
801 PaUtil_FreeMemory( jackHostApi );
802 }
803 return result;
804 }
805
806
807 static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
808 {
809 PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
810
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 );
814
815 ASSERT_CALL( pthread_mutex_destroy( &jackHostApi->mtx ), 0 );
816 ASSERT_CALL( pthread_cond_destroy( &jackHostApi->cond ), 0 );
817
818 ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
819
820 if( jackHostApi->deviceInfoMemory )
821 {
822 PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
823 PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
824 }
825
826 PaUtil_FreeMemory( jackHostApi );
827
828 free( jackErr_ );
829 }
830
831 static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
832 const PaStreamParameters *inputParameters,
833 const PaStreamParameters *outputParameters,
834 double sampleRate )
835 {
836 int inputChannelCount = 0, outputChannelCount = 0;
837 PaSampleFormat inputSampleFormat, outputSampleFormat;
838
839 if( inputParameters )
840 {
841 inputChannelCount = inputParameters->channelCount;
842 inputSampleFormat = inputParameters->sampleFormat;
843
844 /* unless alternate device specification is supported, reject the use of
845 paUseHostApiSpecificDeviceSpecification */
846
847 if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
848 return paInvalidDevice;
849
850 /* check that input device can support inputChannelCount */
851 if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
852 return paInvalidChannelCount;
853
854 /* validate inputStreamInfo */
855 if( inputParameters->hostApiSpecificStreamInfo )
856 return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
857 }
858 else
859 {
860 inputChannelCount = 0;
861 }
862
863 if( outputParameters )
864 {
865 outputChannelCount = outputParameters->channelCount;
866 outputSampleFormat = outputParameters->sampleFormat;
867
868 /* unless alternate device specification is supported, reject the use of
869 paUseHostApiSpecificDeviceSpecification */
870
871 if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
872 return paInvalidDevice;
873
874 /* check that output device can support inputChannelCount */
875 if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
876 return paInvalidChannelCount;
877
878 /* validate outputStreamInfo */
879 if( outputParameters->hostApiSpecificStreamInfo )
880 return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
881 }
882 else
883 {
884 outputChannelCount = 0;
885 }
886
887 /*
888 The following check is not necessary for JACK.
889
890 - if a full duplex stream is requested, check that the combination
891 of input and output parameters is supported
892
893
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.
897
898 - check that input device can support inputSampleFormat, or that
899 we have the capability to convert from outputSampleFormat to
900 a native format
901
902 - check that output device can support outputSampleFormat, or that
903 we have the capability to convert from outputSampleFormat to
904 a native format
905 */
906
907 /* check that the device supports sampleRate */
908
909 #define ABS(x) ( (x) > 0 ? (x) : -(x) )
910 if( ABS(sampleRate - jack_get_sample_rate(((PaJackHostApiRepresentation *) hostApi)->jack_client )) > 1 )
911 return paInvalidSampleRate;
912 #undef ABS
913
914 return paFormatIsSupported;
915 }
916
917 /* Basic stream initialization */
918 static PaError InitializeStream( PaJackStream *stream, PaJackHostApiRepresentation *hostApi, int numInputChannels,
919 int numOutputChannels )
920 {
921 PaError result = paNoError;
922 assert( stream );
923
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;
928
929 if( numInputChannels > 0 )
930 {
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 );
939 }
940 if( numOutputChannels > 0 )
941 {
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 );
950 }
951
952 stream->num_incoming_connections = numInputChannels;
953 stream->num_outgoing_connections = numOutputChannels;
954
955 error:
956 return result;
957 }
958
959 /*!
960 * Free resources associated with stream, and eventually stream itself.
961 *
962 * Frees allocated memory, and closes opened pcms.
963 */
964 static void CleanUpStream( PaJackStream *stream, int terminateStreamRepresentation, int terminateBufferProcessor )
965 {
966 int i;
967 assert( stream );
968
969 if( stream->isBlockingStream )
970 BlockingEnd( stream );
971
972 for( i = 0; i < stream->num_incoming_connections; ++i )
973 {
974 if( stream->local_input_ports[i] )
975 ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_input_ports[i] ), 0 );
976 }
977 for( i = 0; i < stream->num_outgoing_connections; ++i )
978 {
979 if( stream->local_output_ports[i] )
980 ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_output_ports[i] ), 0 );
981 }
982
983 if( terminateStreamRepresentation )
984 PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
985 if( terminateBufferProcessor )
986 PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
987
988 if( stream->stream_memory )
989 {
990 PaUtil_FreeAllAllocations( stream->stream_memory );
991 PaUtil_DestroyAllocationGroup( stream->stream_memory );
992 }
993 PaUtil_FreeMemory( stream );
994 }
995
996 static PaError WaitCondition( PaJackHostApiRepresentation *hostApi )
997 {
998 PaError result = paNoError;
999 int err = 0;
1000 PaTime pt = PaUtil_GetTime();
1001 struct timespec ts;
1002
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 );
1007
1008 /* Make sure we didn't time out */
1009 UNLESS( err != ETIMEDOUT, paTimedOut );
1010 UNLESS( !err, paInternalError );
1011
1012 error:
1013 return result;
1014 }
1015
1016 static PaError AddStream( PaJackStream *stream )
1017 {
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 )
1023 {
1024 hostApi->toAdd = stream;
1025 /* Unlock mutex and await signal from processing thread */
1026 result = WaitCondition( stream->hostApi );
1027 }
1028 ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1029 ENSURE_PA( result );
1030
1031 UNLESS( !hostApi->jackIsDown, paDeviceUnavailable );
1032
1033 error:
1034 return result;
1035 }
1036
1037 /* Remove stream from processing queue */
1038 static PaError RemoveStream( PaJackStream *stream )
1039 {
1040 PaError result = paNoError;
1041 PaJackHostApiRepresentation *hostApi = stream->hostApi;
1042
1043 /* Add to queue over streams that should be processed */
1044 ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
1045 if( !hostApi->jackIsDown )
1046 {
1047 hostApi->toRemove = stream;
1048 /* Unlock mutex and await signal from processing thread */
1049 result = WaitCondition( stream->hostApi );
1050 }
1051 ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1052 ENSURE_PA( result );
1053
1054 error:
1055 return result;
1056 }
1057
1058 /* Add stream to JACK callback processing queue */
1059 static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
1060 PaStream** s,
1061 const PaStreamParameters *inputParameters,
1062 const PaStreamParameters *outputParameters,
1063 double sampleRate,
1064 unsigned long framesPerBuffer,
1065 PaStreamFlags streamFlags,
1066 PaStreamCallback *streamCallback,
1067 void *userData )
1068 {
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 ); */
1077 int i;
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? */
1082 unsigned long ofs;
1083
1084 /* validate platform specific flags */
1085 if( (streamFlags & paPlatformSpecificFlags) != 0 )
1086 return paInvalidFlag; /* unexpected platform specific flag */
1087 if( (streamFlags & paPrimeOutputBuffersUsingStreamCallback) != 0 )
1088 {
1089 streamFlags &= ~paPrimeOutputBuffersUsingStreamCallback;
1090 /*return paInvalidFlag;*/ /* This implementation does not support buffer priming */
1091 }
1092
1093 if( framesPerBuffer != paFramesPerBufferUnspecified )
1094 {
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? */
1097 }
1098
1099 /* Preliminary checks */
1100
1101 if( inputParameters )
1102 {
1103 inputChannelCount = inputParameters->channelCount;
1104 inputSampleFormat = inputParameters->sampleFormat;
1105
1106 /* unless alternate device specification is supported, reject the use of
1107 paUseHostApiSpecificDeviceSpecification */
1108
1109 if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
1110 return paInvalidDevice;
1111
1112 /* check that input device can support inputChannelCount */
1113 if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
1114 return paInvalidChannelCount;
1115
1116 /* validate inputStreamInfo */
1117 if( inputParameters->hostApiSpecificStreamInfo )
1118 return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
1119 }
1120 else
1121 {
1122 inputChannelCount = 0;
1123 }
1124
1125 if( outputParameters )
1126 {
1127 outputChannelCount = outputParameters->channelCount;
1128 outputSampleFormat = outputParameters->sampleFormat;
1129
1130 /* unless alternate device specification is supported, reject the use of
1131 paUseHostApiSpecificDeviceSpecification */
1132
1133 if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
1134 return paInvalidDevice;
1135
1136 /* check that output device can support inputChannelCount */
1137 if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
1138 return paInvalidChannelCount;
1139
1140 /* validate outputStreamInfo */
1141 if( outputParameters->hostApiSpecificStreamInfo )
1142 return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
1143 }
1144 else
1145 {
1146 outputChannelCount = 0;
1147 }
1148
1149 /* ... check that the sample rate exactly matches the ONE acceptable rate
1150 * A: This rate isn't necessarily constant though? */
1151
1152 #define ABS(x) ( (x) > 0 ? (x) : -(x) )
1153 if( ABS(sampleRate - jackSr) > 1 )
1154 return paInvalidSampleRate;
1155 #undef ABS
1156
1157 UNLESS( stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ), paInsufficientMemory );
1158 ENSURE_PA( InitializeStream( stream, jackHostApi, inputChannelCount, outputChannelCount ) );
1159
1160 /* the blocking emulation, if necessary */
1161 stream->isBlockingStream = !streamCallback;
1162 if( stream->isBlockingStream )
1163 {
1164 float latency = 0.001; /* 1ms is the absolute minimum we support */
1165 int minimum_buffer_frames = 0;
1166
1167 if( inputParameters && inputParameters->suggestedLatency > latency )
1168 latency = inputParameters->suggestedLatency;
1169 else if( outputParameters && outputParameters->suggestedLatency > latency )
1170 latency = outputParameters->suggestedLatency;
1171
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 ));
1174
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;
1178
1179 /* setup blocking API data structures (FIXME: can fail) */
1180 BlockingBegin( stream, minimum_buffer_frames );
1181
1182 /* install our own callback for the blocking API */
1183 streamCallback = BlockingCallback;
1184 userData = stream;
1185
1186 PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
1187 &jackHostApi->blockingStreamInterface, streamCallback, userData );
1188 }
1189 else
1190 {
1191 PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
1192 &jackHostApi->callbackStreamInterface, streamCallback, userData );
1193 }
1194 srInitialized = 1;
1195 PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, jackSr );
1196
1197 /* create the JACK ports. We cannot connect them until audio
1198 * processing begins */
1199
1200 /* Register a unique set of ports for this stream
1201 * TODO: Robust allocation of new port names */
1202
1203 ofs = jackHostApi->inputBase;
1204 for( i = 0; i < inputChannelCount; i++ )
1205 {
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 );
1210 }
1211 jackHostApi->inputBase += inputChannelCount;
1212
1213 ofs = jackHostApi->outputBase;
1214 for( i = 0; i < outputChannelCount; i++ )
1215 {
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 );
1220 }
1221 jackHostApi->outputBase += outputChannelCount;
1222
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. */
1226
1227 if( inputChannelCount > 0 )
1228 {
1229 int err = 0;
1230
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++ )
1236 {
1237 if( (stream->remote_output_ports[i] = jack_port_by_name(
1238 jackHostApi->jack_client, jack_ports[i] )) == NULL )
1239 {
1240 err = 1;
1241 break;
1242 }
1243 }
1244 free( jack_ports );
1245 UNLESS( !err, paInsufficientMemory );
1246
1247 /* Fewer ports than expected? */
1248 UNLESS( i == inputChannelCount, paInternalError );
1249 }
1250
1251 if( outputChannelCount > 0 )
1252 {
1253 int err = 0;
1254
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++ )
1260 {
1261 if( (stream->remote_input_ports[i] = jack_port_by_name(
1262 jackHostApi->jack_client, jack_ports[i] )) == 0 )
1263 {
1264 err = 1;
1265 break;
1266 }
1267 }
1268 free( jack_ports );
1269 UNLESS( !err , paInsufficientMemory );
1270
1271 /* Fewer ports than expected? */
1272 UNLESS( i == outputChannelCount, paInternalError );
1273 }
1274
1275 ENSURE_PA( PaUtil_InitializeBufferProcessor(
1276 &stream->bufferProcessor,
1277 inputChannelCount,
1278 inputSampleFormat,
1279 paFloat32, /* hostInputSampleFormat */
1280 outputChannelCount,
1281 outputSampleFormat,
1282 paFloat32, /* hostOutputSampleFormat */
1283 jackSr,
1284 streamFlags,
1285 framesPerBuffer,
1286 0, /* Ignored */
1287 paUtilUnknownHostBufferSize, /* Buffer size may vary on JACK's discretion */
1288 streamCallback,
1289 userData ) );
1290 bpInitialized = 1;
1291
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;
1300
1301 stream->streamRepresentation.streamInfo.sampleRate = jackSr;
1302 stream->t0 = jack_frame_time( jackHostApi->jack_client ); /* A: Time should run from Pa_OpenStream */
1303
1304 /* Add to queue of opened streams */
1305 ENSURE_PA( AddStream( stream ) );
1306
1307 *s = (PaStream*)stream;
1308
1309 return result;
1310
1311 error:
1312 if( stream )
1313 CleanUpStream( stream, srInitialized, bpInitialized );
1314
1315 return result;
1316 }
1317
1318 /*
1319 When CloseStream() is called, the multi-api layer ensures that
1320 the stream has already been stopped or aborted.
1321 */
1322 static PaError CloseStream( PaStream* s )
1323 {
1324 PaError result = paNoError;
1325 PaJackStream *stream = (PaJackStream*)s;
1326
1327 /* Remove this stream from the processing queue */
1328 ENSURE_PA( RemoveStream( stream ) );
1329
1330 error:
1331 CleanUpStream( stream, 1, 1 );
1332 return result;
1333 }
1334
1335 static PaError RealProcess( PaJackStream *stream, jack_nframes_t frames )
1336 {
1337 PaError result = paNoError;
1338 PaStreamCallbackTimeInfo timeInfo = {0,0,0};
1339 int chn;
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;
1343
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 ) )
1348 {
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__ ));
1353
1354 goto end;
1355 }
1356
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] )
1360 / sr;
1361 if( stream->num_outgoing_connections > 0 )
1362 timeInfo.outputBufferDacTime = timeInfo.currentTime + jack_port_get_latency( stream->remote_input_ports[0] )
1363 / sr;
1364
1365 PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
1366
1367 if( stream->xrun )
1368 {
1369 /* XXX: Any way to tell which of these occurred? */
1370 cbFlags = paOutputUnderflow | paInputOverflow;
1371 stream->xrun = FALSE;
1372 }
1373 PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,
1374 cbFlags );
1375
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 );
1380
1381 for( chn = 0; chn < stream->num_incoming_connections; chn++ )
1382 {
1383 jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
1384 jack_port_get_buffer( stream->local_input_ports[chn],
1385 frames );
1386
1387 PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor,
1388 chn,
1389 channel_buf );
1390 }
1391
1392 for( chn = 0; chn < stream->num_outgoing_connections; chn++ )
1393 {
1394 jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
1395 jack_port_get_buffer( stream->local_output_ports[chn],
1396 frames );
1397
1398 PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor,
1399 chn,
1400 channel_buf );
1401 }
1402
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 );
1407
1408 PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
1409
1410 end:
1411 return result;
1412 }
1413
1414 /* Update the JACK callback's stream processing queue. */
1415 static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
1416 {
1417 PaError result = paNoError;
1418 int queueModified = 0;
1419 const double jackSr = jack_get_sample_rate( hostApi->jack_client );
1420 int err;
1421
1422 if( (err = pthread_mutex_trylock( &hostApi->mtx )) != 0 )
1423 {
1424 assert( err == EBUSY );
1425 return paNoError;
1426 }
1427
1428 if( hostApi->toAdd )
1429 {
1430 if( hostApi->processQueue )
1431 {
1432 PaJackStream *node = hostApi->processQueue;
1433 /* Advance to end of queue */
1434 while( node->next )
1435 node = node->next;
1436
1437 node->next = hostApi->toAdd;
1438 }
1439 else
1440 {
1441 /* The only queue entry. */
1442 hostApi->processQueue = (PaJackStream *)hostApi->toAdd;
1443 }
1444
1445 /* If necessary, update stream state */
1446 if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr )
1447 UpdateSampleRate( hostApi->toAdd, jackSr );
1448
1449 hostApi->toAdd = NULL;
1450 queueModified = 1;
1451 }
1452 if( hostApi->toRemove )
1453 {
1454 int removed = 0;
1455 PaJackStream *node = hostApi->processQueue, *prev = NULL;
1456 assert( hostApi->processQueue );
1457
1458 while( node )
1459 {
1460 if( node == hostApi->toRemove )
1461 {
1462 if( prev )
1463 prev->next = node->next;
1464 else
1465 hostApi->processQueue = (PaJackStream *)node->next;
1466
1467 removed = 1;
1468 break;
1469 }
1470
1471 prev = node;
1472 node = node->next;
1473 }
1474 UNLESS( removed, paInternalError );
1475 hostApi->toRemove = NULL;
1476 PA_DEBUG(( "%s: Removed stream from processing queue\n", __FUNCTION__ ));
1477 queueModified = 1;
1478 }
1479
1480 if( queueModified )
1481 {
1482 /* Signal that we've done what was asked of us */
1483 ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 );
1484 }
1485
1486 error:
1487 ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
1488
1489 return result;
1490 }
1491
1492 /* Audio processing callback invoked periodically from JACK. */
1493 static int JackCallback( jack_nframes_t frames, void *userData )
1494 {
1495 PaError result = paNoError;
1496 PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)userData;
1497 PaJackStream *stream = NULL;
1498 int xrun = hostApi->xrun;
1499 hostApi->xrun = 0;
1500
1501 assert( hostApi );
1502
1503 ENSURE_PA( UpdateQueue( hostApi ) );
1504
1505 /* Process each stream */
1506 stream = hostApi->processQueue;
1507 for( ; stream; stream = stream->next )
1508 {
1509 if( xrun ) /* Don't override if already set */
1510 stream->xrun = 1;
1511
1512 /* See if this stream is to be started */
1513 if( stream->doStart )
1514 {
1515 /* If we can't obtain a lock, we'll try next time */
1516 int err = pthread_mutex_trylock( &stream->hostApi->mtx );
1517 if( !err )
1518 {
1519 if( stream->doStart ) /* Could potentially change before obtaining the lock */
1520 {
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;
1527 }
1528
1529 ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1530 }
1531 else
1532 assert( err == EBUSY );
1533 }
1534 else if( stream->doStop || stream->doAbort ) /* Should we stop/abort stream? */
1535 {
1536 if( stream->callbackResult == paContinue ) /* Ok, make it stop */
1537 {
1538 PA_DEBUG(( "%s: Stopping stream\n", __FUNCTION__ ));
1539 stream->callbackResult = stream->doStop ? paComplete : paAbort;
1540 }
1541 }
1542
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 )
1547 {
1548 int i;
1549
1550 /* Silence buffer after entering inactive state */
1551 PA_DEBUG(( "Silencing the output\n" ));
1552 for( i = 0; i < stream->num_outgoing_connections; ++i )
1553 {
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 );
1556 }
1557
1558 stream->isSilenced = 1;
1559 }
1560
1561 if( stream->doStop || stream->doAbort )
1562 {
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 */
1565 {
1566 /* If we can't obtain a lock, we'll try next time */
1567 int err = pthread_mutex_trylock( &stream->hostApi->mtx );
1568 if( !err )
1569 {
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 );
1573 }
1574 else
1575 assert( err == EBUSY );
1576 }
1577 }
1578 }
1579
1580 return 0;
1581 error:
1582 return -1;
1583 }
1584
1585 static PaError StartStream( PaStream *s )
1586 {
1587 PaError result = paNoError;
1588 PaJackStream *stream = (PaJackStream*)s;
1589 int i;
1590
1591 /* Ready the processor */
1592 PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
1593
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. */
1596
1597 if( stream->num_incoming_connections > 0 )
1598 {
1599 for( i = 0; i < stream->num_incoming_connections; i++ )
1600 {
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 );
1604 }
1605 }
1606
1607 if( stream->num_outgoing_connections > 0 )
1608 {
1609 for( i = 0; i < stream->num_outgoing_connections; i++ )
1610 {
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 );
1614 }
1615 }
1616
1617 stream->xrun = FALSE;
1618
1619 /* Enable processing */
1620
1621 ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
1622 stream->doStart = 1;
1623
1624 /* Wait for stream to be started */
1625 result = WaitCondition( stream->hostApi );
1626 /*
1627 do
1628 {
1629 err = pthread_cond_timedwait( &stream->hostApi->cond, &stream->hostApi->mtx, &ts );
1630 } while( !stream->is_active && !err );
1631 */
1632 if( result != paNoError ) /* Something went wrong, call off the stream start */
1633 {
1634 stream->doStart = 0;
1635 stream->is_active = 0; /* Cancel any processing */
1636 }
1637 ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
1638
1639 ENSURE_PA( result );
1640
1641 stream->is_running = TRUE;
1642 PA_DEBUG(( "%s: Stream started\n", __FUNCTION__ ));
1643
1644 error:
1645 return result;
1646 }
1647
1648 static PaError RealStop( PaJackStream *stream, int abort )
1649 {
1650 PaError result = paNoError;
1651 int i;
1652
1653 if( stream->isBlockingStream )
1654 BlockingWaitEmpty ( stream );
1655
1656 ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
1657 if( abort )
1658 stream->doAbort = 1;
1659 else
1660 stream->doStop = 1;
1661
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 );
1666
1667 UNLESS( !stream->is_active, paInternalError );
1668
1669 PA_DEBUG(( "%s: Stream stopped\n", __FUNCTION__ ));
1670
1671 error:
1672 stream->is_running = FALSE;
1673
1674 /* Disconnect ports belonging to this stream */
1675
1676 if( !stream->hostApi->jackIsDown ) /* XXX: Well? */
1677 {
1678 for( i = 0; i < stream->num_incoming_connections; i++ )
1679 {
1680 if( jack_port_connected( stream->local_input_ports[i] ) )
1681 {
1682 UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ),
1683 paUnanticipatedHostError );
1684 }
1685 }
1686 for( i = 0; i < stream->num_outgoing_connections; i++ )
1687 {
1688 if( jack_port_connected( stream->local_output_ports[i] ) )
1689 {
1690 UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ),
1691 paUnanticipatedHostError );
1692 }
1693 }
1694 }
1695
1696 return result;
1697 }
1698
1699 static PaError StopStream( PaStream *s )
1700 {
1701 assert(s);
1702 return RealStop( (PaJackStream *)s, 0 );
1703 }
1704
1705 static PaError AbortStream( PaStream *s )
1706 {
1707 assert(s);
1708 return RealStop( (PaJackStream *)s, 1 );
1709 }
1710
1711 static PaError IsStreamStopped( PaStream *s )
1712 {
1713 PaJackStream *stream = (PaJackStream*)s;
1714 return !stream->is_running;
1715 }
1716
1717
1718 static PaError IsStreamActive( PaStream *s )
1719 {
1720 PaJackStream *stream = (PaJackStream*)s;
1721 return stream->is_active;
1722 }
1723
1724
1725 static PaTime GetStreamTime( PaStream *s )
1726 {
1727 PaJackStream *stream = (PaJackStream*)s;
1728
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 );
1731 }
1732
1733
1734 static double GetStreamCpuLoad( PaStream* s )
1735 {
1736 PaJackStream *stream = (PaJackStream*)s;
1737 return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
1738 }
1739
1740 PaError PaJack_SetClientName( const char* name )
1741 {
1742 if( strlen( name ) > jack_client_name_size() )
1743 {
1744 /* OK, I don't know any better error code */
1745 return paInvalidFlag;
1746 }
1747 clientName_ = name;
1748 return paNoError;
1749 }
1750
1751 PaError PaJack_GetClientName(const char** clientName)
1752 {
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 );
1758
1759 error:
1760 return result;
1761 }

  ViewVC Help
Powered by ViewVC 1.1.22