gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

pa_jack.c (63346B)


      1 /*
      2  * $Id$
      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 pthread_t mainThread_;
     75 static char *jackErr_ = NULL;
     76 static const char* clientName_ = "PortAudio";
     77 
     78 #define STRINGIZE_HELPER(expr) #expr
     79 #define STRINGIZE(expr) STRINGIZE_HELPER(expr)
     80 
     81 /* Check PaError */
     82 #define ENSURE_PA(expr) \
     83     do { \
     84         PaError paErr; \
     85         if( (paErr = (expr)) < paNoError ) \
     86         { \
     87             if( (paErr) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
     88             { \
     89                 const char *err = jackErr_; \
     90                 if (! err ) err = "unknown error"; \
     91                 PaUtil_SetLastHostErrorInfo( paJACK, -1, err ); \
     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                 const char *err = jackErr_; \
    106                 if (!err) err = "unknown error"; \
    107                 PaUtil_SetLastHostErrorInfo( paJACK, -1, err ); \
    108             } \
    109             PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
    110             result = (code); \
    111             goto error; \
    112         } \
    113     } while( 0 )
    114 
    115 #define ASSERT_CALL(expr, success) \
    116     do { \
    117         int err = (expr); \
    118         assert( err == success ); \
    119     } while( 0 )
    120 
    121 /*
    122  * Functions that directly map to the PortAudio stream interface
    123  */
    124 
    125 static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
    126 static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
    127                                   const PaStreamParameters *inputParameters,
    128                                   const PaStreamParameters *outputParameters,
    129                                   double sampleRate );
    130 static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
    131                            PaStream** s,
    132                            const PaStreamParameters *inputParameters,
    133                            const PaStreamParameters *outputParameters,
    134                            double sampleRate,
    135                            unsigned long framesPerBuffer,
    136                            PaStreamFlags streamFlags,
    137                            PaStreamCallback *streamCallback,
    138                            void *userData );
    139 static PaError CloseStream( PaStream* stream );
    140 static PaError StartStream( PaStream *stream );
    141 static PaError StopStream( PaStream *stream );
    142 static PaError AbortStream( PaStream *stream );
    143 static PaError IsStreamStopped( PaStream *s );
    144 static PaError IsStreamActive( PaStream *stream );
    145 /*static PaTime GetStreamInputLatency( PaStream *stream );*/
    146 /*static PaTime GetStreamOutputLatency( PaStream *stream );*/
    147 static PaTime GetStreamTime( PaStream *stream );
    148 static double GetStreamCpuLoad( PaStream* stream );
    149 
    150 
    151 /*
    152  * Data specific to this API
    153  */
    154 
    155 struct PaJackStream;
    156 
    157 typedef struct
    158 {
    159     PaUtilHostApiRepresentation commonHostApiRep;
    160     PaUtilStreamInterface callbackStreamInterface;
    161     PaUtilStreamInterface blockingStreamInterface;
    162 
    163     PaUtilAllocationGroup *deviceInfoMemory;
    164 
    165     jack_client_t *jack_client;
    166     int jack_buffer_size;
    167     PaHostApiIndex hostApiIndex;
    168 
    169     pthread_mutex_t mtx;
    170     pthread_cond_t cond;
    171     unsigned long inputBase, outputBase;
    172 
    173     /* For dealing with the process thread */
    174     volatile int xrun;     /* Received xrun notification from JACK? */
    175     struct PaJackStream * volatile toAdd, * volatile toRemove;
    176     struct PaJackStream *processQueue;
    177     volatile sig_atomic_t jackIsDown;
    178 }
    179 PaJackHostApiRepresentation;
    180 
    181 /* PaJackStream - a stream data structure specifically for this implementation */
    182 
    183 typedef struct PaJackStream
    184 {
    185     PaUtilStreamRepresentation streamRepresentation;
    186     PaUtilBufferProcessor bufferProcessor;
    187     PaUtilCpuLoadMeasurer cpuLoadMeasurer;
    188     PaJackHostApiRepresentation *hostApi;
    189 
    190     /* our input and output ports */
    191     jack_port_t **local_input_ports;
    192     jack_port_t **local_output_ports;
    193 
    194     /* the input and output ports of the client we are connecting to */
    195     jack_port_t **remote_input_ports;
    196     jack_port_t **remote_output_ports;
    197 
    198     int num_incoming_connections;
    199     int num_outgoing_connections;
    200 
    201     jack_client_t *jack_client;
    202 
    203     /* The stream is running if it's still producing samples.
    204      * The stream is active if samples it produced are still being heard.
    205      */
    206     volatile sig_atomic_t is_running;
    207     volatile sig_atomic_t is_active;
    208     /* Used to signal processing thread that stream should start or stop, respectively */
    209     volatile sig_atomic_t doStart, doStop, doAbort;
    210 
    211     jack_nframes_t t0;
    212 
    213     PaUtilAllocationGroup *stream_memory;
    214 
    215     /* These are useful in the process callback */
    216 
    217     int callbackResult;
    218     int isSilenced;
    219     int xrun;
    220 
    221     /* These are useful for the blocking API */
    222 
    223     int                     isBlockingStream;
    224     PaUtilRingBuffer        inFIFO;
    225     PaUtilRingBuffer        outFIFO;
    226     volatile sig_atomic_t   data_available;
    227     sem_t                   data_semaphore;
    228     int                     bytesPerFrame;
    229     int                     samplesPerFrame;
    230 
    231     struct PaJackStream *next;
    232 }
    233 PaJackStream;
    234 
    235 /* In calls to jack_get_ports() this filter expression is used instead of ""
    236  * to prevent any other types (eg Midi ports etc) being listed */
    237 #define JACK_PORT_TYPE_FILTER "audio"
    238 
    239 #define TRUE 1
    240 #define FALSE 0
    241 
    242 /*
    243  * Functions specific to this API
    244  */
    245 
    246 static int JackCallback( jack_nframes_t frames, void *userData );
    247 
    248 
    249 /*
    250  *
    251  * Implementation
    252  *
    253  */
    254 
    255 /* ---- blocking emulation layer ---- */
    256 
    257 /* Allocate buffer. */
    258 static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long bytesPerFrame )
    259 {
    260     long numBytes = numFrames * bytesPerFrame;
    261     char *buffer = (char *) malloc( numBytes );
    262     if( buffer == NULL ) return paInsufficientMemory;
    263     memset( buffer, 0, numBytes );
    264     return (PaError) PaUtil_InitializeRingBuffer( rbuf, 1, numBytes, buffer );
    265 }
    266 
    267 /* Free buffer. */
    268 static PaError BlockingTermFIFO( PaUtilRingBuffer *rbuf )
    269 {
    270     if( rbuf->buffer ) free( rbuf->buffer );
    271     rbuf->buffer = NULL;
    272     return paNoError;
    273 }
    274 
    275 static int
    276 BlockingCallback( const void                      *inputBuffer,
    277                   void                            *outputBuffer,
    278 		  unsigned long                    framesPerBuffer,
    279 		  const PaStreamCallbackTimeInfo*  timeInfo,
    280 		  PaStreamCallbackFlags            statusFlags,
    281 		  void                             *userData )
    282 {
    283     struct PaJackStream *stream = (PaJackStream *)userData;
    284     long numBytes = stream->bytesPerFrame * framesPerBuffer;
    285 
    286     /* This may get called with NULL inputBuffer during initial setup. */
    287     if( inputBuffer != NULL )
    288     {
    289         PaUtil_WriteRingBuffer( &stream->inFIFO, inputBuffer, numBytes );
    290     }
    291     if( outputBuffer != NULL )
    292     {
    293         int numRead = PaUtil_ReadRingBuffer( &stream->outFIFO, outputBuffer, numBytes );
    294         /* Zero out remainder of buffer if we run out of data. */
    295         memset( (char *)outputBuffer + numRead, 0, numBytes - numRead );
    296     }
    297 
    298     if( !stream->data_available )
    299     {
    300         stream->data_available = 1;
    301         sem_post( &stream->data_semaphore );
    302     }
    303     return paContinue;
    304 }
    305 
    306 static PaError
    307 BlockingBegin( PaJackStream *stream, int minimum_buffer_size )
    308 {
    309     long    doRead = 0;
    310     long    doWrite = 0;
    311     PaError result = paNoError;
    312     long    numFrames;
    313 
    314     doRead = stream->local_input_ports != NULL;
    315     doWrite = stream->local_output_ports != NULL;
    316     /* <FIXME> */
    317     stream->samplesPerFrame = 2;
    318     stream->bytesPerFrame = sizeof(float) * stream->samplesPerFrame;
    319     /* </FIXME> */
    320     numFrames = 32;
    321     while (numFrames < minimum_buffer_size)
    322         numFrames *= 2;
    323 
    324     if( doRead )
    325     {
    326         ENSURE_PA( BlockingInitFIFO( &stream->inFIFO, numFrames, stream->bytesPerFrame ) );
    327     }
    328     if( doWrite )
    329     {
    330         long numBytes;
    331 
    332         ENSURE_PA( BlockingInitFIFO( &stream->outFIFO, numFrames, stream->bytesPerFrame ) );
    333 
    334         /* Make Write FIFO appear full initially. */
    335         numBytes = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
    336         PaUtil_AdvanceRingBufferWriteIndex( &stream->outFIFO, numBytes );
    337     }
    338 
    339     stream->data_available = 0;
    340     sem_init( &stream->data_semaphore, 0, 0 );
    341 
    342 error:
    343     return result;
    344 }
    345 
    346 static void
    347 BlockingEnd( PaJackStream *stream )
    348 {
    349     BlockingTermFIFO( &stream->inFIFO );
    350     BlockingTermFIFO( &stream->outFIFO );
    351 
    352     sem_destroy( &stream->data_semaphore );
    353 }
    354 
    355 static PaError BlockingReadStream( PaStream* s, void *data, unsigned long numFrames )
    356 {
    357     PaError result = paNoError;
    358     PaJackStream *stream = (PaJackStream *)s;
    359 
    360     long bytesRead;
    361     char *p = (char *) data;
    362     long numBytes = stream->bytesPerFrame * numFrames;
    363     while( numBytes > 0 )
    364     {
    365         bytesRead = PaUtil_ReadRingBuffer( &stream->inFIFO, p, numBytes );
    366         numBytes -= bytesRead;
    367         p += bytesRead;
    368         if( numBytes > 0 )
    369         {
    370             /* see write for an explanation */
    371             if( stream->data_available )
    372                 stream->data_available = 0;
    373             else
    374                 sem_wait( &stream->data_semaphore );
    375         }
    376     }
    377 
    378     return result;
    379 }
    380 
    381 static PaError BlockingWriteStream( PaStream* s, const void *data, unsigned long numFrames )
    382 {
    383     PaError result = paNoError;
    384     PaJackStream *stream = (PaJackStream *)s;
    385     long bytesWritten;
    386     char *p = (char *) data;
    387     long numBytes = stream->bytesPerFrame * numFrames;
    388     while( numBytes > 0 )
    389     {
    390         bytesWritten = PaUtil_WriteRingBuffer( &stream->outFIFO, p, numBytes );
    391         numBytes -= bytesWritten;
    392         p += bytesWritten;
    393         if( numBytes > 0 )
    394         {
    395             /* we use the following algorithm:
    396              *   (1) write data
    397              *   (2) if some data didn't fit into the ringbuffer, set data_available to 0
    398              *       to indicate to the audio that if space becomes available, we want to know
    399              *   (3) retry to write data (because it might be that between (1) and (2)
    400              *       new space in the buffer became available)
    401              *   (4) if this failed, we are sure that the buffer is really empty and
    402              *       we will definitely receive a notification when it becomes available
    403              *       thus we can safely sleep
    404              *
    405              * if the algorithm bailed out in step (3) before, it leaks a count of 1
    406              * on the semaphore; however, it doesn't matter, because if we block in (4),
    407              * we also do it in a loop
    408              */
    409             if( stream->data_available )
    410                 stream->data_available = 0;
    411             else
    412                 sem_wait( &stream->data_semaphore );
    413         }
    414     }
    415 
    416     return result;
    417 }
    418 
    419 static signed long
    420 BlockingGetStreamReadAvailable( PaStream* s )
    421 {
    422     PaJackStream *stream = (PaJackStream *)s;
    423 
    424     int bytesFull = PaUtil_GetRingBufferReadAvailable( &stream->inFIFO );
    425     return bytesFull / stream->bytesPerFrame;
    426 }
    427 
    428 static signed long
    429 BlockingGetStreamWriteAvailable( PaStream* s )
    430 {
    431     PaJackStream *stream = (PaJackStream *)s;
    432 
    433     int bytesEmpty = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
    434     return bytesEmpty / stream->bytesPerFrame;
    435 }
    436 
    437 static PaError
    438 BlockingWaitEmpty( PaStream *s )
    439 {
    440     PaJackStream *stream = (PaJackStream *)s;
    441 
    442     while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
    443     {
    444         stream->data_available = 0;
    445         sem_wait( &stream->data_semaphore );
    446     }
    447     return 0;
    448 }
    449 
    450 /* ---- jack driver ---- */
    451 
    452 /* BuildDeviceList():
    453  *
    454  * The process of determining a list of PortAudio "devices" from
    455  * JACK's client/port system is fairly involved, so it is separated
    456  * into its own routine.
    457  */
    458 
    459 static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
    460 {
    461     /* Utility macros for the repetitive process of allocating memory */
    462 
    463     /* JACK has no concept of a device.  To JACK, there are clients
    464      * which have an arbitrary number of ports.  To make this
    465      * intelligible to PortAudio clients, we will group each JACK client
    466      * into a device, and make each port of that client a channel */
    467 
    468     PaError result = paNoError;
    469     PaUtilHostApiRepresentation *commonApi = &jackApi->commonHostApiRep;
    470 
    471     const char **jack_ports = NULL;
    472     char **client_names = NULL;
    473     char *regex_pattern = NULL;
    474     int port_index, client_index, i;
    475     double globalSampleRate;
    476     regex_t port_regex;
    477     unsigned long numClients = 0, numPorts = 0;
    478     char *tmp_client_name = NULL;
    479 
    480     commonApi->info.defaultInputDevice = paNoDevice;
    481     commonApi->info.defaultOutputDevice = paNoDevice;
    482     commonApi->info.deviceCount = 0;
    483 
    484     /* Parse the list of ports, using a regex to grab the client names */
    485     ASSERT_CALL( regcomp( &port_regex, "^[^:]*", REG_EXTENDED ), 0 );
    486 
    487     /* since we are rebuilding the list of devices, free all memory
    488      * associated with the previous list */
    489     PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
    490 
    491     regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
    492     tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
    493 
    494     /* We can only retrieve the list of clients indirectly, by first
    495      * asking for a list of all ports, then parsing the port names
    496      * according to the client_name:port_name convention (which is
    497      * enforced by jackd)
    498      * A: If jack_get_ports returns NULL, there's nothing for us to do */
    499     UNLESS( (jack_ports = jack_get_ports( jackApi->jack_client, "", JACK_PORT_TYPE_FILTER, 0 )) && jack_ports[0], paNoError );
    500     /* Find number of ports */
    501     while( jack_ports[numPorts] )
    502         ++numPorts;
    503     /* At least there will be one port per client :) */
    504     UNLESS( client_names = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, numPorts *
    505                 sizeof (char *) ), paInsufficientMemory );
    506 
    507     /* Build a list of clients from the list of ports */
    508     for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
    509     {
    510         int client_seen = FALSE;
    511         regmatch_t match_info;
    512         const char *port = jack_ports[port_index];
    513 
    514         /* extract the client name from the port name, using a regex
    515          * that parses the clientname:portname syntax */
    516         UNLESS( !regexec( &port_regex, port, 1, &match_info, 0 ), paInternalError );
    517         assert(match_info.rm_eo - match_info.rm_so < jack_client_name_size());
    518         memcpy( tmp_client_name, port + match_info.rm_so,
    519                 match_info.rm_eo - match_info.rm_so );
    520         tmp_client_name[match_info.rm_eo - match_info.rm_so] = '\0';
    521 
    522         /* do we know about this port's client yet? */
    523         for( i = 0; i < numClients; i++ )
    524         {
    525             if( strcmp( tmp_client_name, client_names[i] ) == 0 )
    526                 client_seen = TRUE;
    527         }
    528 
    529         if (client_seen)
    530             continue;   /* A: Nothing to see here, move along */
    531 
    532         UNLESS( client_names[numClients] = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
    533                     strlen(tmp_client_name) + 1), paInsufficientMemory );
    534 
    535         /* The alsa_pcm client should go in spot 0.  If this
    536          * is the alsa_pcm client AND we are NOT about to put
    537          * it in spot 0 put it in spot 0 and move whatever
    538          * was already in spot 0 to the end. */
    539         if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && numClients > 0 )
    540         {
    541             /* alsa_pcm goes in spot 0 */
    542             strcpy( client_names[ numClients ], client_names[0] );
    543             strcpy( client_names[0], tmp_client_name );
    544         }
    545         else
    546         {
    547             /* put the new client at the end of the client list */
    548             strcpy( client_names[ numClients ], tmp_client_name );
    549         }
    550         ++numClients;
    551     }
    552 
    553     /* Now we have a list of clients, which will become the list of
    554      * PortAudio devices. */
    555 
    556     /* there is one global sample rate all clients must conform to */
    557 
    558     globalSampleRate = jack_get_sample_rate( jackApi->jack_client );
    559     UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
    560                 sizeof(PaDeviceInfo*) * numClients ), paInsufficientMemory );
    561 
    562     assert( commonApi->info.deviceCount == 0 );
    563 
    564     /* Create a PaDeviceInfo structure for every client */
    565     for( client_index = 0; client_index < numClients; client_index++ )
    566     {
    567         PaDeviceInfo *curDevInfo;
    568         const char **clientPorts = NULL;
    569 
    570         UNLESS( curDevInfo = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
    571                     sizeof(PaDeviceInfo) ), paInsufficientMemory );
    572         UNLESS( curDevInfo->name = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
    573                     strlen(client_names[client_index]) + 1 ), paInsufficientMemory );
    574         strcpy( (char *)curDevInfo->name, client_names[client_index] );
    575 
    576         curDevInfo->structVersion = 2;
    577         curDevInfo->hostApi = jackApi->hostApiIndex;
    578 
    579         /* JACK is very inflexible: there is one sample rate the whole
    580          * system must run at, and all clients must speak IEEE float. */
    581         curDevInfo->defaultSampleRate = globalSampleRate;
    582 
    583         /* To determine how many input and output channels are available,
    584          * we re-query jackd with more specific parameters. */
    585 
    586         sprintf( regex_pattern, "%s:.*", client_names[client_index] );
    587 
    588         /* ... what are your output ports (that we could input from)? */
    589         clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
    590                                      JACK_PORT_TYPE_FILTER, JackPortIsOutput);
    591         curDevInfo->maxInputChannels = 0;
    592         curDevInfo->defaultLowInputLatency = 0.;
    593         curDevInfo->defaultHighInputLatency = 0.;
    594         if( clientPorts )
    595         {
    596             jack_port_t *p = jack_port_by_name( jackApi->jack_client, clientPorts[0] );
    597             curDevInfo->defaultLowInputLatency = curDevInfo->defaultHighInputLatency =
    598                 jack_port_get_latency( p ) / globalSampleRate;
    599 
    600             for( i = 0; clientPorts[i] != NULL; i++)
    601             {
    602                 /* The number of ports returned is the number of output channels.
    603                  * We don't care what they are, we just care how many */
    604                 curDevInfo->maxInputChannels++;
    605             }
    606             free(clientPorts);
    607         }
    608 
    609         /* ... what are your input ports (that we could output to)? */
    610         clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
    611                                      JACK_PORT_TYPE_FILTER, JackPortIsInput);
    612         curDevInfo->maxOutputChannels = 0;
    613         curDevInfo->defaultLowOutputLatency = 0.;
    614         curDevInfo->defaultHighOutputLatency = 0.;
    615         if( clientPorts )
    616         {
    617             jack_port_t *p = jack_port_by_name( jackApi->jack_client, clientPorts[0] );
    618             curDevInfo->defaultLowOutputLatency = curDevInfo->defaultHighOutputLatency =
    619                 jack_port_get_latency( p ) / globalSampleRate;
    620 
    621             for( i = 0; clientPorts[i] != NULL; i++)
    622             {
    623                 /* The number of ports returned is the number of input channels.
    624                  * We don't care what they are, we just care how many */
    625                 curDevInfo->maxOutputChannels++;
    626             }
    627             free(clientPorts);
    628         }
    629 
    630         /* Add this client to the list of devices */
    631         commonApi->deviceInfos[client_index] = curDevInfo;
    632         ++commonApi->info.deviceCount;
    633         if( commonApi->info.defaultInputDevice == paNoDevice && curDevInfo->maxInputChannels > 0 )
    634             commonApi->info.defaultInputDevice = client_index;
    635         if( commonApi->info.defaultOutputDevice == paNoDevice && curDevInfo->maxOutputChannels > 0 )
    636             commonApi->info.defaultOutputDevice = client_index;
    637     }
    638 
    639 error:
    640     regfree( &port_regex );
    641     free( jack_ports );
    642     return result;
    643 }
    644 
    645 static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
    646 {
    647     /* XXX: Maybe not the cleanest way of going about this? */
    648     stream->cpuLoadMeasurer.samplingPeriod = stream->bufferProcessor.samplePeriod = 1. / sampleRate;
    649     stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
    650 }
    651 
    652 static void JackErrorCallback( const char *msg )
    653 {
    654     if( pthread_self() == mainThread_ )
    655     {
    656         assert( msg );
    657         jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
    658         strcpy( jackErr_, msg );
    659     }
    660 }
    661 
    662 static void JackOnShutdown( void *arg )
    663 {
    664     PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
    665     PaJackStream *stream = jackApi->processQueue;
    666 
    667     PA_DEBUG(( "%s: JACK server is shutting down\n", __FUNCTION__ ));
    668     for( ; stream; stream = stream->next )
    669     {
    670         stream->is_active = 0;
    671     }
    672 
    673     /* Make sure that the main thread doesn't get stuck waiting on the condition */
    674     ASSERT_CALL( pthread_mutex_lock( &jackApi->mtx ), 0 );
    675     jackApi->jackIsDown = 1;
    676     ASSERT_CALL( pthread_cond_signal( &jackApi->cond ), 0 );
    677     ASSERT_CALL( pthread_mutex_unlock( &jackApi->mtx ), 0 );
    678 
    679 }
    680 
    681 static int JackSrCb( jack_nframes_t nframes, void *arg )
    682 {
    683     PaJackHostApiRepresentation *jackApi = (PaJackHostApiRepresentation *)arg;
    684     double sampleRate = (double)nframes;
    685     PaJackStream *stream = jackApi->processQueue;
    686 
    687     /* Update all streams in process queue */
    688     PA_DEBUG(( "%s: Acting on change in JACK samplerate: %f\n", __FUNCTION__, sampleRate ));
    689     for( ; stream; stream = stream->next )
    690     {
    691         if( stream->streamRepresentation.streamInfo.sampleRate != sampleRate )
    692         {
    693             PA_DEBUG(( "%s: Updating samplerate\n", __FUNCTION__ ));
    694             UpdateSampleRate( stream, sampleRate );
    695         }
    696     }
    697 
    698     return 0;
    699 }
    700 
    701 static int JackXRunCb(void *arg) {
    702     PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)arg;
    703     assert( hostApi );
    704     hostApi->xrun = TRUE;
    705     PA_DEBUG(( "%s: JACK signalled xrun\n", __FUNCTION__ ));
    706     return 0;
    707 }
    708 
    709 PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,
    710                            PaHostApiIndex hostApiIndex )
    711 {
    712     PaError result = paNoError;
    713     PaJackHostApiRepresentation *jackHostApi;
    714     int activated = 0;
    715     jack_status_t jackStatus = 0;
    716     *hostApi = NULL;    /* Initialize to NULL */
    717 
    718     UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
    719         PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ), paInsufficientMemory );
    720     UNLESS( jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
    721 
    722     mainThread_ = pthread_self();
    723     ASSERT_CALL( pthread_mutex_init( &jackHostApi->mtx, NULL ), 0 );
    724     ASSERT_CALL( pthread_cond_init( &jackHostApi->cond, NULL ), 0 );
    725 
    726     /* Try to become a client of the JACK server.  If we cannot do
    727      * this, then this API cannot be used.
    728      *
    729      * Without the JackNoStartServer option, the jackd server is started
    730      * automatically which we do not want.
    731      */
    732 
    733     jackHostApi->jack_client = jack_client_open( clientName_, JackNoStartServer, &jackStatus );
    734     if( !jackHostApi->jack_client )
    735     {
    736         /* the V19 development docs say that if an implementation
    737          * detects that it cannot be used, it should return a NULL
    738          * interface and paNoError */
    739         PA_DEBUG(( "%s: Couldn't connect to JACK, status: %d\n", __FUNCTION__, jackStatus ));
    740         result = paNoError;
    741         goto error;
    742     }
    743 
    744     jackHostApi->hostApiIndex = hostApiIndex;
    745 
    746     *hostApi = &jackHostApi->commonHostApiRep;
    747     (*hostApi)->info.structVersion = 1;
    748     (*hostApi)->info.type = paJACK;
    749     (*hostApi)->info.name = "JACK Audio Connection Kit";
    750 
    751     /* Build a device list by querying the JACK server */
    752     ENSURE_PA( BuildDeviceList( jackHostApi ) );
    753 
    754     /* Register functions */
    755 
    756     (*hostApi)->Terminate = Terminate;
    757     (*hostApi)->OpenStream = OpenStream;
    758     (*hostApi)->IsFormatSupported = IsFormatSupported;
    759 
    760     PaUtil_InitializeStreamInterface( &jackHostApi->callbackStreamInterface,
    761                                       CloseStream, StartStream,
    762                                       StopStream, AbortStream,
    763                                       IsStreamStopped, IsStreamActive,
    764                                       GetStreamTime, GetStreamCpuLoad,
    765                                       PaUtil_DummyRead, PaUtil_DummyWrite,
    766                                       PaUtil_DummyGetReadAvailable,
    767                                       PaUtil_DummyGetWriteAvailable );
    768 
    769     PaUtil_InitializeStreamInterface( &jackHostApi->blockingStreamInterface, CloseStream, StartStream,
    770                                       StopStream, AbortStream, IsStreamStopped, IsStreamActive,
    771                                       GetStreamTime, PaUtil_DummyGetCpuLoad,
    772                                       BlockingReadStream, BlockingWriteStream,
    773                                       BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable );
    774 
    775     jackHostApi->inputBase = jackHostApi->outputBase = 0;
    776     jackHostApi->xrun = 0;
    777     jackHostApi->toAdd = jackHostApi->toRemove = NULL;
    778     jackHostApi->processQueue = NULL;
    779     jackHostApi->jackIsDown = 0;
    780 
    781     jack_on_shutdown( jackHostApi->jack_client, JackOnShutdown, jackHostApi );
    782     jack_set_error_function( JackErrorCallback );
    783     jackHostApi->jack_buffer_size = jack_get_buffer_size ( jackHostApi->jack_client );
    784     /* Don't check for error, may not be supported (deprecated in at least jackdmp) */
    785     jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi );
    786     UNLESS( !jack_set_xrun_callback( jackHostApi->jack_client, JackXRunCb, jackHostApi ), paUnanticipatedHostError );
    787     UNLESS( !jack_set_process_callback( jackHostApi->jack_client, JackCallback, jackHostApi ), paUnanticipatedHostError );
    788     UNLESS( !jack_activate( jackHostApi->jack_client ), paUnanticipatedHostError );
    789     activated = 1;
    790 
    791     return result;
    792 
    793 error:
    794     if( activated )
    795         ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
    796 
    797     if( jackHostApi )
    798     {
    799         if( jackHostApi->jack_client )
    800             ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
    801 
    802         if( jackHostApi->deviceInfoMemory )
    803         {
    804             PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
    805             PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
    806         }
    807 
    808         PaUtil_FreeMemory( jackHostApi );
    809     }
    810     return result;
    811 }
    812 
    813 
    814 static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
    815 {
    816     PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
    817 
    818     /* note: this automatically disconnects all ports, since a deactivated
    819      * client is not allowed to have any ports connected */
    820     ASSERT_CALL( jack_deactivate( jackHostApi->jack_client ), 0 );
    821 
    822     ASSERT_CALL( pthread_mutex_destroy( &jackHostApi->mtx ), 0 );
    823     ASSERT_CALL( pthread_cond_destroy( &jackHostApi->cond ), 0 );
    824 
    825     ASSERT_CALL( jack_client_close( jackHostApi->jack_client ), 0 );
    826 
    827     if( jackHostApi->deviceInfoMemory )
    828     {
    829         PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory );
    830         PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory );
    831     }
    832 
    833     PaUtil_FreeMemory( jackHostApi );
    834 
    835     free( jackErr_ );
    836     jackErr_ = NULL;
    837 }
    838 
    839 static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
    840                                   const PaStreamParameters *inputParameters,
    841                                   const PaStreamParameters *outputParameters,
    842                                   double sampleRate )
    843 {
    844     int inputChannelCount = 0, outputChannelCount = 0;
    845     PaSampleFormat inputSampleFormat, outputSampleFormat;
    846 
    847     if( inputParameters )
    848     {
    849         inputChannelCount = inputParameters->channelCount;
    850         inputSampleFormat = inputParameters->sampleFormat;
    851 
    852         /* unless alternate device specification is supported, reject the use of
    853             paUseHostApiSpecificDeviceSpecification */
    854 
    855         if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
    856             return paInvalidDevice;
    857 
    858         /* check that input device can support inputChannelCount */
    859         if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
    860             return paInvalidChannelCount;
    861 
    862         /* validate inputStreamInfo */
    863         if( inputParameters->hostApiSpecificStreamInfo )
    864             return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    865     }
    866     else
    867     {
    868         inputChannelCount = 0;
    869     }
    870 
    871     if( outputParameters )
    872     {
    873         outputChannelCount = outputParameters->channelCount;
    874         outputSampleFormat = outputParameters->sampleFormat;
    875 
    876         /* unless alternate device specification is supported, reject the use of
    877             paUseHostApiSpecificDeviceSpecification */
    878 
    879         if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
    880             return paInvalidDevice;
    881 
    882         /* check that output device can support inputChannelCount */
    883         if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
    884             return paInvalidChannelCount;
    885 
    886         /* validate outputStreamInfo */
    887         if( outputParameters->hostApiSpecificStreamInfo )
    888             return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    889     }
    890     else
    891     {
    892         outputChannelCount = 0;
    893     }
    894 
    895     /*
    896         The following check is not necessary for JACK.
    897 
    898             - if a full duplex stream is requested, check that the combination
    899                 of input and output parameters is supported
    900 
    901 
    902         Because the buffer adapter handles conversion between all standard
    903         sample formats, the following checks are only required if paCustomFormat
    904         is implemented, or under some other unusual conditions.
    905 
    906             - check that input device can support inputSampleFormat, or that
    907                 we have the capability to convert from outputSampleFormat to
    908                 a native format
    909 
    910             - check that output device can support outputSampleFormat, or that
    911                 we have the capability to convert from outputSampleFormat to
    912                 a native format
    913     */
    914 
    915     /* check that the device supports sampleRate */
    916 
    917 #define ABS(x) ( (x) > 0 ? (x) : -(x) )
    918     if( ABS(sampleRate - jack_get_sample_rate(((PaJackHostApiRepresentation *) hostApi)->jack_client )) > 1 )
    919        return paInvalidSampleRate;
    920 #undef ABS
    921 
    922     return paFormatIsSupported;
    923 }
    924 
    925 /* Basic stream initialization */
    926 static PaError InitializeStream( PaJackStream *stream, PaJackHostApiRepresentation *hostApi, int numInputChannels,
    927         int numOutputChannels )
    928 {
    929     PaError result = paNoError;
    930     assert( stream );
    931 
    932     memset( stream, 0, sizeof (PaJackStream) );
    933     UNLESS( stream->stream_memory = PaUtil_CreateAllocationGroup(), paInsufficientMemory );
    934     stream->jack_client = hostApi->jack_client;
    935     stream->hostApi = hostApi;
    936 
    937     if( numInputChannels > 0 )
    938     {
    939         UNLESS( stream->local_input_ports =
    940                 (jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numInputChannels ),
    941                 paInsufficientMemory );
    942         memset( stream->local_input_ports, 0, sizeof(jack_port_t*) * numInputChannels );
    943         UNLESS( stream->remote_output_ports =
    944                 (jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numInputChannels ),
    945                 paInsufficientMemory );
    946         memset( stream->remote_output_ports, 0, sizeof(jack_port_t*) * numInputChannels );
    947     }
    948     if( numOutputChannels > 0 )
    949     {
    950         UNLESS( stream->local_output_ports =
    951                 (jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numOutputChannels ),
    952                 paInsufficientMemory );
    953         memset( stream->local_output_ports, 0, sizeof(jack_port_t*) * numOutputChannels );
    954         UNLESS( stream->remote_input_ports =
    955                 (jack_port_t**) PaUtil_GroupAllocateMemory( stream->stream_memory, sizeof(jack_port_t*) * numOutputChannels ),
    956                 paInsufficientMemory );
    957         memset( stream->remote_input_ports, 0, sizeof(jack_port_t*) * numOutputChannels );
    958     }
    959 
    960     stream->num_incoming_connections = numInputChannels;
    961     stream->num_outgoing_connections = numOutputChannels;
    962 
    963 error:
    964     return result;
    965 }
    966 
    967 /*!
    968  * Free resources associated with stream, and eventually stream itself.
    969  *
    970  * Frees allocated memory, and closes opened pcms.
    971  */
    972 static void CleanUpStream( PaJackStream *stream, int terminateStreamRepresentation, int terminateBufferProcessor )
    973 {
    974     int i;
    975     assert( stream );
    976 
    977     if( stream->isBlockingStream )
    978         BlockingEnd( stream );
    979 
    980     for( i = 0; i < stream->num_incoming_connections; ++i )
    981     {
    982         if( stream->local_input_ports[i] )
    983             ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_input_ports[i] ), 0 );
    984     }
    985     for( i = 0; i < stream->num_outgoing_connections; ++i )
    986     {
    987         if( stream->local_output_ports[i] )
    988             ASSERT_CALL( jack_port_unregister( stream->jack_client, stream->local_output_ports[i] ), 0 );
    989     }
    990 
    991     if( terminateStreamRepresentation )
    992         PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
    993     if( terminateBufferProcessor )
    994         PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
    995 
    996     if( stream->stream_memory )
    997     {
    998         PaUtil_FreeAllAllocations( stream->stream_memory );
    999         PaUtil_DestroyAllocationGroup( stream->stream_memory );
   1000     }
   1001     PaUtil_FreeMemory( stream );
   1002 }
   1003 
   1004 static PaError WaitCondition( PaJackHostApiRepresentation *hostApi )
   1005 {
   1006     PaError result = paNoError;
   1007     int err = 0;
   1008     PaTime pt = PaUtil_GetTime();
   1009     struct timespec ts;
   1010 
   1011     ts.tv_sec = (time_t) floor( pt + 10 * 60 /* 10 minutes */ );
   1012     ts.tv_nsec = (long) ((pt - floor( pt )) * 1000000000);
   1013     /* XXX: Best enclose in loop, in case of spurious wakeups? */
   1014     err = pthread_cond_timedwait( &hostApi->cond, &hostApi->mtx, &ts );
   1015 
   1016     /* Make sure we didn't time out */
   1017     UNLESS( err != ETIMEDOUT, paTimedOut );
   1018     UNLESS( !err, paInternalError );
   1019 
   1020 error:
   1021     return result;
   1022 }
   1023 
   1024 static PaError AddStream( PaJackStream *stream )
   1025 {
   1026     PaError result = paNoError;
   1027     PaJackHostApiRepresentation *hostApi = stream->hostApi;
   1028     /* Add to queue of streams that should be processed */
   1029     ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
   1030     if( !hostApi->jackIsDown )
   1031     {
   1032         hostApi->toAdd = stream;
   1033         /* Unlock mutex and await signal from processing thread */
   1034         result = WaitCondition( stream->hostApi );
   1035     }
   1036     ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
   1037     ENSURE_PA( result );
   1038 
   1039     UNLESS( !hostApi->jackIsDown, paDeviceUnavailable );
   1040 
   1041 error:
   1042     return result;
   1043 }
   1044 
   1045 /* Remove stream from processing queue */
   1046 static PaError RemoveStream( PaJackStream *stream )
   1047 {
   1048     PaError result = paNoError;
   1049     PaJackHostApiRepresentation *hostApi = stream->hostApi;
   1050 
   1051     /* Add to queue over streams that should be processed */
   1052     ASSERT_CALL( pthread_mutex_lock( &hostApi->mtx ), 0 );
   1053     if( !hostApi->jackIsDown )
   1054     {
   1055         hostApi->toRemove = stream;
   1056         /* Unlock mutex and await signal from processing thread */
   1057         result = WaitCondition( stream->hostApi );
   1058     }
   1059     ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
   1060     ENSURE_PA( result );
   1061 
   1062 error:
   1063     return result;
   1064 }
   1065 
   1066 /* Add stream to JACK callback processing queue */
   1067 static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
   1068                            PaStream** s,
   1069                            const PaStreamParameters *inputParameters,
   1070                            const PaStreamParameters *outputParameters,
   1071                            double sampleRate,
   1072                            unsigned long framesPerBuffer,
   1073                            PaStreamFlags streamFlags,
   1074                            PaStreamCallback *streamCallback,
   1075                            void *userData )
   1076 {
   1077     PaError result = paNoError;
   1078     PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
   1079     PaJackStream *stream = NULL;
   1080     char *port_string = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_port_name_size() );
   1081     unsigned long regexSz = jack_client_name_size() + 3;
   1082     char *regex_pattern = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, regexSz );
   1083     const char **jack_ports = NULL;
   1084     /* int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); */
   1085     int i;
   1086     int inputChannelCount, outputChannelCount;
   1087     const double jackSr = jack_get_sample_rate( jackHostApi->jack_client );
   1088     PaSampleFormat inputSampleFormat = 0, outputSampleFormat = 0;
   1089     int bpInitialized = 0, srInitialized = 0;   /* Initialized buffer processor and stream representation? */
   1090     unsigned long ofs;
   1091 
   1092     /* validate platform specific flags */
   1093     if( (streamFlags & paPlatformSpecificFlags) != 0 )
   1094         return paInvalidFlag; /* unexpected platform specific flag */
   1095     if( (streamFlags & paPrimeOutputBuffersUsingStreamCallback) != 0 )
   1096     {
   1097         streamFlags &= ~paPrimeOutputBuffersUsingStreamCallback;
   1098         /*return paInvalidFlag;*/   /* This implementation does not support buffer priming */
   1099     }
   1100 
   1101     if( framesPerBuffer != paFramesPerBufferUnspecified )
   1102     {
   1103         /* Jack operates with power of two buffers, and we don't support non-integer buffer adaption (yet) */
   1104         /*UNLESS( !(framesPerBuffer & (framesPerBuffer - 1)), paBufferTooBig );*/  /* TODO: Add descriptive error code? */
   1105     }
   1106 
   1107     /* Preliminary checks */
   1108 
   1109     if( inputParameters )
   1110     {
   1111         inputChannelCount = inputParameters->channelCount;
   1112         inputSampleFormat = inputParameters->sampleFormat;
   1113 
   1114         /* unless alternate device specification is supported, reject the use of
   1115             paUseHostApiSpecificDeviceSpecification */
   1116 
   1117         if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
   1118             return paInvalidDevice;
   1119 
   1120         /* check that input device can support inputChannelCount */
   1121         if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
   1122             return paInvalidChannelCount;
   1123 
   1124         /* validate inputStreamInfo */
   1125         if( inputParameters->hostApiSpecificStreamInfo )
   1126             return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
   1127     }
   1128     else
   1129     {
   1130         inputChannelCount = 0;
   1131     }
   1132 
   1133     if( outputParameters )
   1134     {
   1135         outputChannelCount = outputParameters->channelCount;
   1136         outputSampleFormat = outputParameters->sampleFormat;
   1137 
   1138         /* unless alternate device specification is supported, reject the use of
   1139             paUseHostApiSpecificDeviceSpecification */
   1140 
   1141         if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
   1142             return paInvalidDevice;
   1143 
   1144         /* check that output device can support inputChannelCount */
   1145         if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
   1146             return paInvalidChannelCount;
   1147 
   1148         /* validate outputStreamInfo */
   1149         if( outputParameters->hostApiSpecificStreamInfo )
   1150             return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
   1151     }
   1152     else
   1153     {
   1154         outputChannelCount = 0;
   1155     }
   1156 
   1157     /* ... check that the sample rate exactly matches the ONE acceptable rate
   1158      * A: This rate isn't necessarily constant though? */
   1159 
   1160 #define ABS(x) ( (x) > 0 ? (x) : -(x) )
   1161     if( ABS(sampleRate - jackSr) > 1 )
   1162        return paInvalidSampleRate;
   1163 #undef ABS
   1164 
   1165     UNLESS( stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ), paInsufficientMemory );
   1166     ENSURE_PA( InitializeStream( stream, jackHostApi, inputChannelCount, outputChannelCount ) );
   1167 
   1168     /* the blocking emulation, if necessary */
   1169     stream->isBlockingStream = !streamCallback;
   1170     if( stream->isBlockingStream )
   1171     {
   1172         float latency = 0.001; /* 1ms is the absolute minimum we support */
   1173         int   minimum_buffer_frames = 0;
   1174 
   1175         if( inputParameters && inputParameters->suggestedLatency > latency )
   1176             latency = inputParameters->suggestedLatency;
   1177         else if( outputParameters && outputParameters->suggestedLatency > latency )
   1178             latency = outputParameters->suggestedLatency;
   1179 
   1180         /* the latency the user asked for indicates the minimum buffer size in frames */
   1181         minimum_buffer_frames = (int) (latency * jack_get_sample_rate( jackHostApi->jack_client ));
   1182 
   1183         /* we also need to be able to store at least three full jack buffers to avoid dropouts */
   1184         if( jackHostApi->jack_buffer_size * 3 > minimum_buffer_frames )
   1185             minimum_buffer_frames = jackHostApi->jack_buffer_size * 3;
   1186 
   1187         /* setup blocking API data structures (FIXME: can fail) */
   1188         BlockingBegin( stream, minimum_buffer_frames );
   1189 
   1190         /* install our own callback for the blocking API */
   1191         streamCallback = BlockingCallback;
   1192         userData = stream;
   1193 
   1194         PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
   1195                                                &jackHostApi->blockingStreamInterface, streamCallback, userData );
   1196     }
   1197     else
   1198     {
   1199         PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
   1200                                                &jackHostApi->callbackStreamInterface, streamCallback, userData );
   1201     }
   1202     srInitialized = 1;
   1203     PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, jackSr );
   1204 
   1205     /* create the JACK ports.  We cannot connect them until audio
   1206      * processing begins */
   1207 
   1208     /* Register a unique set of ports for this stream
   1209      * TODO: Robust allocation of new port names */
   1210 
   1211     ofs = jackHostApi->inputBase;
   1212     for( i = 0; i < inputChannelCount; i++ )
   1213     {
   1214         snprintf( port_string, jack_port_name_size(), "in_%lu", ofs + i );
   1215         UNLESS( stream->local_input_ports[i] = jack_port_register(
   1216               jackHostApi->jack_client, port_string,
   1217               JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ), paInsufficientMemory );
   1218     }
   1219     jackHostApi->inputBase += inputChannelCount;
   1220 
   1221     ofs = jackHostApi->outputBase;
   1222     for( i = 0; i < outputChannelCount; i++ )
   1223     {
   1224         snprintf( port_string, jack_port_name_size(), "out_%lu", ofs + i );
   1225         UNLESS( stream->local_output_ports[i] = jack_port_register(
   1226              jackHostApi->jack_client, port_string,
   1227              JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ), paInsufficientMemory );
   1228     }
   1229     jackHostApi->outputBase += outputChannelCount;
   1230 
   1231     /* look up the jack_port_t's for the remote ports.  We could do
   1232      * this at stream start time, but doing it here ensures the
   1233      * name lookup only happens once. */
   1234 
   1235     if( inputChannelCount > 0 )
   1236     {
   1237         int err = 0;
   1238 
   1239         /* Get output ports of our capture device */
   1240         snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
   1241         UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
   1242                                      JACK_PORT_TYPE_FILTER, JackPortIsOutput ), paUnanticipatedHostError );
   1243         for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
   1244         {
   1245             if( (stream->remote_output_ports[i] = jack_port_by_name(
   1246                  jackHostApi->jack_client, jack_ports[i] )) == NULL )
   1247             {
   1248                 err = 1;
   1249                 break;
   1250             }
   1251         }
   1252         free( jack_ports );
   1253         UNLESS( !err, paInsufficientMemory );
   1254 
   1255         /* Fewer ports than expected? */
   1256         UNLESS( i == inputChannelCount, paInternalError );
   1257     }
   1258 
   1259     if( outputChannelCount > 0 )
   1260     {
   1261         int err = 0;
   1262 
   1263         /* Get input ports of our playback device */
   1264         snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
   1265         UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
   1266                                      JACK_PORT_TYPE_FILTER, JackPortIsInput ), paUnanticipatedHostError );
   1267         for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )
   1268         {
   1269             if( (stream->remote_input_ports[i] = jack_port_by_name(
   1270                  jackHostApi->jack_client, jack_ports[i] )) == 0 )
   1271             {
   1272                 err = 1;
   1273                 break;
   1274             }
   1275         }
   1276         free( jack_ports );
   1277         UNLESS( !err , paInsufficientMemory );
   1278 
   1279         /* Fewer ports than expected? */
   1280         UNLESS( i == outputChannelCount, paInternalError );
   1281     }
   1282 
   1283     ENSURE_PA( PaUtil_InitializeBufferProcessor(
   1284                   &stream->bufferProcessor,
   1285                   inputChannelCount,
   1286                   inputSampleFormat,
   1287                   paFloat32 | paNonInterleaved, /* hostInputSampleFormat */
   1288                   outputChannelCount,
   1289                   outputSampleFormat,
   1290                   paFloat32 | paNonInterleaved, /* hostOutputSampleFormat */
   1291                   jackSr,
   1292                   streamFlags,
   1293                   framesPerBuffer,
   1294                   0,                            /* Ignored */
   1295                   paUtilUnknownHostBufferSize,  /* Buffer size may vary on JACK's discretion */
   1296                   streamCallback,
   1297                   userData ) );
   1298     bpInitialized = 1;
   1299 
   1300     if( stream->num_incoming_connections > 0 )
   1301         stream->streamRepresentation.streamInfo.inputLatency = (jack_port_get_latency( stream->remote_output_ports[0] )
   1302                 - jack_get_buffer_size( jackHostApi->jack_client )  /* One buffer is not counted as latency */
   1303             + PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor )) / sampleRate;
   1304     if( stream->num_outgoing_connections > 0 )
   1305         stream->streamRepresentation.streamInfo.outputLatency = (jack_port_get_latency( stream->remote_input_ports[0] )
   1306                 - jack_get_buffer_size( jackHostApi->jack_client )  /* One buffer is not counted as latency */
   1307             + PaUtil_GetBufferProcessorOutputLatencyFrames( &stream->bufferProcessor )) / sampleRate;
   1308 
   1309     stream->streamRepresentation.streamInfo.sampleRate = jackSr;
   1310     stream->t0 = jack_frame_time( jackHostApi->jack_client );   /* A: Time should run from Pa_OpenStream */
   1311 
   1312     /* Add to queue of opened streams */
   1313     ENSURE_PA( AddStream( stream ) );
   1314 
   1315     *s = (PaStream*)stream;
   1316 
   1317     return result;
   1318 
   1319 error:
   1320     if( stream )
   1321         CleanUpStream( stream, srInitialized, bpInitialized );
   1322 
   1323     return result;
   1324 }
   1325 
   1326 /*
   1327     When CloseStream() is called, the multi-api layer ensures that
   1328     the stream has already been stopped or aborted.
   1329 */
   1330 static PaError CloseStream( PaStream* s )
   1331 {
   1332     PaError result = paNoError;
   1333     PaJackStream *stream = (PaJackStream*)s;
   1334 
   1335     /* Remove this stream from the processing queue */
   1336     ENSURE_PA( RemoveStream( stream ) );
   1337 
   1338 error:
   1339     CleanUpStream( stream, 1, 1 );
   1340     return result;
   1341 }
   1342 
   1343 static PaError RealProcess( PaJackStream *stream, jack_nframes_t frames )
   1344 {
   1345     PaError result = paNoError;
   1346     PaStreamCallbackTimeInfo timeInfo = {0,0,0};
   1347     int chn;
   1348     int framesProcessed;
   1349     const double sr = jack_get_sample_rate( stream->jack_client );    /* Shouldn't change during the process callback */
   1350     PaStreamCallbackFlags cbFlags = 0;
   1351 
   1352     /* If the user has returned !paContinue from the callback we'll want to flush the internal buffers,
   1353      * when these are empty we can finally mark the stream as inactive */
   1354     if( stream->callbackResult != paContinue &&
   1355             PaUtil_IsBufferProcessorOutputEmpty( &stream->bufferProcessor ) )
   1356     {
   1357         stream->is_active = 0;
   1358         if( stream->streamRepresentation.streamFinishedCallback )
   1359             stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
   1360         PA_DEBUG(( "%s: Callback finished\n", __FUNCTION__ ));
   1361 
   1362         goto end;
   1363     }
   1364 
   1365     timeInfo.currentTime = (jack_frame_time( stream->jack_client ) - stream->t0) / sr;
   1366     if( stream->num_incoming_connections > 0 )
   1367         timeInfo.inputBufferAdcTime = timeInfo.currentTime - jack_port_get_latency( stream->remote_output_ports[0] )
   1368             / sr;
   1369     if( stream->num_outgoing_connections > 0 )
   1370         timeInfo.outputBufferDacTime = timeInfo.currentTime + jack_port_get_latency( stream->remote_input_ports[0] )
   1371             / sr;
   1372 
   1373     PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
   1374 
   1375     if( stream->xrun )
   1376     {
   1377         /* XXX: Any way to tell which of these occurred? */
   1378         cbFlags = paOutputUnderflow | paInputOverflow;
   1379         stream->xrun = FALSE;
   1380     }
   1381     PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,
   1382             cbFlags );
   1383 
   1384     if( stream->num_incoming_connections > 0 )
   1385         PaUtil_SetInputFrameCount( &stream->bufferProcessor, frames );
   1386     if( stream->num_outgoing_connections > 0 )
   1387         PaUtil_SetOutputFrameCount( &stream->bufferProcessor, frames );
   1388 
   1389     for( chn = 0; chn < stream->num_incoming_connections; chn++ )
   1390     {
   1391         jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
   1392             jack_port_get_buffer( stream->local_input_ports[chn],
   1393                     frames );
   1394 
   1395         PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor,
   1396                 chn,
   1397                 channel_buf );
   1398     }
   1399 
   1400     for( chn = 0; chn < stream->num_outgoing_connections; chn++ )
   1401     {
   1402         jack_default_audio_sample_t *channel_buf = (jack_default_audio_sample_t*)
   1403             jack_port_get_buffer( stream->local_output_ports[chn],
   1404                     frames );
   1405 
   1406         PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor,
   1407                 chn,
   1408                 channel_buf );
   1409     }
   1410 
   1411     framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,
   1412             &stream->callbackResult );
   1413     /* We've specified a host buffer size mode where every frame should be consumed by the buffer processor */
   1414     assert( framesProcessed == frames );
   1415 
   1416     PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
   1417 
   1418 end:
   1419     return result;
   1420 }
   1421 
   1422 /* Update the JACK callback's stream processing queue. */
   1423 static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
   1424 {
   1425     PaError result = paNoError;
   1426     int queueModified = 0;
   1427     const double jackSr = jack_get_sample_rate( hostApi->jack_client );
   1428     int err;
   1429 
   1430     if( (err = pthread_mutex_trylock( &hostApi->mtx )) != 0 )
   1431     {
   1432         assert( err == EBUSY );
   1433         return paNoError;
   1434     }
   1435 
   1436     if( hostApi->toAdd )
   1437     {
   1438         if( hostApi->processQueue )
   1439         {
   1440             PaJackStream *node = hostApi->processQueue;
   1441             /* Advance to end of queue */
   1442             while( node->next )
   1443                 node = node->next;
   1444 
   1445             node->next = hostApi->toAdd;
   1446         }
   1447         else
   1448         {
   1449             /* The only queue entry. */
   1450             hostApi->processQueue = (PaJackStream *)hostApi->toAdd;
   1451         }
   1452 
   1453         /* If necessary, update stream state */
   1454         if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr )
   1455             UpdateSampleRate( hostApi->toAdd, jackSr );
   1456 
   1457         hostApi->toAdd = NULL;
   1458         queueModified = 1;
   1459     }
   1460     if( hostApi->toRemove )
   1461     {
   1462         int removed = 0;
   1463         PaJackStream *node = hostApi->processQueue, *prev = NULL;
   1464         assert( hostApi->processQueue );
   1465 
   1466         while( node )
   1467         {
   1468             if( node == hostApi->toRemove )
   1469             {
   1470                 if( prev )
   1471                     prev->next = node->next;
   1472                 else
   1473                     hostApi->processQueue = (PaJackStream *)node->next;
   1474 
   1475                 removed = 1;
   1476                 break;
   1477             }
   1478 
   1479             prev = node;
   1480             node = node->next;
   1481         }
   1482         UNLESS( removed, paInternalError );
   1483         hostApi->toRemove = NULL;
   1484         PA_DEBUG(( "%s: Removed stream from processing queue\n", __FUNCTION__ ));
   1485         queueModified = 1;
   1486     }
   1487 
   1488     if( queueModified )
   1489     {
   1490         /* Signal that we've done what was asked of us */
   1491         ASSERT_CALL( pthread_cond_signal( &hostApi->cond ), 0 );
   1492     }
   1493 
   1494 error:
   1495     ASSERT_CALL( pthread_mutex_unlock( &hostApi->mtx ), 0 );
   1496 
   1497     return result;
   1498 }
   1499 
   1500 /* Audio processing callback invoked periodically from JACK. */
   1501 static int JackCallback( jack_nframes_t frames, void *userData )
   1502 {
   1503     PaError result = paNoError;
   1504     PaJackHostApiRepresentation *hostApi = (PaJackHostApiRepresentation *)userData;
   1505     PaJackStream *stream = NULL;
   1506     int xrun = hostApi->xrun;
   1507     hostApi->xrun = 0;
   1508 
   1509     assert( hostApi );
   1510 
   1511     ENSURE_PA( UpdateQueue( hostApi ) );
   1512 
   1513     /* Process each stream */
   1514     stream = hostApi->processQueue;
   1515     for( ; stream; stream = stream->next )
   1516     {
   1517         if( xrun )  /* Don't override if already set */
   1518             stream->xrun = 1;
   1519 
   1520         /* See if this stream is to be started */
   1521         if( stream->doStart )
   1522         {
   1523             /* If we can't obtain a lock, we'll try next time */
   1524             int err = pthread_mutex_trylock( &stream->hostApi->mtx );
   1525             if( !err )
   1526             {
   1527                 if( stream->doStart )   /* Could potentially change before obtaining the lock */
   1528                 {
   1529                     stream->is_active = 1;
   1530                     stream->doStart = 0;
   1531                     PA_DEBUG(( "%s: Starting stream\n", __FUNCTION__ ));
   1532                     ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
   1533                     stream->callbackResult = paContinue;
   1534                     stream->isSilenced = 0;
   1535                 }
   1536 
   1537                 ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
   1538             }
   1539             else
   1540                 assert( err == EBUSY );
   1541         }
   1542         else if( stream->doStop || stream->doAbort )    /* Should we stop/abort stream? */
   1543         {
   1544             if( stream->callbackResult == paContinue )     /* Ok, make it stop */
   1545             {
   1546                 PA_DEBUG(( "%s: Stopping stream\n", __FUNCTION__ ));
   1547                 stream->callbackResult = stream->doStop ? paComplete : paAbort;
   1548             }
   1549         }
   1550 
   1551         if( stream->is_active )
   1552             ENSURE_PA( RealProcess( stream, frames ) );
   1553         /* If we have just entered inactive state, silence output */
   1554         if( !stream->is_active && !stream->isSilenced )
   1555         {
   1556             int i;
   1557 
   1558             /* Silence buffer after entering inactive state */
   1559             PA_DEBUG(( "Silencing the output\n" ));
   1560             for( i = 0; i < stream->num_outgoing_connections; ++i )
   1561             {
   1562                 jack_default_audio_sample_t *buffer = jack_port_get_buffer( stream->local_output_ports[i], frames );
   1563                 memset( buffer, 0, sizeof (jack_default_audio_sample_t) * frames );
   1564             }
   1565 
   1566             stream->isSilenced = 1;
   1567         }
   1568 
   1569         if( stream->doStop || stream->doAbort )
   1570         {
   1571             /* See if RealProcess has acted on the request */
   1572             if( !stream->is_active )   /* Ok, signal to the main thread that we've carried out the operation */
   1573             {
   1574                 /* If we can't obtain a lock, we'll try next time */
   1575                 int err = pthread_mutex_trylock( &stream->hostApi->mtx );
   1576                 if( !err )
   1577                 {
   1578                     stream->doStop = stream->doAbort = 0;
   1579                     ASSERT_CALL( pthread_cond_signal( &stream->hostApi->cond ), 0 );
   1580                     ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
   1581                 }
   1582                 else
   1583                     assert( err == EBUSY );
   1584             }
   1585         }
   1586     }
   1587 
   1588     return 0;
   1589 error:
   1590     return -1;
   1591 }
   1592 
   1593 static PaError StartStream( PaStream *s )
   1594 {
   1595     PaError result = paNoError;
   1596     PaJackStream *stream = (PaJackStream*)s;
   1597     int i;
   1598 
   1599     /* Ready the processor */
   1600     PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
   1601 
   1602     /* Connect the ports. Note that the ports may already have been connected by someone else in
   1603      * the meantime, in which case JACK returns EEXIST. */
   1604 
   1605     if( stream->num_incoming_connections > 0 )
   1606     {
   1607         for( i = 0; i < stream->num_incoming_connections; i++ )
   1608         {
   1609             int r = jack_connect( stream->jack_client, jack_port_name( stream->remote_output_ports[i] ),
   1610                     jack_port_name( stream->local_input_ports[i] ) );
   1611            UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
   1612         }
   1613     }
   1614 
   1615     if( stream->num_outgoing_connections > 0 )
   1616     {
   1617         for( i = 0; i < stream->num_outgoing_connections; i++ )
   1618         {
   1619             int r = jack_connect( stream->jack_client, jack_port_name( stream->local_output_ports[i] ),
   1620                     jack_port_name( stream->remote_input_ports[i] ) );
   1621            UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
   1622         }
   1623     }
   1624 
   1625     stream->xrun = FALSE;
   1626 
   1627     /* Enable processing */
   1628 
   1629     ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
   1630     stream->doStart = 1;
   1631 
   1632     /* Wait for stream to be started */
   1633     result = WaitCondition( stream->hostApi );
   1634     /*
   1635     do
   1636     {
   1637         err = pthread_cond_timedwait( &stream->hostApi->cond, &stream->hostApi->mtx, &ts );
   1638     } while( !stream->is_active && !err );
   1639     */
   1640     if( result != paNoError )   /* Something went wrong, call off the stream start */
   1641     {
   1642         stream->doStart = 0;
   1643         stream->is_active = 0;  /* Cancel any processing */
   1644     }
   1645     ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
   1646 
   1647     ENSURE_PA( result );
   1648 
   1649     stream->is_running = TRUE;
   1650     PA_DEBUG(( "%s: Stream started\n", __FUNCTION__ ));
   1651 
   1652 error:
   1653     return result;
   1654 }
   1655 
   1656 static PaError RealStop( PaJackStream *stream, int abort )
   1657 {
   1658     PaError result = paNoError;
   1659     int i;
   1660 
   1661     if( stream->isBlockingStream )
   1662         BlockingWaitEmpty ( stream );
   1663 
   1664     ASSERT_CALL( pthread_mutex_lock( &stream->hostApi->mtx ), 0 );
   1665     if( abort )
   1666         stream->doAbort = 1;
   1667     else
   1668         stream->doStop = 1;
   1669 
   1670     /* Wait for stream to be stopped */
   1671     result = WaitCondition( stream->hostApi );
   1672     ASSERT_CALL( pthread_mutex_unlock( &stream->hostApi->mtx ), 0 );
   1673     ENSURE_PA( result );
   1674 
   1675     UNLESS( !stream->is_active, paInternalError );
   1676 
   1677     PA_DEBUG(( "%s: Stream stopped\n", __FUNCTION__ ));
   1678 
   1679 error:
   1680     stream->is_running = FALSE;
   1681 
   1682     /* Disconnect ports belonging to this stream */
   1683 
   1684     if( !stream->hostApi->jackIsDown )  /* XXX: Well? */
   1685     {
   1686         for( i = 0; i < stream->num_incoming_connections; i++ )
   1687         {
   1688             if( jack_port_connected( stream->local_input_ports[i] ) )
   1689             {
   1690                 UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ),
   1691                         paUnanticipatedHostError );
   1692             }
   1693         }
   1694         for( i = 0; i < stream->num_outgoing_connections; i++ )
   1695         {
   1696             if( jack_port_connected( stream->local_output_ports[i] ) )
   1697             {
   1698                 UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ),
   1699                         paUnanticipatedHostError );
   1700             }
   1701         }
   1702     }
   1703 
   1704     return result;
   1705 }
   1706 
   1707 static PaError StopStream( PaStream *s )
   1708 {
   1709     assert(s);
   1710     return RealStop( (PaJackStream *)s, 0 );
   1711 }
   1712 
   1713 static PaError AbortStream( PaStream *s )
   1714 {
   1715     assert(s);
   1716     return RealStop( (PaJackStream *)s, 1 );
   1717 }
   1718 
   1719 static PaError IsStreamStopped( PaStream *s )
   1720 {
   1721     PaJackStream *stream = (PaJackStream*)s;
   1722     return !stream->is_running;
   1723 }
   1724 
   1725 
   1726 static PaError IsStreamActive( PaStream *s )
   1727 {
   1728     PaJackStream *stream = (PaJackStream*)s;
   1729     return stream->is_active;
   1730 }
   1731 
   1732 
   1733 static PaTime GetStreamTime( PaStream *s )
   1734 {
   1735     PaJackStream *stream = (PaJackStream*)s;
   1736 
   1737     /* A: Is this relevant?? --> TODO: what if we're recording-only? */
   1738     return (jack_frame_time( stream->jack_client ) - stream->t0) / (PaTime)jack_get_sample_rate( stream->jack_client );
   1739 }
   1740 
   1741 
   1742 static double GetStreamCpuLoad( PaStream* s )
   1743 {
   1744     PaJackStream *stream = (PaJackStream*)s;
   1745     return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
   1746 }
   1747 
   1748 PaError PaJack_SetClientName( const char* name )
   1749 {
   1750     if( strlen( name ) > jack_client_name_size() )
   1751     {
   1752         /* OK, I don't know any better error code */
   1753         return paInvalidFlag;
   1754     }
   1755     clientName_ = name;
   1756     return paNoError;
   1757 }
   1758 
   1759 PaError PaJack_GetClientName(const char** clientName)
   1760 {
   1761     PaError result = paNoError;
   1762     PaJackHostApiRepresentation* jackHostApi = NULL;
   1763     PaJackHostApiRepresentation** ref = &jackHostApi;
   1764     ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)ref, paJACK ) );
   1765     *clientName = jack_get_client_name( jackHostApi->jack_client );
   1766 
   1767 error:
   1768     return result;
   1769 }