pa_front.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770
  1. /*
  2. * $Id: pa_front.c 1880 2012-12-04 18:39:48Z rbencina $
  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. * The text above constitutes the entire PortAudio license; however,
  30. * the PortAudio community also makes the following non-binding requests:
  31. *
  32. * Any person wishing to distribute modifications to the Software is
  33. * requested to send the modifications to the original developer so that
  34. * they can be incorporated into the canonical version. It is also
  35. * requested that these non-binding requests be included along with the
  36. * license above.
  37. */
  38. /** @file
  39. @ingroup common_src
  40. @brief Implements PortAudio API functions defined in portaudio.h, checks
  41. some errors, delegates platform-specific behavior to host API implementations.
  42. Implements the functions defined in the PortAudio API (portaudio.h),
  43. validates some parameters and checks for state inconsistencies before
  44. forwarding API requests to specific Host API implementations (via the
  45. interface declared in pa_hostapi.h), and Streams (via the interface
  46. declared in pa_stream.h).
  47. This file manages initialization and termination of Host API
  48. implementations via initializer functions stored in the paHostApiInitializers
  49. global array (usually defined in an os-specific pa_[os]_hostapis.c file).
  50. This file maintains a list of all open streams and closes them at Pa_Terminate().
  51. Some utility functions declared in pa_util.h are implemented in this file.
  52. All PortAudio API functions can be conditionally compiled with logging code.
  53. To compile with logging, define the PA_LOG_API_CALLS precompiler symbol.
  54. */
  55. #include <stdio.h>
  56. #include <memory.h>
  57. #include <string.h>
  58. #include <assert.h> /* needed by PA_VALIDATE_ENDIANNESS */
  59. #include "portaudio.h"
  60. #include "pa_util.h"
  61. #include "pa_endianness.h"
  62. #include "pa_types.h"
  63. #include "pa_hostapi.h"
  64. #include "pa_stream.h"
  65. #include "pa_trace.h" /* still usefull?*/
  66. #include "pa_debugprint.h"
  67. #define PA_VERSION_ 1899
  68. #define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ " " __TIME__ ")"
  69. int Pa_GetVersion( void )
  70. {
  71. return PA_VERSION_;
  72. }
  73. const char* Pa_GetVersionText( void )
  74. {
  75. return PA_VERSION_TEXT_;
  76. }
  77. #define PA_LAST_HOST_ERROR_TEXT_LENGTH_ 1024
  78. static char lastHostErrorText_[ PA_LAST_HOST_ERROR_TEXT_LENGTH_ + 1 ] = {0};
  79. static PaHostErrorInfo lastHostErrorInfo_ = { (PaHostApiTypeId)-1, 0, lastHostErrorText_ };
  80. void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
  81. const char *errorText )
  82. {
  83. lastHostErrorInfo_.hostApiType = hostApiType;
  84. lastHostErrorInfo_.errorCode = errorCode;
  85. strncpy( lastHostErrorText_, errorText, PA_LAST_HOST_ERROR_TEXT_LENGTH_ );
  86. }
  87. static PaUtilHostApiRepresentation **hostApis_ = 0;
  88. static int hostApisCount_ = 0;
  89. static int defaultHostApiIndex_ = 0;
  90. static int initializationCount_ = 0;
  91. static int deviceCount_ = 0;
  92. PaUtilStreamRepresentation *firstOpenStream_ = NULL;
  93. #define PA_IS_INITIALISED_ (initializationCount_ != 0)
  94. static int CountHostApiInitializers( void )
  95. {
  96. int result = 0;
  97. while( paHostApiInitializers[ result ] != 0 )
  98. ++result;
  99. return result;
  100. }
  101. static void TerminateHostApis( void )
  102. {
  103. /* terminate in reverse order from initialization */
  104. PA_DEBUG(("TerminateHostApis in \n"));
  105. while( hostApisCount_ > 0 )
  106. {
  107. --hostApisCount_;
  108. hostApis_[hostApisCount_]->Terminate( hostApis_[hostApisCount_] );
  109. }
  110. hostApisCount_ = 0;
  111. defaultHostApiIndex_ = 0;
  112. deviceCount_ = 0;
  113. if( hostApis_ != 0 )
  114. PaUtil_FreeMemory( hostApis_ );
  115. hostApis_ = 0;
  116. PA_DEBUG(("TerminateHostApis out\n"));
  117. }
  118. static PaError InitializeHostApis( void )
  119. {
  120. PaError result = paNoError;
  121. int i, initializerCount, baseDeviceIndex;
  122. initializerCount = CountHostApiInitializers();
  123. hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
  124. sizeof(PaUtilHostApiRepresentation*) * initializerCount );
  125. if( !hostApis_ )
  126. {
  127. result = paInsufficientMemory;
  128. goto error;
  129. }
  130. hostApisCount_ = 0;
  131. defaultHostApiIndex_ = -1; /* indicates that we haven't determined the default host API yet */
  132. deviceCount_ = 0;
  133. baseDeviceIndex = 0;
  134. for( i=0; i< initializerCount; ++i )
  135. {
  136. hostApis_[hostApisCount_] = NULL;
  137. PA_DEBUG(( "before paHostApiInitializers[%d].\n",i));
  138. result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ );
  139. if( result != paNoError )
  140. goto error;
  141. PA_DEBUG(( "after paHostApiInitializers[%d].\n",i));
  142. if( hostApis_[hostApisCount_] )
  143. {
  144. PaUtilHostApiRepresentation* hostApi = hostApis_[hostApisCount_];
  145. assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
  146. assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
  147. /* the first successfully initialized host API with a default input *or*
  148. output device is used as the default host API.
  149. */
  150. if( (defaultHostApiIndex_ == -1) &&
  151. ( hostApi->info.defaultInputDevice != paNoDevice
  152. || hostApi->info.defaultOutputDevice != paNoDevice ) )
  153. {
  154. defaultHostApiIndex_ = hostApisCount_;
  155. }
  156. hostApi->privatePaFrontInfo.baseDeviceIndex = baseDeviceIndex;
  157. if( hostApi->info.defaultInputDevice != paNoDevice )
  158. hostApi->info.defaultInputDevice += baseDeviceIndex;
  159. if( hostApi->info.defaultOutputDevice != paNoDevice )
  160. hostApi->info.defaultOutputDevice += baseDeviceIndex;
  161. baseDeviceIndex += hostApi->info.deviceCount;
  162. deviceCount_ += hostApi->info.deviceCount;
  163. ++hostApisCount_;
  164. }
  165. }
  166. /* if no host APIs have devices, the default host API is the first initialized host API */
  167. if( defaultHostApiIndex_ == -1 )
  168. defaultHostApiIndex_ = 0;
  169. return result;
  170. error:
  171. TerminateHostApis();
  172. return result;
  173. }
  174. /*
  175. FindHostApi() finds the index of the host api to which
  176. <device> belongs and returns it. if <hostSpecificDeviceIndex> is
  177. non-null, the host specific device index is returned in it.
  178. returns -1 if <device> is out of range.
  179. */
  180. static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
  181. {
  182. int i=0;
  183. if( !PA_IS_INITIALISED_ )
  184. return -1;
  185. if( device < 0 )
  186. return -1;
  187. while( i < hostApisCount_
  188. && device >= hostApis_[i]->info.deviceCount )
  189. {
  190. device -= hostApis_[i]->info.deviceCount;
  191. ++i;
  192. }
  193. if( i >= hostApisCount_ )
  194. return -1;
  195. if( hostSpecificDeviceIndex )
  196. *hostSpecificDeviceIndex = device;
  197. return i;
  198. }
  199. static void AddOpenStream( PaStream* stream )
  200. {
  201. ((PaUtilStreamRepresentation*)stream)->nextOpenStream = firstOpenStream_;
  202. firstOpenStream_ = (PaUtilStreamRepresentation*)stream;
  203. }
  204. static void RemoveOpenStream( PaStream* stream )
  205. {
  206. PaUtilStreamRepresentation *previous = NULL;
  207. PaUtilStreamRepresentation *current = firstOpenStream_;
  208. while( current != NULL )
  209. {
  210. if( ((PaStream*)current) == stream )
  211. {
  212. if( previous == NULL )
  213. {
  214. firstOpenStream_ = current->nextOpenStream;
  215. }
  216. else
  217. {
  218. previous->nextOpenStream = current->nextOpenStream;
  219. }
  220. return;
  221. }
  222. else
  223. {
  224. previous = current;
  225. current = current->nextOpenStream;
  226. }
  227. }
  228. }
  229. static void CloseOpenStreams( void )
  230. {
  231. /* we call Pa_CloseStream() here to ensure that the same destruction
  232. logic is used for automatically closed streams */
  233. while( firstOpenStream_ != NULL )
  234. Pa_CloseStream( firstOpenStream_ );
  235. }
  236. PaError Pa_Initialize( void )
  237. {
  238. PaError result;
  239. PA_LOGAPI_ENTER( "Pa_Initialize" );
  240. if( PA_IS_INITIALISED_ )
  241. {
  242. ++initializationCount_;
  243. result = paNoError;
  244. }
  245. else
  246. {
  247. PA_VALIDATE_TYPE_SIZES;
  248. PA_VALIDATE_ENDIANNESS;
  249. PaUtil_InitializeClock();
  250. PaUtil_ResetTraceMessages();
  251. result = InitializeHostApis();
  252. if( result == paNoError )
  253. ++initializationCount_;
  254. }
  255. PA_LOGAPI_EXIT_PAERROR( "Pa_Initialize", result );
  256. return result;
  257. }
  258. PaError Pa_Terminate( void )
  259. {
  260. PaError result;
  261. PA_LOGAPI_ENTER( "Pa_Terminate" );
  262. if( PA_IS_INITIALISED_ )
  263. {
  264. if( --initializationCount_ == 0 )
  265. {
  266. CloseOpenStreams();
  267. TerminateHostApis();
  268. PaUtil_DumpTraceMessages();
  269. }
  270. result = paNoError;
  271. }
  272. else
  273. {
  274. result= paNotInitialized;
  275. }
  276. PA_LOGAPI_EXIT_PAERROR( "Pa_Terminate", result );
  277. return result;
  278. }
  279. const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void )
  280. {
  281. return &lastHostErrorInfo_;
  282. }
  283. const char *Pa_GetErrorText( PaError errorCode )
  284. {
  285. const char *result;
  286. switch( errorCode )
  287. {
  288. case paNoError: result = "Success"; break;
  289. case paNotInitialized: result = "PortAudio not initialized"; break;
  290. /** @todo could catenate the last host error text to result in the case of paUnanticipatedHostError. see: http://www.portaudio.com/trac/ticket/114 */
  291. case paUnanticipatedHostError: result = "Unanticipated host error"; break;
  292. case paInvalidChannelCount: result = "Invalid number of channels"; break;
  293. case paInvalidSampleRate: result = "Invalid sample rate"; break;
  294. case paInvalidDevice: result = "Invalid device"; break;
  295. case paInvalidFlag: result = "Invalid flag"; break;
  296. case paSampleFormatNotSupported: result = "Sample format not supported"; break;
  297. case paBadIODeviceCombination: result = "Illegal combination of I/O devices"; break;
  298. case paInsufficientMemory: result = "Insufficient memory"; break;
  299. case paBufferTooBig: result = "Buffer too big"; break;
  300. case paBufferTooSmall: result = "Buffer too small"; break;
  301. case paNullCallback: result = "No callback routine specified"; break;
  302. case paBadStreamPtr: result = "Invalid stream pointer"; break;
  303. case paTimedOut: result = "Wait timed out"; break;
  304. case paInternalError: result = "Internal PortAudio error"; break;
  305. case paDeviceUnavailable: result = "Device unavailable"; break;
  306. case paIncompatibleHostApiSpecificStreamInfo: result = "Incompatible host API specific stream info"; break;
  307. case paStreamIsStopped: result = "Stream is stopped"; break;
  308. case paStreamIsNotStopped: result = "Stream is not stopped"; break;
  309. case paInputOverflowed: result = "Input overflowed"; break;
  310. case paOutputUnderflowed: result = "Output underflowed"; break;
  311. case paHostApiNotFound: result = "Host API not found"; break;
  312. case paInvalidHostApi: result = "Invalid host API"; break;
  313. case paCanNotReadFromACallbackStream: result = "Can't read from a callback stream"; break;
  314. case paCanNotWriteToACallbackStream: result = "Can't write to a callback stream"; break;
  315. case paCanNotReadFromAnOutputOnlyStream: result = "Can't read from an output only stream"; break;
  316. case paCanNotWriteToAnInputOnlyStream: result = "Can't write to an input only stream"; break;
  317. case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break;
  318. case paBadBufferPtr: result = "Bad buffer pointer"; break;
  319. default:
  320. if( errorCode > 0 )
  321. result = "Invalid error code (value greater than zero)";
  322. else
  323. result = "Invalid error code";
  324. break;
  325. }
  326. return result;
  327. }
  328. PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
  329. {
  330. PaHostApiIndex result;
  331. int i;
  332. PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiTypeIdToHostApiIndex" );
  333. PA_LOGAPI(("\tPaHostApiTypeId type: %d\n", type ));
  334. if( !PA_IS_INITIALISED_ )
  335. {
  336. result = paNotInitialized;
  337. }
  338. else
  339. {
  340. result = paHostApiNotFound;
  341. for( i=0; i < hostApisCount_; ++i )
  342. {
  343. if( hostApis_[i]->info.type == type )
  344. {
  345. result = i;
  346. break;
  347. }
  348. }
  349. }
  350. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_HostApiTypeIdToHostApiIndex", "PaHostApiIndex: %d", result );
  351. return result;
  352. }
  353. PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
  354. PaHostApiTypeId type )
  355. {
  356. PaError result;
  357. int i;
  358. if( !PA_IS_INITIALISED_ )
  359. {
  360. result = paNotInitialized;
  361. }
  362. else
  363. {
  364. result = paHostApiNotFound;
  365. for( i=0; i < hostApisCount_; ++i )
  366. {
  367. if( hostApis_[i]->info.type == type )
  368. {
  369. *hostApi = hostApis_[i];
  370. result = paNoError;
  371. break;
  372. }
  373. }
  374. }
  375. return result;
  376. }
  377. PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
  378. PaDeviceIndex *hostApiDevice, PaDeviceIndex device, struct PaUtilHostApiRepresentation *hostApi )
  379. {
  380. PaError result;
  381. PaDeviceIndex x;
  382. x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
  383. if( x < 0 || x >= hostApi->info.deviceCount )
  384. {
  385. result = paInvalidDevice;
  386. }
  387. else
  388. {
  389. *hostApiDevice = x;
  390. result = paNoError;
  391. }
  392. return result;
  393. }
  394. PaHostApiIndex Pa_GetHostApiCount( void )
  395. {
  396. int result;
  397. PA_LOGAPI_ENTER( "Pa_GetHostApiCount" );
  398. if( !PA_IS_INITIALISED_ )
  399. {
  400. result = paNotInitialized;
  401. }
  402. else
  403. {
  404. result = hostApisCount_;
  405. }
  406. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetHostApiCount", "PaHostApiIndex: %d", result );
  407. return result;
  408. }
  409. PaHostApiIndex Pa_GetDefaultHostApi( void )
  410. {
  411. int result;
  412. PA_LOGAPI_ENTER( "Pa_GetDefaultHostApi" );
  413. if( !PA_IS_INITIALISED_ )
  414. {
  415. result = paNotInitialized;
  416. }
  417. else
  418. {
  419. result = defaultHostApiIndex_;
  420. /* internal consistency check: make sure that the default host api
  421. index is within range */
  422. if( result < 0 || result >= hostApisCount_ )
  423. {
  424. result = paInternalError;
  425. }
  426. }
  427. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDefaultHostApi", "PaHostApiIndex: %d", result );
  428. return result;
  429. }
  430. const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
  431. {
  432. PaHostApiInfo *info;
  433. PA_LOGAPI_ENTER_PARAMS( "Pa_GetHostApiInfo" );
  434. PA_LOGAPI(("\tPaHostApiIndex hostApi: %d\n", hostApi ));
  435. if( !PA_IS_INITIALISED_ )
  436. {
  437. info = NULL;
  438. PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
  439. PA_LOGAPI(("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n" ));
  440. }
  441. else if( hostApi < 0 || hostApi >= hostApisCount_ )
  442. {
  443. info = NULL;
  444. PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
  445. PA_LOGAPI(("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n" ));
  446. }
  447. else
  448. {
  449. info = &hostApis_[hostApi]->info;
  450. PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
  451. PA_LOGAPI(("\tPaHostApiInfo*: 0x%p\n", info ));
  452. PA_LOGAPI(("\t{\n" ));
  453. PA_LOGAPI(("\t\tint structVersion: %d\n", info->structVersion ));
  454. PA_LOGAPI(("\t\tPaHostApiTypeId type: %d\n", info->type ));
  455. PA_LOGAPI(("\t\tconst char *name: %s\n", info->name ));
  456. PA_LOGAPI(("\t}\n" ));
  457. }
  458. return info;
  459. }
  460. PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int hostApiDeviceIndex )
  461. {
  462. PaDeviceIndex result;
  463. PA_LOGAPI_ENTER_PARAMS( "Pa_HostApiDeviceIndexToPaDeviceIndex" );
  464. PA_LOGAPI(("\tPaHostApiIndex hostApi: %d\n", hostApi ));
  465. PA_LOGAPI(("\tint hostApiDeviceIndex: %d\n", hostApiDeviceIndex ));
  466. if( !PA_IS_INITIALISED_ )
  467. {
  468. result = paNotInitialized;
  469. }
  470. else
  471. {
  472. if( hostApi < 0 || hostApi >= hostApisCount_ )
  473. {
  474. result = paInvalidHostApi;
  475. }
  476. else
  477. {
  478. if( hostApiDeviceIndex < 0 ||
  479. hostApiDeviceIndex >= hostApis_[hostApi]->info.deviceCount )
  480. {
  481. result = paInvalidDevice;
  482. }
  483. else
  484. {
  485. result = hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex;
  486. }
  487. }
  488. }
  489. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_HostApiDeviceIndexToPaDeviceIndex", "PaDeviceIndex: %d", result );
  490. return result;
  491. }
  492. PaDeviceIndex Pa_GetDeviceCount( void )
  493. {
  494. PaDeviceIndex result;
  495. PA_LOGAPI_ENTER( "Pa_GetDeviceCount" );
  496. if( !PA_IS_INITIALISED_ )
  497. {
  498. result = paNotInitialized;
  499. }
  500. else
  501. {
  502. result = deviceCount_;
  503. }
  504. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDeviceCount", "PaDeviceIndex: %d", result );
  505. return result;
  506. }
  507. PaDeviceIndex Pa_GetDefaultInputDevice( void )
  508. {
  509. PaHostApiIndex hostApi;
  510. PaDeviceIndex result;
  511. PA_LOGAPI_ENTER( "Pa_GetDefaultInputDevice" );
  512. hostApi = Pa_GetDefaultHostApi();
  513. if( hostApi < 0 )
  514. {
  515. result = paNoDevice;
  516. }
  517. else
  518. {
  519. result = hostApis_[hostApi]->info.defaultInputDevice;
  520. }
  521. PA_LOGAPI_EXIT_T( "Pa_GetDefaultInputDevice", "PaDeviceIndex: %d", result );
  522. return result;
  523. }
  524. PaDeviceIndex Pa_GetDefaultOutputDevice( void )
  525. {
  526. PaHostApiIndex hostApi;
  527. PaDeviceIndex result;
  528. PA_LOGAPI_ENTER( "Pa_GetDefaultOutputDevice" );
  529. hostApi = Pa_GetDefaultHostApi();
  530. if( hostApi < 0 )
  531. {
  532. result = paNoDevice;
  533. }
  534. else
  535. {
  536. result = hostApis_[hostApi]->info.defaultOutputDevice;
  537. }
  538. PA_LOGAPI_EXIT_T( "Pa_GetDefaultOutputDevice", "PaDeviceIndex: %d", result );
  539. return result;
  540. }
  541. const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
  542. {
  543. int hostSpecificDeviceIndex;
  544. int hostApiIndex = FindHostApi( device, &hostSpecificDeviceIndex );
  545. PaDeviceInfo *result;
  546. PA_LOGAPI_ENTER_PARAMS( "Pa_GetDeviceInfo" );
  547. PA_LOGAPI(("\tPaDeviceIndex device: %d\n", device ));
  548. if( hostApiIndex < 0 )
  549. {
  550. result = NULL;
  551. PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" ));
  552. PA_LOGAPI(("\tPaDeviceInfo* NULL [ invalid device index ]\n" ));
  553. }
  554. else
  555. {
  556. result = hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ];
  557. PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" ));
  558. PA_LOGAPI(("\tPaDeviceInfo*: 0x%p:\n", result ));
  559. PA_LOGAPI(("\t{\n" ));
  560. PA_LOGAPI(("\t\tint structVersion: %d\n", result->structVersion ));
  561. PA_LOGAPI(("\t\tconst char *name: %s\n", result->name ));
  562. PA_LOGAPI(("\t\tPaHostApiIndex hostApi: %d\n", result->hostApi ));
  563. PA_LOGAPI(("\t\tint maxInputChannels: %d\n", result->maxInputChannels ));
  564. PA_LOGAPI(("\t\tint maxOutputChannels: %d\n", result->maxOutputChannels ));
  565. PA_LOGAPI(("\t}\n" ));
  566. }
  567. return result;
  568. }
  569. /*
  570. SampleFormatIsValid() returns 1 if sampleFormat is a sample format
  571. defined in portaudio.h, or 0 otherwise.
  572. */
  573. static int SampleFormatIsValid( PaSampleFormat format )
  574. {
  575. switch( format & ~paNonInterleaved )
  576. {
  577. case paFloat32: return 1;
  578. case paInt16: return 1;
  579. case paInt32: return 1;
  580. case paInt24: return 1;
  581. case paInt8: return 1;
  582. case paUInt8: return 1;
  583. case paCustomFormat: return 1;
  584. default: return 0;
  585. }
  586. }
  587. /*
  588. NOTE: make sure this validation list is kept syncronised with the one in
  589. pa_hostapi.h
  590. ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
  591. conform to the expected values as described below. This function is
  592. also designed to be used with the proposed Pa_IsFormatSupported() function.
  593. There are basically two types of validation that could be performed:
  594. Generic conformance validation, and device capability mismatch
  595. validation. This function performs only generic conformance validation.
  596. Validation that would require knowledge of device capabilities is
  597. not performed because of potentially complex relationships between
  598. combinations of parameters - for example, even if the sampleRate
  599. seems ok, it might not be for a duplex stream - we have no way of
  600. checking this in an API-neutral way, so we don't try.
  601. On success the function returns PaNoError and fills in hostApi,
  602. hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
  603. the function returns an error code indicating the first encountered
  604. parameter error.
  605. If ValidateOpenStreamParameters() returns paNoError, the following
  606. assertions are guaranteed to be true.
  607. - at least one of inputParameters & outputParmeters is valid (not NULL)
  608. - if inputParameters & outputParameters are both valid, that
  609. inputParameters->device & outputParameters->device both use the same host api
  610. PaDeviceIndex inputParameters->device
  611. - is within range (0 to Pa_GetDeviceCount-1) Or:
  612. - is paUseHostApiSpecificDeviceSpecification and
  613. inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
  614. to a valid host api
  615. int inputParameters->channelCount
  616. - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
  617. - upper bound is NOT validated against device capabilities
  618. PaSampleFormat inputParameters->sampleFormat
  619. - is one of the sample formats defined in portaudio.h
  620. void *inputParameters->hostApiSpecificStreamInfo
  621. - if supplied its hostApi field matches the input device's host Api
  622. PaDeviceIndex outputParmeters->device
  623. - is within range (0 to Pa_GetDeviceCount-1)
  624. int outputParmeters->channelCount
  625. - if inputDevice is valid, channelCount is > 0
  626. - upper bound is NOT validated against device capabilities
  627. PaSampleFormat outputParmeters->sampleFormat
  628. - is one of the sample formats defined in portaudio.h
  629. void *outputParmeters->hostApiSpecificStreamInfo
  630. - if supplied its hostApi field matches the output device's host Api
  631. double sampleRate
  632. - is not an 'absurd' rate (less than 1000. or greater than 384000.)
  633. - sampleRate is NOT validated against device capabilities
  634. PaStreamFlags streamFlags
  635. - unused platform neutral flags are zero
  636. - paNeverDropInput is only used for full-duplex callback streams with
  637. variable buffer size (paFramesPerBufferUnspecified)
  638. */
  639. static PaError ValidateOpenStreamParameters(
  640. const PaStreamParameters *inputParameters,
  641. const PaStreamParameters *outputParameters,
  642. double sampleRate,
  643. unsigned long framesPerBuffer,
  644. PaStreamFlags streamFlags,
  645. PaStreamCallback *streamCallback,
  646. PaUtilHostApiRepresentation **hostApi,
  647. PaDeviceIndex *hostApiInputDevice,
  648. PaDeviceIndex *hostApiOutputDevice )
  649. {
  650. int inputHostApiIndex = -1, /* Surpress uninitialised var warnings: compiler does */
  651. outputHostApiIndex = -1; /* not see that if inputParameters and outputParame- */
  652. /* ters are both nonzero, these indices are set. */
  653. if( (inputParameters == NULL) && (outputParameters == NULL) )
  654. {
  655. return paInvalidDevice; /** @todo should be a new error code "invalid device parameters" or something */
  656. }
  657. else
  658. {
  659. if( inputParameters == NULL )
  660. {
  661. *hostApiInputDevice = paNoDevice;
  662. }
  663. else if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
  664. {
  665. if( inputParameters->hostApiSpecificStreamInfo )
  666. {
  667. inputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
  668. ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType );
  669. if( inputHostApiIndex != -1 )
  670. {
  671. *hostApiInputDevice = paUseHostApiSpecificDeviceSpecification;
  672. *hostApi = hostApis_[inputHostApiIndex];
  673. }
  674. else
  675. {
  676. return paInvalidDevice;
  677. }
  678. }
  679. else
  680. {
  681. return paInvalidDevice;
  682. }
  683. }
  684. else
  685. {
  686. if( inputParameters->device < 0 || inputParameters->device >= deviceCount_ )
  687. return paInvalidDevice;
  688. inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice );
  689. if( inputHostApiIndex < 0 )
  690. return paInternalError;
  691. *hostApi = hostApis_[inputHostApiIndex];
  692. if( inputParameters->channelCount <= 0 )
  693. return paInvalidChannelCount;
  694. if( !SampleFormatIsValid( inputParameters->sampleFormat ) )
  695. return paSampleFormatNotSupported;
  696. if( inputParameters->hostApiSpecificStreamInfo != NULL )
  697. {
  698. if( ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType
  699. != (*hostApi)->info.type )
  700. return paIncompatibleHostApiSpecificStreamInfo;
  701. }
  702. }
  703. if( outputParameters == NULL )
  704. {
  705. *hostApiOutputDevice = paNoDevice;
  706. }
  707. else if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
  708. {
  709. if( outputParameters->hostApiSpecificStreamInfo )
  710. {
  711. outputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
  712. ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType );
  713. if( outputHostApiIndex != -1 )
  714. {
  715. *hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification;
  716. *hostApi = hostApis_[outputHostApiIndex];
  717. }
  718. else
  719. {
  720. return paInvalidDevice;
  721. }
  722. }
  723. else
  724. {
  725. return paInvalidDevice;
  726. }
  727. }
  728. else
  729. {
  730. if( outputParameters->device < 0 || outputParameters->device >= deviceCount_ )
  731. return paInvalidDevice;
  732. outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice );
  733. if( outputHostApiIndex < 0 )
  734. return paInternalError;
  735. *hostApi = hostApis_[outputHostApiIndex];
  736. if( outputParameters->channelCount <= 0 )
  737. return paInvalidChannelCount;
  738. if( !SampleFormatIsValid( outputParameters->sampleFormat ) )
  739. return paSampleFormatNotSupported;
  740. if( outputParameters->hostApiSpecificStreamInfo != NULL )
  741. {
  742. if( ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType
  743. != (*hostApi)->info.type )
  744. return paIncompatibleHostApiSpecificStreamInfo;
  745. }
  746. }
  747. if( (inputParameters != NULL) && (outputParameters != NULL) )
  748. {
  749. /* ensure that both devices use the same API */
  750. if( inputHostApiIndex != outputHostApiIndex )
  751. return paBadIODeviceCombination;
  752. }
  753. }
  754. /* Check for absurd sample rates. */
  755. if( (sampleRate < 1000.0) || (sampleRate > 384000.0) )
  756. return paInvalidSampleRate;
  757. if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 )
  758. return paInvalidFlag;
  759. if( streamFlags & paNeverDropInput )
  760. {
  761. /* must be a callback stream */
  762. if( !streamCallback )
  763. return paInvalidFlag;
  764. /* must be a full duplex stream */
  765. if( (inputParameters == NULL) || (outputParameters == NULL) )
  766. return paInvalidFlag;
  767. /* must use paFramesPerBufferUnspecified */
  768. if( framesPerBuffer != paFramesPerBufferUnspecified )
  769. return paInvalidFlag;
  770. }
  771. return paNoError;
  772. }
  773. PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
  774. const PaStreamParameters *outputParameters,
  775. double sampleRate )
  776. {
  777. PaError result;
  778. PaUtilHostApiRepresentation *hostApi = 0;
  779. PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice;
  780. PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
  781. PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
  782. #ifdef PA_LOG_API_CALLS
  783. PA_LOGAPI_ENTER_PARAMS( "Pa_IsFormatSupported" );
  784. if( inputParameters == NULL ){
  785. PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" ));
  786. }else{
  787. PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters ));
  788. PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device ));
  789. PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount ));
  790. PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat ));
  791. PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency ));
  792. PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo ));
  793. }
  794. if( outputParameters == NULL ){
  795. PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" ));
  796. }else{
  797. PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters ));
  798. PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device ));
  799. PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount ));
  800. PA_LOGAPI(("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat ));
  801. PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
  802. PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
  803. }
  804. PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
  805. #endif
  806. if( !PA_IS_INITIALISED_ )
  807. {
  808. result = paNotInitialized;
  809. PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
  810. return result;
  811. }
  812. result = ValidateOpenStreamParameters( inputParameters,
  813. outputParameters,
  814. sampleRate, 0, paNoFlag, 0,
  815. &hostApi,
  816. &hostApiInputDevice,
  817. &hostApiOutputDevice );
  818. if( result != paNoError )
  819. {
  820. PA_LOGAPI_EXIT_PAERROR( "Pa_IsFormatSupported", result );
  821. return result;
  822. }
  823. if( inputParameters )
  824. {
  825. hostApiInputParameters.device = hostApiInputDevice;
  826. hostApiInputParameters.channelCount = inputParameters->channelCount;
  827. hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
  828. hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
  829. hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
  830. hostApiInputParametersPtr = &hostApiInputParameters;
  831. }
  832. else
  833. {
  834. hostApiInputParametersPtr = NULL;
  835. }
  836. if( outputParameters )
  837. {
  838. hostApiOutputParameters.device = hostApiOutputDevice;
  839. hostApiOutputParameters.channelCount = outputParameters->channelCount;
  840. hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
  841. hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
  842. hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
  843. hostApiOutputParametersPtr = &hostApiOutputParameters;
  844. }
  845. else
  846. {
  847. hostApiOutputParametersPtr = NULL;
  848. }
  849. result = hostApi->IsFormatSupported( hostApi,
  850. hostApiInputParametersPtr, hostApiOutputParametersPtr,
  851. sampleRate );
  852. #ifdef PA_LOG_API_CALLS
  853. PA_LOGAPI(("Pa_OpenStream returned:\n" ));
  854. if( result == paFormatIsSupported )
  855. PA_LOGAPI(("\tPaError: 0 [ paFormatIsSupported ]\n" ));
  856. else
  857. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  858. #endif
  859. return result;
  860. }
  861. PaError Pa_OpenStream( PaStream** stream,
  862. const PaStreamParameters *inputParameters,
  863. const PaStreamParameters *outputParameters,
  864. double sampleRate,
  865. unsigned long framesPerBuffer,
  866. PaStreamFlags streamFlags,
  867. PaStreamCallback *streamCallback,
  868. void *userData )
  869. {
  870. PaError result;
  871. PaUtilHostApiRepresentation *hostApi = 0;
  872. PaDeviceIndex hostApiInputDevice = paNoDevice, hostApiOutputDevice = paNoDevice;
  873. PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
  874. PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
  875. #ifdef PA_LOG_API_CALLS
  876. PA_LOGAPI_ENTER_PARAMS( "Pa_OpenStream" );
  877. PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream ));
  878. if( inputParameters == NULL ){
  879. PA_LOGAPI(("\tPaStreamParameters *inputParameters: NULL\n" ));
  880. }else{
  881. PA_LOGAPI(("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters ));
  882. PA_LOGAPI(("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device ));
  883. PA_LOGAPI(("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount ));
  884. PA_LOGAPI(("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat ));
  885. PA_LOGAPI(("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency ));
  886. PA_LOGAPI(("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo ));
  887. }
  888. if( outputParameters == NULL ){
  889. PA_LOGAPI(("\tPaStreamParameters *outputParameters: NULL\n" ));
  890. }else{
  891. PA_LOGAPI(("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters ));
  892. PA_LOGAPI(("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device ));
  893. PA_LOGAPI(("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount ));
  894. PA_LOGAPI(("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat ));
  895. PA_LOGAPI(("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency ));
  896. PA_LOGAPI(("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo ));
  897. }
  898. PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
  899. PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
  900. PA_LOGAPI(("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags ));
  901. PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback ));
  902. PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData ));
  903. #endif
  904. if( !PA_IS_INITIALISED_ )
  905. {
  906. result = paNotInitialized;
  907. PA_LOGAPI(("Pa_OpenStream returned:\n" ));
  908. PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
  909. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  910. return result;
  911. }
  912. /* Check for parameter errors.
  913. NOTE: make sure this validation list is kept syncronised with the one
  914. in pa_hostapi.h
  915. */
  916. if( stream == NULL )
  917. {
  918. result = paBadStreamPtr;
  919. PA_LOGAPI(("Pa_OpenStream returned:\n" ));
  920. PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
  921. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  922. return result;
  923. }
  924. result = ValidateOpenStreamParameters( inputParameters,
  925. outputParameters,
  926. sampleRate, framesPerBuffer,
  927. streamFlags, streamCallback,
  928. &hostApi,
  929. &hostApiInputDevice,
  930. &hostApiOutputDevice );
  931. if( result != paNoError )
  932. {
  933. PA_LOGAPI(("Pa_OpenStream returned:\n" ));
  934. PA_LOGAPI(("\t*(PaStream** stream): undefined\n" ));
  935. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  936. return result;
  937. }
  938. if( inputParameters )
  939. {
  940. hostApiInputParameters.device = hostApiInputDevice;
  941. hostApiInputParameters.channelCount = inputParameters->channelCount;
  942. hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
  943. hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
  944. hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
  945. hostApiInputParametersPtr = &hostApiInputParameters;
  946. }
  947. else
  948. {
  949. hostApiInputParametersPtr = NULL;
  950. }
  951. if( outputParameters )
  952. {
  953. hostApiOutputParameters.device = hostApiOutputDevice;
  954. hostApiOutputParameters.channelCount = outputParameters->channelCount;
  955. hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
  956. hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
  957. hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
  958. hostApiOutputParametersPtr = &hostApiOutputParameters;
  959. }
  960. else
  961. {
  962. hostApiOutputParametersPtr = NULL;
  963. }
  964. result = hostApi->OpenStream( hostApi, stream,
  965. hostApiInputParametersPtr, hostApiOutputParametersPtr,
  966. sampleRate, framesPerBuffer, streamFlags, streamCallback, userData );
  967. if( result == paNoError )
  968. AddOpenStream( *stream );
  969. PA_LOGAPI(("Pa_OpenStream returned:\n" ));
  970. PA_LOGAPI(("\t*(PaStream** stream): 0x%p\n", *stream ));
  971. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  972. return result;
  973. }
  974. PaError Pa_OpenDefaultStream( PaStream** stream,
  975. int inputChannelCount,
  976. int outputChannelCount,
  977. PaSampleFormat sampleFormat,
  978. double sampleRate,
  979. unsigned long framesPerBuffer,
  980. PaStreamCallback *streamCallback,
  981. void *userData )
  982. {
  983. PaError result;
  984. PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
  985. PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
  986. PA_LOGAPI_ENTER_PARAMS( "Pa_OpenDefaultStream" );
  987. PA_LOGAPI(("\tPaStream** stream: 0x%p\n", stream ));
  988. PA_LOGAPI(("\tint inputChannelCount: %d\n", inputChannelCount ));
  989. PA_LOGAPI(("\tint outputChannelCount: %d\n", outputChannelCount ));
  990. PA_LOGAPI(("\tPaSampleFormat sampleFormat: %d\n", sampleFormat ));
  991. PA_LOGAPI(("\tdouble sampleRate: %g\n", sampleRate ));
  992. PA_LOGAPI(("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer ));
  993. PA_LOGAPI(("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback ));
  994. PA_LOGAPI(("\tvoid *userData: 0x%p\n", userData ));
  995. if( inputChannelCount > 0 )
  996. {
  997. hostApiInputParameters.device = Pa_GetDefaultInputDevice();
  998. if( hostApiInputParameters.device == paNoDevice )
  999. return paDeviceUnavailable;
  1000. hostApiInputParameters.channelCount = inputChannelCount;
  1001. hostApiInputParameters.sampleFormat = sampleFormat;
  1002. /* defaultHighInputLatency is used below instead of
  1003. defaultLowInputLatency because it is more important for the default
  1004. stream to work reliably than it is for it to work with the lowest
  1005. latency.
  1006. */
  1007. hostApiInputParameters.suggestedLatency =
  1008. Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
  1009. hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
  1010. hostApiInputParametersPtr = &hostApiInputParameters;
  1011. }
  1012. else
  1013. {
  1014. hostApiInputParametersPtr = NULL;
  1015. }
  1016. if( outputChannelCount > 0 )
  1017. {
  1018. hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
  1019. if( hostApiOutputParameters.device == paNoDevice )
  1020. return paDeviceUnavailable;
  1021. hostApiOutputParameters.channelCount = outputChannelCount;
  1022. hostApiOutputParameters.sampleFormat = sampleFormat;
  1023. /* defaultHighOutputLatency is used below instead of
  1024. defaultLowOutputLatency because it is more important for the default
  1025. stream to work reliably than it is for it to work with the lowest
  1026. latency.
  1027. */
  1028. hostApiOutputParameters.suggestedLatency =
  1029. Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
  1030. hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
  1031. hostApiOutputParametersPtr = &hostApiOutputParameters;
  1032. }
  1033. else
  1034. {
  1035. hostApiOutputParametersPtr = NULL;
  1036. }
  1037. result = Pa_OpenStream(
  1038. stream, hostApiInputParametersPtr, hostApiOutputParametersPtr,
  1039. sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
  1040. PA_LOGAPI(("Pa_OpenDefaultStream returned:\n" ));
  1041. PA_LOGAPI(("\t*(PaStream** stream): 0x%p", *stream ));
  1042. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  1043. return result;
  1044. }
  1045. PaError PaUtil_ValidateStreamPointer( PaStream* stream )
  1046. {
  1047. if( !PA_IS_INITIALISED_ ) return paNotInitialized;
  1048. if( stream == NULL ) return paBadStreamPtr;
  1049. if( ((PaUtilStreamRepresentation*)stream)->magic != PA_STREAM_MAGIC )
  1050. return paBadStreamPtr;
  1051. return paNoError;
  1052. }
  1053. PaError Pa_CloseStream( PaStream* stream )
  1054. {
  1055. PaUtilStreamInterface *interface;
  1056. PaError result = PaUtil_ValidateStreamPointer( stream );
  1057. PA_LOGAPI_ENTER_PARAMS( "Pa_CloseStream" );
  1058. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1059. /* always remove the open stream from our list, even if this function
  1060. eventually returns an error. Otherwise CloseOpenStreams() will
  1061. get stuck in an infinite loop */
  1062. RemoveOpenStream( stream ); /* be sure to call this _before_ closing the stream */
  1063. if( result == paNoError )
  1064. {
  1065. interface = PA_STREAM_INTERFACE(stream);
  1066. /* abort the stream if it isn't stopped */
  1067. result = interface->IsStopped( stream );
  1068. if( result == 1 )
  1069. result = paNoError;
  1070. else if( result == 0 )
  1071. result = interface->Abort( stream );
  1072. if( result == paNoError ) /** @todo REVIEW: shouldn't we close anyway? see: http://www.portaudio.com/trac/ticket/115 */
  1073. result = interface->Close( stream );
  1074. }
  1075. PA_LOGAPI_EXIT_PAERROR( "Pa_CloseStream", result );
  1076. return result;
  1077. }
  1078. PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback )
  1079. {
  1080. PaError result = PaUtil_ValidateStreamPointer( stream );
  1081. PA_LOGAPI_ENTER_PARAMS( "Pa_SetStreamFinishedCallback" );
  1082. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1083. PA_LOGAPI(("\tPaStreamFinishedCallback* streamFinishedCallback: 0x%p\n", streamFinishedCallback ));
  1084. if( result == paNoError )
  1085. {
  1086. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1087. if( result == 0 )
  1088. {
  1089. result = paStreamIsNotStopped ;
  1090. }
  1091. if( result == 1 )
  1092. {
  1093. PA_STREAM_REP( stream )->streamFinishedCallback = streamFinishedCallback;
  1094. result = paNoError;
  1095. }
  1096. }
  1097. PA_LOGAPI_EXIT_PAERROR( "Pa_SetStreamFinishedCallback", result );
  1098. return result;
  1099. }
  1100. PaError Pa_StartStream( PaStream *stream )
  1101. {
  1102. PaError result = PaUtil_ValidateStreamPointer( stream );
  1103. PA_LOGAPI_ENTER_PARAMS( "Pa_StartStream" );
  1104. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1105. if( result == paNoError )
  1106. {
  1107. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1108. if( result == 0 )
  1109. {
  1110. result = paStreamIsNotStopped ;
  1111. }
  1112. else if( result == 1 )
  1113. {
  1114. result = PA_STREAM_INTERFACE(stream)->Start( stream );
  1115. }
  1116. }
  1117. PA_LOGAPI_EXIT_PAERROR( "Pa_StartStream", result );
  1118. return result;
  1119. }
  1120. PaError Pa_StopStream( PaStream *stream )
  1121. {
  1122. PaError result = PaUtil_ValidateStreamPointer( stream );
  1123. PA_LOGAPI_ENTER_PARAMS( "Pa_StopStream" );
  1124. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1125. if( result == paNoError )
  1126. {
  1127. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1128. if( result == 0 )
  1129. {
  1130. result = PA_STREAM_INTERFACE(stream)->Stop( stream );
  1131. }
  1132. else if( result == 1 )
  1133. {
  1134. result = paStreamIsStopped;
  1135. }
  1136. }
  1137. PA_LOGAPI_EXIT_PAERROR( "Pa_StopStream", result );
  1138. return result;
  1139. }
  1140. PaError Pa_AbortStream( PaStream *stream )
  1141. {
  1142. PaError result = PaUtil_ValidateStreamPointer( stream );
  1143. PA_LOGAPI_ENTER_PARAMS( "Pa_AbortStream" );
  1144. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1145. if( result == paNoError )
  1146. {
  1147. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1148. if( result == 0 )
  1149. {
  1150. result = PA_STREAM_INTERFACE(stream)->Abort( stream );
  1151. }
  1152. else if( result == 1 )
  1153. {
  1154. result = paStreamIsStopped;
  1155. }
  1156. }
  1157. PA_LOGAPI_EXIT_PAERROR( "Pa_AbortStream", result );
  1158. return result;
  1159. }
  1160. PaError Pa_IsStreamStopped( PaStream *stream )
  1161. {
  1162. PaError result = PaUtil_ValidateStreamPointer( stream );
  1163. PA_LOGAPI_ENTER_PARAMS( "Pa_IsStreamStopped" );
  1164. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1165. if( result == paNoError )
  1166. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1167. PA_LOGAPI_EXIT_PAERROR( "Pa_IsStreamStopped", result );
  1168. return result;
  1169. }
  1170. PaError Pa_IsStreamActive( PaStream *stream )
  1171. {
  1172. PaError result = PaUtil_ValidateStreamPointer( stream );
  1173. PA_LOGAPI_ENTER_PARAMS( "Pa_IsStreamActive" );
  1174. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1175. if( result == paNoError )
  1176. result = PA_STREAM_INTERFACE(stream)->IsActive( stream );
  1177. PA_LOGAPI_EXIT_PAERROR( "Pa_IsStreamActive", result );
  1178. return result;
  1179. }
  1180. const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream )
  1181. {
  1182. PaError error = PaUtil_ValidateStreamPointer( stream );
  1183. const PaStreamInfo *result;
  1184. PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamInfo" );
  1185. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1186. if( error != paNoError )
  1187. {
  1188. result = 0;
  1189. PA_LOGAPI(("Pa_GetStreamInfo returned:\n" ));
  1190. PA_LOGAPI(("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n", error, Pa_GetErrorText( error ) ));
  1191. }
  1192. else
  1193. {
  1194. result = &PA_STREAM_REP( stream )->streamInfo;
  1195. PA_LOGAPI(("Pa_GetStreamInfo returned:\n" ));
  1196. PA_LOGAPI(("\tconst PaStreamInfo*: 0x%p:\n", result ));
  1197. PA_LOGAPI(("\t{" ));
  1198. PA_LOGAPI(("\t\tint structVersion: %d\n", result->structVersion ));
  1199. PA_LOGAPI(("\t\tPaTime inputLatency: %f\n", result->inputLatency ));
  1200. PA_LOGAPI(("\t\tPaTime outputLatency: %f\n", result->outputLatency ));
  1201. PA_LOGAPI(("\t\tdouble sampleRate: %f\n", result->sampleRate ));
  1202. PA_LOGAPI(("\t}\n" ));
  1203. }
  1204. return result;
  1205. }
  1206. PaTime Pa_GetStreamTime( PaStream *stream )
  1207. {
  1208. PaError error = PaUtil_ValidateStreamPointer( stream );
  1209. PaTime result;
  1210. PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamTime" );
  1211. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1212. if( error != paNoError )
  1213. {
  1214. result = 0;
  1215. PA_LOGAPI(("Pa_GetStreamTime returned:\n" ));
  1216. PA_LOGAPI(("\tPaTime: 0 [PaError error:%d ( %s )]\n", result, error, Pa_GetErrorText( error ) ));
  1217. }
  1218. else
  1219. {
  1220. result = PA_STREAM_INTERFACE(stream)->GetTime( stream );
  1221. PA_LOGAPI(("Pa_GetStreamTime returned:\n" ));
  1222. PA_LOGAPI(("\tPaTime: %g\n", result ));
  1223. }
  1224. return result;
  1225. }
  1226. double Pa_GetStreamCpuLoad( PaStream* stream )
  1227. {
  1228. PaError error = PaUtil_ValidateStreamPointer( stream );
  1229. double result;
  1230. PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamCpuLoad" );
  1231. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1232. if( error != paNoError )
  1233. {
  1234. result = 0.0;
  1235. PA_LOGAPI(("Pa_GetStreamCpuLoad returned:\n" ));
  1236. PA_LOGAPI(("\tdouble: 0.0 [PaError error: %d ( %s )]\n", error, Pa_GetErrorText( error ) ));
  1237. }
  1238. else
  1239. {
  1240. result = PA_STREAM_INTERFACE(stream)->GetCpuLoad( stream );
  1241. PA_LOGAPI(("Pa_GetStreamCpuLoad returned:\n" ));
  1242. PA_LOGAPI(("\tdouble: %g\n", result ));
  1243. }
  1244. return result;
  1245. }
  1246. PaError Pa_ReadStream( PaStream* stream,
  1247. void *buffer,
  1248. unsigned long frames )
  1249. {
  1250. PaError result = PaUtil_ValidateStreamPointer( stream );
  1251. PA_LOGAPI_ENTER_PARAMS( "Pa_ReadStream" );
  1252. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1253. if( result == paNoError )
  1254. {
  1255. if( frames == 0 )
  1256. {
  1257. /* @todo Should we not allow the implementation to signal any overflow condition? see: http://www.portaudio.com/trac/ticket/116*/
  1258. result = paNoError;
  1259. }
  1260. else if( buffer == 0 )
  1261. {
  1262. result = paBadBufferPtr;
  1263. }
  1264. else
  1265. {
  1266. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1267. if( result == 0 )
  1268. {
  1269. result = PA_STREAM_INTERFACE(stream)->Read( stream, buffer, frames );
  1270. }
  1271. else if( result == 1 )
  1272. {
  1273. result = paStreamIsStopped;
  1274. }
  1275. }
  1276. }
  1277. PA_LOGAPI_EXIT_PAERROR( "Pa_ReadStream", result );
  1278. return result;
  1279. }
  1280. PaError Pa_WriteStream( PaStream* stream,
  1281. const void *buffer,
  1282. unsigned long frames )
  1283. {
  1284. PaError result = PaUtil_ValidateStreamPointer( stream );
  1285. PA_LOGAPI_ENTER_PARAMS( "Pa_WriteStream" );
  1286. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1287. if( result == paNoError )
  1288. {
  1289. if( frames == 0 )
  1290. {
  1291. /* @todo Should we not allow the implementation to signal any underflow condition? see: http://www.portaudio.com/trac/ticket/116*/
  1292. result = paNoError;
  1293. }
  1294. else if( buffer == 0 )
  1295. {
  1296. result = paBadBufferPtr;
  1297. }
  1298. else
  1299. {
  1300. result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
  1301. if( result == 0 )
  1302. {
  1303. result = PA_STREAM_INTERFACE(stream)->Write( stream, buffer, frames );
  1304. }
  1305. else if( result == 1 )
  1306. {
  1307. result = paStreamIsStopped;
  1308. }
  1309. }
  1310. }
  1311. PA_LOGAPI_EXIT_PAERROR( "Pa_WriteStream", result );
  1312. return result;
  1313. }
  1314. signed long Pa_GetStreamReadAvailable( PaStream* stream )
  1315. {
  1316. PaError error = PaUtil_ValidateStreamPointer( stream );
  1317. signed long result;
  1318. PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamReadAvailable" );
  1319. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1320. if( error != paNoError )
  1321. {
  1322. result = 0;
  1323. PA_LOGAPI(("Pa_GetStreamReadAvailable returned:\n" ));
  1324. PA_LOGAPI(("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n", error, Pa_GetErrorText( error ) ));
  1325. }
  1326. else
  1327. {
  1328. result = PA_STREAM_INTERFACE(stream)->GetReadAvailable( stream );
  1329. PA_LOGAPI(("Pa_GetStreamReadAvailable returned:\n" ));
  1330. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  1331. }
  1332. return result;
  1333. }
  1334. signed long Pa_GetStreamWriteAvailable( PaStream* stream )
  1335. {
  1336. PaError error = PaUtil_ValidateStreamPointer( stream );
  1337. signed long result;
  1338. PA_LOGAPI_ENTER_PARAMS( "Pa_GetStreamWriteAvailable" );
  1339. PA_LOGAPI(("\tPaStream* stream: 0x%p\n", stream ));
  1340. if( error != paNoError )
  1341. {
  1342. result = 0;
  1343. PA_LOGAPI(("Pa_GetStreamWriteAvailable returned:\n" ));
  1344. PA_LOGAPI(("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n", error, Pa_GetErrorText( error ) ));
  1345. }
  1346. else
  1347. {
  1348. result = PA_STREAM_INTERFACE(stream)->GetWriteAvailable( stream );
  1349. PA_LOGAPI(("Pa_GetStreamWriteAvailable returned:\n" ));
  1350. PA_LOGAPI(("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ));
  1351. }
  1352. return result;
  1353. }
  1354. PaError Pa_GetSampleSize( PaSampleFormat format )
  1355. {
  1356. int result;
  1357. PA_LOGAPI_ENTER_PARAMS( "Pa_GetSampleSize" );
  1358. PA_LOGAPI(("\tPaSampleFormat format: %d\n", format ));
  1359. switch( format & ~paNonInterleaved )
  1360. {
  1361. case paUInt8:
  1362. case paInt8:
  1363. result = 1;
  1364. break;
  1365. case paInt16:
  1366. result = 2;
  1367. break;
  1368. case paInt24:
  1369. result = 3;
  1370. break;
  1371. case paFloat32:
  1372. case paInt32:
  1373. result = 4;
  1374. break;
  1375. default:
  1376. result = paSampleFormatNotSupported;
  1377. break;
  1378. }
  1379. PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetSampleSize", "int: %d", result );
  1380. return (PaError) result;
  1381. }