To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / portaudio_20161030_catalina_patch / src / common / pa_front.c @ 162:d43aab368df9

History | View | Annotate | Download (55.1 KB)

1
/*
2
 * $Id$
3
 * Portable Audio I/O Library Multi-Host API front end
4
 * Validate function parameters and manage multiple host APIs.
5
 *
6
 * Based on the Open Source API proposed by Ross Bencina
7
 * Copyright (c) 1999-2008 Ross Bencina, Phil Burk
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining
10
 * a copy of this software and associated documentation files
11
 * (the "Software"), to deal in the Software without restriction,
12
 * including without limitation the rights to use, copy, modify, merge,
13
 * publish, distribute, sublicense, and/or sell copies of the Software,
14
 * and to permit persons to whom the Software is furnished to do so,
15
 * subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be
18
 * included in all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
24
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
 */
28

    
29
/*
30
 * The text above constitutes the entire PortAudio license; however,
31
 * the PortAudio community also makes the following non-binding requests:
32
 *
33
 * Any person wishing to distribute modifications to the Software is
34
 * requested to send the modifications to the original developer so that
35
 * they can be incorporated into the canonical version. It is also
36
 * requested that these non-binding requests be included along with the
37
 * license above.
38
 */
39

    
40
/** @file
41
 @ingroup common_src
42

43
 @brief Implements PortAudio API functions defined in portaudio.h, checks
44
 some errors, delegates platform-specific behavior to host API implementations.
45

46
 Implements the functions defined in the PortAudio API (portaudio.h),
47
 validates some parameters and checks for state inconsistencies before
48
 forwarding API requests to specific Host API implementations (via the
49
 interface declared in pa_hostapi.h), and Streams (via the interface
50
 declared in pa_stream.h).
51

52
 This file manages initialization and termination of Host API
53
 implementations via initializer functions stored in the paHostApiInitializers
54
 global array (usually defined in an os-specific pa_[os]_hostapis.c file).
55

56
 This file maintains a list of all open streams and closes them at Pa_Terminate().
57

58
 Some utility functions declared in pa_util.h are implemented in this file.
59

60
 All PortAudio API functions can be conditionally compiled with logging code.
61
 To compile with logging, define the PA_LOG_API_CALLS precompiler symbol.
62
*/
63

    
64

    
65
#include <stdio.h>
66
#include <memory.h>
67
#include <string.h>
68
#include <stdlib.h> /* needed for strtol() */
69
#include <assert.h> /* needed by PA_VALIDATE_ENDIANNESS */
70

    
71
#include "portaudio.h"
72
#include "pa_util.h"
73
#include "pa_endianness.h"
74
#include "pa_types.h"
75
#include "pa_hostapi.h"
76
#include "pa_stream.h"
77
#include "pa_trace.h" /* still usefull?*/
78
#include "pa_debugprint.h"
79

    
80
#ifndef PA_GIT_REVISION
81
#include "pa_gitrevision.h"
82
#endif
83

    
84
/**
85
 * This is incremented if we make incompatible API changes.
86
 * This version scheme is based loosely on http://semver.org/
87
 */
88
#define paVersionMajor     19
89

    
90
/**
91
 * This is incremented when we add functionality in a backwards-compatible manner.
92
 * Or it is set to zero when paVersionMajor is incremented.
93
 */
94
#define paVersionMinor      6
95

    
96
/**
97
 * This is incremented when we make backwards-compatible bug fixes.
98
 * Or it is set to zero when paVersionMinor changes.
99
 */
100
#define paVersionSubMinor   0
101

    
102
/**
103
 * This is a combination of paVersionMajor, paVersionMinor and paVersionSubMinor.
104
 * It will always increase so that version numbers can be compared as integers to
105
 * see which is later.
106
 */
107
#define paVersion  paMakeVersionNumber(paVersionMajor, paVersionMinor, paVersionSubMinor)
108

    
109
#define STRINGIFY(x) #x
110
#define TOSTRING(x) STRINGIFY(x)
111

    
112
#define PA_VERSION_STRING_ TOSTRING(paVersionMajor) "." TOSTRING(paVersionMinor) "." TOSTRING(paVersionSubMinor)
113
#define PA_VERSION_TEXT_   "PortAudio V" PA_VERSION_STRING_ "-devel, revision " TOSTRING(PA_GIT_REVISION)
114

    
115
int Pa_GetVersion( void )
116
{
117
    return paVersion;
118
}
119

    
120
const char* Pa_GetVersionText( void )
121
{
122
    return PA_VERSION_TEXT_;
123
}
124

    
125
static PaVersionInfo versionInfo_ = {
126
    /*.versionMajor =*/ paVersionMajor,
127
    /*.versionMinor =*/ paVersionMinor,
128
    /*.versionSubMinor =*/ paVersionSubMinor,
129
    /*.versionControlRevision =*/ TOSTRING(PA_GIT_REVISION),
130
    /*.versionText =*/ PA_VERSION_TEXT_
131
};
132

    
133
const PaVersionInfo* Pa_GetVersionInfo()
134
{
135
    return &versionInfo_;
136
}
137

    
138
#define PA_LAST_HOST_ERROR_TEXT_LENGTH_  1024
139

    
140
static char lastHostErrorText_[ PA_LAST_HOST_ERROR_TEXT_LENGTH_ + 1 ] = {0};
141

    
142
static PaHostErrorInfo lastHostErrorInfo_ = { (PaHostApiTypeId)-1, 0, lastHostErrorText_ };
143

    
144

    
145
void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
146
        const char *errorText )
147
{
148
    lastHostErrorInfo_.hostApiType = hostApiType;
149
    lastHostErrorInfo_.errorCode = errorCode;
150

    
151
    strncpy( lastHostErrorText_, errorText, PA_LAST_HOST_ERROR_TEXT_LENGTH_ );
152
}
153

    
154

    
155

    
156
static PaUtilHostApiRepresentation **hostApis_ = 0;
157
static int hostApisCount_ = 0;
158
static int defaultHostApiIndex_ = 0;
159
static int initializationCount_ = 0;
160
static int deviceCount_ = 0;
161

    
162
PaUtilStreamRepresentation *firstOpenStream_ = NULL;
163

    
164

    
165
#define PA_IS_INITIALISED_ (initializationCount_ != 0)
166

    
167

    
168
static int CountHostApiInitializers( void )
169
{
170
    int result = 0;
171

    
172
    while( paHostApiInitializers[ result ] != 0 )
173
        ++result;
174
    return result;
175
}
176

    
177

    
178
static void TerminateHostApis( void )
179
{
180
    /* terminate in reverse order from initialization */
181
    PA_DEBUG(("TerminateHostApis in \n"));
182

    
183
    while( hostApisCount_ > 0 )
184
    {
185
        --hostApisCount_;
186
        hostApis_[hostApisCount_]->Terminate( hostApis_[hostApisCount_] );
187
    }
188
    hostApisCount_ = 0;
189
    defaultHostApiIndex_ = 0;
190
    deviceCount_ = 0;
191

    
192
    if( hostApis_ != 0 )
193
        PaUtil_FreeMemory( hostApis_ );
194
    hostApis_ = 0;
195

    
196
    PA_DEBUG(("TerminateHostApis out\n"));
197
}
198

    
199

    
200
static PaError InitializeHostApis( void )
201
{
202
    PaError result = paNoError;
203
    int i, initializerCount, baseDeviceIndex;
204

    
205
    initializerCount = CountHostApiInitializers();
206

    
207
    hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
208
            sizeof(PaUtilHostApiRepresentation*) * initializerCount );
209
    if( !hostApis_ )
210
    {
211
        result = paInsufficientMemory;
212
        goto error;
213
    }
214

    
215
    hostApisCount_ = 0;
216
    defaultHostApiIndex_ = -1; /* indicates that we haven't determined the default host API yet */
217
    deviceCount_ = 0;
218
    baseDeviceIndex = 0;
219

    
220
    for( i=0; i< initializerCount; ++i )
221
    {
222
        hostApis_[hostApisCount_] = NULL;
223

    
224
        PA_DEBUG(( "before paHostApiInitializers[%d].\n",i));
225

    
226
        result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ );
227
        if( result != paNoError )
228
            goto error;
229

    
230
        PA_DEBUG(( "after paHostApiInitializers[%d].\n",i));
231

    
232
        if( hostApis_[hostApisCount_] )
233
        {
234
            PaUtilHostApiRepresentation* hostApi = hostApis_[hostApisCount_];
235
            assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
236
            assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
237

    
238
            /* the first successfully initialized host API with a default input *or*
239
               output device is used as the default host API.
240
            */
241
            if( (defaultHostApiIndex_ == -1) &&
242
                    ( hostApi->info.defaultInputDevice != paNoDevice
243
                        || hostApi->info.defaultOutputDevice != paNoDevice ) )
244
            {
245
                defaultHostApiIndex_ = hostApisCount_;
246
            }
247

    
248
            hostApi->privatePaFrontInfo.baseDeviceIndex = baseDeviceIndex;
249

    
250
            if( hostApi->info.defaultInputDevice != paNoDevice )
251
                hostApi->info.defaultInputDevice += baseDeviceIndex;
252

    
253
            if( hostApi->info.defaultOutputDevice != paNoDevice )
254
                hostApi->info.defaultOutputDevice += baseDeviceIndex;
255

    
256
            baseDeviceIndex += hostApi->info.deviceCount;
257
            deviceCount_ += hostApi->info.deviceCount;
258

    
259
            ++hostApisCount_;
260
        }
261
    }
262

    
263
    /* if no host APIs have devices, the default host API is the first initialized host API */
264
    if( defaultHostApiIndex_ == -1 )
265
        defaultHostApiIndex_ = 0;
266

    
267
    return result;
268

    
269
error:
270
    TerminateHostApis();
271
    return result;
272
}
273

    
274

    
275
/*
276
    FindHostApi() finds the index of the host api to which
277
    <device> belongs and returns it. if <hostSpecificDeviceIndex> is
278
    non-null, the host specific device index is returned in it.
279
    returns -1 if <device> is out of range.
280

281
*/
282
static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
283
{
284
    int i=0;
285

    
286
    if( !PA_IS_INITIALISED_ )
287
        return -1;
288

    
289
    if( device < 0 )
290
        return -1;
291

    
292
    while( i < hostApisCount_
293
            && device >= hostApis_[i]->info.deviceCount )
294
    {
295

    
296
        device -= hostApis_[i]->info.deviceCount;
297
        ++i;
298
    }
299

    
300
    if( i >= hostApisCount_ )
301
        return -1;
302

    
303
    if( hostSpecificDeviceIndex )
304
        *hostSpecificDeviceIndex = device;
305

    
306
    return i;
307
}
308

    
309

    
310
static void AddOpenStream( PaStream* stream )
311
{
312
    ((PaUtilStreamRepresentation*)stream)->nextOpenStream = firstOpenStream_;
313
    firstOpenStream_ = (PaUtilStreamRepresentation*)stream;
314
}
315

    
316

    
317
static void RemoveOpenStream( PaStream* stream )
318
{
319
    PaUtilStreamRepresentation *previous = NULL;
320
    PaUtilStreamRepresentation *current = firstOpenStream_;
321

    
322
    while( current != NULL )
323
    {
324
        if( ((PaStream*)current) == stream )
325
        {
326
            if( previous == NULL )
327
            {
328
                firstOpenStream_ = current->nextOpenStream;
329
            }
330
            else
331
            {
332
                previous->nextOpenStream = current->nextOpenStream;
333
            }
334
            return;
335
        }
336
        else
337
        {
338
            previous = current;
339
            current = current->nextOpenStream;
340
        }
341
    }
342
}
343

    
344

    
345
static void CloseOpenStreams( void )
346
{
347
    /* we call Pa_CloseStream() here to ensure that the same destruction
348
        logic is used for automatically closed streams */
349

    
350
    while( firstOpenStream_ != NULL )
351
        Pa_CloseStream( firstOpenStream_ );
352
}
353

    
354

    
355
PaError Pa_Initialize( void )
356
{
357
    PaError result;
358

    
359
    PA_LOGAPI_ENTER( "Pa_Initialize" );
360

    
361
    if( PA_IS_INITIALISED_ )
362
    {
363
        ++initializationCount_;
364
        result = paNoError;
365
    }
366
    else
367
    {
368
        PA_VALIDATE_TYPE_SIZES;
369
        PA_VALIDATE_ENDIANNESS;
370

    
371
        PaUtil_InitializeClock();
372
        PaUtil_ResetTraceMessages();
373

    
374
        result = InitializeHostApis();
375
        if( result == paNoError )
376
            ++initializationCount_;
377
    }
378

    
379
    PA_LOGAPI_EXIT_PAERROR( "Pa_Initialize", result );
380

    
381
    return result;
382
}
383

    
384

    
385
PaError Pa_Terminate( void )
386
{
387
    PaError result;
388

    
389
    PA_LOGAPI_ENTER( "Pa_Terminate" );
390

    
391
    if( PA_IS_INITIALISED_ )
392
    {
393
        // leave initializationCount_>0 so that Pa_CloseStream() can execute
394
        if( initializationCount_ == 1 )
395
        {
396
            CloseOpenStreams();
397

    
398
            TerminateHostApis();
399

    
400
            PaUtil_DumpTraceMessages();
401
        }
402
        --initializationCount_;
403
        result = paNoError;
404
    }
405
    else
406
    {
407
        result=  paNotInitialized;
408
    }
409

    
410
    PA_LOGAPI_EXIT_PAERROR( "Pa_Terminate", result );
411

    
412
    return result;
413
}
414

    
415

    
416
const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void )
417
{
418
    return &lastHostErrorInfo_;
419
}
420

    
421

    
422
const char *Pa_GetErrorText( PaError errorCode )
423
{
424
    const char *result;
425

    
426
    switch( errorCode )
427
    {
428
    case paNoError:                  result = "Success"; break;
429
    case paNotInitialized:           result = "PortAudio not initialized"; break;
430
    /** @todo could catenate the last host error text to result in the case of paUnanticipatedHostError. see: http://www.portaudio.com/trac/ticket/114 */
431
    case paUnanticipatedHostError:   result = "Unanticipated host error"; break;
432
    case paInvalidChannelCount:      result = "Invalid number of channels"; break;
433
    case paInvalidSampleRate:        result = "Invalid sample rate"; break;
434
    case paInvalidDevice:            result = "Invalid device"; break;
435
    case paInvalidFlag:              result = "Invalid flag"; break;
436
    case paSampleFormatNotSupported: result = "Sample format not supported"; break;
437
    case paBadIODeviceCombination:   result = "Illegal combination of I/O devices"; break;
438
    case paInsufficientMemory:       result = "Insufficient memory"; break;
439
    case paBufferTooBig:             result = "Buffer too big"; break;
440
    case paBufferTooSmall:           result = "Buffer too small"; break;
441
    case paNullCallback:             result = "No callback routine specified"; break;
442
    case paBadStreamPtr:             result = "Invalid stream pointer"; break;
443
    case paTimedOut:                 result = "Wait timed out"; break;
444
    case paInternalError:            result = "Internal PortAudio error"; break;
445
    case paDeviceUnavailable:        result = "Device unavailable"; break;
446
    case paIncompatibleHostApiSpecificStreamInfo:   result = "Incompatible host API specific stream info"; break;
447
    case paStreamIsStopped:          result = "Stream is stopped"; break;
448
    case paStreamIsNotStopped:       result = "Stream is not stopped"; break;
449
    case paInputOverflowed:          result = "Input overflowed"; break;
450
    case paOutputUnderflowed:        result = "Output underflowed"; break;
451
    case paHostApiNotFound:          result = "Host API not found"; break;
452
    case paInvalidHostApi:           result = "Invalid host API"; break;
453
    case paCanNotReadFromACallbackStream:       result = "Can't read from a callback stream"; break;
454
    case paCanNotWriteToACallbackStream:        result = "Can't write to a callback stream"; break;
455
    case paCanNotReadFromAnOutputOnlyStream:    result = "Can't read from an output only stream"; break;
456
    case paCanNotWriteToAnInputOnlyStream:      result = "Can't write to an input only stream"; break;
457
    case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break;
458
    case paBadBufferPtr:             result = "Bad buffer pointer"; break;
459
    default:
460
                if( errorCode > 0 )
461
                        result = "Invalid error code (value greater than zero)";
462
        else
463
                        result = "Invalid error code";
464
        break;
465
    }
466
    return result;
467
}
468

    
469

    
470
PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
471
{
472
    PaHostApiIndex result;
473
    int i;
474

    
475
    PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiTypeIdToHostApiIndex" );
476
    PA_LOGAPI(("\tPaHostApiTypeId type: %d\n", type ));
477

    
478
    if( !PA_IS_INITIALISED_ )
479
    {
480
        result = paNotInitialized;
481
    }
482
    else
483
    {
484
        result = paHostApiNotFound;
485

    
486
        for( i=0; i < hostApisCount_; ++i )
487
        {
488
            if( hostApis_[i]->info.type == type )
489
            {
490
                result = i;
491
                break;
492
            }
493
        }
494
    }
495

    
496
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_HostApiTypeIdToHostApiIndex", "PaHostApiIndex: %d", result );
497

    
498
    return result;
499
}
500

    
501

    
502
PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
503
        PaHostApiTypeId type )
504
{
505
    PaError result;
506
    int i;
507

    
508
    if( !PA_IS_INITIALISED_ )
509
    {
510
        result = paNotInitialized;
511
    }
512
    else
513
    {
514
        result = paHostApiNotFound;
515

    
516
        for( i=0; i < hostApisCount_; ++i )
517
        {
518
            if( hostApis_[i]->info.type == type )
519
            {
520
                *hostApi = hostApis_[i];
521
                result = paNoError;
522
                break;
523
            }
524
        }
525
    }
526

    
527
    return result;
528
}
529

    
530

    
531
PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
532
        PaDeviceIndex *hostApiDevice, PaDeviceIndex device, struct PaUtilHostApiRepresentation *hostApi )
533
{
534
    PaError result;
535
    PaDeviceIndex x;
536

    
537
    x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
538

    
539
    if( x < 0 || x >= hostApi->info.deviceCount )
540
    {
541
        result = paInvalidDevice;
542
    }
543
    else
544
    {
545
        *hostApiDevice = x;
546
        result = paNoError;
547
    }
548

    
549
    return result;
550
}
551

    
552

    
553
PaHostApiIndex Pa_GetHostApiCount( void )
554
{
555
    int result;
556

    
557
    PA_LOGAPI_ENTER( "Pa_GetHostApiCount" );
558

    
559
    if( !PA_IS_INITIALISED_ )
560
    {
561
        result = paNotInitialized;
562
    }
563
    else
564
    {
565
        result = hostApisCount_;
566
    }
567

    
568
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetHostApiCount", "PaHostApiIndex: %d", result );
569

    
570
    return result;
571
}
572

    
573

    
574
PaHostApiIndex Pa_GetDefaultHostApi( void )
575
{
576
    int result;
577

    
578
    PA_LOGAPI_ENTER( "Pa_GetDefaultHostApi" );
579

    
580
    if( !PA_IS_INITIALISED_ )
581
    {
582
        result = paNotInitialized;
583
    }
584
    else
585
    {
586
        result = defaultHostApiIndex_;
587

    
588
        /* internal consistency check: make sure that the default host api
589
         index is within range */
590

    
591
        if( result < 0 || result >= hostApisCount_ )
592
        {
593
            result = paInternalError;
594
        }
595
    }
596

    
597
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDefaultHostApi", "PaHostApiIndex: %d", result );
598

    
599
    return result;
600
}
601

    
602

    
603
const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
604
{
605
    PaHostApiInfo *info;
606

    
607
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetHostApiInfo" );
608
    PA_LOGAPI(("\tPaHostApiIndex hostApi: %d\n", hostApi ));
609

    
610
    if( !PA_IS_INITIALISED_ )
611
    {
612
        info = NULL;
613

    
614
        PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
615
        PA_LOGAPI(("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n" ));
616

    
617
    }
618
    else if( hostApi < 0 || hostApi >= hostApisCount_ )
619
    {
620
        info = NULL;
621

    
622
        PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
623
        PA_LOGAPI(("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n" ));
624

    
625
    }
626
    else
627
    {
628
        info = &hostApis_[hostApi]->info;
629

    
630
        PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
631
        PA_LOGAPI(("\tPaHostApiInfo*: 0x%p\n", info ));
632
        PA_LOGAPI(("\t{\n" ));
633
        PA_LOGAPI(("\t\tint structVersion: %d\n", info->structVersion ));
634
        PA_LOGAPI(("\t\tPaHostApiTypeId type: %d\n", info->type ));
635
        PA_LOGAPI(("\t\tconst char *name: %s\n", info->name ));
636
        PA_LOGAPI(("\t}\n" ));
637

    
638
    }
639

    
640
     return info;
641
}
642

    
643

    
644
PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int hostApiDeviceIndex )
645
{
646
    PaDeviceIndex result;
647

    
648
    PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiDeviceIndexToPaDeviceIndex" );
649
    PA_LOGAPI(("\tPaHostApiIndex hostApi: %d\n", hostApi ));
650
    PA_LOGAPI(("\tint hostApiDeviceIndex: %d\n", hostApiDeviceIndex ));
651

    
652
    if( !PA_IS_INITIALISED_ )
653
    {
654
        result = paNotInitialized;
655
    }
656
    else
657
    {
658
        if( hostApi < 0 || hostApi >= hostApisCount_ )
659
        {
660
            result = paInvalidHostApi;
661
        }
662
        else
663
        {
664
            if( hostApiDeviceIndex < 0 ||
665
                    hostApiDeviceIndex >= hostApis_[hostApi]->info.deviceCount )
666
            {
667
                result = paInvalidDevice;
668
            }
669
            else
670
            {
671
                result = hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex;
672
            }
673
        }
674
    }
675

    
676
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_HostApiDeviceIndexToPaDeviceIndex", "PaDeviceIndex: %d", result );
677

    
678
    return result;
679
}
680

    
681

    
682
PaDeviceIndex Pa_GetDeviceCount( void )
683
{
684
    PaDeviceIndex result;
685

    
686
    PA_LOGAPI_ENTER( "Pa_GetDeviceCount" );
687

    
688
    if( !PA_IS_INITIALISED_ )
689
    {
690
        result = paNotInitialized;
691
    }
692
    else
693
    {
694
        result = deviceCount_;
695
    }
696

    
697
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDeviceCount", "PaDeviceIndex: %d", result );
698

    
699
    return result;
700
}
701

    
702

    
703
PaDeviceIndex Pa_GetDefaultInputDevice( void )
704
{
705
    PaHostApiIndex hostApi;
706
    PaDeviceIndex result;
707

    
708
    PA_LOGAPI_ENTER( "Pa_GetDefaultInputDevice" );
709

    
710
    hostApi = Pa_GetDefaultHostApi();
711
    if( hostApi < 0 )
712
    {
713
        result = paNoDevice;
714
    }
715
    else
716
    {
717
        result = hostApis_[hostApi]->info.defaultInputDevice;
718
    }
719

    
720
    PA_LOGAPI_EXIT_T( "Pa_GetDefaultInputDevice", "PaDeviceIndex: %d", result );
721

    
722
    return result;
723
}
724

    
725

    
726
PaDeviceIndex Pa_GetDefaultOutputDevice( void )
727
{
728
    PaHostApiIndex hostApi;
729
    PaDeviceIndex result;
730

    
731
    PA_LOGAPI_ENTER( "Pa_GetDefaultOutputDevice" );
732

    
733
    hostApi = Pa_GetDefaultHostApi();
734
    if( hostApi < 0 )
735
    {
736
        result = paNoDevice;
737
    }
738
    else
739
    {
740
        result = hostApis_[hostApi]->info.defaultOutputDevice;
741
    }
742

    
743
    PA_LOGAPI_EXIT_T( "Pa_GetDefaultOutputDevice", "PaDeviceIndex: %d", result );
744

    
745
    return result;
746
}
747

    
748

    
749
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
750
{
751
    int hostSpecificDeviceIndex;
752
    int hostApiIndex = FindHostApi( device, &hostSpecificDeviceIndex );
753
    PaDeviceInfo *result;
754

    
755

    
756
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetDeviceInfo" );
757
    PA_LOGAPI(("\tPaDeviceIndex device: %d\n", device ));
758

    
759
    if( hostApiIndex < 0 )
760
    {
761
        result = NULL;
762

    
763
        PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" ));
764
        PA_LOGAPI(("\tPaDeviceInfo* NULL [ invalid device index ]\n" ));
765

    
766
    }
767
    else
768
    {
769
        result = hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ];
770

    
771
        PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" ));
772
        PA_LOGAPI(("\tPaDeviceInfo*: 0x%p:\n", result ));
773
        PA_LOGAPI(("\t{\n" ));
774

    
775
        PA_LOGAPI(("\t\tint structVersion: %d\n", result->structVersion ));
776
        PA_LOGAPI(("\t\tconst char *name: %s\n", result->name ));
777
        PA_LOGAPI(("\t\tPaHostApiIndex hostApi: %d\n", result->hostApi ));
778
        PA_LOGAPI(("\t\tint maxInputChannels: %d\n", result->maxInputChannels ));
779
        PA_LOGAPI(("\t\tint maxOutputChannels: %d\n", result->maxOutputChannels ));
780
        PA_LOGAPI(("\t}\n" ));
781

    
782
    }
783

    
784
    return result;
785
}
786

    
787

    
788
/*
789
    SampleFormatIsValid() returns 1 if sampleFormat is a sample format
790
    defined in portaudio.h, or 0 otherwise.
791
*/
792
static int SampleFormatIsValid( PaSampleFormat format )
793
{
794
    switch( format & ~paNonInterleaved )
795
    {
796
    case paFloat32: return 1;
797
    case paInt16: return 1;
798
    case paInt32: return 1;
799
    case paInt24: return 1;
800
    case paInt8: return 1;
801
    case paUInt8: return 1;
802
    case paCustomFormat: return 1;
803
    default: return 0;
804
    }
805
}
806

    
807
/*
808
    NOTE: make sure this validation list is kept syncronised with the one in
809
            pa_hostapi.h
810

811
    ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
812
    conform to the expected values as described below. This function is
813
    also designed to be used with the proposed Pa_IsFormatSupported() function.
814

815
    There are basically two types of validation that could be performed:
816
    Generic conformance validation, and device capability mismatch
817
    validation. This function performs only generic conformance validation.
818
    Validation that would require knowledge of device capabilities is
819
    not performed because of potentially complex relationships between
820
    combinations of parameters - for example, even if the sampleRate
821
    seems ok, it might not be for a duplex stream - we have no way of
822
    checking this in an API-neutral way, so we don't try.
823

824
    On success the function returns PaNoError and fills in hostApi,
825
    hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
826
    the function returns an error code indicating the first encountered
827
    parameter error.
828

829

830
    If ValidateOpenStreamParameters() returns paNoError, the following
831
    assertions are guaranteed to be true.
832

833
    - at least one of inputParameters & outputParmeters is valid (not NULL)
834

835
    - if inputParameters & outputParameters are both valid, that
836
        inputParameters->device & outputParameters->device  both use the same host api
837

838
    PaDeviceIndex inputParameters->device
839
        - is within range (0 to Pa_GetDeviceCount-1) Or:
840
        - is paUseHostApiSpecificDeviceSpecification and
841
            inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
842
            to a valid host api
843

844
    int inputParameters->channelCount
845
        - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
846
        - upper bound is NOT validated against device capabilities
847

848
    PaSampleFormat inputParameters->sampleFormat
849
        - is one of the sample formats defined in portaudio.h
850

851
    void *inputParameters->hostApiSpecificStreamInfo
852
        - if supplied its hostApi field matches the input device's host Api
853

854
    PaDeviceIndex outputParmeters->device
855
        - is within range (0 to Pa_GetDeviceCount-1)
856

857
    int outputParmeters->channelCount
858
        - if inputDevice is valid, channelCount is > 0
859
        - upper bound is NOT validated against device capabilities
860

861
    PaSampleFormat outputParmeters->sampleFormat
862
        - is one of the sample formats defined in portaudio.h
863

864
    void *outputParmeters->hostApiSpecificStreamInfo
865
        - if supplied its hostApi field matches the output device's host Api
866

867
    double sampleRate
868
        - is not an 'absurd' rate (less than 1000. or greater than 384000.)
869
        - sampleRate is NOT validated against device capabilities
870

871
    PaStreamFlags streamFlags
872
        - unused platform neutral flags are zero
873
        - paNeverDropInput is only used for full-duplex callback streams with
874
            variable buffer size (paFramesPerBufferUnspecified)
875
*/
876
static PaError ValidateOpenStreamParameters(
877
    const PaStreamParameters *inputParameters,
878
    const PaStreamParameters *outputParameters,
879
    double sampleRate,
880
    unsigned long framesPerBuffer,
881
    PaStreamFlags streamFlags,
882
    PaStreamCallback *streamCallback,
883
    PaUtilHostApiRepresentation **hostApi,
884
    PaDeviceIndex *hostApiInputDevice,
885
    PaDeviceIndex *hostApiOutputDevice )
886
{
887
    int inputHostApiIndex  = -1, /* Surpress uninitialised var warnings: compiler does */
888
        outputHostApiIndex = -1; /* not see that if inputParameters and outputParame-  */
889
                                 /* ters are both nonzero, these indices are set.      */
890

    
891
    if( (inputParameters == NULL) && (outputParameters == NULL) )
892
    {
893
        return paInvalidDevice; /** @todo should be a new error code "invalid device parameters" or something */
894
    }
895
    else
896
    {
897
        if( inputParameters == NULL )
898
        {
899
            *hostApiInputDevice = paNoDevice;
900
        }
901
        else if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
902
        {
903
            if( inputParameters->hostApiSpecificStreamInfo )
904
            {
905
                inputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
906
                        ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType );
907

    
908
                if( inputHostApiIndex != -1 )
909
                {
910
                    *hostApiInputDevice = paUseHostApiSpecificDeviceSpecification;
911
                    *hostApi = hostApis_[inputHostApiIndex];
912
                }
913
                else
914
                {
915
                    return paInvalidDevice;
916
                }
917
            }
918
            else
919
            {
920
                return paInvalidDevice;
921
            }
922
        }
923
        else
924
        {
925
            if( inputParameters->device < 0 || inputParameters->device >= deviceCount_ )
926
                return paInvalidDevice;
927

    
928
            inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice );
929
            if( inputHostApiIndex < 0 )
930
                return paInternalError;
931

    
932
            *hostApi = hostApis_[inputHostApiIndex];
933

    
934
            if( inputParameters->channelCount <= 0 )
935
                return paInvalidChannelCount;
936

    
937
            if( !SampleFormatIsValid( inputParameters->sampleFormat ) )
938
                return paSampleFormatNotSupported;
939

    
940
            if( inputParameters->hostApiSpecificStreamInfo != NULL )
941
            {
942
                if( ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType
943
                        != (*hostApi)->info.type )
944
                    return paIncompatibleHostApiSpecificStreamInfo;
945
            }
946
        }
947

    
948
        if( outputParameters == NULL )
949
        {
950
            *hostApiOutputDevice = paNoDevice;
951
        }
952
        else if( outputParameters->device == paUseHostApiSpecificDeviceSpecification  )
953
        {
954
            if( outputParameters->hostApiSpecificStreamInfo )
955
            {
956
                outputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
957
                        ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType );
958

    
959
                if( outputHostApiIndex != -1 )
960
                {
961
                    *hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification;
962
                    *hostApi = hostApis_[outputHostApiIndex];
963
                }
964
                else
965
                {
966
                    return paInvalidDevice;
967
                }
968
            }
969
            else
970
            {
971
                return paInvalidDevice;
972
            }
973
        }
974
        else
975
        {
976
            if( outputParameters->device < 0 || outputParameters->device >= deviceCount_ )
977
                return paInvalidDevice;
978

    
979
            outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice );
980
            if( outputHostApiIndex < 0 )
981
                return paInternalError;
982

    
983
            *hostApi = hostApis_[outputHostApiIndex];
984

    
985
            if( outputParameters->channelCount <= 0 )
986
                return paInvalidChannelCount;
987

    
988
            if( !SampleFormatIsValid( outputParameters->sampleFormat ) )
989
                return paSampleFormatNotSupported;
990

    
991
            if( outputParameters->hostApiSpecificStreamInfo != NULL )
992
            {
993
                if( ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType
994
                        != (*hostApi)->info.type )
995
                    return paIncompatibleHostApiSpecificStreamInfo;
996
            }
997
        }
998

    
999
        if( (inputParameters != NULL) && (outputParameters != NULL) )
1000
        {
1001
            /* ensure that both devices use the same API */
1002
            if( inputHostApiIndex != outputHostApiIndex )
1003
                return paBadIODeviceCombination;
1004
        }
1005
    }
1006

    
1007

    
1008
    /* Check for absurd sample rates. */
1009
    if( (sampleRate < 1000.0) || (sampleRate > 384000.0) )
1010
        return paInvalidSampleRate;
1011

    
1012
    if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 )
1013
        return paInvalidFlag;
1014

    
1015
    if( streamFlags & paNeverDropInput )
1016
    {
1017
        /* must be a callback stream */
1018
        if( !streamCallback )
1019
             return paInvalidFlag;
1020

    
1021
        /* must be a full duplex stream */
1022
        if( (inputParameters == NULL) || (outputParameters == NULL) )
1023
            return paInvalidFlag;
1024

    
1025
        /* must use paFramesPerBufferUnspecified */
1026
        if( framesPerBuffer != paFramesPerBufferUnspecified )
1027
            return paInvalidFlag;
1028
    }
1029

    
1030
    return paNoError;
1031
}
1032

    
1033

    
1034
PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
1035
                              const PaStreamParameters *outputParameters,
1036
                              double sampleRate )
1037
{
1038
    PaError result;
1039
    PaUtilHostApiRepresentation *hostApi = 0;
1040
    PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice;
1041
    PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1042
    PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1043

    
1044

    
1045
#ifdef PA_LOG_API_CALLS
1046
    PA_LOGAPI_ENTER_PARAMS( "Pa_IsFormatSupported" );
1047

    
1048
    if( inputParameters == NULL ){
1049
        PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" ));
1050
    }else{
1051
        PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters ));
1052
        PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device ));
1053
        PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount ));
1054
        PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat ));
1055
        PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency ));
1056
        PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo ));
1057
    }
1058

    
1059
    if( outputParameters == NULL ){
1060
        PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" ));
1061
    }else{
1062
        PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters ));
1063
        PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device ));
1064
        PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount ));
1065
        PA_LOGAPI(("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat ));
1066
        PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
1067
        PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
1068
    }
1069

    
1070
    PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
1071
#endif
1072

    
1073
    if( !PA_IS_INITIALISED_ )
1074
    {
1075
        result = paNotInitialized;
1076

    
1077
        PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
1078
        return result;
1079
    }
1080

    
1081
    result = ValidateOpenStreamParameters( inputParameters,
1082
                                           outputParameters,
1083
                                           sampleRate, 0, paNoFlag, 0,
1084
                                           &hostApi,
1085
                                           &hostApiInputDevice,
1086
                                           &hostApiOutputDevice );
1087
    if( result != paNoError )
1088
    {
1089
        PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
1090
        return result;
1091
    }
1092

    
1093

    
1094
    if( inputParameters )
1095
    {
1096
        hostApiInputParameters.device = hostApiInputDevice;
1097
        hostApiInputParameters.channelCount = inputParameters->channelCount;
1098
        hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
1099
        hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
1100
        hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
1101
        hostApiInputParametersPtr = &hostApiInputParameters;
1102
    }
1103
    else
1104
    {
1105
        hostApiInputParametersPtr = NULL;
1106
    }
1107

    
1108
    if( outputParameters )
1109
    {
1110
        hostApiOutputParameters.device = hostApiOutputDevice;
1111
        hostApiOutputParameters.channelCount = outputParameters->channelCount;
1112
        hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
1113
        hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
1114
        hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
1115
        hostApiOutputParametersPtr = &hostApiOutputParameters;
1116
    }
1117
    else
1118
    {
1119
        hostApiOutputParametersPtr = NULL;
1120
    }
1121

    
1122
    result = hostApi->IsFormatSupported( hostApi,
1123
                                  hostApiInputParametersPtr, hostApiOutputParametersPtr,
1124
                                  sampleRate );
1125

    
1126
#ifdef PA_LOG_API_CALLS
1127
    PA_LOGAPI(("Pa_OpenStream returned:\n" ));
1128
    if( result == paFormatIsSupported )
1129
        PA_LOGAPI(("\tPaError: 0 [ paFormatIsSupported ]\n" ));
1130
    else
1131
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1132
#endif
1133

    
1134
    return result;
1135
}
1136

    
1137

    
1138
PaError Pa_OpenStream( PaStream** stream,
1139
                       const PaStreamParameters *inputParameters,
1140
                       const PaStreamParameters *outputParameters,
1141
                       double sampleRate,
1142
                       unsigned long framesPerBuffer,
1143
                       PaStreamFlags streamFlags,
1144
                       PaStreamCallback *streamCallback,
1145
                       void *userData )
1146
{
1147
    PaError result;
1148
    PaUtilHostApiRepresentation *hostApi = 0;
1149
    PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice;
1150
    PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1151
    PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1152

    
1153

    
1154
#ifdef PA_LOG_API_CALLS
1155
    PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" );
1156
    PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream ));
1157

    
1158
    if( inputParameters == NULL ){
1159
        PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" ));
1160
    }else{
1161
        PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters ));
1162
        PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device ));
1163
        PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount ));
1164
        PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat ));
1165
        PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency ));
1166
        PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo ));
1167
    }
1168

    
1169
    if( outputParameters == NULL ){
1170
        PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" ));
1171
    }else{
1172
        PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters ));
1173
        PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device ));
1174
        PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount ));
1175
        PA_LOGAPI(("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat ));
1176
        PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
1177
        PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
1178
    }
1179

    
1180
    PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
1181
    PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
1182
    PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags ));
1183
    PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback ));
1184
    PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData ));
1185
#endif
1186

    
1187
    if( !PA_IS_INITIALISED_ )
1188
    {
1189
        result = paNotInitialized;
1190

    
1191
        PA_LOGAPI(("Pa_OpenStream returned:\n" ));
1192
        PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
1193
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1194
        return result;
1195
    }
1196

    
1197
    /* Check for parameter errors.
1198
        NOTE: make sure this validation list is kept syncronised with the one
1199
        in pa_hostapi.h
1200
    */
1201

    
1202
    if( stream == NULL )
1203
    {
1204
        result = paBadStreamPtr;
1205

    
1206
        PA_LOGAPI(("Pa_OpenStream returned:\n" ));
1207
        PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
1208
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1209
        return result;
1210
    }
1211

    
1212
    result = ValidateOpenStreamParameters( inputParameters,
1213
                                           outputParameters,
1214
                                           sampleRate, framesPerBuffer,
1215
                                           streamFlags, streamCallback,
1216
                                           &hostApi,
1217
                                           &hostApiInputDevice,
1218
                                           &hostApiOutputDevice );
1219
    if( result != paNoError )
1220
    {
1221
        PA_LOGAPI(("Pa_OpenStream returned:\n" ));
1222
        PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
1223
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1224
        return result;
1225
    }
1226

    
1227

    
1228
    if( inputParameters )
1229
    {
1230
        hostApiInputParameters.device = hostApiInputDevice;
1231
        hostApiInputParameters.channelCount = inputParameters->channelCount;
1232
        hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
1233
        hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
1234
        hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
1235
        hostApiInputParametersPtr = &hostApiInputParameters;
1236
    }
1237
    else
1238
    {
1239
        hostApiInputParametersPtr = NULL;
1240
    }
1241

    
1242
    if( outputParameters )
1243
    {
1244
        hostApiOutputParameters.device = hostApiOutputDevice;
1245
        hostApiOutputParameters.channelCount = outputParameters->channelCount;
1246
        hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
1247
        hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
1248
        hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
1249
        hostApiOutputParametersPtr = &hostApiOutputParameters;
1250
    }
1251
    else
1252
    {
1253
        hostApiOutputParametersPtr = NULL;
1254
    }
1255

    
1256
    result = hostApi->OpenStream( hostApi, stream,
1257
                                  hostApiInputParametersPtr, hostApiOutputParametersPtr,
1258
                                  sampleRate, framesPerBuffer, streamFlags, streamCallback, userData );
1259

    
1260
    if( result == paNoError )
1261
        AddOpenStream( *stream );
1262

    
1263

    
1264
    PA_LOGAPI(("Pa_OpenStream returned:\n" ));
1265
    PA_LOGAPI(("\t*(PaStream** stream): 0x%p\n", *stream ));
1266
    PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1267

    
1268
    return result;
1269
}
1270

    
1271

    
1272
PaError Pa_OpenDefaultStream( PaStream** stream,
1273
                              int inputChannelCount,
1274
                              int outputChannelCount,
1275
                              PaSampleFormat sampleFormat,
1276
                              double sampleRate,
1277
                              unsigned long framesPerBuffer,
1278
                              PaStreamCallback *streamCallback,
1279
                              void *userData )
1280
{
1281
    PaError result;
1282
    PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1283
    PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1284

    
1285
    PA_LOGAPI_ENTER_PARAMS( "Pa_OpenDefaultStream" );
1286
    PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream ));
1287
    PA_LOGAPI(("\tint inputChannelCount: %d\n", inputChannelCount ));
1288
    PA_LOGAPI(("\tint outputChannelCount: %d\n", outputChannelCount ));
1289
    PA_LOGAPI(("\tPaSampleFormat sampleFormat: %d\n", sampleFormat ));
1290
    PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
1291
    PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
1292
    PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback ));
1293
    PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData ));
1294

    
1295

    
1296
    if( inputChannelCount > 0 )
1297
    {
1298
        hostApiInputParameters.device = Pa_GetDefaultInputDevice();
1299
                if( hostApiInputParameters.device == paNoDevice )
1300
                        return paDeviceUnavailable;
1301

    
1302
        hostApiInputParameters.channelCount = inputChannelCount;
1303
        hostApiInputParameters.sampleFormat = sampleFormat;
1304
        /* defaultHighInputLatency is used below instead of
1305
           defaultLowInputLatency because it is more important for the default
1306
           stream to work reliably than it is for it to work with the lowest
1307
           latency.
1308
         */
1309
        hostApiInputParameters.suggestedLatency =
1310
             Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
1311
        hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
1312
        hostApiInputParametersPtr = &hostApiInputParameters;
1313
    }
1314
    else
1315
    {
1316
        hostApiInputParametersPtr = NULL;
1317
    }
1318

    
1319
    if( outputChannelCount > 0 )
1320
    {
1321
        hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
1322
                if( hostApiOutputParameters.device == paNoDevice )
1323
                        return paDeviceUnavailable;
1324

    
1325
        hostApiOutputParameters.channelCount = outputChannelCount;
1326
        hostApiOutputParameters.sampleFormat = sampleFormat;
1327
        /* defaultHighOutputLatency is used below instead of
1328
           defaultLowOutputLatency because it is more important for the default
1329
           stream to work reliably than it is for it to work with the lowest
1330
           latency.
1331
         */
1332
        hostApiOutputParameters.suggestedLatency =
1333
             Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
1334
        hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
1335
        hostApiOutputParametersPtr = &hostApiOutputParameters;
1336
    }
1337
    else
1338
    {
1339
        hostApiOutputParametersPtr = NULL;
1340
    }
1341

    
1342

    
1343
    result = Pa_OpenStream(
1344
                 stream, hostApiInputParametersPtr, hostApiOutputParametersPtr,
1345
                 sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
1346

    
1347
    PA_LOGAPI(("Pa_OpenDefaultStream returned:\n" ));
1348
    PA_LOGAPI(("\t*(PaStream** stream): 0x%p", *stream ));
1349
    PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1350

    
1351
    return result;
1352
}
1353

    
1354

    
1355
PaError PaUtil_ValidateStreamPointer( PaStream* stream )
1356
{
1357
    if( !PA_IS_INITIALISED_ ) return paNotInitialized;
1358

    
1359
    if( stream == NULL ) return paBadStreamPtr;
1360

    
1361
    if( ((PaUtilStreamRepresentation*)stream)->magic != PA_STREAM_MAGIC )
1362
        return paBadStreamPtr;
1363

    
1364
    return paNoError;
1365
}
1366

    
1367

    
1368
PaError Pa_CloseStream( PaStream* stream )
1369
{
1370
    PaUtilStreamInterface *interface;
1371
    PaError result = PaUtil_ValidateStreamPointer( stream );
1372

    
1373
    PA_LOGAPI_ENTER_PARAMS( "Pa_CloseStream" );
1374
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1375

    
1376
    /* always remove the open stream from our list, even if this function
1377
        eventually returns an error. Otherwise CloseOpenStreams() will
1378
        get stuck in an infinite loop */
1379
    RemoveOpenStream( stream ); /* be sure to call this _before_ closing the stream */
1380

    
1381
    if( result == paNoError )
1382
    {
1383
        interface = PA_STREAM_INTERFACE(stream);
1384

    
1385
        /* abort the stream if it isn't stopped */
1386
        result = interface->IsStopped( stream );
1387
        if( result == 1 )
1388
            result = paNoError;
1389
        else if( result == 0 )
1390
            result = interface->Abort( stream );
1391

    
1392
        if( result == paNoError )                 /** @todo REVIEW: shouldn't we close anyway? see: http://www.portaudio.com/trac/ticket/115 */
1393
            result = interface->Close( stream );
1394
    }
1395

    
1396
    PA_LOGAPI_EXIT_PAERROR( "Pa_CloseStream", result );
1397

    
1398
    return result;
1399
}
1400

    
1401

    
1402
PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback )
1403
{
1404
    PaError result = PaUtil_ValidateStreamPointer( stream );
1405

    
1406
    PA_LOGAPI_ENTER_PARAMS( "Pa_SetStreamFinishedCallback" );
1407
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1408
    PA_LOGAPI(("\tPaStreamFinishedCallback* streamFinishedCallback: 0x%p\n", streamFinishedCallback ));
1409

    
1410
    if( result == paNoError )
1411
    {
1412
        result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1413
        if( result == 0 )
1414
        {
1415
            result = paStreamIsNotStopped ;
1416
        }
1417
        if( result == 1 )
1418
        {
1419
            PA_STREAM_REP( stream )->streamFinishedCallback = streamFinishedCallback;
1420
            result = paNoError;
1421
        }
1422
    }
1423

    
1424
    PA_LOGAPI_EXIT_PAERROR( "Pa_SetStreamFinishedCallback", result );
1425

    
1426
    return result;
1427

    
1428
}
1429

    
1430

    
1431
PaError Pa_StartStream( PaStream *stream )
1432
{
1433
    PaError result = PaUtil_ValidateStreamPointer( stream );
1434

    
1435
    PA_LOGAPI_ENTER_PARAMS( "Pa_StartStream" );
1436
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1437

    
1438
    if( result == paNoError )
1439
    {
1440
        result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1441
        if( result == 0 )
1442
        {
1443
            result = paStreamIsNotStopped ;
1444
        }
1445
        else if( result == 1 )
1446
        {
1447
            result = PA_STREAM_INTERFACE(stream)->Start( stream );
1448
        }
1449
    }
1450

    
1451
    PA_LOGAPI_EXIT_PAERROR( "Pa_StartStream", result );
1452

    
1453
    return result;
1454
}
1455

    
1456

    
1457
PaError Pa_StopStream( PaStream *stream )
1458
{
1459
    PaError result = PaUtil_ValidateStreamPointer( stream );
1460

    
1461
    PA_LOGAPI_ENTER_PARAMS( "Pa_StopStream" );
1462
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1463

    
1464
    if( result == paNoError )
1465
    {
1466
        result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1467
        if( result == 0 )
1468
        {
1469
            result = PA_STREAM_INTERFACE(stream)->Stop( stream );
1470
        }
1471
        else if( result == 1 )
1472
        {
1473
            result = paStreamIsStopped;
1474
        }
1475
    }
1476

    
1477
    PA_LOGAPI_EXIT_PAERROR( "Pa_StopStream", result );
1478

    
1479
    return result;
1480
}
1481

    
1482

    
1483
PaError Pa_AbortStream( PaStream *stream )
1484
{
1485
    PaError result = PaUtil_ValidateStreamPointer( stream );
1486

    
1487
    PA_LOGAPI_ENTER_PARAMS( "Pa_AbortStream" );
1488
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1489

    
1490
    if( result == paNoError )
1491
    {
1492
        result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1493
        if( result == 0 )
1494
        {
1495
            result = PA_STREAM_INTERFACE(stream)->Abort( stream );
1496
        }
1497
        else if( result == 1 )
1498
        {
1499
            result = paStreamIsStopped;
1500
        }
1501
    }
1502

    
1503
    PA_LOGAPI_EXIT_PAERROR( "Pa_AbortStream", result );
1504

    
1505
    return result;
1506
}
1507

    
1508

    
1509
PaError Pa_IsStreamStopped( PaStream *stream )
1510
{
1511
    PaError result = PaUtil_ValidateStreamPointer( stream );
1512

    
1513
    PA_LOGAPI_ENTER_PARAMS( "Pa_IsStreamStopped" );
1514
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1515

    
1516
    if( result == paNoError )
1517
        result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1518

    
1519
    PA_LOGAPI_EXIT_PAERROR( "Pa_IsStreamStopped", result );
1520

    
1521
    return result;
1522
}
1523

    
1524

    
1525
PaError Pa_IsStreamActive( PaStream *stream )
1526
{
1527
    PaError result = PaUtil_ValidateStreamPointer( stream );
1528

    
1529
    PA_LOGAPI_ENTER_PARAMS( "Pa_IsStreamActive" );
1530
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1531

    
1532
    if( result == paNoError )
1533
        result = PA_STREAM_INTERFACE(stream)->IsActive( stream );
1534

    
1535

    
1536
    PA_LOGAPI_EXIT_PAERROR( "Pa_IsStreamActive", result );
1537

    
1538
    return result;
1539
}
1540

    
1541

    
1542
const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream )
1543
{
1544
    PaError error = PaUtil_ValidateStreamPointer( stream );
1545
    const PaStreamInfo *result;
1546

    
1547
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamInfo" );
1548
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1549

    
1550
    if( error != paNoError )
1551
    {
1552
        result = 0;
1553

    
1554
        PA_LOGAPI(("Pa_GetStreamInfo returned:\n" ));
1555
        PA_LOGAPI(("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n", error, Pa_GetErrorText( error ) ));
1556

    
1557
    }
1558
    else
1559
    {
1560
        result = &PA_STREAM_REP( stream )->streamInfo;
1561

    
1562
        PA_LOGAPI(("Pa_GetStreamInfo returned:\n" ));
1563
        PA_LOGAPI(("\tconst PaStreamInfo*: 0x%p:\n", result ));
1564
        PA_LOGAPI(("\t{" ));
1565

    
1566
        PA_LOGAPI(("\t\tint structVersion: %d\n", result->structVersion ));
1567
        PA_LOGAPI(("\t\tPaTime inputLatency: %f\n", result->inputLatency ));
1568
        PA_LOGAPI(("\t\tPaTime outputLatency: %f\n", result->outputLatency ));
1569
        PA_LOGAPI(("\t\tdouble sampleRate: %f\n", result->sampleRate ));
1570
        PA_LOGAPI(("\t}\n" ));
1571

    
1572
    }
1573

    
1574
    return result;
1575
}
1576

    
1577

    
1578
PaTime Pa_GetStreamTime( PaStream *stream )
1579
{
1580
    PaError error = PaUtil_ValidateStreamPointer( stream );
1581
    PaTime result;
1582

    
1583
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamTime" );
1584
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1585

    
1586
    if( error != paNoError )
1587
    {
1588
        result = 0;
1589

    
1590
        PA_LOGAPI(("Pa_GetStreamTime returned:\n" ));
1591
        PA_LOGAPI(("\tPaTime: 0 [PaError error:%d ( %s )]\n", result, error, Pa_GetErrorText( error ) ));
1592

    
1593
    }
1594
    else
1595
    {
1596
        result = PA_STREAM_INTERFACE(stream)->GetTime( stream );
1597

    
1598
        PA_LOGAPI(("Pa_GetStreamTime returned:\n" ));
1599
        PA_LOGAPI(("\tPaTime: %g\n", result ));
1600

    
1601
    }
1602

    
1603
    return result;
1604
}
1605

    
1606

    
1607
double Pa_GetStreamCpuLoad( PaStream* stream )
1608
{
1609
    PaError error = PaUtil_ValidateStreamPointer( stream );
1610
    double result;
1611

    
1612
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamCpuLoad" );
1613
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1614

    
1615
    if( error != paNoError )
1616
    {
1617

    
1618
        result = 0.0;
1619

    
1620
        PA_LOGAPI(("Pa_GetStreamCpuLoad returned:\n" ));
1621
        PA_LOGAPI(("\tdouble: 0.0 [PaError error: %d ( %s )]\n", error, Pa_GetErrorText( error ) ));
1622

    
1623
    }
1624
    else
1625
    {
1626
        result = PA_STREAM_INTERFACE(stream)->GetCpuLoad( stream );
1627

    
1628
        PA_LOGAPI(("Pa_GetStreamCpuLoad returned:\n" ));
1629
        PA_LOGAPI(("\tdouble: %g\n", result ));
1630

    
1631
    }
1632

    
1633
    return result;
1634
}
1635

    
1636

    
1637
PaError Pa_ReadStream( PaStream* stream,
1638
                       void *buffer,
1639
                       unsigned long frames )
1640
{
1641
    PaError result = PaUtil_ValidateStreamPointer( stream );
1642

    
1643
    PA_LOGAPI_ENTER_PARAMS( "Pa_ReadStream" );
1644
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1645

    
1646
    if( result == paNoError )
1647
    {
1648
        if( frames == 0 )
1649
        {
1650
            /* @todo Should we not allow the implementation to signal any overflow condition? see: http://www.portaudio.com/trac/ticket/116*/
1651
            result = paNoError;
1652
        }
1653
        else if( buffer == 0 )
1654
        {
1655
            result = paBadBufferPtr;
1656
        }
1657
        else
1658
        {
1659
            result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1660
            if( result == 0 )
1661
            {
1662
                result = PA_STREAM_INTERFACE(stream)->Read( stream, buffer, frames );
1663
            }
1664
            else if( result == 1 )
1665
            {
1666
                result = paStreamIsStopped;
1667
            }
1668
        }
1669
    }
1670

    
1671
    PA_LOGAPI_EXIT_PAERROR( "Pa_ReadStream", result );
1672

    
1673
    return result;
1674
}
1675

    
1676

    
1677
PaError Pa_WriteStream( PaStream* stream,
1678
                        const void *buffer,
1679
                        unsigned long frames )
1680
{
1681
    PaError result = PaUtil_ValidateStreamPointer( stream );
1682

    
1683
    PA_LOGAPI_ENTER_PARAMS( "Pa_WriteStream" );
1684
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1685

    
1686
    if( result == paNoError )
1687
    {
1688
        if( frames == 0 )
1689
        {
1690
            /* @todo Should we not allow the implementation to signal any underflow condition? see: http://www.portaudio.com/trac/ticket/116*/
1691
            result = paNoError;
1692
        }
1693
        else if( buffer == 0 )
1694
        {
1695
            result = paBadBufferPtr;
1696
        }
1697
        else
1698
        {
1699
            result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1700
            if( result == 0 )
1701
            {
1702
                result = PA_STREAM_INTERFACE(stream)->Write( stream, buffer, frames );
1703
            }
1704
            else if( result == 1 )
1705
            {
1706
                result = paStreamIsStopped;
1707
            }
1708
        }
1709
    }
1710

    
1711
    PA_LOGAPI_EXIT_PAERROR( "Pa_WriteStream", result );
1712

    
1713
    return result;
1714
}
1715

    
1716
signed long Pa_GetStreamReadAvailable( PaStream* stream )
1717
{
1718
    PaError error = PaUtil_ValidateStreamPointer( stream );
1719
    signed long result;
1720

    
1721
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamReadAvailable" );
1722
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1723

    
1724
    if( error != paNoError )
1725
    {
1726
        result = 0;
1727

    
1728
        PA_LOGAPI(("Pa_GetStreamReadAvailable returned:\n" ));
1729
        PA_LOGAPI(("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n", error, Pa_GetErrorText( error ) ));
1730

    
1731
    }
1732
    else
1733
    {
1734
        result = PA_STREAM_INTERFACE(stream)->GetReadAvailable( stream );
1735

    
1736
        PA_LOGAPI(("Pa_GetStreamReadAvailable returned:\n" ));
1737
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1738

    
1739
    }
1740

    
1741
    return result;
1742
}
1743

    
1744

    
1745
signed long Pa_GetStreamWriteAvailable( PaStream* stream )
1746
{
1747
    PaError error = PaUtil_ValidateStreamPointer( stream );
1748
    signed long result;
1749

    
1750
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamWriteAvailable" );
1751
    PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
1752

    
1753
    if( error != paNoError )
1754
    {
1755
        result = 0;
1756

    
1757
        PA_LOGAPI(("Pa_GetStreamWriteAvailable returned:\n" ));
1758
        PA_LOGAPI(("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n", error, Pa_GetErrorText( error ) ));
1759

    
1760
    }
1761
    else
1762
    {
1763
        result = PA_STREAM_INTERFACE(stream)->GetWriteAvailable( stream );
1764

    
1765
        PA_LOGAPI(("Pa_GetStreamWriteAvailable returned:\n" ));
1766
        PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
1767

    
1768
    }
1769

    
1770
    return result;
1771
}
1772

    
1773

    
1774
PaError Pa_GetSampleSize( PaSampleFormat format )
1775
{
1776
    int result;
1777

    
1778
    PA_LOGAPI_ENTER_PARAMS( "Pa_GetSampleSize" );
1779
    PA_LOGAPI(("\tPaSampleFormat format: %d\n", format ));
1780

    
1781
    switch( format & ~paNonInterleaved )
1782
    {
1783

    
1784
    case paUInt8:
1785
    case paInt8:
1786
        result = 1;
1787
        break;
1788

    
1789
    case paInt16:
1790
        result = 2;
1791
        break;
1792

    
1793
    case paInt24:
1794
        result = 3;
1795
        break;
1796

    
1797
    case paFloat32:
1798
    case paInt32:
1799
        result = 4;
1800
        break;
1801

    
1802
    default:
1803
        result = paSampleFormatNotSupported;
1804
        break;
1805
    }
1806

    
1807
    PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetSampleSize", "int: %d", result );
1808

    
1809
    return (PaError) result;
1810
}
1811