1 /*
2  * $Id: pa_front.c,v 1.1 2006/06/10 21:30:55 dmazzoni Exp $
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-2002 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  * Any person wishing to distribute modifications to the Software is
21  * requested to send the modifications to the original developer so that
22  * they can be incorporated into the canonical version.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
28  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31  */
32 
33 /* doxygen index page */
34 /** @mainpage
35 
36 PortAudio is an open-source cross-platform C library for audio input
37 and output. It is designed to simplify the porting of audio applications
38 between various platforms, and also to simplify the development of audio
39 software in general by hiding the complexities of device interfacing.
40 
41 See the PortAudio website for further information http://www.portaudio.com/
42 
43 This documentation pertains to PortAudio V19, API version 2.0 which is
44 currently under development. API version 2.0 differs in a number of ways from
45 previous versions, please consult the enhancement proposals for further details:
46 http://www.portaudio.com/docs/proposals/index.html
47 
48 This documentation is under construction. Things you might be interested in
49 include:
50 
51 - The PortAudio API 2.0, as documented in portaudio.h
52 
53 - The <a href="todo.html">TODO List</a>
54 
55 Feel free to pick an item off TODO list and fix/implement it. You may want to
56 enquire about status on the PortAudio mailing list first.
57 */
58 
59 
60 /** @file
61  @brief Implements public PortAudio API, checks some errors, forwards to
62  host API implementations.
63 
64  Implements the functions defined in the PortAudio API, checks for
65  some parameter and state inconsistencies and forwards API requests to
66  specific Host API implementations (via the interface declared in
67  pa_hostapi.h), and Streams (via the interface declared in pa_stream.h).
68 
69  This file handles initialization and termination of Host API
70  implementations via initializers stored in the paHostApiInitializers
71  global variable.
72 
73  Some utility functions declared in pa_util.h are implemented in this file.
74 
75  All PortAudio API functions can be conditionally compiled with logging code.
76  To compile with logging, define the PA_LOG_API_CALLS precompiler symbol.
77 
78     @todo Consider adding host API specific error text in Pa_GetErrorText() for
79     paUnanticipatedHostError
80 
81     @todo Consider adding a new error code for when (inputParameters == NULL)
82     && (outputParameters == NULL)
83 
84     @todo review whether Pa_CloseStream() should call the interface's
85     CloseStream function if aborting the stream returns an error code.
86 
87     @todo Create new error codes if a NULL buffer pointer, or a
88     zero frame count is passed to Pa_ReadStream or Pa_WriteStream.
89 */
90 
91 
92 #include <stdio.h>
93 #include <stdarg.h>
94 #include <memory.h>
95 #include <string.h>
96 #include <assert.h> /* needed by PA_VALIDATE_ENDIANNESS */
97 
98 #include "portaudio.h"
99 #include "pa_util.h"
100 #include "pa_endianness.h"
101 #include "pa_types.h"
102 #include "pa_hostapi.h"
103 #include "pa_stream.h"
104 
105 #include "pa_trace.h"
106 
107 
108 #define PA_VERSION_  1899
109 #define PA_VERSION_TEXT_ "PortAudio V19-devel"
110 
111 
112 
113 /* #define PA_LOG_API_CALLS */
114 
115 /*
116     The basic format for log messages is described below. If you need to
117     add any log messages, please follow this format.
118 
119     Function entry (void function):
120 
121         "FunctionName called.\n"
122 
123     Function entry (non void function):
124 
125         "FunctionName called:\n"
126         "\tParam1Type param1: param1Value\n"
127         "\tParam2Type param2: param2Value\n"      (etc...)
128 
129 
130     Function exit (no return value):
131 
132         "FunctionName returned.\n"
133 
134     Function exit (simple return value):
135 
136         "FunctionName returned:\n"
137         "\tReturnType: returnValue\n\n"
138 
139     If the return type is an error code, the error text is displayed in ()
140 
141     If the return type is not an error code, but has taken a special value
142     because an error occurred, then the reason for the error is shown in []
143 
144     If the return type is a struct ptr, the struct is dumped.
145 
146     See the code below for examples
147 */
148 
149 
Pa_GetVersion(void)150 int Pa_GetVersion( void )
151 {
152     return PA_VERSION_;
153 }
154 
155 
Pa_GetVersionText(void)156 const char* Pa_GetVersionText( void )
157 {
158     return PA_VERSION_TEXT_;
159 }
160 
161 
162 
163 #define PA_LAST_HOST_ERROR_TEXT_LENGTH_  1024
164 
165 static char lastHostErrorText_[ PA_LAST_HOST_ERROR_TEXT_LENGTH_ + 1 ] = {0};
166 
167 static PaHostErrorInfo lastHostErrorInfo_ = { (PaHostApiTypeId)-1, 0, lastHostErrorText_ };
168 
169 
PaUtil_SetLastHostErrorInfo(PaHostApiTypeId hostApiType,long errorCode,const char * errorText)170 void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
171         const char *errorText )
172 {
173     lastHostErrorInfo_.hostApiType = hostApiType;
174     lastHostErrorInfo_.errorCode = errorCode;
175 
176     strncpy( lastHostErrorText_, errorText, PA_LAST_HOST_ERROR_TEXT_LENGTH_ );
177 }
178 
179 
PaUtil_DebugPrint(const char * format,...)180 void PaUtil_DebugPrint( const char *format, ... )
181 {
182     va_list ap;
183 
184     va_start( ap, format );
185     vfprintf( stderr, format, ap );
186     va_end( ap );
187 
188     fflush( stderr );
189 }
190 
191 
192 static PaUtilHostApiRepresentation **hostApis_ = 0;
193 static int hostApisCount_ = 0;
194 static int initializationCount_ = 0;
195 static int deviceCount_ = 0;
196 
197 PaUtilStreamRepresentation *firstOpenStream_ = NULL;
198 
199 
200 #define PA_IS_INITIALISED_ (initializationCount_ != 0)
201 
202 
CountHostApiInitializers(void)203 static int CountHostApiInitializers( void )
204 {
205     int result = 0;
206 
207     while( paHostApiInitializers[ result ] != 0 )
208         ++result;
209     return result;
210 }
211 
212 
TerminateHostApis(void)213 static void TerminateHostApis( void )
214 {
215     /* terminate in reverse order from initialization */
216 
217     while( hostApisCount_ > 0 )
218     {
219         --hostApisCount_;
220         hostApis_[hostApisCount_]->Terminate( hostApis_[hostApisCount_] );
221     }
222     hostApisCount_ = 0;
223     deviceCount_ = 0;
224 
225     if( hostApis_ != 0 )
226         PaUtil_FreeMemory( hostApis_ );
227     hostApis_ = 0;
228 }
229 
230 
InitializeHostApis(void)231 static PaError InitializeHostApis( void )
232 {
233     PaError result = paNoError;
234     int i, initializerCount, baseDeviceIndex;
235 
236     initializerCount = CountHostApiInitializers();
237 
238     hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
239             sizeof(PaUtilHostApiRepresentation*) * initializerCount );
240     if( !hostApis_ )
241     {
242         result = paInsufficientMemory;
243         goto error;
244     }
245 
246     hostApisCount_ = 0;
247     deviceCount_ = 0;
248     baseDeviceIndex = 0;
249 
250     for( i=0; i< initializerCount; ++i )
251     {
252         hostApis_[hostApisCount_] = NULL;
253         result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ );
254         if( result != paNoError )
255             goto error;
256 
257         if( hostApis_[hostApisCount_] )
258         {
259             PaUtilHostApiRepresentation* hostApi = hostApis_[hostApisCount_];
260             assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
261             assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
262 
263             hostApis_[hostApisCount_]->privatePaFrontInfo.baseDeviceIndex = baseDeviceIndex;
264 
265             if( hostApis_[hostApisCount_]->info.defaultInputDevice != paNoDevice )
266                 hostApis_[hostApisCount_]->info.defaultInputDevice += baseDeviceIndex;
267 
268             if( hostApis_[hostApisCount_]->info.defaultOutputDevice != paNoDevice )
269                 hostApis_[hostApisCount_]->info.defaultOutputDevice += baseDeviceIndex;
270 
271             baseDeviceIndex += hostApis_[hostApisCount_]->info.deviceCount;
272             deviceCount_ += hostApis_[hostApisCount_]->info.deviceCount;
273 
274             ++hostApisCount_;
275         }
276     }
277 
278     return result;
279 
280 error:
281     TerminateHostApis();
282     return result;
283 }
284 
285 
286 /*
287     FindHostApi() finds the index of the host api to which
288     <device> belongs and returns it. if <hostSpecificDeviceIndex> is
289     non-null, the host specific device index is returned in it.
290     returns -1 if <device> is out of range.
291 
292 */
FindHostApi(PaDeviceIndex device,int * hostSpecificDeviceIndex)293 static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
294 {
295     int i=0;
296 
297     if( !PA_IS_INITIALISED_ )
298         return -1;
299 
300     if( device < 0 )
301         return -1;
302 
303     while( i < hostApisCount_
304             && device >= hostApis_[i]->info.deviceCount )
305     {
306 
307         device -= hostApis_[i]->info.deviceCount;
308         ++i;
309     }
310 
311     if( i >= hostApisCount_ )
312         return -1;
313 
314     if( hostSpecificDeviceIndex )
315         *hostSpecificDeviceIndex = device;
316 
317     return i;
318 }
319 
320 
AddOpenStream(PaStream * stream)321 static void AddOpenStream( PaStream* stream )
322 {
323     ((PaUtilStreamRepresentation*)stream)->nextOpenStream = firstOpenStream_;
324     firstOpenStream_ = (PaUtilStreamRepresentation*)stream;
325 }
326 
327 
RemoveOpenStream(PaStream * stream)328 static void RemoveOpenStream( PaStream* stream )
329 {
330     PaUtilStreamRepresentation *previous = NULL;
331     PaUtilStreamRepresentation *current = firstOpenStream_;
332 
333     while( current != NULL )
334     {
335         if( ((PaStream*)current) == stream )
336         {
337             if( previous == NULL )
338             {
339                 firstOpenStream_ = current->nextOpenStream;
340             }
341             else
342             {
343                 previous->nextOpenStream = current->nextOpenStream;
344             }
345             return;
346         }
347         else
348         {
349             previous = current;
350             current = current->nextOpenStream;
351         }
352     }
353 }
354 
355 
CloseOpenStreams(void)356 static void CloseOpenStreams( void )
357 {
358     /* we call Pa_CloseStream() here to ensure that the same destruction
359         logic is used for automatically closed streams */
360 
361     while( firstOpenStream_ != NULL )
362         Pa_CloseStream( firstOpenStream_ );
363 }
364 
365 
Pa_Initialize(void)366 PaError Pa_Initialize( void )
367 {
368     PaError result;
369 
370 #ifdef PA_LOG_API_CALLS
371     PaUtil_DebugPrint( "Pa_Initialize called.\n" );
372 #endif
373 
374     if( PA_IS_INITIALISED_ )
375     {
376         ++initializationCount_;
377         result = paNoError;
378     }
379     else
380     {
381         PA_VALIDATE_TYPE_SIZES;
382         PA_VALIDATE_ENDIANNESS;
383 
384         PaUtil_InitializeClock();
385         PaUtil_ResetTraceMessages();
386 
387         result = InitializeHostApis();
388         if( result == paNoError )
389             ++initializationCount_;
390     }
391 
392 #ifdef PA_LOG_API_CALLS
393     PaUtil_DebugPrint( "Pa_Initialize returned:\n" );
394     PaUtil_DebugPrint( "\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
395 #endif
396 
397     return result;
398 }
399 
400 
Pa_Terminate(void)401 PaError Pa_Terminate( void )
402 {
403     PaError result;
404 
405 #ifdef PA_LOG_API_CALLS
406     PaUtil_DebugPrint("Pa_Terminate called.\n" );
407 #endif
408 
409     if( PA_IS_INITIALISED_ )
410     {
411         if( --initializationCount_ == 0 )
412         {
413             CloseOpenStreams();
414 
415             TerminateHostApis();
416 
417             PaUtil_DumpTraceMessages();
418         }
419         result = paNoError;
420     }
421     else
422     {
423         result=  paNotInitialized;
424     }
425 
426 #ifdef PA_LOG_API_CALLS
427     PaUtil_DebugPrint("Pa_Terminate returned:\n" );
428     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
429 #endif
430 
431     return result;
432 }
433 
434 
Pa_GetLastHostErrorInfo(void)435 const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void )
436 {
437     return &lastHostErrorInfo_;
438 }
439 
440 
Pa_GetErrorText(PaError errorCode)441 const char *Pa_GetErrorText( PaError errorCode )
442 {
443     const char *result;
444 
445     switch( errorCode )
446     {
447     case paNoError:                  result = "Success"; break;
448     case paNotInitialized:           result = "PortAudio not initialized"; break;
449     /** @todo could catenate the last host error text to result in the case of paUnanticipatedHostError */
450     case paUnanticipatedHostError:   result = "Unanticipated host error"; break;
451     case paInvalidChannelCount:      result = "Invalid number of channels"; break;
452     case paInvalidSampleRate:        result = "Invalid sample rate"; break;
453     case paInvalidDevice:            result = "Invalid device"; break;
454     case paInvalidFlag:              result = "Invalid flag"; break;
455     case paSampleFormatNotSupported: result = "Sample format not supported"; break;
456     case paBadIODeviceCombination:   result = "Illegal combination of I/O devices"; break;
457     case paInsufficientMemory:       result = "Insufficient memory"; break;
458     case paBufferTooBig:             result = "Buffer too big"; break;
459     case paBufferTooSmall:           result = "Buffer too small"; break;
460     case paNullCallback:             result = "No callback routine specified"; break;
461     case paBadStreamPtr:             result = "Invalid stream pointer"; break;
462     case paTimedOut:                 result = "Wait timed out"; break;
463     case paInternalError:            result = "Internal PortAudio error"; break;
464     case paDeviceUnavailable:        result = "Device unavailable"; break;
465     case paIncompatibleHostApiSpecificStreamInfo:   result = "Incompatible host API specific stream info"; break;
466     case paStreamIsStopped:          result = "Stream is stopped"; break;
467     case paStreamIsNotStopped:       result = "Stream is not stopped"; break;
468     case paInputOverflowed:          result = "Input overflowed"; break;
469     case paOutputUnderflowed:        result = "Output underflowed"; break;
470     case paHostApiNotFound:          result = "Host API not found"; break;
471     case paInvalidHostApi:           result = "Invalid host API"; break;
472     case paCanNotReadFromACallbackStream:       result = "Can't read from a callback stream"; break;
473     case paCanNotWriteToACallbackStream:        result = "Can't write to a callback stream"; break;
474     case paCanNotReadFromAnOutputOnlyStream:    result = "Can't read from an output only stream"; break;
475     case paCanNotWriteToAnInputOnlyStream:      result = "Can't write to an input only stream"; break;
476     default:                         result = "Illegal error number"; break;
477     }
478     return result;
479 }
480 
481 
Pa_HostApiTypeIdToHostApiIndex(PaHostApiTypeId type)482 PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
483 {
484     PaHostApiIndex result;
485     int i;
486 
487 #ifdef PA_LOG_API_CALLS
488     PaUtil_DebugPrint("Pa_HostApiTypeIdToHostApiIndex called:\n" );
489     PaUtil_DebugPrint("\tPaHostApiTypeId type: %d\n", type );
490 #endif
491 
492     if( !PA_IS_INITIALISED_ )
493     {
494         result = paNotInitialized;
495     }
496     else
497     {
498         result = paHostApiNotFound;
499 
500         for( i=0; i < hostApisCount_; ++i )
501         {
502             if( hostApis_[i]->info.type == type )
503             {
504                 result = i;
505                 break;
506             }
507         }
508     }
509 
510 #ifdef PA_LOG_API_CALLS
511     PaUtil_DebugPrint("Pa_HostApiTypeIdToHostApiIndex returned:\n" );
512     if( result < 0 )
513         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
514     else
515         PaUtil_DebugPrint("\tPaHostApiIndex: %d\n\n", result );
516 #endif
517 
518     return result;
519 }
520 
521 
PaUtil_GetHostApiRepresentation(struct PaUtilHostApiRepresentation ** hostApi,PaHostApiTypeId type)522 PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
523         PaHostApiTypeId type )
524 {
525     PaError result;
526     int i;
527 
528     if( !PA_IS_INITIALISED_ )
529     {
530         result = paNotInitialized;
531     }
532     else
533     {
534         result = paHostApiNotFound;
535 
536         for( i=0; i < hostApisCount_; ++i )
537         {
538             if( hostApis_[i]->info.type == type )
539             {
540                 *hostApi = hostApis_[i];
541                 result = paNoError;
542                 break;
543             }
544         }
545     }
546 
547     return result;
548 }
549 
550 
PaUtil_DeviceIndexToHostApiDeviceIndex(PaDeviceIndex * hostApiDevice,PaDeviceIndex device,struct PaUtilHostApiRepresentation * hostApi)551 PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
552         PaDeviceIndex *hostApiDevice, PaDeviceIndex device, struct PaUtilHostApiRepresentation *hostApi )
553 {
554     PaError result;
555     PaDeviceIndex x;
556 
557     x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
558 
559     if( x < 0 || x >= hostApi->info.deviceCount )
560     {
561         result = paInvalidDevice;
562     }
563     else
564     {
565         *hostApiDevice = x;
566         result = paNoError;
567     }
568 
569     return result;
570 }
571 
572 
Pa_GetHostApiCount(void)573 PaHostApiIndex Pa_GetHostApiCount( void )
574 {
575     int result;
576 
577 #ifdef PA_LOG_API_CALLS
578     PaUtil_DebugPrint("Pa_GetHostApiCount called.\n" );
579 #endif
580 
581     if( !PA_IS_INITIALISED_ )
582     {
583         result = paNotInitialized;
584     }
585     else
586     {
587         result = hostApisCount_;
588     }
589 
590 #ifdef PA_LOG_API_CALLS
591     PaUtil_DebugPrint("Pa_GetHostApiCount returned:\n" );
592     if( result < 0 )
593         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
594     else
595         PaUtil_DebugPrint("\tPaHostApiIndex %d\n\n", result );
596 #endif
597 
598     return result;
599 }
600 
601 
Pa_GetDefaultHostApi(void)602 PaHostApiIndex Pa_GetDefaultHostApi( void )
603 {
604     int result;
605 
606 #ifdef PA_LOG_API_CALLS
607     PaUtil_DebugPrint("Pa_GetDefaultHostApi called.\n" );
608 #endif
609 
610     if( !PA_IS_INITIALISED_ )
611     {
612         result = paNotInitialized;
613     }
614     else
615     {
616         result = paDefaultHostApiIndex;
617 
618         /* internal consistency check: make sure that the default host api
619          index is within range */
620 
621         if( result < 0 || result >= hostApisCount_ )
622         {
623             result = paInternalError;
624         }
625     }
626 
627 #ifdef PA_LOG_API_CALLS
628     PaUtil_DebugPrint("Pa_GetDefaultHostApi returned:\n" );
629     if( result < 0 )
630         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
631     else
632         PaUtil_DebugPrint("\tPaHostApiIndex %d\n\n", result );
633 #endif
634 
635     return result;
636 }
637 
638 
Pa_GetHostApiInfo(PaHostApiIndex hostApi)639 const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
640 {
641     PaHostApiInfo *info;
642 
643 #ifdef PA_LOG_API_CALLS
644     PaUtil_DebugPrint("Pa_GetHostApiInfo called:\n" );
645     PaUtil_DebugPrint("\tPaHostApiIndex hostApi: %d\n", hostApi );
646 #endif
647 
648     if( !PA_IS_INITIALISED_ )
649     {
650         info = NULL;
651 
652 #ifdef PA_LOG_API_CALLS
653         PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
654         PaUtil_DebugPrint("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n\n" );
655 #endif
656 
657     }
658     else if( hostApi < 0 || hostApi >= hostApisCount_ )
659     {
660         info = NULL;
661 
662 #ifdef PA_LOG_API_CALLS
663         PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
664         PaUtil_DebugPrint("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n\n" );
665 #endif
666 
667     }
668     else
669     {
670         info = &hostApis_[hostApi]->info;
671 
672 #ifdef PA_LOG_API_CALLS
673         PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
674         PaUtil_DebugPrint("\tPaHostApiInfo*: 0x%p\n", info );
675         PaUtil_DebugPrint("\t{" );
676         PaUtil_DebugPrint("\t\tint structVersion: %d\n", info->structVersion );
677         PaUtil_DebugPrint("\t\tPaHostApiTypeId type: %d\n", info->type );
678         PaUtil_DebugPrint("\t\tconst char *name: %s\n\n", info->name );
679         PaUtil_DebugPrint("\t}\n\n" );
680 #endif
681 
682     }
683 
684      return info;
685 }
686 
687 
Pa_HostApiDeviceIndexToDeviceIndex(PaHostApiIndex hostApi,int hostApiDeviceIndex)688 PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int hostApiDeviceIndex )
689 {
690     PaDeviceIndex result;
691 
692 #ifdef PA_LOG_API_CALLS
693     PaUtil_DebugPrint("Pa_HostApiDeviceIndexToPaDeviceIndex called:\n" );
694     PaUtil_DebugPrint("\tPaHostApiIndex hostApi: %d\n", hostApi );
695     PaUtil_DebugPrint("\tint hostApiDeviceIndex: %d\n", hostApiDeviceIndex );
696 #endif
697 
698     if( !PA_IS_INITIALISED_ )
699     {
700         result = paNotInitialized;
701     }
702     else
703     {
704         if( hostApi < 0 || hostApi >= hostApisCount_ )
705         {
706             result = paInvalidHostApi;
707         }
708         else
709         {
710             if( hostApiDeviceIndex < 0 ||
711                     hostApiDeviceIndex >= hostApis_[hostApi]->info.deviceCount )
712             {
713                 result = paInvalidDevice;
714             }
715             else
716             {
717                 result = hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex;
718             }
719         }
720     }
721 
722 #ifdef PA_LOG_API_CALLS
723     PaUtil_DebugPrint("Pa_HostApiDeviceIndexToPaDeviceIndex returned:\n" );
724     if( result < 0 )
725         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
726     else
727         PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
728 #endif
729 
730     return result;
731 }
732 
733 
Pa_GetDeviceCount(void)734 PaDeviceIndex Pa_GetDeviceCount( void )
735 {
736     PaDeviceIndex result;
737 
738 #ifdef PA_LOG_API_CALLS
739     PaUtil_DebugPrint("Pa_GetDeviceCount called.\n" );
740 #endif
741 
742     if( !PA_IS_INITIALISED_ )
743     {
744         result = paNotInitialized;
745     }
746     else
747     {
748         result = deviceCount_;
749     }
750 
751 #ifdef PA_LOG_API_CALLS
752     PaUtil_DebugPrint("Pa_GetDeviceCount returned:\n" );
753     if( result < 0 )
754         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
755     else
756         PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
757 #endif
758 
759     return result;
760 }
761 
762 
Pa_GetDefaultInputDevice(void)763 PaDeviceIndex Pa_GetDefaultInputDevice( void )
764 {
765     PaHostApiIndex hostApi;
766     PaDeviceIndex result;
767 
768 #ifdef PA_LOG_API_CALLS
769     PaUtil_DebugPrint("Pa_GetDefaultInputDevice called.\n" );
770 #endif
771 
772     hostApi = Pa_GetDefaultHostApi();
773     if( hostApi < 0 )
774     {
775         result = paNoDevice;
776     }
777     else
778     {
779         result = hostApis_[hostApi]->info.defaultInputDevice;
780     }
781 
782 #ifdef PA_LOG_API_CALLS
783     PaUtil_DebugPrint("Pa_GetDefaultInputDevice returned:\n" );
784     PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
785 #endif
786 
787     return result;
788 }
789 
790 
Pa_GetDefaultOutputDevice(void)791 PaDeviceIndex Pa_GetDefaultOutputDevice( void )
792 {
793     PaHostApiIndex hostApi;
794     PaDeviceIndex result;
795 
796 #ifdef PA_LOG_API_CALLS
797     PaUtil_DebugPrint("Pa_GetDefaultOutputDevice called.\n" );
798 #endif
799 
800     hostApi = Pa_GetDefaultHostApi();
801     if( hostApi < 0 )
802     {
803         result = paNoDevice;
804     }
805     else
806     {
807         result = hostApis_[hostApi]->info.defaultOutputDevice;
808     }
809 
810 #ifdef PA_LOG_API_CALLS
811     PaUtil_DebugPrint("Pa_GetDefaultOutputDevice returned:\n" );
812     PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
813 #endif
814 
815     return result;
816 }
817 
818 
Pa_GetDeviceInfo(PaDeviceIndex device)819 const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
820 {
821     int hostSpecificDeviceIndex;
822     int hostApiIndex = FindHostApi( device, &hostSpecificDeviceIndex );
823     PaDeviceInfo *result;
824 
825 
826 #ifdef PA_LOG_API_CALLS
827     PaUtil_DebugPrint("Pa_GetDeviceInfo called:\n" );
828     PaUtil_DebugPrint("\tPaDeviceIndex device: %d\n", device );
829 #endif
830 
831     if( hostApiIndex < 0 )
832     {
833         result = NULL;
834 
835 #ifdef PA_LOG_API_CALLS
836         PaUtil_DebugPrint("Pa_GetDeviceInfo returned:\n" );
837         PaUtil_DebugPrint("\tPaDeviceInfo* NULL [ invalid device index ]\n\n" );
838 #endif
839 
840     }
841     else
842     {
843         result = hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ];
844 
845 #ifdef PA_LOG_API_CALLS
846         PaUtil_DebugPrint("Pa_GetDeviceInfo returned:\n" );
847         PaUtil_DebugPrint("\tPaDeviceInfo*: 0x%p:\n", result );
848         PaUtil_DebugPrint("\t{\n" );
849 
850         PaUtil_DebugPrint("\t\tint structVersion: %d\n", result->structVersion );
851         PaUtil_DebugPrint("\t\tconst char *name: %s\n", result->name );
852         PaUtil_DebugPrint("\t\tPaHostApiIndex hostApi: %d\n", result->hostApi );
853         PaUtil_DebugPrint("\t\tint maxInputChannels: %d\n", result->maxInputChannels );
854         PaUtil_DebugPrint("\t\tint maxOutputChannels: %d\n", result->maxOutputChannels );
855         PaUtil_DebugPrint("\t}\n\n" );
856 #endif
857 
858     }
859 
860     return result;
861 }
862 
863 
864 /*
865     SampleFormatIsValid() returns 1 if sampleFormat is a sample format
866     defined in portaudio.h, or 0 otherwise.
867 */
SampleFormatIsValid(PaSampleFormat format)868 static int SampleFormatIsValid( PaSampleFormat format )
869 {
870     switch( format & ~paNonInterleaved )
871     {
872     case paFloat32: return 1;
873     case paInt16: return 1;
874     case paInt32: return 1;
875     case paInt24: return 1;
876     case paInt8: return 1;
877     case paUInt8: return 1;
878     case paCustomFormat: return 1;
879     default: return 0;
880     }
881 }
882 
883 /*
884     NOTE: make sure this validation list is kept syncronised with the one in
885             pa_hostapi.h
886 
887     ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
888     conform to the expected values as described below. This function is
889     also designed to be used with the proposed Pa_IsFormatSupported() function.
890 
891     There are basically two types of validation that could be performed:
892     Generic conformance validation, and device capability mismatch
893     validation. This function performs only generic conformance validation.
894     Validation that would require knowledge of device capabilities is
895     not performed because of potentially complex relationships between
896     combinations of parameters - for example, even if the sampleRate
897     seems ok, it might not be for a duplex stream - we have no way of
898     checking this in an API-neutral way, so we don't try.
899 
900     On success the function returns PaNoError and fills in hostApi,
901     hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
902     the function returns an error code indicating the first encountered
903     parameter error.
904 
905 
906     If ValidateOpenStreamParameters() returns paNoError, the following
907     assertions are guaranteed to be true.
908 
909     - at least one of inputParameters & outputParmeters is valid (not NULL)
910 
911     - if inputParameters & outputParameters are both valid, that
912         inputParameters->device & outputParameters->device  both use the same host api
913 
914     PaDeviceIndex inputParameters->device
915         - is within range (0 to Pa_GetDeviceCount-1) Or:
916         - is paUseHostApiSpecificDeviceSpecification and
917             inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
918             to a valid host api
919 
920     int inputParameters->channelCount
921         - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
922         - upper bound is NOT validated against device capabilities
923 
924     PaSampleFormat inputParameters->sampleFormat
925         - is one of the sample formats defined in portaudio.h
926 
927     void *inputParameters->hostApiSpecificStreamInfo
928         - if supplied its hostApi field matches the input device's host Api
929 
930     PaDeviceIndex outputParmeters->device
931         - is within range (0 to Pa_GetDeviceCount-1)
932 
933     int outputParmeters->channelCount
934         - if inputDevice is valid, channelCount is > 0
935         - upper bound is NOT validated against device capabilities
936 
937     PaSampleFormat outputParmeters->sampleFormat
938         - is one of the sample formats defined in portaudio.h
939 
940     void *outputParmeters->hostApiSpecificStreamInfo
941         - if supplied its hostApi field matches the output device's host Api
942 
943     double sampleRate
944         - is not an 'absurd' rate (less than 1000. or greater than 200000.)
945         - sampleRate is NOT validated against device capabilities
946 
947     PaStreamFlags streamFlags
948         - unused platform neutral flags are zero
949         - paNeverDropInput is only used for full-duplex callback streams with
950             variable buffer size (paFramesPerBufferUnspecified)
951 */
ValidateOpenStreamParameters(const PaStreamParameters * inputParameters,const PaStreamParameters * outputParameters,double sampleRate,unsigned long framesPerBuffer,PaStreamFlags streamFlags,PaStreamCallback * streamCallback,PaUtilHostApiRepresentation ** hostApi,PaDeviceIndex * hostApiInputDevice,PaDeviceIndex * hostApiOutputDevice)952 static PaError ValidateOpenStreamParameters(
953     const PaStreamParameters *inputParameters,
954     const PaStreamParameters *outputParameters,
955     double sampleRate,
956     unsigned long framesPerBuffer,
957     PaStreamFlags streamFlags,
958     PaStreamCallback *streamCallback,
959     PaUtilHostApiRepresentation **hostApi,
960     PaDeviceIndex *hostApiInputDevice,
961     PaDeviceIndex *hostApiOutputDevice )
962 {
963     int inputHostApiIndex  = -1, /* Surpress uninitialised var warnings: compiler does */
964         outputHostApiIndex = -1; /* not see that if inputParameters and outputParame-  */
965                                  /* ters are both nonzero, these indices are set.      */
966 
967     if( (inputParameters == NULL) && (outputParameters == NULL) )
968     {
969         return paInvalidDevice; /** @todo should be a new error code "invalid device parameters" or something */
970     }
971     else
972     {
973         if( inputParameters == NULL )
974         {
975             *hostApiInputDevice = paNoDevice;
976         }
977         else if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
978         {
979             if( inputParameters->hostApiSpecificStreamInfo )
980             {
981                 inputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
982                         ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType );
983 
984                 if( inputHostApiIndex != -1 )
985                 {
986                     *hostApiInputDevice = paUseHostApiSpecificDeviceSpecification;
987                     *hostApi = hostApis_[inputHostApiIndex];
988                 }
989                 else
990                 {
991                     return paInvalidDevice;
992                 }
993             }
994             else
995             {
996                 return paInvalidDevice;
997             }
998         }
999         else
1000         {
1001             if( inputParameters->device < 0 || inputParameters->device >= deviceCount_ )
1002                 return paInvalidDevice;
1003 
1004             inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice );
1005             if( inputHostApiIndex < 0 )
1006                 return paInternalError;
1007 
1008             *hostApi = hostApis_[inputHostApiIndex];
1009 
1010             if( inputParameters->channelCount <= 0 )
1011                 return paInvalidChannelCount;
1012 
1013             if( !SampleFormatIsValid( inputParameters->sampleFormat ) )
1014                 return paSampleFormatNotSupported;
1015 
1016             if( inputParameters->hostApiSpecificStreamInfo != NULL )
1017             {
1018                 if( ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType
1019                         != (*hostApi)->info.type )
1020                     return paIncompatibleHostApiSpecificStreamInfo;
1021             }
1022         }
1023 
1024         if( outputParameters == NULL )
1025         {
1026             *hostApiOutputDevice = paNoDevice;
1027         }
1028         else if( outputParameters->device == paUseHostApiSpecificDeviceSpecification  )
1029         {
1030             if( outputParameters->hostApiSpecificStreamInfo )
1031             {
1032                 outputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
1033                         ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType );
1034 
1035                 if( outputHostApiIndex != -1 )
1036                 {
1037                     *hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification;
1038                     *hostApi = hostApis_[outputHostApiIndex];
1039                 }
1040                 else
1041                 {
1042                     return paInvalidDevice;
1043                 }
1044             }
1045             else
1046             {
1047                 return paInvalidDevice;
1048             }
1049         }
1050         else
1051         {
1052             if( outputParameters->device < 0 || outputParameters->device >= deviceCount_ )
1053                 return paInvalidDevice;
1054 
1055             outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice );
1056             if( outputHostApiIndex < 0 )
1057                 return paInternalError;
1058 
1059             *hostApi = hostApis_[outputHostApiIndex];
1060 
1061             if( outputParameters->channelCount <= 0 )
1062                 return paInvalidChannelCount;
1063 
1064             if( !SampleFormatIsValid( outputParameters->sampleFormat ) )
1065                 return paSampleFormatNotSupported;
1066 
1067             if( outputParameters->hostApiSpecificStreamInfo != NULL )
1068             {
1069                 if( ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType
1070                         != (*hostApi)->info.type )
1071                     return paIncompatibleHostApiSpecificStreamInfo;
1072             }
1073         }
1074 
1075         if( (inputParameters != NULL) && (outputParameters != NULL) )
1076         {
1077             /* ensure that both devices use the same API */
1078             if( inputHostApiIndex != outputHostApiIndex )
1079                 return paBadIODeviceCombination;
1080         }
1081     }
1082 
1083 
1084     /* Check for absurd sample rates. */
1085     if( (sampleRate < 1000.0) || (sampleRate > 200000.0) )
1086         return paInvalidSampleRate;
1087 
1088     if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 )
1089         return paInvalidFlag;
1090 
1091     if( streamFlags & paNeverDropInput )
1092     {
1093         /* must be a callback stream */
1094         if( !streamCallback )
1095              return paInvalidFlag;
1096 
1097         /* must be a full duplex stream */
1098         if( (inputParameters == NULL) || (outputParameters == NULL) )
1099             return paInvalidFlag;
1100 
1101         /* must use paFramesPerBufferUnspecified */
1102         if( framesPerBuffer != paFramesPerBufferUnspecified )
1103             return paInvalidFlag;
1104     }
1105 
1106     return paNoError;
1107 }
1108 
1109 
Pa_IsFormatSupported(const PaStreamParameters * inputParameters,const PaStreamParameters * outputParameters,double sampleRate)1110 PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
1111                               const PaStreamParameters *outputParameters,
1112                               double sampleRate )
1113 {
1114     PaError result;
1115     PaUtilHostApiRepresentation *hostApi;
1116     PaDeviceIndex hostApiInputDevice, hostApiOutputDevice;
1117     PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1118     PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1119 
1120 
1121 #ifdef PA_LOG_API_CALLS
1122     PaUtil_DebugPrint("Pa_IsFormatSupported called:\n" );
1123 
1124     if( inputParameters == NULL ){
1125         PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: NULL\n" );
1126     }else{
1127         PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters );
1128         PaUtil_DebugPrint("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device );
1129         PaUtil_DebugPrint("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount );
1130         PaUtil_DebugPrint("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat );
1131         PaUtil_DebugPrint("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency );
1132         PaUtil_DebugPrint("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo );
1133     }
1134 
1135     if( outputParameters == NULL ){
1136         PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: NULL\n" );
1137     }else{
1138         PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters );
1139         PaUtil_DebugPrint("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device );
1140         PaUtil_DebugPrint("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount );
1141         PaUtil_DebugPrint("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat );
1142         PaUtil_DebugPrint("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency );
1143         PaUtil_DebugPrint("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo );
1144     }
1145 
1146     PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
1147 #endif
1148 
1149     if( !PA_IS_INITIALISED_ )
1150     {
1151         result = paNotInitialized;
1152 
1153 #ifdef PA_LOG_API_CALLS
1154         PaUtil_DebugPrint("Pa_IsFormatSupported returned:\n" );
1155         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1156 #endif
1157         return result;
1158     }
1159 
1160     result = ValidateOpenStreamParameters( inputParameters,
1161                                            outputParameters,
1162                                            sampleRate, 0, paNoFlag, 0,
1163                                            &hostApi,
1164                                            &hostApiInputDevice,
1165                                            &hostApiOutputDevice );
1166     if( result != paNoError )
1167     {
1168 #ifdef PA_LOG_API_CALLS
1169         PaUtil_DebugPrint("Pa_IsFormatSupported returned:\n" );
1170         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1171 #endif
1172         return result;
1173     }
1174 
1175 
1176     if( inputParameters )
1177     {
1178         hostApiInputParameters.device = hostApiInputDevice;
1179         hostApiInputParameters.channelCount = inputParameters->channelCount;
1180         hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
1181         hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
1182         hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
1183         hostApiInputParametersPtr = &hostApiInputParameters;
1184     }
1185     else
1186     {
1187         hostApiInputParametersPtr = NULL;
1188     }
1189 
1190     if( outputParameters )
1191     {
1192         hostApiOutputParameters.device = hostApiOutputDevice;
1193         hostApiOutputParameters.channelCount = outputParameters->channelCount;
1194         hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
1195         hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
1196         hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
1197         hostApiOutputParametersPtr = &hostApiOutputParameters;
1198     }
1199     else
1200     {
1201         hostApiOutputParametersPtr = NULL;
1202     }
1203 
1204     result = hostApi->IsFormatSupported( hostApi,
1205                                   hostApiInputParametersPtr, hostApiOutputParametersPtr,
1206                                   sampleRate );
1207 
1208 #ifdef PA_LOG_API_CALLS
1209     PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
1210     if( result == paFormatIsSupported )
1211         PaUtil_DebugPrint("\tPaError: 0 [ paFormatIsSupported ]\n\n" );
1212     else
1213         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1214 #endif
1215 
1216     return result;
1217 }
1218 
1219 
Pa_OpenStream(PaStream ** stream,const PaStreamParameters * inputParameters,const PaStreamParameters * outputParameters,double sampleRate,unsigned long framesPerBuffer,PaStreamFlags streamFlags,PaStreamCallback * streamCallback,void * userData)1220 PaError Pa_OpenStream( PaStream** stream,
1221                        const PaStreamParameters *inputParameters,
1222                        const PaStreamParameters *outputParameters,
1223                        double sampleRate,
1224                        unsigned long framesPerBuffer,
1225                        PaStreamFlags streamFlags,
1226                        PaStreamCallback *streamCallback,
1227                        void *userData )
1228 {
1229     PaError result;
1230     PaUtilHostApiRepresentation *hostApi;
1231     PaDeviceIndex hostApiInputDevice, hostApiOutputDevice;
1232     PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1233     PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1234 
1235 
1236 #ifdef PA_LOG_API_CALLS
1237     PaUtil_DebugPrint("Pa_OpenStream called:\n" );
1238     PaUtil_DebugPrint("\tPaStream** stream: 0x%p\n", stream );
1239 
1240     if( inputParameters == NULL ){
1241         PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: NULL\n" );
1242     }else{
1243         PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters );
1244         PaUtil_DebugPrint("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device );
1245         PaUtil_DebugPrint("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount );
1246         PaUtil_DebugPrint("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat );
1247         PaUtil_DebugPrint("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency );
1248         PaUtil_DebugPrint("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo );
1249     }
1250 
1251     if( outputParameters == NULL ){
1252         PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: NULL\n" );
1253     }else{
1254         PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters );
1255         PaUtil_DebugPrint("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device );
1256         PaUtil_DebugPrint("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount );
1257         PaUtil_DebugPrint("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat );
1258         PaUtil_DebugPrint("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency );
1259         PaUtil_DebugPrint("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo );
1260     }
1261 
1262     PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
1263     PaUtil_DebugPrint("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer );
1264     PaUtil_DebugPrint("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags );
1265     PaUtil_DebugPrint("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback );
1266     PaUtil_DebugPrint("\tvoid *userData: 0x%p\n", userData );
1267 #endif
1268 
1269     if( !PA_IS_INITIALISED_ )
1270     {
1271         result = paNotInitialized;
1272 
1273 #ifdef PA_LOG_API_CALLS
1274         PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
1275         PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
1276         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1277 #endif
1278         return result;
1279     }
1280 
1281     /* Check for parameter errors.
1282         NOTE: make sure this validation list is kept syncronised with the one
1283         in pa_hostapi.h
1284     */
1285 
1286     if( stream == NULL )
1287     {
1288         result = paBadStreamPtr;
1289 
1290 #ifdef PA_LOG_API_CALLS
1291         PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
1292         PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
1293         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1294 #endif
1295         return result;
1296     }
1297 
1298     result = ValidateOpenStreamParameters( inputParameters,
1299                                            outputParameters,
1300                                            sampleRate, framesPerBuffer,
1301                                            streamFlags, streamCallback,
1302                                            &hostApi,
1303                                            &hostApiInputDevice,
1304                                            &hostApiOutputDevice );
1305     if( result != paNoError )
1306     {
1307 #ifdef PA_LOG_API_CALLS
1308         PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
1309         PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
1310         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1311 #endif
1312         return result;
1313     }
1314 
1315 
1316     if( inputParameters )
1317     {
1318         hostApiInputParameters.device = hostApiInputDevice;
1319         hostApiInputParameters.channelCount = inputParameters->channelCount;
1320         hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
1321         hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
1322         hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
1323         hostApiInputParametersPtr = &hostApiInputParameters;
1324     }
1325     else
1326     {
1327         hostApiInputParametersPtr = NULL;
1328     }
1329 
1330     if( outputParameters )
1331     {
1332         hostApiOutputParameters.device = hostApiOutputDevice;
1333         hostApiOutputParameters.channelCount = outputParameters->channelCount;
1334         hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
1335         hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
1336         hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
1337         hostApiOutputParametersPtr = &hostApiOutputParameters;
1338     }
1339     else
1340     {
1341         hostApiOutputParametersPtr = NULL;
1342     }
1343 
1344     result = hostApi->OpenStream( hostApi, stream,
1345                                   hostApiInputParametersPtr, hostApiOutputParametersPtr,
1346                                   sampleRate, framesPerBuffer, streamFlags, streamCallback, userData );
1347 
1348     if( result == paNoError )
1349         AddOpenStream( *stream );
1350 
1351 
1352 #ifdef PA_LOG_API_CALLS
1353     PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
1354     PaUtil_DebugPrint("\t*(PaStream** stream): 0x%p\n", *stream );
1355     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1356 #endif
1357 
1358     return result;
1359 }
1360 
1361 
Pa_OpenDefaultStream(PaStream ** stream,int inputChannelCount,int outputChannelCount,PaSampleFormat sampleFormat,double sampleRate,unsigned long framesPerBuffer,PaStreamCallback * streamCallback,void * userData)1362 PaError Pa_OpenDefaultStream( PaStream** stream,
1363                               int inputChannelCount,
1364                               int outputChannelCount,
1365                               PaSampleFormat sampleFormat,
1366                               double sampleRate,
1367                               unsigned long framesPerBuffer,
1368                               PaStreamCallback *streamCallback,
1369                               void *userData )
1370 {
1371     PaError result;
1372     PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
1373     PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
1374 
1375 #ifdef PA_LOG_API_CALLS
1376     PaUtil_DebugPrint("Pa_OpenDefaultStream called:\n" );
1377     PaUtil_DebugPrint("\tPaStream** stream: 0x%p\n", stream );
1378     PaUtil_DebugPrint("\tint inputChannelCount: %d\n", inputChannelCount );
1379     PaUtil_DebugPrint("\tint outputChannelCount: %d\n", outputChannelCount );
1380     PaUtil_DebugPrint("\tPaSampleFormat sampleFormat: %d\n", sampleFormat );
1381     PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
1382     PaUtil_DebugPrint("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer );
1383     PaUtil_DebugPrint("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback );
1384     PaUtil_DebugPrint("\tvoid *userData: 0x%p\n", userData );
1385 #endif
1386 
1387 
1388     if( inputChannelCount > 0 )
1389     {
1390         hostApiInputParameters.device = Pa_GetDefaultInputDevice();
1391         hostApiInputParameters.channelCount = inputChannelCount;
1392         hostApiInputParameters.sampleFormat = sampleFormat;
1393         /* defaultHighInputLatency is used below instead of
1394            defaultLowInputLatency because it is more important for the default
1395            stream to work reliably than it is for it to work with the lowest
1396            latency.
1397          */
1398         hostApiInputParameters.suggestedLatency =
1399              Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
1400         hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
1401         hostApiInputParametersPtr = &hostApiInputParameters;
1402     }
1403     else
1404     {
1405         hostApiInputParametersPtr = NULL;
1406     }
1407 
1408     if( outputChannelCount > 0 )
1409     {
1410         hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
1411         hostApiOutputParameters.channelCount = outputChannelCount;
1412         hostApiOutputParameters.sampleFormat = sampleFormat;
1413         /* defaultHighOutputLatency is used below instead of
1414            defaultLowOutputLatency because it is more important for the default
1415            stream to work reliably than it is for it to work with the lowest
1416            latency.
1417          */
1418         hostApiOutputParameters.suggestedLatency =
1419              Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
1420         hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
1421         hostApiOutputParametersPtr = &hostApiOutputParameters;
1422     }
1423     else
1424     {
1425         hostApiOutputParametersPtr = NULL;
1426     }
1427 
1428 
1429     result = Pa_OpenStream(
1430                  stream, hostApiInputParametersPtr, hostApiOutputParametersPtr,
1431                  sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
1432 
1433 #ifdef PA_LOG_API_CALLS
1434     PaUtil_DebugPrint("Pa_OpenDefaultStream returned:\n" );
1435     PaUtil_DebugPrint("\t*(PaStream** stream): 0x%p", *stream );
1436     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1437 #endif
1438 
1439     return result;
1440 }
1441 
1442 
PaUtil_ValidateStreamPointer(PaStream * stream)1443 PaError PaUtil_ValidateStreamPointer( PaStream* stream )
1444 {
1445     if( !PA_IS_INITIALISED_ ) return paNotInitialized;
1446 
1447     if( stream == NULL ) return paBadStreamPtr;
1448 
1449     if( ((PaUtilStreamRepresentation*)stream)->magic != PA_STREAM_MAGIC )
1450         return paBadStreamPtr;
1451 
1452     return paNoError;
1453 }
1454 
1455 
Pa_CloseStream(PaStream * stream)1456 PaError Pa_CloseStream( PaStream* stream )
1457 {
1458     PaUtilStreamInterface *interface;
1459     PaError result = PaUtil_ValidateStreamPointer( stream );
1460 
1461 #ifdef PA_LOG_API_CALLS
1462     PaUtil_DebugPrint("Pa_CloseStream called:\n" );
1463     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1464 #endif
1465 
1466     /* always remove the open stream from our list, even if this function
1467         eventually returns an error. Otherwise CloseOpenStreams() will
1468         get stuck in an infinite loop */
1469     RemoveOpenStream( stream ); /* be sure to call this _before_ closing the stream */
1470 
1471     if( result == paNoError )
1472     {
1473         interface = PA_STREAM_INTERFACE(stream);
1474 
1475         /* abort the stream if it isn't stopped */
1476         result = interface->IsStopped( stream );
1477         if( result == 1 )
1478             result = paNoError;
1479         else if( result == 0 )
1480             result = interface->Abort( stream );
1481 
1482         if( result == paNoError )                 /** @todo REVIEW: shouldn't we close anyway? */
1483             result = interface->Close( stream );
1484     }
1485 
1486 #ifdef PA_LOG_API_CALLS
1487     PaUtil_DebugPrint("Pa_CloseStream returned:\n" );
1488     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1489 #endif
1490 
1491     return result;
1492 }
1493 
1494 
Pa_SetStreamFinishedCallback(PaStream * stream,PaStreamFinishedCallback * streamFinishedCallback)1495 PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback )
1496 {
1497     PaError result = PaUtil_ValidateStreamPointer( stream );
1498 
1499 #ifdef PA_LOG_API_CALLS
1500     PaUtil_DebugPrint("Pa_SetStreamFinishedCallback called:\n" );
1501     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1502     PaUtil_DebugPrint("\tPaStreamFinishedCallback* streamFinishedCallback: 0x%p\n", streamFinishedCallback );
1503 #endif
1504 
1505     if( result == paNoError )
1506     {
1507         result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1508         if( result == 0 )
1509         {
1510             result = paStreamIsNotStopped ;
1511         }
1512         if( result == 1 )
1513         {
1514             PA_STREAM_REP( stream )->streamFinishedCallback = streamFinishedCallback;
1515             result = paNoError;
1516         }
1517     }
1518 
1519 #ifdef PA_LOG_API_CALLS
1520     PaUtil_DebugPrint("Pa_SetStreamFinishedCallback returned:\n" );
1521     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1522 #endif
1523 
1524     return result;
1525 
1526 }
1527 
1528 
Pa_StartStream(PaStream * stream)1529 PaError Pa_StartStream( PaStream *stream )
1530 {
1531     PaError result = PaUtil_ValidateStreamPointer( stream );
1532 
1533 #ifdef PA_LOG_API_CALLS
1534     PaUtil_DebugPrint("Pa_StartStream called:\n" );
1535     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1536 #endif
1537 
1538     if( result == paNoError )
1539     {
1540         result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1541         if( result == 0 )
1542         {
1543             result = paStreamIsNotStopped ;
1544         }
1545         else if( result == 1 )
1546         {
1547             result = PA_STREAM_INTERFACE(stream)->Start( stream );
1548         }
1549     }
1550 
1551 #ifdef PA_LOG_API_CALLS
1552     PaUtil_DebugPrint("Pa_StartStream returned:\n" );
1553     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1554 #endif
1555 
1556     return result;
1557 }
1558 
1559 
Pa_StopStream(PaStream * stream)1560 PaError Pa_StopStream( PaStream *stream )
1561 {
1562     PaError result = PaUtil_ValidateStreamPointer( stream );
1563 
1564 #ifdef PA_LOG_API_CALLS
1565     PaUtil_DebugPrint("Pa_StopStream called\n" );
1566     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1567 #endif
1568 
1569     if( result == paNoError )
1570     {
1571         result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1572         if( result == 0 )
1573         {
1574             result = PA_STREAM_INTERFACE(stream)->Stop( stream );
1575         }
1576         else if( result == 1 )
1577         {
1578             result = paStreamIsStopped;
1579         }
1580     }
1581 
1582 #ifdef PA_LOG_API_CALLS
1583     PaUtil_DebugPrint("Pa_StopStream returned:\n" );
1584     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1585 #endif
1586 
1587     return result;
1588 }
1589 
1590 
Pa_AbortStream(PaStream * stream)1591 PaError Pa_AbortStream( PaStream *stream )
1592 {
1593     PaError result = PaUtil_ValidateStreamPointer( stream );
1594 
1595 #ifdef PA_LOG_API_CALLS
1596     PaUtil_DebugPrint("Pa_AbortStream called:\n" );
1597     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1598 #endif
1599 
1600     if( result == paNoError )
1601     {
1602         result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1603         if( result == 0 )
1604         {
1605             result = PA_STREAM_INTERFACE(stream)->Abort( stream );
1606         }
1607         else if( result == 1 )
1608         {
1609             result = paStreamIsStopped;
1610         }
1611     }
1612 
1613 #ifdef PA_LOG_API_CALLS
1614     PaUtil_DebugPrint("Pa_AbortStream returned:\n" );
1615     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1616 #endif
1617 
1618     return result;
1619 }
1620 
1621 
Pa_IsStreamStopped(PaStream * stream)1622 PaError Pa_IsStreamStopped( PaStream *stream )
1623 {
1624     PaError result = PaUtil_ValidateStreamPointer( stream );
1625 
1626 #ifdef PA_LOG_API_CALLS
1627     PaUtil_DebugPrint("Pa_IsStreamStopped called:\n" );
1628     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1629 #endif
1630 
1631     if( result == paNoError )
1632         result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1633 
1634 #ifdef PA_LOG_API_CALLS
1635     PaUtil_DebugPrint("Pa_IsStreamStopped returned:\n" );
1636     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1637 #endif
1638 
1639     return result;
1640 }
1641 
1642 
Pa_IsStreamActive(PaStream * stream)1643 PaError Pa_IsStreamActive( PaStream *stream )
1644 {
1645     PaError result = PaUtil_ValidateStreamPointer( stream );
1646 
1647 #ifdef PA_LOG_API_CALLS
1648     PaUtil_DebugPrint("Pa_IsStreamActive called:\n" );
1649     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1650 #endif
1651 
1652     if( result == paNoError )
1653         result = PA_STREAM_INTERFACE(stream)->IsActive( stream );
1654 
1655 #ifdef PA_LOG_API_CALLS
1656     PaUtil_DebugPrint("Pa_IsStreamActive returned:\n" );
1657     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1658 #endif
1659 
1660     return result;
1661 }
1662 
1663 
Pa_GetStreamInfo(PaStream * stream)1664 const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream )
1665 {
1666     PaError error = PaUtil_ValidateStreamPointer( stream );
1667     const PaStreamInfo *result;
1668 
1669 #ifdef PA_LOG_API_CALLS
1670     PaUtil_DebugPrint("Pa_GetStreamInfo called:\n" );
1671     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1672 #endif
1673 
1674     if( error != paNoError )
1675     {
1676         result = 0;
1677 
1678 #ifdef PA_LOG_API_CALLS
1679         PaUtil_DebugPrint("Pa_GetStreamInfo returned:\n" );
1680         PaUtil_DebugPrint("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n\n", result, error, Pa_GetErrorText( error ) );
1681 #endif
1682 
1683     }
1684     else
1685     {
1686         result = &PA_STREAM_REP( stream )->streamInfo;
1687 
1688 #ifdef PA_LOG_API_CALLS
1689         PaUtil_DebugPrint("Pa_GetStreamInfo returned:\n" );
1690         PaUtil_DebugPrint("\tconst PaStreamInfo*: 0x%p:\n", result );
1691         PaUtil_DebugPrint("\t{" );
1692 
1693         PaUtil_DebugPrint("\t\tint structVersion: %d\n", result->structVersion );
1694         PaUtil_DebugPrint("\t\tPaTime inputLatency: %f\n", result->inputLatency );
1695         PaUtil_DebugPrint("\t\tPaTime outputLatency: %f\n", result->outputLatency );
1696         PaUtil_DebugPrint("\t\tdouble sampleRate: %f\n", result->sampleRate );
1697         PaUtil_DebugPrint("\t}\n\n" );
1698 #endif
1699 
1700     }
1701 
1702     return result;
1703 }
1704 
1705 
Pa_GetStreamTime(PaStream * stream)1706 PaTime Pa_GetStreamTime( PaStream *stream )
1707 {
1708     PaError error = PaUtil_ValidateStreamPointer( stream );
1709     PaTime result;
1710 
1711 #ifdef PA_LOG_API_CALLS
1712     PaUtil_DebugPrint("Pa_GetStreamTime called:\n" );
1713     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1714 #endif
1715 
1716     if( error != paNoError )
1717     {
1718         result = 0;
1719 
1720 #ifdef PA_LOG_API_CALLS
1721         PaUtil_DebugPrint("Pa_GetStreamTime returned:\n" );
1722         PaUtil_DebugPrint("\tPaTime: 0 [PaError error:%d ( %s )]\n\n", result, error, Pa_GetErrorText( error ) );
1723 #endif
1724 
1725     }
1726     else
1727     {
1728         result = PA_STREAM_INTERFACE(stream)->GetTime( stream );
1729 
1730 #ifdef PA_LOG_API_CALLS
1731         PaUtil_DebugPrint("Pa_GetStreamTime returned:\n" );
1732         PaUtil_DebugPrint("\tPaTime: %g\n\n", result );
1733 #endif
1734 
1735     }
1736 
1737     return result;
1738 }
1739 
1740 
Pa_GetStreamCpuLoad(PaStream * stream)1741 double Pa_GetStreamCpuLoad( PaStream* stream )
1742 {
1743     PaError error = PaUtil_ValidateStreamPointer( stream );
1744     double result;
1745 
1746 #ifdef PA_LOG_API_CALLS
1747     PaUtil_DebugPrint("Pa_GetStreamCpuLoad called:\n" );
1748     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1749 #endif
1750 
1751     if( error != paNoError )
1752     {
1753 
1754         result = 0.0;
1755 
1756 #ifdef PA_LOG_API_CALLS
1757         PaUtil_DebugPrint("Pa_GetStreamCpuLoad returned:\n" );
1758         PaUtil_DebugPrint("\tdouble: 0.0 [PaError error: %d ( %s )]\n\n", error, Pa_GetErrorText( error ) );
1759 #endif
1760 
1761     }
1762     else
1763     {
1764         result = PA_STREAM_INTERFACE(stream)->GetCpuLoad( stream );
1765 
1766 #ifdef PA_LOG_API_CALLS
1767         PaUtil_DebugPrint("Pa_GetStreamCpuLoad returned:\n" );
1768         PaUtil_DebugPrint("\tdouble: %g\n\n", result );
1769 #endif
1770 
1771     }
1772 
1773     return result;
1774 }
1775 
1776 
Pa_ReadStream(PaStream * stream,void * buffer,unsigned long frames)1777 PaError Pa_ReadStream( PaStream* stream,
1778                        void *buffer,
1779                        unsigned long frames )
1780 {
1781     PaError result = PaUtil_ValidateStreamPointer( stream );
1782 
1783 #ifdef PA_LOG_API_CALLS
1784     PaUtil_DebugPrint("Pa_ReadStream called:\n" );
1785     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1786 #endif
1787 
1788     if( result == paNoError )
1789     {
1790         if( frames == 0 )
1791         {
1792             /* XXX: Should we not allow the implementation to signal any overflow condition? */
1793             result = paNoError;
1794         }
1795         else if( buffer == 0 )
1796         {
1797             result = paBadBufferPtr;
1798         }
1799         else
1800         {
1801             result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1802             if( result == 0 )
1803             {
1804                 result = PA_STREAM_INTERFACE(stream)->Read( stream, buffer, frames );
1805             }
1806             else if( result == 1 )
1807             {
1808                 result = paStreamIsStopped;
1809             }
1810         }
1811     }
1812 
1813 #ifdef PA_LOG_API_CALLS
1814     PaUtil_DebugPrint("Pa_ReadStream returned:\n" );
1815     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1816 #endif
1817 
1818     return result;
1819 }
1820 
1821 
Pa_WriteStream(PaStream * stream,const void * buffer,unsigned long frames)1822 PaError Pa_WriteStream( PaStream* stream,
1823                         const void *buffer,
1824                         unsigned long frames )
1825 {
1826     PaError result = PaUtil_ValidateStreamPointer( stream );
1827 
1828 #ifdef PA_LOG_API_CALLS
1829     PaUtil_DebugPrint("Pa_WriteStream called:\n" );
1830     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1831 #endif
1832 
1833     if( result == paNoError )
1834     {
1835         if( frames == 0 )
1836         {
1837             /* XXX: Should we not allow the implementation to signal any underflow condition? */
1838             result = paNoError;
1839         }
1840         else if( buffer == 0 )
1841         {
1842             result = paBadBufferPtr;
1843         }
1844         else
1845         {
1846             result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
1847             if( result == 0 )
1848             {
1849                 result = PA_STREAM_INTERFACE(stream)->Write( stream, buffer, frames );
1850             }
1851             else if( result == 1 )
1852             {
1853                 result = paStreamIsStopped;
1854             }
1855         }
1856     }
1857 
1858 #ifdef PA_LOG_API_CALLS
1859     PaUtil_DebugPrint("Pa_WriteStream returned:\n" );
1860     PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1861 #endif
1862 
1863     return result;
1864 }
1865 
Pa_GetStreamReadAvailable(PaStream * stream)1866 signed long Pa_GetStreamReadAvailable( PaStream* stream )
1867 {
1868     PaError error = PaUtil_ValidateStreamPointer( stream );
1869     signed long result;
1870 
1871 #ifdef PA_LOG_API_CALLS
1872     PaUtil_DebugPrint("Pa_GetStreamReadAvailable called:\n" );
1873     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1874 #endif
1875 
1876     if( error != paNoError )
1877     {
1878         result = 0;
1879 
1880 #ifdef PA_LOG_API_CALLS
1881         PaUtil_DebugPrint("Pa_GetStreamReadAvailable returned:\n" );
1882         PaUtil_DebugPrint("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n\n", error, Pa_GetErrorText( error ) );
1883 #endif
1884 
1885     }
1886     else
1887     {
1888         result = PA_STREAM_INTERFACE(stream)->GetReadAvailable( stream );
1889 
1890 #ifdef PA_LOG_API_CALLS
1891         PaUtil_DebugPrint("Pa_GetStreamReadAvailable returned:\n" );
1892         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1893 #endif
1894 
1895     }
1896 
1897     return result;
1898 }
1899 
1900 
Pa_GetStreamWriteAvailable(PaStream * stream)1901 signed long Pa_GetStreamWriteAvailable( PaStream* stream )
1902 {
1903     PaError error = PaUtil_ValidateStreamPointer( stream );
1904     signed long result;
1905 
1906 #ifdef PA_LOG_API_CALLS
1907     PaUtil_DebugPrint("Pa_GetStreamWriteAvailable called:\n" );
1908     PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
1909 #endif
1910 
1911     if( error != paNoError )
1912     {
1913         result = 0;
1914 
1915 #ifdef PA_LOG_API_CALLS
1916         PaUtil_DebugPrint("Pa_GetStreamWriteAvailable returned:\n" );
1917         PaUtil_DebugPrint("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n\n", error, Pa_GetErrorText( error ) );
1918 #endif
1919 
1920     }
1921     else
1922     {
1923         result = PA_STREAM_INTERFACE(stream)->GetWriteAvailable( stream );
1924 
1925 #ifdef PA_LOG_API_CALLS
1926         PaUtil_DebugPrint("Pa_GetStreamWriteAvailable returned:\n" );
1927         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1928 #endif
1929 
1930     }
1931 
1932     return result;
1933 }
1934 
1935 
Pa_GetSampleSize(PaSampleFormat format)1936 PaError Pa_GetSampleSize( PaSampleFormat format )
1937 {
1938     int result;
1939 
1940 #ifdef PA_LOG_API_CALLS
1941     PaUtil_DebugPrint("Pa_GetSampleSize called:\n" );
1942     PaUtil_DebugPrint("\tPaSampleFormat format: %d\n", format );
1943 #endif
1944 
1945     switch( format & ~paNonInterleaved )
1946     {
1947 
1948     case paUInt8:
1949     case paInt8:
1950         result = 1;
1951         break;
1952 
1953     case paInt16:
1954         result = 2;
1955         break;
1956 
1957     case paInt24:
1958         result = 3;
1959         break;
1960 
1961     case paFloat32:
1962     case paInt32:
1963         result = 4;
1964         break;
1965 
1966     default:
1967         result = paSampleFormatNotSupported;
1968         break;
1969     }
1970 
1971 #ifdef PA_LOG_API_CALLS
1972     PaUtil_DebugPrint("Pa_GetSampleSize returned:\n" );
1973     if( result > 0 )
1974         PaUtil_DebugPrint("\tint: %d\n\n", result );
1975     else
1976         PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
1977 #endif
1978 
1979     return (PaError) result;
1980 }
1981 
1982