~ubuntu-branches/ubuntu/wily/sflphone/wily-proposed

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/third_party/portaudio/src/hostapi/jack/pa_jack.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}