~ubuntu-branches/ubuntu/gutsy/audacity/gutsy-backports

« back to all changes in this revision

Viewing changes to lib-src/portaudio-v19/src/hostapi/jack/pa_jack.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-18 21:58:19 UTC
  • mfrom: (13.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080218215819-tmbcf1rx238r8gdv
Tags: 1.3.4-1.1ubuntu1~gutsy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: pa_jack.c,v 1.3 2006/09/29 00:09:54 llucius Exp $
 
2
 * $Id: pa_jack.c,v 1.6 2007/08/16 20:45:36 richardash1981 Exp $
3
3
 * PortAudio Portable Real-Time Audio Library
4
4
 * Latest Version at: http://www.portaudio.com
5
5
 * JACK Implementation by Joshua Haberman
32
32
 */
33
33
 
34
34
/*
35
 
 * The text above constitutes the entire PortAudio license; however, 
 
35
 * The text above constitutes the entire PortAudio license; however,
36
36
 * the PortAudio community also makes the following non-binding requests:
37
37
 *
38
38
 * Any person wishing to distribute modifications to the Software is
39
39
 * requested to send the modifications to the original developer so that
40
 
 * they can be incorporated into the canonical version. It is also 
41
 
 * requested that these non-binding requests be included along with the 
 
40
 * they can be incorporated into the canonical version. It is also
 
41
 * requested that these non-binding requests be included along with the
42
42
 * license above.
43
43
 */
44
44
 
45
45
/**
46
46
 @file
47
 
 @ingroup hostaip_src
 
47
 @ingroup hostapi_src
48
48
*/
49
49
 
50
50
#include <string.h>
68
68
#include "pa_process.h"
69
69
#include "pa_allocation.h"
70
70
#include "pa_cpuload.h"
71
 
#include "../pablio/ringbuffer.c"
 
71
#include "pa_ringbuffer.h"
 
72
#include "pa_debugprint.h"
72
73
 
73
74
static int aErr_;
74
75
static PaError paErr_;     /* For use with ENSURE_PA */
75
76
static pthread_t mainThread_;
76
77
static char *jackErr_ = NULL;
 
78
static const char* clientName_ = "PortAudio";
77
79
 
78
80
#define STRINGIZE_HELPER(expr) #expr
79
81
#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
85
87
        { \
86
88
            if( (paErr_) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
87
89
            { \
88
 
                assert( jackErr_ ); \
 
90
                if (! jackErr_ ) jackErr_ = "unknown error";\
89
91
                PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
90
92
            } \
91
93
            PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
100
102
        { \
101
103
            if( (code) == paUnanticipatedHostError && pthread_self() == mainThread_ ) \
102
104
            { \
103
 
                assert( jackErr_ ); \
 
105
                if (!jackErr_) jackErr_ = "unknown error";\
104
106
                PaUtil_SetLastHostErrorInfo( paJACK, -1, jackErr_ ); \
105
107
            } \
106
108
            PaUtil_DebugPrint(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \
216
218
    /* These are useful for the blocking API */
217
219
 
218
220
    int                     isBlockingStream;
219
 
    RingBuffer              inFIFO;
220
 
    RingBuffer              outFIFO;
 
221
    PaUtilRingBuffer        inFIFO;
 
222
    PaUtilRingBuffer        outFIFO;
221
223
    volatile sig_atomic_t   data_available;
222
224
    sem_t                   data_semaphore;
223
225
    int                     bytesPerFrame;
246
248
/* ---- blocking emulation layer ---- */
247
249
 
248
250
/* Allocate buffer. */
249
 
static PaError BlockingInitFIFO( RingBuffer *rbuf, long numFrames, long bytesPerFrame )
 
251
static PaError BlockingInitFIFO( PaUtilRingBuffer *rbuf, long numFrames, long bytesPerFrame )
250
252
{
251
253
    long numBytes = numFrames * bytesPerFrame;
252
254
    char *buffer = (char *) malloc( numBytes );
253
255
    if( buffer == NULL ) return paInsufficientMemory;
254
256
    memset( buffer, 0, numBytes );
255
 
    return (PaError) RingBuffer_Init( rbuf, numBytes, buffer );
 
257
    return (PaError) PaUtil_InitializeRingBuffer( rbuf, numBytes, buffer );
256
258
}
257
259
 
258
260
/* Free buffer. */
259
 
static PaError BlockingTermFIFO( RingBuffer *rbuf )
 
261
static PaError BlockingTermFIFO( PaUtilRingBuffer *rbuf )
260
262
{
261
263
    if( rbuf->buffer ) free( rbuf->buffer );
262
264
    rbuf->buffer = NULL;
277
279
    /* This may get called with NULL inputBuffer during initial setup. */
278
280
    if( inputBuffer != NULL )
279
281
    {
280
 
        RingBuffer_Write( &stream->inFIFO, inputBuffer, numBytes );
 
282
        PaUtil_WriteRingBuffer( &stream->inFIFO, inputBuffer, numBytes );
281
283
    }
282
284
    if( outputBuffer != NULL )
283
285
    {
284
 
        int numRead = RingBuffer_Read( &stream->outFIFO, outputBuffer, numBytes );
 
286
        int numRead = PaUtil_ReadRingBuffer( &stream->outFIFO, outputBuffer, numBytes );
285
287
        /* Zero out remainder of buffer if we run out of data. */
286
288
        memset( (char *)outputBuffer + numRead, 0, numBytes - numRead );
287
289
    }
323
325
        ENSURE_PA( BlockingInitFIFO( &stream->outFIFO, numFrames, stream->bytesPerFrame ) );
324
326
 
325
327
        /* Make Write FIFO appear full initially. */
326
 
        numBytes = RingBuffer_GetWriteAvailable( &stream->outFIFO );
327
 
        RingBuffer_AdvanceWriteIndex( &stream->outFIFO, numBytes );
 
328
        numBytes = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
 
329
        PaUtil_AdvanceRingBufferWriteIndex( &stream->outFIFO, numBytes );
328
330
    }
329
331
 
330
332
    stream->data_available = 0;
353
355
    long numBytes = stream->bytesPerFrame * numFrames;
354
356
    while( numBytes > 0 )
355
357
    {
356
 
        bytesRead = RingBuffer_Read( &stream->inFIFO, p, numBytes );
 
358
        bytesRead = PaUtil_ReadRingBuffer( &stream->inFIFO, p, numBytes );
357
359
        numBytes -= bytesRead;
358
360
        p += bytesRead;
359
361
        if( numBytes > 0 )
378
380
    long numBytes = stream->bytesPerFrame * numFrames;
379
381
    while( numBytes > 0 )
380
382
    {
381
 
        bytesWritten = RingBuffer_Write( &stream->outFIFO, p, numBytes );
 
383
        bytesWritten = PaUtil_WriteRingBuffer( &stream->outFIFO, p, numBytes );
382
384
        numBytes -= bytesWritten;
383
385
        p += bytesWritten;
384
 
        if( numBytes > 0 ) 
 
386
        if( numBytes > 0 )
385
387
        {
386
 
            /* we use the following algorithm: 
 
388
            /* we use the following algorithm:
387
389
             *   (1) write data
388
390
             *   (2) if some data didn't fit into the ringbuffer, set data_available to 0
389
391
             *       to indicate to the audio that if space becomes available, we want to know
412
414
{
413
415
    PaJackStream *stream = (PaJackStream *)s;
414
416
 
415
 
    int bytesFull = RingBuffer_GetReadAvailable( &stream->inFIFO );
 
417
    int bytesFull = PaUtil_GetRingBufferReadAvailable( &stream->inFIFO );
416
418
    return bytesFull / stream->bytesPerFrame;
417
419
}
418
420
 
421
423
{
422
424
    PaJackStream *stream = (PaJackStream *)s;
423
425
 
424
 
    int bytesEmpty = RingBuffer_GetWriteAvailable( &stream->outFIFO );
 
426
    int bytesEmpty = PaUtil_GetRingBufferWriteAvailable( &stream->outFIFO );
425
427
    return bytesEmpty / stream->bytesPerFrame;
426
428
}
427
429
 
430
432
{
431
433
    PaJackStream *stream = (PaJackStream *)s;
432
434
 
433
 
    while( RingBuffer_GetReadAvailable( &stream->outFIFO ) > 0 )
 
435
    while( PaUtil_GetRingBufferReadAvailable( &stream->outFIFO ) > 0 )
434
436
    {
435
437
        stream->data_available = 0;
436
438
        sem_wait( &stream->data_semaphore );
451
453
{
452
454
    /* Utility macros for the repetitive process of allocating memory */
453
455
 
454
 
    /* ... MALLOC: allocate memory as part of the device list
455
 
     * allocation group */
456
 
#define MALLOC(size) \
457
 
     (PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, (size) ))
458
 
 
459
456
    /* JACK has no concept of a device.  To JACK, there are clients
460
457
     * which have an arbitrary number of ports.  To make this
461
458
     * intelligible to PortAudio clients, we will group each JACK client
484
481
     * associated with the previous list */
485
482
    PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
486
483
 
487
 
    regex_pattern = MALLOC( jack_client_name_size() + 3 );
488
 
    tmp_client_name = MALLOC( jack_client_name_size() );
 
484
    regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
 
485
    tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
489
486
 
490
487
    /* We can only retrieve the list of clients indirectly, by first
491
488
     * asking for a list of all ports, then parsing the port names
497
494
    while( jack_ports[numPorts] )
498
495
        ++numPorts;
499
496
    /* At least there will be one port per client :) */
500
 
    UNLESS( client_names = MALLOC( numPorts * sizeof (char *) ), paInsufficientMemory );
 
497
    UNLESS( client_names = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, numPorts *
 
498
                sizeof (char *) ), paInsufficientMemory );
501
499
 
502
500
    /* Build a list of clients from the list of ports */
503
501
    for( numClients = 0, port_index = 0; jack_ports[port_index] != NULL; port_index++ )
524
522
        if (client_seen)
525
523
            continue;   /* A: Nothing to see here, move along */
526
524
 
527
 
        UNLESS( client_names[numClients] = (char*)MALLOC(strlen(tmp_client_name) + 1), paInsufficientMemory );
 
525
        UNLESS( client_names[numClients] = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
 
526
                    strlen(tmp_client_name) + 1), paInsufficientMemory );
528
527
 
529
528
        /* The alsa_pcm client should go in spot 0.  If this
530
529
         * is the alsa_pcm client AND we are NOT about to put
550
549
    /* there is one global sample rate all clients must conform to */
551
550
 
552
551
    globalSampleRate = jack_get_sample_rate( jackApi->jack_client );
553
 
    UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)MALLOC( sizeof(PaDeviceInfo*) *
554
 
                                                     numClients ), paInsufficientMemory );
 
552
    UNLESS( commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
 
553
                sizeof(PaDeviceInfo*) * numClients ), paInsufficientMemory );
555
554
 
556
555
    assert( commonApi->info.deviceCount == 0 );
557
556
 
561
560
        PaDeviceInfo *curDevInfo;
562
561
        const char **clientPorts = NULL;
563
562
 
564
 
        UNLESS( curDevInfo = (PaDeviceInfo*)MALLOC( sizeof(PaDeviceInfo) ), paInsufficientMemory );
565
 
        UNLESS( curDevInfo->name = (char*)MALLOC( strlen(client_names[client_index]) + 1 ), paInsufficientMemory );
 
563
        UNLESS( curDevInfo = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
 
564
                    sizeof(PaDeviceInfo) ), paInsufficientMemory );
 
565
        UNLESS( curDevInfo->name = (char*)PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory,
 
566
                    strlen(client_names[client_index]) + 1 ), paInsufficientMemory );
566
567
        strcpy( (char *)curDevInfo->name, client_names[client_index] );
567
568
 
568
569
        curDevInfo->structVersion = 2;
633
634
    free( jack_ports );
634
635
    return result;
635
636
}
636
 
#undef MALLOC
637
637
 
638
638
static void UpdateSampleRate( PaJackStream *stream, double sampleRate )
639
639
{
647
647
    if( pthread_self() == mainThread_ )
648
648
    {
649
649
        assert( msg );
650
 
        free( jackErr_ );
651
 
        jackErr_ = malloc( strlen( msg ) );
652
 
        sprintf( jackErr_, msg );
 
650
        jackErr_ = realloc( jackErr_, strlen( msg ) + 1 );
 
651
        strcpy( jackErr_, msg );
653
652
    }
654
653
}
655
654
 
706
705
    PaError result = paNoError;
707
706
    PaJackHostApiRepresentation *jackHostApi;
708
707
    int activated = 0;
709
 
    char *clientName;
710
 
    int written;
 
708
    jack_status_t jackStatus = 0;
711
709
    *hostApi = NULL;    /* Initialize to NULL */
712
710
 
713
711
    UNLESS( jackHostApi = (PaJackHostApiRepresentation*)
721
719
    /* Try to become a client of the JACK server.  If we cannot do
722
720
     * this, then this API cannot be used. */
723
721
 
724
 
    clientName = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_client_name_size() );
725
 
    written = snprintf( clientName, jack_client_name_size(), "PortAudio-%d", getpid() );
726
 
    assert( written < jack_client_name_size() );
727
 
    jackHostApi->jack_client = jack_client_new( clientName );
728
 
    if( jackHostApi->jack_client == NULL )
 
722
    jackHostApi->jack_client = jack_client_open( clientName_, 0, &jackStatus );
 
723
    if( !jackHostApi->jack_client )
729
724
    {
730
 
       /* the V19 development docs say that if an implementation
731
 
        * detects that it cannot be used, it should return a NULL
732
 
        * interface and paNoError */
733
 
       result = paNoError;
734
 
       goto error;
 
725
        /* the V19 development docs say that if an implementation
 
726
         * detects that it cannot be used, it should return a NULL
 
727
         * interface and paNoError */
 
728
        result = paNoError;
 
729
        goto error;
735
730
    }
736
731
 
737
732
    jackHostApi->hostApiIndex = hostApiIndex;
775
770
    jack_on_shutdown( jackHostApi->jack_client, JackOnShutdown, jackHostApi );
776
771
    jack_set_error_function( JackErrorCallback );
777
772
    jackHostApi->jack_buffer_size = jack_get_buffer_size ( jackHostApi->jack_client );
778
 
    UNLESS( !jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi ), paUnanticipatedHostError );
 
773
    /* Don't check for error, may not be supported (deprecated in at least jackdmp) */
 
774
    jack_set_sample_rate_callback( jackHostApi->jack_client, JackSrCb, jackHostApi );
779
775
    UNLESS( !jack_set_xrun_callback( jackHostApi->jack_client, JackXRunCb, jackHostApi ), paUnanticipatedHostError );
780
776
    UNLESS( !jack_set_process_callback( jackHostApi->jack_client, JackCallback, jackHostApi ), paUnanticipatedHostError );
781
777
    UNLESS( !jack_activate( jackHostApi->jack_client ), paUnanticipatedHostError );
886
882
 
887
883
    /*
888
884
        The following check is not necessary for JACK.
889
 
        
 
885
 
890
886
            - if a full duplex stream is requested, check that the combination
891
887
                of input and output parameters is supported
892
888
 
894
890
        Because the buffer adapter handles conversion between all standard
895
891
        sample formats, the following checks are only required if paCustomFormat
896
892
        is implemented, or under some other unusual conditions.
897
 
        
 
893
 
898
894
            - check that input device can support inputSampleFormat, or that
899
895
                we have the capability to convert from outputSampleFormat to
900
896
                a native format
905
901
    */
906
902
 
907
903
    /* check that the device supports sampleRate */
908
 
    
 
904
 
909
905
#define ABS(x) ( (x) > 0 ? (x) : -(x) )
910
906
    if( ABS(sampleRate - jack_get_sample_rate(((PaJackHostApiRepresentation *) hostApi)->jack_client )) > 1 )
911
907
       return paInvalidSampleRate;
1055
1051
    return result;
1056
1052
}
1057
1053
 
1058
 
/* Add stream to processing queue */
 
1054
/* Add stream to JACK callback processing queue */
1059
1055
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
1060
1056
                           PaStream** s,
1061
1057
                           const PaStreamParameters *inputParameters,
1227
1223
    if( inputChannelCount > 0 )
1228
1224
    {
1229
1225
        int err = 0;
1230
 
        
1231
 
        /* ... remote output ports (that we input from) */
 
1226
 
 
1227
        /* Get output ports of our capture device */
1232
1228
        snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
1233
1229
        UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1234
1230
                                     NULL, JackPortIsOutput ), paUnanticipatedHostError );
1235
1231
        for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
1236
1232
        {
1237
1233
            if( (stream->remote_output_ports[i] = jack_port_by_name(
1238
 
                 jackHostApi->jack_client, jack_ports[i] )) == NULL ) 
 
1234
                 jackHostApi->jack_client, jack_ports[i] )) == NULL )
1239
1235
            {
1240
1236
                err = 1;
1241
1237
                break;
1252
1248
    {
1253
1249
        int err = 0;
1254
1250
 
1255
 
        /* ... remote input ports (that we output to) */
 
1251
        /* Get input ports of our playback device */
1256
1252
        snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
1257
1253
        UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
1258
1254
                                     NULL, JackPortIsInput ), paUnanticipatedHostError );
1301
1297
    stream->streamRepresentation.streamInfo.sampleRate = jackSr;
1302
1298
    stream->t0 = jack_frame_time( jackHostApi->jack_client );   /* A: Time should run from Pa_OpenStream */
1303
1299
 
1304
 
    ENSURE_PA( AddStream( stream ) );  /* Add to queue over opened streams */
1305
 
    
 
1300
    /* Add to queue of opened streams */
 
1301
    ENSURE_PA( AddStream( stream ) );
 
1302
 
1306
1303
    *s = (PaStream*)stream;
1307
1304
 
1308
1305
    return result;
1410
1407
    return result;
1411
1408
}
1412
1409
 
1413
 
/* Alter the processing queue if necessary */
 
1410
/* Update the JACK callback's stream processing queue. */
1414
1411
static PaError UpdateQueue( PaJackHostApiRepresentation *hostApi )
1415
1412
{
1416
1413
    PaError result = paNoError;
1436
1433
            node->next = hostApi->toAdd;
1437
1434
        }
1438
1435
        else
 
1436
        {
 
1437
            /* The only queue entry. */
1439
1438
            hostApi->processQueue = (PaJackStream *)hostApi->toAdd;
 
1439
        }
1440
1440
 
1441
1441
        /* If necessary, update stream state */
1442
1442
        if( hostApi->toAdd->streamRepresentation.streamInfo.sampleRate != jackSr )
1485
1485
    return result;
1486
1486
}
1487
1487
 
 
1488
/* Audio processing callback invoked periodically from JACK. */
1488
1489
static int JackCallback( jack_nframes_t frames, void *userData )
1489
1490
{
1490
1491
    PaError result = paNoError;
1586
1587
    /* Ready the processor */
1587
1588
    PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
1588
1589
 
1589
 
    /* connect the ports */
 
1590
    /* Connect the ports. Note that the ports may already have been connected by someone else in
 
1591
     * the meantime, in which case JACK returns EEXIST. */
1590
1592
 
1591
 
    /* NOTE: I would rather use jack_port_connect which uses jack_port_t's
1592
 
     * instead of port names, but it is not implemented yet. */
1593
1593
    if( stream->num_incoming_connections > 0 )
1594
1594
    {
1595
1595
        for( i = 0; i < stream->num_incoming_connections; i++ )
1596
 
            UNLESS( jack_connect( stream->jack_client,
1597
 
                    jack_port_name( stream->remote_output_ports[i] ),
1598
 
                    jack_port_name( stream->local_input_ports[i] ) ) == 0, paUnanticipatedHostError );
 
1596
        {
 
1597
            int r = jack_connect( stream->jack_client, jack_port_name( stream->remote_output_ports[i] ),
 
1598
                    jack_port_name( stream->local_input_ports[i] ) );
 
1599
           UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
 
1600
        }
1599
1601
    }
1600
1602
 
1601
1603
    if( stream->num_outgoing_connections > 0 )
1602
1604
    {
1603
1605
        for( i = 0; i < stream->num_outgoing_connections; i++ )
1604
 
            UNLESS( jack_connect( stream->jack_client,
1605
 
                    jack_port_name( stream->local_output_ports[i] ),
1606
 
                    jack_port_name( stream->remote_input_ports[i] ) ) == 0, paUnanticipatedHostError );
 
1606
        {
 
1607
            int r = jack_connect( stream->jack_client, jack_port_name( stream->local_output_ports[i] ),
 
1608
                    jack_port_name( stream->remote_input_ports[i] ) );
 
1609
           UNLESS( 0 == r || EEXIST == r, paUnanticipatedHostError );
 
1610
        }
1607
1611
    }
1608
1612
 
1609
1613
    stream->xrun = FALSE;
1657
1661
    ENSURE_PA( result );
1658
1662
 
1659
1663
    UNLESS( !stream->is_active, paInternalError );
1660
 
    
 
1664
 
1661
1665
    PA_DEBUG(( "%s: Stream stopped\n", __FUNCTION__ ));
1662
1666
 
1663
1667
error:
1669
1673
    {
1670
1674
        for( i = 0; i < stream->num_incoming_connections; i++ )
1671
1675
        {
1672
 
            UNLESS( !jack_port_lock( stream->jack_client, stream->local_input_ports[i] ),
1673
 
                    paUnanticipatedHostError );
1674
1676
            if( jack_port_connected( stream->local_input_ports[i] ) )
1675
1677
            {
1676
1678
                UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_input_ports[i] ),
1677
1679
                        paUnanticipatedHostError );
1678
1680
            }
1679
 
            UNLESS( !jack_port_unlock( stream->jack_client, stream->local_input_ports[i] ),
1680
 
                    paUnanticipatedHostError );
1681
1681
        }
1682
1682
        for( i = 0; i < stream->num_outgoing_connections; i++ )
1683
1683
        {
1684
 
            UNLESS( !jack_port_lock( stream->jack_client, stream->local_output_ports[i] ),
1685
 
                    paUnanticipatedHostError );
1686
1684
            if( jack_port_connected( stream->local_output_ports[i] ) )
1687
1685
            {
1688
1686
                UNLESS( !jack_port_disconnect( stream->jack_client, stream->local_output_ports[i] ),
1689
1687
                        paUnanticipatedHostError );
1690
1688
            }
1691
 
            UNLESS( !jack_port_unlock( stream->jack_client, stream->local_output_ports[i] ),
1692
 
                    paUnanticipatedHostError );
1693
1689
        }
1694
1690
    }
1695
1691
 
1736
1732
    PaJackStream *stream = (PaJackStream*)s;
1737
1733
    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
1738
1734
}
 
1735
 
 
1736
PaError PaJack_SetClientName( const char* name )
 
1737
{
 
1738
    if( strlen( name ) > jack_client_name_size() )
 
1739
    {
 
1740
        /* OK, I don't know any better error code */
 
1741
        return paInvalidFlag;
 
1742
    }
 
1743
    clientName_ = name;
 
1744
    return paNoError;
 
1745
}
 
1746
 
 
1747
PaError PaJack_GetClientName(const char** clientName)
 
1748
{
 
1749
    PaError result = paNoError;
 
1750
    PaJackHostApiRepresentation* jackHostApi = NULL;
 
1751
    ENSURE_PA( PaUtil_GetHostApiRepresentation( (PaUtilHostApiRepresentation**)&jackHostApi, paJACK ) );
 
1752
    *clientName = jack_get_client_name( jackHostApi->jack_client );
 
1753
 
 
1754
error:
 
1755
    return result;
 
1756
}