pa_skeleton.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /*
  2. * $Id: pa_skeleton.c 1097 2006-08-26 08:27:53Z rossb $
  3. * Portable Audio I/O Library skeleton implementation
  4. * demonstrates how to use the common functions to implement support
  5. * for a host API
  6. *
  7. * Based on the Open Source API proposed by Ross Bencina
  8. * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
  9. *
  10. * Permission is hereby granted, free of charge, to any person obtaining
  11. * a copy of this software and associated documentation files
  12. * (the "Software"), to deal in the Software without restriction,
  13. * including without limitation the rights to use, copy, modify, merge,
  14. * publish, distribute, sublicense, and/or sell copies of the Software,
  15. * and to permit persons to whom the Software is furnished to do so,
  16. * subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be
  19. * included in all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  24. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  25. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  26. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. */
  29. /*
  30. * The text above constitutes the entire PortAudio license; however,
  31. * the PortAudio community also makes the following non-binding requests:
  32. *
  33. * Any person wishing to distribute modifications to the Software is
  34. * requested to send the modifications to the original developer so that
  35. * they can be incorporated into the canonical version. It is also
  36. * requested that these non-binding requests be included along with the
  37. * license above.
  38. */
  39. /** @file
  40. @ingroup common_src
  41. @brief Skeleton implementation of support for a host API.
  42. @note This file is provided as a starting point for implementing support for
  43. a new host API. IMPLEMENT ME comments are used to indicate functionality
  44. which much be customised for each implementation.
  45. */
  46. #include <string.h> /* strlen() */
  47. #include "pa_util.h"
  48. #include "pa_allocation.h"
  49. #include "pa_hostapi.h"
  50. #include "pa_stream.h"
  51. #include "pa_cpuload.h"
  52. #include "pa_process.h"
  53. /* prototypes for functions declared in this file */
  54. #ifdef __cplusplus
  55. extern "C"
  56. {
  57. #endif /* __cplusplus */
  58. PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
  59. #ifdef __cplusplus
  60. }
  61. #endif /* __cplusplus */
  62. static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
  63. static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
  64. const PaStreamParameters *inputParameters,
  65. const PaStreamParameters *outputParameters,
  66. double sampleRate );
  67. static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
  68. PaStream** s,
  69. const PaStreamParameters *inputParameters,
  70. const PaStreamParameters *outputParameters,
  71. double sampleRate,
  72. unsigned long framesPerBuffer,
  73. PaStreamFlags streamFlags,
  74. PaStreamCallback *streamCallback,
  75. void *userData );
  76. static PaError CloseStream( PaStream* stream );
  77. static PaError StartStream( PaStream *stream );
  78. static PaError StopStream( PaStream *stream );
  79. static PaError AbortStream( PaStream *stream );
  80. static PaError IsStreamStopped( PaStream *s );
  81. static PaError IsStreamActive( PaStream *stream );
  82. static PaTime GetStreamTime( PaStream *stream );
  83. static double GetStreamCpuLoad( PaStream* stream );
  84. static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
  85. static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
  86. static signed long GetStreamReadAvailable( PaStream* stream );
  87. static signed long GetStreamWriteAvailable( PaStream* stream );
  88. /* IMPLEMENT ME: a macro like the following one should be used for reporting
  89. host errors */
  90. #define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
  91. PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
  92. /* PaSkeletonHostApiRepresentation - host api datastructure specific to this implementation */
  93. typedef struct
  94. {
  95. PaUtilHostApiRepresentation inheritedHostApiRep;
  96. PaUtilStreamInterface callbackStreamInterface;
  97. PaUtilStreamInterface blockingStreamInterface;
  98. PaUtilAllocationGroup *allocations;
  99. /* implementation specific data goes here */
  100. }
  101. PaSkeletonHostApiRepresentation; /* IMPLEMENT ME: rename this */
  102. PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
  103. {
  104. PaError result = paNoError;
  105. int i, deviceCount;
  106. PaSkeletonHostApiRepresentation *skeletonHostApi;
  107. PaDeviceInfo *deviceInfoArray;
  108. skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) );
  109. if( !skeletonHostApi )
  110. {
  111. result = paInsufficientMemory;
  112. goto error;
  113. }
  114. skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
  115. if( !skeletonHostApi->allocations )
  116. {
  117. result = paInsufficientMemory;
  118. goto error;
  119. }
  120. *hostApi = &skeletonHostApi->inheritedHostApiRep;
  121. (*hostApi)->info.structVersion = 1;
  122. (*hostApi)->info.type = paInDevelopment; /* IMPLEMENT ME: change to correct type id */
  123. (*hostApi)->info.name = "skeleton implementation"; /* IMPLEMENT ME: change to correct name */
  124. (*hostApi)->info.defaultInputDevice = paNoDevice; /* IMPLEMENT ME */
  125. (*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */
  126. (*hostApi)->info.deviceCount = 0;
  127. deviceCount = 0; /* IMPLEMENT ME */
  128. if( deviceCount > 0 )
  129. {
  130. (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
  131. skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
  132. if( !(*hostApi)->deviceInfos )
  133. {
  134. result = paInsufficientMemory;
  135. goto error;
  136. }
  137. /* allocate all device info structs in a contiguous block */
  138. deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
  139. skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
  140. if( !deviceInfoArray )
  141. {
  142. result = paInsufficientMemory;
  143. goto error;
  144. }
  145. for( i=0; i < deviceCount; ++i )
  146. {
  147. PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
  148. deviceInfo->structVersion = 2;
  149. deviceInfo->hostApi = hostApiIndex;
  150. deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg:
  151. deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 );
  152. if( !deviceName )
  153. {
  154. result = paInsufficientMemory;
  155. goto error;
  156. }
  157. strcpy( deviceName, srcName );
  158. deviceInfo->name = deviceName;
  159. */
  160. deviceInfo->maxInputChannels = 0; /* IMPLEMENT ME */
  161. deviceInfo->maxOutputChannels = 0; /* IMPLEMENT ME */
  162. deviceInfo->defaultLowInputLatency = 0.; /* IMPLEMENT ME */
  163. deviceInfo->defaultLowOutputLatency = 0.; /* IMPLEMENT ME */
  164. deviceInfo->defaultHighInputLatency = 0.; /* IMPLEMENT ME */
  165. deviceInfo->defaultHighOutputLatency = 0.; /* IMPLEMENT ME */
  166. deviceInfo->defaultSampleRate = 0.; /* IMPLEMENT ME */
  167. (*hostApi)->deviceInfos[i] = deviceInfo;
  168. ++(*hostApi)->info.deviceCount;
  169. }
  170. }
  171. (*hostApi)->Terminate = Terminate;
  172. (*hostApi)->OpenStream = OpenStream;
  173. (*hostApi)->IsFormatSupported = IsFormatSupported;
  174. PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
  175. StopStream, AbortStream, IsStreamStopped, IsStreamActive,
  176. GetStreamTime, GetStreamCpuLoad,
  177. PaUtil_DummyRead, PaUtil_DummyWrite,
  178. PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
  179. PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream,
  180. StopStream, AbortStream, IsStreamStopped, IsStreamActive,
  181. GetStreamTime, PaUtil_DummyGetCpuLoad,
  182. ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
  183. return result;
  184. error:
  185. if( skeletonHostApi )
  186. {
  187. if( skeletonHostApi->allocations )
  188. {
  189. PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
  190. PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
  191. }
  192. PaUtil_FreeMemory( skeletonHostApi );
  193. }
  194. return result;
  195. }
  196. static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
  197. {
  198. PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
  199. /*
  200. IMPLEMENT ME:
  201. - clean up any resources not handled by the allocation group
  202. */
  203. if( skeletonHostApi->allocations )
  204. {
  205. PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
  206. PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
  207. }
  208. PaUtil_FreeMemory( skeletonHostApi );
  209. }
  210. static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
  211. const PaStreamParameters *inputParameters,
  212. const PaStreamParameters *outputParameters,
  213. double sampleRate )
  214. {
  215. int inputChannelCount, outputChannelCount;
  216. PaSampleFormat inputSampleFormat, outputSampleFormat;
  217. if( inputParameters )
  218. {
  219. inputChannelCount = inputParameters->channelCount;
  220. inputSampleFormat = inputParameters->sampleFormat;
  221. /* all standard sample formats are supported by the buffer adapter,
  222. this implementation doesn't support any custom sample formats */
  223. if( inputSampleFormat & paCustomFormat )
  224. return paSampleFormatNotSupported;
  225. /* unless alternate device specification is supported, reject the use of
  226. paUseHostApiSpecificDeviceSpecification */
  227. if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
  228. return paInvalidDevice;
  229. /* check that input device can support inputChannelCount */
  230. if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
  231. return paInvalidChannelCount;
  232. /* validate inputStreamInfo */
  233. if( inputParameters->hostApiSpecificStreamInfo )
  234. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  235. }
  236. else
  237. {
  238. inputChannelCount = 0;
  239. }
  240. if( outputParameters )
  241. {
  242. outputChannelCount = outputParameters->channelCount;
  243. outputSampleFormat = outputParameters->sampleFormat;
  244. /* all standard sample formats are supported by the buffer adapter,
  245. this implementation doesn't support any custom sample formats */
  246. if( outputSampleFormat & paCustomFormat )
  247. return paSampleFormatNotSupported;
  248. /* unless alternate device specification is supported, reject the use of
  249. paUseHostApiSpecificDeviceSpecification */
  250. if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
  251. return paInvalidDevice;
  252. /* check that output device can support outputChannelCount */
  253. if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
  254. return paInvalidChannelCount;
  255. /* validate outputStreamInfo */
  256. if( outputParameters->hostApiSpecificStreamInfo )
  257. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  258. }
  259. else
  260. {
  261. outputChannelCount = 0;
  262. }
  263. /*
  264. IMPLEMENT ME:
  265. - if a full duplex stream is requested, check that the combination
  266. of input and output parameters is supported if necessary
  267. - check that the device supports sampleRate
  268. Because the buffer adapter handles conversion between all standard
  269. sample formats, the following checks are only required if paCustomFormat
  270. is implemented, or under some other unusual conditions.
  271. - check that input device can support inputSampleFormat, or that
  272. we have the capability to convert from inputSampleFormat to
  273. a native format
  274. - check that output device can support outputSampleFormat, or that
  275. we have the capability to convert from outputSampleFormat to
  276. a native format
  277. */
  278. /* suppress unused variable warnings */
  279. (void) sampleRate;
  280. return paFormatIsSupported;
  281. }
  282. /* PaSkeletonStream - a stream data structure specifically for this implementation */
  283. typedef struct PaSkeletonStream
  284. { /* IMPLEMENT ME: rename this */
  285. PaUtilStreamRepresentation streamRepresentation;
  286. PaUtilCpuLoadMeasurer cpuLoadMeasurer;
  287. PaUtilBufferProcessor bufferProcessor;
  288. /* IMPLEMENT ME:
  289. - implementation specific data goes here
  290. */
  291. unsigned long framesPerHostCallback; /* just an example */
  292. }
  293. PaSkeletonStream;
  294. /* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
  295. static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
  296. PaStream** s,
  297. const PaStreamParameters *inputParameters,
  298. const PaStreamParameters *outputParameters,
  299. double sampleRate,
  300. unsigned long framesPerBuffer,
  301. PaStreamFlags streamFlags,
  302. PaStreamCallback *streamCallback,
  303. void *userData )
  304. {
  305. PaError result = paNoError;
  306. PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
  307. PaSkeletonStream *stream = 0;
  308. unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
  309. int inputChannelCount, outputChannelCount;
  310. PaSampleFormat inputSampleFormat, outputSampleFormat;
  311. PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
  312. if( inputParameters )
  313. {
  314. inputChannelCount = inputParameters->channelCount;
  315. inputSampleFormat = inputParameters->sampleFormat;
  316. /* unless alternate device specification is supported, reject the use of
  317. paUseHostApiSpecificDeviceSpecification */
  318. if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
  319. return paInvalidDevice;
  320. /* check that input device can support inputChannelCount */
  321. if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
  322. return paInvalidChannelCount;
  323. /* validate inputStreamInfo */
  324. if( inputParameters->hostApiSpecificStreamInfo )
  325. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  326. /* IMPLEMENT ME - establish which host formats are available */
  327. hostInputSampleFormat =
  328. PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
  329. }
  330. else
  331. {
  332. inputChannelCount = 0;
  333. inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
  334. }
  335. if( outputParameters )
  336. {
  337. outputChannelCount = outputParameters->channelCount;
  338. outputSampleFormat = outputParameters->sampleFormat;
  339. /* unless alternate device specification is supported, reject the use of
  340. paUseHostApiSpecificDeviceSpecification */
  341. if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
  342. return paInvalidDevice;
  343. /* check that output device can support inputChannelCount */
  344. if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
  345. return paInvalidChannelCount;
  346. /* validate outputStreamInfo */
  347. if( outputParameters->hostApiSpecificStreamInfo )
  348. return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
  349. /* IMPLEMENT ME - establish which host formats are available */
  350. hostOutputSampleFormat =
  351. PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
  352. }
  353. else
  354. {
  355. outputChannelCount = 0;
  356. outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
  357. }
  358. /*
  359. IMPLEMENT ME:
  360. ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )
  361. - check that input device can support inputSampleFormat, or that
  362. we have the capability to convert from outputSampleFormat to
  363. a native format
  364. - check that output device can support outputSampleFormat, or that
  365. we have the capability to convert from outputSampleFormat to
  366. a native format
  367. - if a full duplex stream is requested, check that the combination
  368. of input and output parameters is supported
  369. - check that the device supports sampleRate
  370. - alter sampleRate to a close allowable rate if possible / necessary
  371. - validate suggestedInputLatency and suggestedOutputLatency parameters,
  372. use default values where necessary
  373. */
  374. /* validate platform specific flags */
  375. if( (streamFlags & paPlatformSpecificFlags) != 0 )
  376. return paInvalidFlag; /* unexpected platform specific flag */
  377. stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) );
  378. if( !stream )
  379. {
  380. result = paInsufficientMemory;
  381. goto error;
  382. }
  383. if( streamCallback )
  384. {
  385. PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
  386. &skeletonHostApi->callbackStreamInterface, streamCallback, userData );
  387. }
  388. else
  389. {
  390. PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
  391. &skeletonHostApi->blockingStreamInterface, streamCallback, userData );
  392. }
  393. PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
  394. /* we assume a fixed host buffer size in this example, but the buffer processor
  395. can also support bounded and unknown host buffer sizes by passing
  396. paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
  397. paUtilFixedHostBufferSize below. */
  398. result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
  399. inputChannelCount, inputSampleFormat, hostInputSampleFormat,
  400. outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
  401. sampleRate, streamFlags, framesPerBuffer,
  402. framesPerHostBuffer, paUtilFixedHostBufferSize,
  403. streamCallback, userData );
  404. if( result != paNoError )
  405. goto error;
  406. /*
  407. IMPLEMENT ME: initialise the following fields with estimated or actual
  408. values.
  409. */
  410. stream->streamRepresentation.streamInfo.inputLatency =
  411. PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);
  412. stream->streamRepresentation.streamInfo.outputLatency =
  413. PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);
  414. stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
  415. /*
  416. IMPLEMENT ME:
  417. - additional stream setup + opening
  418. */
  419. stream->framesPerHostCallback = framesPerHostBuffer;
  420. *s = (PaStream*)stream;
  421. return result;
  422. error:
  423. if( stream )
  424. PaUtil_FreeMemory( stream );
  425. return result;
  426. }
  427. /*
  428. ExampleHostProcessingLoop() illustrates the kind of processing which may
  429. occur in a host implementation.
  430. */
  431. static void ExampleHostProcessingLoop( void *inputBuffer, void *outputBuffer, void *userData )
  432. {
  433. PaSkeletonStream *stream = (PaSkeletonStream*)userData;
  434. PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
  435. int callbackResult;
  436. unsigned long framesProcessed;
  437. PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
  438. /*
  439. IMPLEMENT ME:
  440. - generate timing information
  441. - handle buffer slips
  442. */
  443. /*
  444. If you need to byte swap or shift inputBuffer to convert it into a
  445. portaudio format, do it here.
  446. */
  447. PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );
  448. /*
  449. depending on whether the host buffers are interleaved, non-interleaved
  450. or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
  451. PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
  452. */
  453. PaUtil_SetInputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
  454. PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
  455. 0, /* first channel of inputBuffer is channel 0 */
  456. inputBuffer,
  457. 0 ); /* 0 - use inputChannelCount passed to init buffer processor */
  458. PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
  459. PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
  460. 0, /* first channel of outputBuffer is channel 0 */
  461. outputBuffer,
  462. 0 ); /* 0 - use outputChannelCount passed to init buffer processor */
  463. /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
  464. in general you would pass paContinue for normal operation, and
  465. paComplete to drain the buffer processor's internal output buffer.
  466. You can check whether the buffer processor's output buffer is empty
  467. using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
  468. */
  469. callbackResult = paContinue;
  470. framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
  471. /*
  472. If you need to byte swap or shift outputBuffer to convert it to
  473. host format, do it here.
  474. */
  475. PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
  476. if( callbackResult == paContinue )
  477. {
  478. /* nothing special to do */
  479. }
  480. else if( callbackResult == paAbort )
  481. {
  482. /* IMPLEMENT ME - finish playback immediately */
  483. /* once finished, call the finished callback */
  484. if( stream->streamRepresentation.streamFinishedCallback != 0 )
  485. stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
  486. }
  487. else
  488. {
  489. /* User callback has asked us to stop with paComplete or other non-zero value */
  490. /* IMPLEMENT ME - finish playback once currently queued audio has completed */
  491. /* once finished, call the finished callback */
  492. if( stream->streamRepresentation.streamFinishedCallback != 0 )
  493. stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
  494. }
  495. }
  496. /*
  497. When CloseStream() is called, the multi-api layer ensures that
  498. the stream has already been stopped or aborted.
  499. */
  500. static PaError CloseStream( PaStream* s )
  501. {
  502. PaError result = paNoError;
  503. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  504. /*
  505. IMPLEMENT ME:
  506. - additional stream closing + cleanup
  507. */
  508. PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
  509. PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
  510. PaUtil_FreeMemory( stream );
  511. return result;
  512. }
  513. static PaError StartStream( PaStream *s )
  514. {
  515. PaError result = paNoError;
  516. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  517. PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
  518. /* IMPLEMENT ME, see portaudio.h for required behavior */
  519. /* suppress unused function warning. the code in ExampleHostProcessingLoop or
  520. something similar should be implemented to feed samples to and from the
  521. host after StartStream() is called.
  522. */
  523. (void) ExampleHostProcessingLoop;
  524. return result;
  525. }
  526. static PaError StopStream( PaStream *s )
  527. {
  528. PaError result = paNoError;
  529. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  530. /* suppress unused variable warnings */
  531. (void) stream;
  532. /* IMPLEMENT ME, see portaudio.h for required behavior */
  533. return result;
  534. }
  535. static PaError AbortStream( PaStream *s )
  536. {
  537. PaError result = paNoError;
  538. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  539. /* suppress unused variable warnings */
  540. (void) stream;
  541. /* IMPLEMENT ME, see portaudio.h for required behavior */
  542. return result;
  543. }
  544. static PaError IsStreamStopped( PaStream *s )
  545. {
  546. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  547. /* suppress unused variable warnings */
  548. (void) stream;
  549. /* IMPLEMENT ME, see portaudio.h for required behavior */
  550. return 0;
  551. }
  552. static PaError IsStreamActive( PaStream *s )
  553. {
  554. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  555. /* suppress unused variable warnings */
  556. (void) stream;
  557. /* IMPLEMENT ME, see portaudio.h for required behavior */
  558. return 0;
  559. }
  560. static PaTime GetStreamTime( PaStream *s )
  561. {
  562. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  563. /* suppress unused variable warnings */
  564. (void) stream;
  565. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  566. return 0;
  567. }
  568. static double GetStreamCpuLoad( PaStream* s )
  569. {
  570. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  571. return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
  572. }
  573. /*
  574. As separate stream interfaces are used for blocking and callback
  575. streams, the following functions can be guaranteed to only be called
  576. for blocking streams.
  577. */
  578. static PaError ReadStream( PaStream* s,
  579. void *buffer,
  580. unsigned long frames )
  581. {
  582. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  583. /* suppress unused variable warnings */
  584. (void) buffer;
  585. (void) frames;
  586. (void) stream;
  587. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  588. return paNoError;
  589. }
  590. static PaError WriteStream( PaStream* s,
  591. const void *buffer,
  592. unsigned long frames )
  593. {
  594. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  595. /* suppress unused variable warnings */
  596. (void) buffer;
  597. (void) frames;
  598. (void) stream;
  599. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  600. return paNoError;
  601. }
  602. static signed long GetStreamReadAvailable( PaStream* s )
  603. {
  604. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  605. /* suppress unused variable warnings */
  606. (void) stream;
  607. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  608. return 0;
  609. }
  610. static signed long GetStreamWriteAvailable( PaStream* s )
  611. {
  612. PaSkeletonStream *stream = (PaSkeletonStream*)s;
  613. /* suppress unused variable warnings */
  614. (void) stream;
  615. /* IMPLEMENT ME, see portaudio.h for required behavior*/
  616. return 0;
  617. }