AUD_StreamBuffering.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*****************************************************************************
  19. ** **
  20. ** Westwood Studios Pacific. **
  21. ** **
  22. ** Confidential Information **
  23. ** Copyright (C) 2000 - All Rights Reserved **
  24. ** **
  25. ******************************************************************************
  26. ** **
  27. ** Project: Dune Emperor **
  28. ** **
  29. ** Module: <module> (<prefix>_) **
  30. ** **
  31. ** Version: $ID$ **
  32. ** **
  33. ** File name: audstrm.cpp **
  34. ** **
  35. ** Created by: 11/10/95 TR **
  36. ** **
  37. ** Description: <description> **
  38. ** **
  39. *****************************************************************************/
  40. /*****************************************************************************
  41. ** Includes **
  42. *****************************************************************************/
  43. #include <memory.h>
  44. #include <wpaudio/altypes.h>
  45. #include <wpaudio/list.h>
  46. #include <wpaudio/StreamBuffering.h>
  47. #include <wpaudio/memory.h>
  48. #include <wsys/file.h>
  49. // 'assignment within condition expression'.
  50. #pragma warning(disable : 4706)
  51. DBG_DECLARE_TYPE ( STM_SBUFFER )
  52. DBG_DECLARE_TYPE ( STM_ACCESS )
  53. DBG_DECLARE_TYPE ( STM_STREAM )
  54. /*****************************************************************************
  55. ** Externals **
  56. *****************************************************************************/
  57. /*****************************************************************************
  58. ** Defines **
  59. *****************************************************************************/
  60. /*****************************************************************************
  61. ** Private Types **
  62. *****************************************************************************/
  63. /*****************************************************************************
  64. ** Private Data **
  65. *****************************************************************************/
  66. /*****************************************************************************
  67. ** Public Data **
  68. *****************************************************************************/
  69. /*****************************************************************************
  70. ** Private Prototypes **
  71. *****************************************************************************/
  72. static STM_SBUFFER* STM_next_sbuffer ( STM_SBUFFER * sbuf );
  73. static void STM_stream_init ( STM_STREAM * stm );
  74. static void STM_stream_reset ( STM_STREAM * stm );
  75. static void STM_access_init ( STM_STREAM * stm, STM_ACCESS *access, int id );
  76. static void STM_access_reset ( STM_ACCESS *access, STM_SBUFFER *first );
  77. static void STM_access_return_to_start ( STM_ACCESS *access );
  78. static void STM_sbuffer_init ( STM_SBUFFER * buf );
  79. static void STM_sbuffer_reset( STM_SBUFFER *sbuf );
  80. /*****************************************************************************
  81. ** Private Functions **
  82. *****************************************************************************/
  83. /******************************************************************/
  84. /* */
  85. /* */
  86. /******************************************************************/
  87. static STM_SBUFFER* STM_next_sbuffer ( STM_SBUFFER * sbuf )
  88. {
  89. STM_STREAM *stm;
  90. STM_SBUFFER *head;
  91. DBG_Function ("STM_next_sbuffer");
  92. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  93. stm = sbuf->stream;
  94. head = (STM_SBUFFER *) &stm->buffer_list;
  95. sbuf = (STM_SBUFFER *)sbuf->nd.next;
  96. if ( sbuf == head )
  97. {
  98. sbuf = (STM_SBUFFER *)sbuf->nd.next;
  99. if (sbuf == head )
  100. {
  101. return NULL;
  102. }
  103. }
  104. return sbuf;
  105. }
  106. /******************************************************************/
  107. /* */
  108. /* */
  109. /******************************************************************/
  110. static void STM_stream_init ( STM_STREAM * stm )
  111. {
  112. int i;
  113. /*DBG_Function ("STM_stream_init"); */
  114. DBG_SET_TYPE ( stm, STM_STREAM );
  115. ListInit ( &stm->buffer_list );
  116. LockInit ( &stm->ref );
  117. /* init access structs */
  118. for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
  119. {
  120. STM_access_init ( stm, &stm->access[i], i );
  121. }
  122. }
  123. /******************************************************************/
  124. /* */
  125. /* */
  126. /******************************************************************/
  127. void STM_stream_reset( STM_STREAM* stm )
  128. {
  129. STM_SBUFFER *head,
  130. *first,
  131. *buf;
  132. DBG_Function ("STM_StreamReset");
  133. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  134. head = (STM_SBUFFER *) &stm->buffer_list;
  135. if ( (first = (STM_SBUFFER *) head->nd.next) == head )
  136. {
  137. first = NULL;
  138. }
  139. if ( first ) /* there is at least one buffer */
  140. {
  141. int id = 0;
  142. buf = first;
  143. while ( buf != head )
  144. {
  145. STM_sbuffer_reset ( buf );
  146. buf->id = id++;
  147. buf = (STM_SBUFFER *) buf->nd.next;
  148. }
  149. }
  150. { /* reset the access interfaces */
  151. int i;
  152. for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
  153. {
  154. STM_access_reset ( &stm->access[i], first );
  155. }
  156. /* kick start the IN accessor */
  157. stm->access[vSTM_ACCESS_ID_IN].bytes_in += stm->bytes;
  158. }
  159. }
  160. /******************************************************************/
  161. /* */
  162. /* */
  163. /******************************************************************/
  164. static void STM_access_init ( STM_STREAM * stm, STM_ACCESS *access, int id )
  165. {
  166. DBG_Function ("STM_access_init");
  167. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  168. DBG_SET_TYPE ( access, STM_ACCESS );
  169. access->stream = stm;
  170. DBG_CODE
  171. (
  172. LockInit ( &access->in_service ); /* we use the ref to stop nesting */
  173. )
  174. LockInit ( &access->ref );
  175. access->last_error = vNO_ERROR;
  176. access->id = id;
  177. access->mode = vSTM_ACCESS_MODE_UPDATE;
  178. }
  179. /******************************************************************/
  180. /* */
  181. /* */
  182. /******************************************************************/
  183. static void STM_access_reset( STM_ACCESS *access, STM_SBUFFER *first )
  184. {
  185. DBG_Function ("STM_access_reset");
  186. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  187. access->start_buffer = first;
  188. access->bytes_in = W_UINT_MAX -1000;
  189. access->bytes_out = access->bytes_in;
  190. access->position = 0;
  191. STM_access_return_to_start ( access );
  192. }
  193. /******************************************************************/
  194. /* */
  195. /* */
  196. /******************************************************************/
  197. static void STM_access_return_to_start ( STM_ACCESS *access )
  198. {
  199. access->access_pos = 0;
  200. access->SBuffer = access->start_buffer;
  201. if ( access->start_buffer )
  202. {
  203. access->Block.Data = access->start_buffer->region[access->id].Data;
  204. }
  205. else
  206. {
  207. access->Block.Data = NULL;
  208. }
  209. access->Block.Bytes = 0;
  210. W_FlagsClear ( access->flags, mSTM_ACCESS_TOP_OF_START);
  211. }
  212. /******************************************************************/
  213. /* */
  214. /* */
  215. /******************************************************************/
  216. static void STM_sbuffer_init ( STM_SBUFFER *buf )
  217. {
  218. DBG_SET_TYPE ( buf, STM_SBUFFER );
  219. ListNodeInit ( &buf->nd );
  220. }
  221. /******************************************************************/
  222. /* */
  223. /* */
  224. /******************************************************************/
  225. static void STM_sbuffer_reset( STM_SBUFFER *sbuf )
  226. {
  227. int i;
  228. DBG_Function ("STM_sbuffer_reset");
  229. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  230. /* init access structs */
  231. for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
  232. {
  233. sbuf->region[i].Data = sbuf->data_region.Data;
  234. sbuf->region[i].Bytes = sbuf->data_region.Bytes;
  235. }
  236. }
  237. /*****************************************************************************
  238. ** Public Functions **
  239. *****************************************************************************/
  240. /******************************************************************/
  241. /* */
  242. /* */
  243. /******************************************************************/
  244. STM_STREAM* STM_StreamCreate( void )
  245. {
  246. STM_STREAM *stm;
  247. DBG_Function ("STM_StreamCreate");
  248. MEM_ALLOC_STRUCT ( stm, STM_STREAM, mMEM_INTERNAL| vMEM_ANY );
  249. STM_stream_init ( stm );
  250. /* that was simple ;-) */
  251. return stm;
  252. }
  253. /******************************************************************/
  254. /* */
  255. /* */
  256. /******************************************************************/
  257. void STM_StreamDestroy( STM_STREAM* stm )
  258. {
  259. DBG_Function ("STM_StreamDestroy");
  260. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  261. DBG_ASSERT ( ! (stm->flags & mSTM_STREAM_FAKE )); /* you can not destroy a fake stream */
  262. DBG_ASSERT ( !Locked ( &stm->ref) ); /* you are trying to destroy a stream that is still being accessed */
  263. STM_StreamDestroyBuffers ( stm );
  264. DBG_CODE
  265. (
  266. int i;
  267. for ( i = 0; i < vSTM_MAX_ACCESSORS; i++)
  268. {
  269. DBG_INVALIDATE_TYPE ( &stm->access[i] ); /* ensure that nobody tries to use an accessor after it is dead */
  270. }
  271. )
  272. DBG_INVALIDATE_TYPE ( stm );
  273. MEM_Free ( stm );
  274. }
  275. /******************************************************************/
  276. /* */
  277. /* */
  278. /******************************************************************/
  279. void STM_StreamDestroyBuffers( STM_STREAM* stm )
  280. {
  281. STM_SBUFFER *buf,
  282. *head;
  283. DBG_Function ("STM_StreamDestroy");
  284. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  285. DBG_ASSERT ( !Locked ( &stm->ref) ); /* you are trying to destroy a stream that is still being accessed */
  286. head = (STM_SBUFFER *) &stm->buffer_list;
  287. while ( ( buf = (STM_SBUFFER *) head->nd.next) != head )
  288. {
  289. STM_SBufferRemove ( buf );
  290. STM_SBufferDestroy ( buf );
  291. }
  292. STM_StreamReset ( stm );
  293. }
  294. /******************************************************************/
  295. /* */
  296. /* */
  297. /******************************************************************/
  298. void STM_StreamReset( STM_STREAM* stm )
  299. {
  300. DBG_Function ("STM_StreamReset");
  301. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  302. DBG_ASSERT ( !Locked ( &stm->ref )); /* you cannot reset the stream will it's in use */
  303. STM_stream_reset ( stm );
  304. }
  305. /******************************************************************/
  306. /* */
  307. /* */
  308. /******************************************************************/
  309. void STM_StreamAddSBuffer( STM_STREAM* stm, STM_SBUFFER *sbuf )
  310. {
  311. DBG_Function ("STM_StreamAddSBuffer");
  312. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  313. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  314. DBG_ASSERT ( !(ListNodeInList ( &sbuf->nd ))); /* buffer is already in a list */
  315. ListNodeAppend ( (ListNode *) &stm->buffer_list, &sbuf->nd );
  316. stm->buffers++;
  317. stm->bytes += sbuf->data_region.Bytes;
  318. sbuf->stream = stm;
  319. W_FlagsClear ( stm->flags, mSTM_STREAM_RESET_DONE ); /* make sure that a reset is performed again */
  320. }
  321. /******************************************************************/
  322. /* */
  323. /* */
  324. /******************************************************************/
  325. int STM_StreamCreateSBuffers( STM_STREAM* stm, int num_buffers, int buf_size, int align )
  326. {
  327. int bcount = 0;
  328. STM_SBUFFER *buf;
  329. DBG_Function ("STM_StreamAddBuffers");
  330. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  331. DBG_ASSERT ( num_buffers > 0 );
  332. DBG_ASSERT ( buf_size > 0 );
  333. DBG_ASSERT ( align >= 0 );
  334. while (num_buffers--)
  335. {
  336. if (! (buf = STM_SBufferCreate ( buf_size, align )))
  337. {
  338. break;
  339. }
  340. STM_StreamAddSBuffer ( stm, buf );
  341. bcount++;
  342. }
  343. return bcount;
  344. }
  345. /******************************************************************/
  346. /* */
  347. /* */
  348. /******************************************************************/
  349. STM_ACCESS* STM_StreamAcquireAccess ( STM_STREAM *stm, int access_id )
  350. {
  351. STM_ACCESS *access;
  352. DBG_Function ("STM_StreamAcquireAccess");
  353. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  354. DBG_ASSERT ( access_id >= 0); /* ilegal value */
  355. DBG_ASSERT ( access_id < vSTM_MAX_ACCESSORS ); /* legal values are vSTM_ACCESS_ID_OUT or vSTM_ACCESS_ID_IN */
  356. access = &stm->access[access_id];
  357. if ( Locked ( &access->ref ) ) /* someone has already acquired access */
  358. {
  359. DBGPRINTF (( "%s access to stream failed. Access already acquired.\n",access->id == vSTM_ACCESS_ID_IN ? "Write" : "Read" ));
  360. return NULL;
  361. }
  362. DBG_CODE
  363. (
  364. if ( !stm->buffers)
  365. {
  366. msg_assert ( FALSE, ( "Trying to acquire a stream with no buffers") );
  367. }
  368. ) /* you must add at least one buffer to a stream before you can use it */
  369. /* if this is the first time the stream has been acquired then perform a reset on the buffers */
  370. if ( !Locked ( &stm->ref ) )
  371. {
  372. STM_stream_reset ( stm );
  373. }
  374. LockAcquire ( &access->ref ); /* mark access interface as in use */
  375. LockAcquire ( &stm->ref ); /* mark stream as in use */
  376. return access;
  377. }
  378. /******************************************************************/
  379. /* */
  380. /* */
  381. /******************************************************************/
  382. uint STM_StreamTotalBytesIn ( STM_STREAM *stm )
  383. {
  384. DBG_Function ("STM_StreamTotalBytesIn");
  385. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  386. return STM_AccessTotalBytes (&stm->access[vSTM_ACCESS_ID_OUT]);
  387. }
  388. /******************************************************************/
  389. /* */
  390. /* */
  391. /******************************************************************/
  392. uint STM_StreamTotalBytesTillFull ( STM_STREAM *stm )
  393. {
  394. DBG_Function ("STM_StreamTotalBytesTillFull");
  395. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  396. return STM_AccessTotalBytes (&stm->access[vSTM_ACCESS_ID_IN]);
  397. }
  398. /******************************************************************/
  399. /* */
  400. /* */
  401. /******************************************************************/
  402. uint STM_StreamTotalBytes ( STM_STREAM *stm )
  403. {
  404. DBG_Function ("STM_StreamTotalBytes");
  405. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  406. return stm->bytes;
  407. }
  408. /******************************************************************/
  409. /* */
  410. /* */
  411. /******************************************************************/
  412. int STM_StreamFull ( STM_STREAM *stm )
  413. {
  414. DBG_Function ("STM_StreamFull");
  415. DBG_ASSERT_TYPE ( stm, STM_STREAM );
  416. return STM_StreamTotalBytesTillFull( stm ) == 0;
  417. }
  418. /******************************************************************/
  419. /* */
  420. /* */
  421. /******************************************************************/
  422. STM_SBUFFER* STM_SBufferCreate( int bytes, int align )
  423. {
  424. STM_SBUFFER *buf;
  425. DBG_Function ("STM_SBufferCreate");
  426. DBG_ASSERT ( bytes > 0 );
  427. DBG_ASSERT ( align >= 0 );
  428. MEM_ALLOC_STRUCT ( buf, STM_SBUFFER, mMEM_INTERNAL | vMEM_ANY );
  429. DBG_SET_TYPE ( buf, STM_SBUFFER );
  430. STM_sbuffer_init ( buf );
  431. /* allocate the buffer, add space for alignment */
  432. buf->buffer_memory = (uint8 *) AudioMemAlloc ( bytes + ALIGN_UPBY(1,align));
  433. if ( !buf->buffer_memory )
  434. {
  435. goto error;
  436. }
  437. buf->align = align;
  438. buf->data_region.Data = ( uint8 *)ALIGN_UPBY ( buf->buffer_memory, align);
  439. buf->data_region.Bytes = bytes;
  440. return buf;
  441. error:
  442. if ( buf )
  443. {
  444. STM_SBufferDestroy ( buf );
  445. }
  446. return NULL;
  447. }
  448. /******************************************************************/
  449. /* */
  450. /* */
  451. /******************************************************************/
  452. void STM_SBufferDestroy( STM_SBUFFER *sbuf )
  453. {
  454. DBG_Function ("STM_SBufferDestroy");
  455. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  456. DBG_ASSERT ( !ListNodeInList( &sbuf->nd )); /* you must remove the buffer from its stream */
  457. if ( sbuf->buffer_memory )
  458. {
  459. MEM_Free ( sbuf->buffer_memory );
  460. }
  461. DBG_INVALIDATE_TYPE ( sbuf );
  462. MEM_Free ( sbuf );
  463. }
  464. /******************************************************************/
  465. /* */
  466. /* */
  467. /******************************************************************/
  468. void STM_SBufferRemove( STM_SBUFFER *sbuf )
  469. {
  470. STM_STREAM *stm;
  471. DBG_Function ("STM_SBufferRemove");
  472. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  473. DBG_ASSERT ( ListNodeInList ( &sbuf->nd )); /* buffer is not presently in a stream */
  474. DBG_ASSERT ( sbuf->stream != NULL ); /* bad data */
  475. DBG_ASSERT ( !Locked ( &sbuf->stream->ref)); /* stream is in use */
  476. ListNodeRemove ( &sbuf->nd );
  477. stm = sbuf->stream;
  478. sbuf->stream = NULL;
  479. stm->buffers--;
  480. stm->bytes -= sbuf->data_region.Bytes;
  481. DBG_ASSERT ( stm->bytes >= 0 ); /* somethings gone very wrong */
  482. DBG_ASSERT ( stm->buffers >= 0 ); /* somethings gone very wrong */
  483. W_FlagsClear ( stm->flags, mSTM_STREAM_RESET_DONE ); /* make sure that a reset is performed again */
  484. }
  485. /******************************************************************/
  486. /* */
  487. /* */
  488. /******************************************************************/
  489. STM_SBUFFER* STM_SBufferNext( STM_SBUFFER *sbuf )
  490. {
  491. DBG_Function ("STM_SBufferNext");
  492. DBG_ASSERT_TYPE ( sbuf, STM_SBUFFER );
  493. DBG_ASSERT ( sbuf->stream != NULL ); /* buffer is not currently in a stream */
  494. return STM_next_sbuffer ( sbuf );
  495. }
  496. /******************************************************************/
  497. /* */
  498. /* */
  499. /******************************************************************/
  500. void STM_AccessRelease ( STM_ACCESS *access )
  501. {
  502. DBG_Function ("STM_AccessRelease");
  503. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  504. DBG_ASSERT ( Locked ( &access->ref ) ); /* already released, or was never acquired */
  505. LockRelease ( &access->ref );
  506. LockRelease ( &access->stream->ref );
  507. }
  508. /******************************************************************/
  509. /* */
  510. /* */
  511. /******************************************************************/
  512. int STM_AccessSetMode ( STM_ACCESS *access, int mode )
  513. {
  514. DBG_Function ("STM_AccessSetMode");
  515. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  516. DBG_ASSERT ( mode >= 0 ); /* invalid mode */
  517. DBG_ASSERT ( mode < vSTM_ACCESS_MAX_MODES ); /* see vSTM_ACCESS_MODE_?? in wcore/stream.h */
  518. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  519. access->mode = mode;
  520. return vNO_ERROR;
  521. }
  522. /******************************************************************/
  523. /* */
  524. /* */
  525. /******************************************************************/
  526. int STM_AccessMode ( STM_ACCESS *access )
  527. {
  528. DBG_Function ("STM_AccessMode");
  529. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  530. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  531. return access->mode;
  532. }
  533. /******************************************************************/
  534. /* */
  535. /* */
  536. /******************************************************************/
  537. int STM_AccessID ( STM_ACCESS *access )
  538. {
  539. DBG_Function ("STM_AccessID");
  540. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  541. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  542. return access->id;
  543. }
  544. /******************************************************************/
  545. /* */
  546. /* */
  547. /******************************************************************/
  548. int STM_AccessTransfer( STM_ACCESS* access, void *data, int bytes )
  549. {
  550. int transfer,
  551. transfered = 0;
  552. uint8 *data8;
  553. DBG_Function ("STM_AccessTransfer");
  554. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  555. DBG_ASSERT ( data != NULL );
  556. DBG_ASSERT ( bytes > 0);
  557. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  558. data8 = (uint8 *) data;
  559. STM_AccessGetBlock ( access );
  560. do
  561. {
  562. /* how much can we transfer this block */
  563. if ( (transfer = access->Block.Bytes) > bytes )
  564. {
  565. transfer = bytes;
  566. }
  567. if ( !transfer )
  568. {
  569. break; /* stream has been exhuasted */
  570. }
  571. /* do the transfer */
  572. switch ( access->id )
  573. {
  574. case vSTM_ACCESS_ID_IN:
  575. {
  576. memcpy ( access->Block.Data, data8, transfer );
  577. break;
  578. }
  579. case vSTM_ACCESS_ID_OUT:
  580. default: /* all accessor default to out */
  581. {
  582. memcpy ( data8, access->Block.Data, transfer );
  583. break;
  584. }
  585. }
  586. /* advance pointers */
  587. STM_AccessAdvance ( access, transfer );
  588. data8 += transfer;
  589. /* record work done */
  590. bytes -= transfer;
  591. transfered += transfer;
  592. } while ( bytes );
  593. return transfered;
  594. }
  595. /******************************************************************/
  596. /* */
  597. /* */
  598. /******************************************************************/
  599. int STM_AccessFileTransfer( STM_ACCESS* access, File *file, int bytes, int *transfered)
  600. {
  601. int transfer;
  602. DBG_Function ("STM_AccessFileTransfer");
  603. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  604. DBG_ASSERT ( file != NULL );
  605. DBG_ASSERT ( bytes >= 0);
  606. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  607. STM_AccessGetBlock ( access );
  608. int dummy;
  609. if ( !transfered )
  610. {
  611. transfered = &dummy;
  612. }
  613. *transfered = 0;
  614. do
  615. {
  616. if ( (transfer = access->Block.Bytes) > bytes )
  617. {
  618. transfer = bytes;
  619. }
  620. if ( !transfer )
  621. {
  622. break; /* stream has been exhuasted */
  623. }
  624. switch ( access->id )
  625. {
  626. case vSTM_ACCESS_ID_IN:
  627. {
  628. transfer = file->read ( access->Block.Data, transfer );
  629. if ( transfer < 0 )
  630. {
  631. access->last_error = ERROR_CODE_FAIL;
  632. }
  633. break;
  634. }
  635. case vSTM_ACCESS_ID_OUT:
  636. default: /* all accessor default to out */
  637. {
  638. transfer = file->write ( access->Block.Data, transfer );
  639. if ( transfer < 0 )
  640. {
  641. access->last_error = ERROR_CODE_FAIL;
  642. }
  643. break;
  644. }
  645. }
  646. if ( !transfer )
  647. {
  648. return STM_EOF;
  649. }
  650. if ( transfer == -1 )
  651. {
  652. return STM_FAIL;
  653. }
  654. /* do the transfer */
  655. STM_AccessAdvance ( access, transfer );
  656. bytes -= transfer;
  657. *transfered += transfer;
  658. } while ( bytes );
  659. return STM_OK;
  660. }
  661. /******************************************************************/
  662. /* */
  663. /* */
  664. /******************************************************************/
  665. int STM_AccessGetError ( STM_ACCESS *access )
  666. {
  667. DBG_Function ("STM_AccessGetError");
  668. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  669. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  670. return access->last_error;
  671. }
  672. /******************************************************************/
  673. /* */
  674. /* */
  675. /******************************************************************/
  676. int STM_AccessUpdate ( STM_ACCESS *access )
  677. {
  678. STM_SBUFFER *sbuf;
  679. int bytes_to_update;
  680. int bytes_updated;
  681. STM_ACCESS *up_stream_accessor;
  682. DBG_Function ("STM_AccessUpdate");
  683. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  684. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  685. if ( (bytes_to_update = access->access_pos ) == 0)
  686. {
  687. return 0; /* no updating to perform */
  688. }
  689. /* first thing to do is to tell the up stream accessor that there is more
  690. buffer area avaiable for him to process */
  691. up_stream_accessor = STM_AccessUpStreamAccessor ( access );
  692. access->bytes_out += bytes_to_update; /* reduce our byte count accordingly */
  693. up_stream_accessor->bytes_in += bytes_to_update;
  694. /* now move our start buffer to its new posistion */
  695. sbuf = access->start_buffer ;
  696. DBG_ASSERT ( sbuf != NULL ); /* fubar */
  697. bytes_updated = bytes_to_update;
  698. do
  699. {
  700. STM_REGION *region;
  701. region = &sbuf->region[access->id];
  702. if ( region->Bytes <= bytes_to_update )
  703. {
  704. bytes_to_update -= region->Bytes;
  705. /* reset the current sbuffer region and move on to the next */
  706. region->Data = sbuf->data_region.Data; /* reset back to top of buffer */
  707. region->Bytes = sbuf->data_region.Bytes;
  708. sbuf = STM_next_sbuffer ( sbuf );
  709. }
  710. else
  711. {
  712. /* adjust start of data pointer and bytes accordingly */
  713. region->Data += bytes_to_update;
  714. region->Bytes -= bytes_to_update;
  715. bytes_to_update = 0; /* no more bytes to up date */
  716. }
  717. } while ( bytes_to_update );
  718. access->start_buffer = sbuf; /* update to new start buffer */
  719. STM_AccessReturnToStart ( access ); /* resycn access */
  720. return bytes_updated;
  721. }
  722. /******************************************************************/
  723. /* */
  724. /* */
  725. /******************************************************************/
  726. int STM_AccessAdvance ( STM_ACCESS *access, int bytes_to_advance )
  727. {
  728. int bytes_advanced = 0,
  729. bytes_available,
  730. advance;
  731. int total_bytes;
  732. int ok = TRUE;
  733. DBG_Function ("STM_AccessAdvance");
  734. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  735. DBG_ASSERT ( bytes_to_advance >= 0);
  736. total_bytes = STM_AccessTotalBytes ( access );
  737. DBG_ASSERT ( access->access_pos <= total_bytes );
  738. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  739. if ( (bytes_available = total_bytes - access->access_pos ) == 0)
  740. {
  741. /* we are at the end of the data */
  742. access->Block.Bytes = 0;
  743. return 0;
  744. }
  745. DBG_ASSERT ( bytes_available >= 0 );
  746. if ( bytes_available < bytes_to_advance )
  747. {
  748. bytes_to_advance = bytes_available;
  749. }
  750. DBG_ASSERT ( access->SBuffer != NULL ); /* fubar */
  751. do
  752. {
  753. STM_REGION *buf_region;
  754. buf_region = &access->SBuffer->region[access->id];
  755. /* update block Bytes to real value */
  756. if ( access->flags & mSTM_ACCESS_TOP_OF_START )
  757. {
  758. access->Block.Bytes = bytes_available; /* this must be a valid range as total_bytes
  759. cannot be greater then the total stream bytes */
  760. }
  761. else
  762. {
  763. int actual_bytes =buf_region->Bytes - ( (uint) access->Block.Data - (uint) buf_region->Data );
  764. if ( actual_bytes < bytes_available )
  765. {
  766. access->Block.Bytes = actual_bytes;
  767. }
  768. else
  769. {
  770. access->Block.Bytes = bytes_available;
  771. }
  772. }
  773. /* advance access */
  774. if ( (advance = bytes_to_advance) == 0 )
  775. {
  776. break; /* we are done */
  777. }
  778. if ( advance >= access->Block.Bytes )
  779. {
  780. advance = access->Block.Bytes;
  781. /* move on to next buffer */
  782. access->SBuffer = STM_next_sbuffer ( access->SBuffer );
  783. if ( access->SBuffer == access->start_buffer )
  784. {
  785. /* this is a special case where we have come back round
  786. to the start buffer. This means that area we are interested in
  787. the area at the top of the buffer */
  788. W_FlagsSet ( access->flags, mSTM_ACCESS_TOP_OF_START);
  789. access->Block.Data = access->SBuffer->data_region.Data; /* this is the top of the buffer */
  790. }
  791. else
  792. {
  793. access->Block.Data = access->SBuffer->region[access->id].Data;
  794. }
  795. }
  796. else
  797. {
  798. access->Block.Data += advance;
  799. }
  800. bytes_to_advance -= advance;
  801. bytes_advanced += advance;
  802. bytes_available -= advance;
  803. } while ( ok );
  804. access->access_pos += bytes_advanced; /* update our position */
  805. access->position += bytes_advanced;
  806. if ( access->position >= STM_StreamTotalBytes(access->stream) )
  807. {
  808. access->position = access->position % STM_StreamTotalBytes ( access->stream );
  809. }
  810. if ( (access->access_pos )&& (STM_AccessMode ( access ) == vSTM_ACCESS_MODE_UPDATE) )
  811. {
  812. STM_AccessUpdate ( access );
  813. }
  814. return bytes_advanced;
  815. }
  816. /******************************************************************/
  817. /* */
  818. /* */
  819. /******************************************************************/
  820. void STM_AccessReturnToStart ( STM_ACCESS *access )
  821. {
  822. DBG_Function ("STM_AccessReturnToStart");
  823. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  824. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  825. STM_access_return_to_start ( access );
  826. STM_AccessAdvance ( access, 0 ); /* make sure data block is valid */
  827. }
  828. /******************************************************************/
  829. /* */
  830. /* */
  831. /******************************************************************/
  832. int STM_AccessNextBlock ( STM_ACCESS *access )
  833. {
  834. DBG_Function ("STM_AccessNextBlock");
  835. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  836. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  837. STM_AccessGetBlock ( access );
  838. if ( access->Block.Bytes )
  839. {
  840. STM_AccessAdvance ( access, access->Block.Bytes );
  841. }
  842. return ERROR_CODE_FAIL;
  843. }
  844. /******************************************************************/
  845. /* */
  846. /* */
  847. /******************************************************************/
  848. int STM_AccessGetBlock ( STM_ACCESS *access )
  849. {
  850. DBG_Function ("STM_AccessGetBlock");
  851. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  852. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  853. STM_AccessAdvance ( access, 0 ); /* kick start access */
  854. return access->Block.Bytes;
  855. }
  856. /******************************************************************/
  857. /* */
  858. /* */
  859. /******************************************************************/
  860. uint STM_AccessTotalBytes ( STM_ACCESS *access )
  861. {
  862. uint total_bytes,
  863. bytes_in,
  864. bytes_out;
  865. DBG_Function ("STM_AccessTotalBytes");
  866. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  867. bytes_in = access->bytes_in;
  868. bytes_out = access->bytes_out;
  869. if ( (bytes_in < bytes_out))
  870. {
  871. total_bytes = (W_UINT_MAX - bytes_out) +1 + bytes_in;
  872. }
  873. else
  874. {
  875. total_bytes = bytes_in - bytes_out;
  876. }
  877. return total_bytes;
  878. }
  879. /******************************************************************/
  880. /* */
  881. /* */
  882. /******************************************************************/
  883. uint STM_AccessPosition ( STM_ACCESS *access )
  884. {
  885. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  886. return access->position;
  887. }
  888. /******************************************************************/
  889. /* */
  890. /* */
  891. /******************************************************************/
  892. STM_ACCESS* STM_AccessUpStreamAccessor ( STM_ACCESS *access )
  893. {
  894. int id;
  895. DBG_Function ("STM_AccessUpStreamAccessor");
  896. DBG_ASSERT_TYPE ( access, STM_ACCESS );
  897. DBG_ASSERT ( access->id >= 0 );
  898. DBG_ASSERT ( access->id < vSTM_MAX_ACCESSORS ); /* something has gone wrong. id should not be out of range */
  899. DBG_ASSERT ( Locked ( &access->ref ) ); /* you did not re-acquired access*/
  900. if ( (id = access->id + 1 ) == vSTM_MAX_ACCESSORS )
  901. {
  902. id = 0;
  903. }
  904. return &access->stream->access[id];
  905. }
  906. #ifdef _DEBUG
  907. #include <wpaudio/time.h>
  908. /******************************************************************/
  909. /* */
  910. /* */
  911. /******************************************************************/
  912. void STM_ProfileStart ( STM_PROFILE *pf )
  913. {
  914. DBG_Function ("STM_ProfileStart");
  915. DBG_ASSERT ( pf != NULL );
  916. pf->bytes = 0;
  917. pf->last_update = AudioGetTime ();
  918. pf->update_interval = SECONDS(3);
  919. W_FlagsSet ( pf->flags, mSTM_PROFILE_ACTIVE );
  920. pf->rate = 0;
  921. }
  922. /******************************************************************/
  923. /* */
  924. /* */
  925. /******************************************************************/
  926. void STM_ProfileStop ( STM_PROFILE *pf )
  927. {
  928. DBG_Function ("STM_ProfileStop");
  929. DBG_ASSERT ( pf != NULL );
  930. W_FlagsClear ( pf->flags, mSTM_PROFILE_ACTIVE );
  931. pf->rate = 0;
  932. }
  933. /******************************************************************/
  934. /* */
  935. /* */
  936. /******************************************************************/
  937. void STM_ProfileUpdate ( STM_PROFILE *pf, int bytes )
  938. {
  939. TimeStamp duration;
  940. DBG_Function ("STM_ProfileUpdate");
  941. DBG_ASSERT ( pf != NULL );
  942. if ( pf->flags & mSTM_PROFILE_ACTIVE )
  943. {
  944. duration = AudioGetTime() - pf->last_update;
  945. pf->bytes += bytes;
  946. if ( duration > pf->update_interval )
  947. {
  948. pf->rate = (int) ((pf->bytes * SECONDS(1)) / duration);
  949. pf->last_update = AudioGetTime ();
  950. pf->bytes = 0;
  951. }
  952. }
  953. }
  954. /******************************************************************/
  955. /* */
  956. /* */
  957. /******************************************************************/
  958. int STM_ProfileResult ( STM_PROFILE *pf )
  959. {
  960. DBG_Function ("STM_ProfileResult");
  961. DBG_ASSERT ( pf != NULL );
  962. if ( pf->flags & mSTM_PROFILE_ACTIVE )
  963. {
  964. return pf->rate;
  965. }
  966. return 0;
  967. }
  968. /******************************************************************/
  969. /* */
  970. /* */
  971. /******************************************************************/
  972. int STM_ProfileActive ( STM_PROFILE *pf )
  973. {
  974. return pf->flags & mSTM_PROFILE_ACTIVE ;
  975. }
  976. #endif // _DEBUG