rtplay.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // RtPlay.CPP
  21. //
  22. // History:
  23. // 09/21/95 JMI Started.
  24. //
  25. //////////////////////////////////////////////////////////////////////////////
  26. //
  27. // This class controls the flow of the streaming of a file. By putting this
  28. // at a higher level than the basic read stuff, we have allowed one to write
  29. // their own flow control for a stream that could override or use any of the
  30. // components used by this module (i.e., CFileWin, CFilter, CDispatch, CRes,
  31. // etc.).
  32. //
  33. //////////////////////////////////////////////////////////////////////////////
  34. //
  35. // There are many states that the streaming can be in. The following table
  36. // shows the states that can be changed from/to. It is not necessary to
  37. // handle transitions not in this table (this should make message handler
  38. // logic much simpler) (you may want to use a default: case in your switch,
  39. // if you have one, that displays a warning if you get a transition not in
  40. // this table).
  41. //
  42. // From\To | Stopped | Starting | Begin | Playing | Aborting | Ending | Pause
  43. // ---------+---------+----------+-------+---------+----------+--------+------
  44. // Stopped | -- | Yes | No | No | No | No | No
  45. // Starting | No | -- | Yes | No | Yes | No | No
  46. // Begin | No | No | -- | Yes | Yes | No | No
  47. // Playing | No | No | No | -- | Yes | Yes | Yes
  48. // Aborting | Yes | No | No | No | -- | No | No
  49. // Ending | Yes | No | No | No | Yes | -- | No
  50. // Pause | No | No | No | Yes | Yes | No | --
  51. //
  52. // Currently there are a total of 13 transitions that could be handled by
  53. // your handler.
  54. //
  55. //////////////////////////////////////////////////////////////////////////////
  56. //////////////////////////////////////////////////////////////////////////////
  57. // C Headers.
  58. //////////////////////////////////////////////////////////////////////////////
  59. #include <malloc.h>
  60. //////////////////////////////////////////////////////////////////////////////
  61. // Blue Headers.
  62. //////////////////////////////////////////////////////////////////////////////
  63. #include "System.h"
  64. #include "bdebug.h"
  65. #include "bcritic.h"
  66. //////////////////////////////////////////////////////////////////////////////
  67. // Green Headers.
  68. //////////////////////////////////////////////////////////////////////////////
  69. #include "rtplay.h"
  70. #include "rttypes.h"
  71. //////////////////////////////////////////////////////////////////////////////
  72. // Orange Headers.
  73. //////////////////////////////////////////////////////////////////////////////
  74. //////////////////////////////////////////////////////////////////////////////
  75. // Yellow Headers.
  76. //////////////////////////////////////////////////////////////////////////////
  77. //////////////////////////////////////////////////////////////////////////////
  78. // Module specific macros.
  79. //////////////////////////////////////////////////////////////////////////////
  80. // If behind more than MAX_LAG a TRACE displays how far behind we are in
  81. // debug build only.
  82. #define MAX_LAG 500L // One half second.
  83. // Default size for file window.
  84. #define DEF_WINDOW_SIZE (60L * 1024L)
  85. #define DEF_INPUTPANE_SIZE (20L * 1024L)
  86. #define DEF_FILTERPANE_SIZE (20L * 1024L)
  87. // Commands from the RTF.
  88. #define CMD_INIT 0x0000
  89. #define CMD_SUSPENDREADS 0x0001
  90. #define CMD_RESUMEREADS 0x0002
  91. #define CMD_EOC 0x0003
  92. #define CMD_ENDING 0x0004
  93. #define CMD_STREAMHIT 0x0005
  94. //////////////////////////////////////////////////////////////////////////////
  95. // Module specific typedefs.
  96. //////////////////////////////////////////////////////////////////////////////
  97. //////////////////////////////////////////////////////////////////////////////
  98. // Module specific (static) variables.
  99. //////////////////////////////////////////////////////////////////////////////
  100. //////////////////////////////////////////////////////////////////////////////
  101. // Construction/Destruction Functions.
  102. //////////////////////////////////////////////////////////////////////////////
  103. //////////////////////////////////////////////////////////////////////////////
  104. //
  105. // Default constructor.
  106. //
  107. //////////////////////////////////////////////////////////////////////////////
  108. CRtPlay::CRtPlay()
  109. {
  110. // These values are set only on construction, or by the user.
  111. m_lWindowSize = DEF_WINDOW_SIZE;
  112. m_lInputPaneSize = DEF_INPUTPANE_SIZE;
  113. m_lFilterPaneSize = DEF_FILTERPANE_SIZE;
  114. Set();
  115. }
  116. //////////////////////////////////////////////////////////////////////////////
  117. //
  118. // Destructor.
  119. //
  120. //////////////////////////////////////////////////////////////////////////////
  121. CRtPlay::~CRtPlay()
  122. {
  123. Reset();
  124. }
  125. //////////////////////////////////////////////////////////////////////////////
  126. // Internal Functions.
  127. //////////////////////////////////////////////////////////////////////////////
  128. //////////////////////////////////////////////////////////////////////////////
  129. //
  130. // Sets variables w/o regard to current values.
  131. //
  132. //////////////////////////////////////////////////////////////////////////////
  133. void CRtPlay::Set(void)
  134. {
  135. // Set data handler (where we get direction from the RT file).
  136. m_dispatch.SetDataHandler( RT_TYPE_RTFINFO, RtInfoCallStatic);
  137. m_dispatch.SetUserVal(RT_TYPE_RTFINFO, (long)this);
  138. // Let resource know who the dispatcher is.
  139. m_res.SetDispatcher(&m_dispatch);
  140. // Let dispatcher know who the filter is.
  141. m_dispatch.SetFilter(&m_filter);
  142. // Let dispatcher know what time base to use.
  143. m_dispatch.SetTimeFunc(CRtTime::GetTime, (long)&m_rttime);
  144. // Let filter know who the file window is.
  145. m_filter.SetFileWin(&m_filewin);
  146. // Let file win know what time base to use.
  147. m_filewin.SetTimeFunc(CRtTime::GetTime, (long)&m_rttime);
  148. m_usState = RT_STATE_STOPPED;
  149. }
  150. //////////////////////////////////////////////////////////////////////////////
  151. //
  152. // Resets variables. Performs deallocation if necessary.
  153. //
  154. //////////////////////////////////////////////////////////////////////////////
  155. void CRtPlay::Reset(void)
  156. {
  157. Set();
  158. }
  159. //////////////////////////////////////////////////////////////////////////////
  160. //
  161. // Adds an RT_TYPE_RTFINFO chunk to the dispatcher with the specified command
  162. // and parameters.
  163. // Returns 0 on success.
  164. //
  165. //////////////////////////////////////////////////////////////////////////////
  166. short CRtPlay::CreateCmd(USHORT usCmd, long lTime, long lParm1, long lParm2)
  167. {
  168. short sRes = 0; // Assume success.
  169. long lSize = sizeof(usCmd) + sizeof(lParm1) + sizeof(lParm2);
  170. UCHAR* puc = (UCHAR*)malloc(lSize);
  171. // If successful . . .
  172. if (puc != NULL)
  173. {
  174. CNFile file;
  175. file.Open(puc, lSize, ENDIAN_BIG);
  176. file.Write(&usCmd);
  177. file.Write(&lParm1);
  178. file.Write(&lParm2);
  179. file.Close();
  180. // Send chunk to dispatcher.
  181. if (m_dispatch.AddItem(puc, lSize, RT_TYPE_RTFINFO, 0, lTime) == 0)
  182. {
  183. // Success.
  184. }
  185. else
  186. {
  187. TRACE("CreateCmd(): Unable to add command to dispatcher.\n");
  188. sRes = -1;
  189. }
  190. // If any errors occurred after allocation . . .
  191. if (sRes != 0)
  192. {
  193. free(puc);
  194. }
  195. }
  196. else
  197. {
  198. TRACE("CreateCmd(): Unable to allocate chunk for command.\n");
  199. sRes = -1;
  200. }
  201. return sRes;
  202. }
  203. //////////////////////////////////////////////////////////////////////////////
  204. //
  205. // Handles data callbacks from dispatch.
  206. // Returns RET_FREE if puc should be freed and RET_DONTFREE, otherwise.
  207. //
  208. //////////////////////////////////////////////////////////////////////////////
  209. short CRtPlay::RtInfoCall( UCHAR* puc, long lSize, USHORT usType, UCHAR ucFlags,
  210. long lTime)
  211. {
  212. short sError = 0;
  213. // If this is the init/first chunk . . .
  214. if (ucFlags & RT_FLAG_INIT)
  215. {
  216. // Suspend reading (remembers time until next read).
  217. m_filewin.Suspend();
  218. // Set time to INIT time.
  219. m_rttime.SetTime(lTime);
  220. // Resume reading (next read will occur based on time until next read at
  221. // Suspend() call above).
  222. m_filewin.Start();
  223. }
  224. else
  225. {
  226. #if _DEBUG
  227. if (lTime + MAX_LAG < m_rttime.GetTime())
  228. {
  229. TRACE("RtInfoCall(): %ld ms behind!\n",
  230. m_rttime.GetTime() - lTime);
  231. }
  232. #endif // _DEBUG
  233. }
  234. CNFile file;
  235. if (file.Open(puc, lSize, ENDIAN_BIG) == 0)
  236. {
  237. USHORT usCmd;
  238. ULONG ulChannels;
  239. long lTimeVal;
  240. long lVal;
  241. // Get type of info.
  242. file.Read(&usCmd);
  243. switch (usCmd)
  244. {
  245. case CMD_INIT:
  246. // Gives us info on this rtf. This is, basically, the header and
  247. // could contain the record table, etc. This should be the very
  248. // first chunk of any RTF.
  249. // Read the maximum read rate in bytes per second.
  250. file.Read(&lVal);
  251. ASSERT(lVal != 0L);
  252. // Compute the input interval.
  253. m_filewin.SetInputInterval((m_lInputPaneSize * 1000) / lVal);
  254. break;
  255. case CMD_SUSPENDREADS:
  256. // Suspend the file window until lTimeVal.
  257. file.Read(&lTimeVal);
  258. if (m_filewin.Suspend() == 0)
  259. {
  260. // Add an RTFINFO chunk at the specified time to tell us to restart.
  261. if (CreateCmd(CMD_RESUMEREADS, lTimeVal, 0L, 0L) == 0)
  262. {
  263. // Success.
  264. }
  265. else
  266. {
  267. TRACE("RtInfoCall(): Failed to add RTFINFO RESUME command chunk "
  268. "to the dispatcher.\n");
  269. sError = -3;
  270. }
  271. }
  272. else
  273. {
  274. TRACE("RtInfoCall(): Failed to suspend file window! Aborting.\n");
  275. sError = -2;
  276. }
  277. break;
  278. case CMD_RESUMEREADS:
  279. // Restart file window.
  280. if (m_filewin.Start() == 0)
  281. {
  282. // Success.
  283. }
  284. else
  285. {
  286. TRACE("RtInfoCall(): Failed to restart file window! Aborting.\n");
  287. sError = -4;
  288. }
  289. break;
  290. case CMD_EOC:
  291. // Get the channels that are done so far.
  292. file.Read(&ulChannels);
  293. // Add to done mask.
  294. m_ulChannelsDone |= ulChannels;
  295. // If all current channels done . . .
  296. if ((m_ulChannelsDone & m_filter.GetFilter()) == m_filter.GetFilter())
  297. {
  298. // Attempt to stop file window, if still running . . .
  299. if (m_filewin.Suspend() == 0)
  300. {
  301. // Done streaming (processing may need to continue).
  302. SetState(RT_STATE_ENDING);
  303. // Dispatcher should be done.
  304. ASSERT(m_dispatch.IsEmpty() == TRUE);
  305. }
  306. else
  307. {
  308. TRACE("RtInfoCall(): Failed to suspend file window! All channels "
  309. "complete.\n");
  310. sError = -5;
  311. }
  312. }
  313. break;
  314. case CMD_STREAMHIT:
  315. // This is simply data to provide minimum throughput for the stream.
  316. // On a CD this can be used to periodically hit the disc to keep it
  317. // from straying too far ahead.
  318. break;
  319. default:
  320. TRACE("RtInfoCall(): Invalid type.\n");
  321. sError = -3;
  322. break;
  323. }
  324. file.Close();
  325. }
  326. else
  327. {
  328. TRACE("RtInfoCall(): Unable to open info.\n");
  329. sError = -1;
  330. }
  331. // If we got any errors . . .
  332. if (sError != 0)
  333. {
  334. if (Abort() == 0)
  335. {
  336. }
  337. else
  338. {
  339. TRACE("RtInfoCall(): Failed to abort current play after error.\n");
  340. }
  341. }
  342. // Have dispatcher free this buffer for us.
  343. return RET_FREE;
  344. }
  345. //////////////////////////////////////////////////////////////////////////////
  346. //
  347. // Callback dispatcher (calls the implied this version).
  348. // Returns RET_FREE if puc should be freed and RET_DONTFREE, otherwise.
  349. // (static)
  350. //
  351. //////////////////////////////////////////////////////////////////////////////
  352. short CRtPlay::RtInfoCallStatic( UCHAR* puc, long lSize, USHORT usType,
  353. UCHAR ucFlags, long lTime, long l_pRtPlay)
  354. {
  355. return ((CRtPlay*)l_pRtPlay)->RtInfoCall(puc, lSize, usType, ucFlags, lTime);
  356. }
  357. //////////////////////////////////////////////////////////////////////////////
  358. //
  359. // Sets the state to the new state. Generates messages if a state change
  360. // occurs.
  361. // Returns 0 on success.
  362. //
  363. //////////////////////////////////////////////////////////////////////////////
  364. short CRtPlay::SetState(USHORT usState)
  365. {
  366. short sRes = 0; // Assume success.
  367. // If new state . . .
  368. if (m_usState != usState)
  369. {
  370. // Currently there is a one to one correspondence between the
  371. // RT_STATE_*'s and the RT_MSG_*'s so we simply copy the state
  372. // as the message. If the correspondence is somehow removed,
  373. // this should be updated. Of course, if you simply change the
  374. // macros, you'll never see this until you figure out that there's
  375. // a problem.
  376. USHORT usMsg = usState;
  377. short sNum = m_dispatch.SendHandlerMessage(usMsg);
  378. if (sNum == 0)
  379. {
  380. // All message handlers okayed the new state. Change it.
  381. m_usState = usState;
  382. }
  383. else
  384. {
  385. TRACE("SetState(): Attempt to change to %s state rejected by %d "
  386. "handlers!\n",
  387. (usState == RT_STATE_STOPPED ? "STOPPED" :
  388. (usState == RT_STATE_STARTING ? "STARTING" :
  389. (usState == RT_STATE_BEGIN ? "BEGIN" :
  390. (usState == RT_STATE_PLAYING ? "PLAYING" :
  391. (usState == RT_STATE_PAUSE ? "PAUSE" :
  392. (usState == RT_STATE_ABORTING ? "ABORTING" :
  393. (usState == RT_STATE_ENDING ? "ENDING" : "UNKNOWN"
  394. ) ) ) ) ) ) ), sNum);
  395. // At least one handler rejected the state change.
  396. sRes = 1;
  397. }
  398. }
  399. return sRes;
  400. }
  401. //////////////////////////////////////////////////////////////////////////////
  402. //
  403. // Handles current state. Called by Blue's critical handler list.
  404. //
  405. //////////////////////////////////////////////////////////////////////////////
  406. void CRtPlay::Critical(void)
  407. {
  408. short sError = 0;
  409. switch (m_usState)
  410. {
  411. case RT_STATE_STOPPED:
  412. // Done.
  413. if (Blu_RemoveCritical(CriticalStatic) == 0)
  414. {
  415. }
  416. else
  417. {
  418. TRACE("Critical(): Unable to remove critical handler.\n");
  419. }
  420. break;
  421. case RT_STATE_STARTING:
  422. // If all handlers ready . . .
  423. if (m_dispatch.SendHandlerMessage(RT_STATE_BEGIN) == 0)
  424. {
  425. // Switch to playing state.
  426. SetState(RT_STATE_PLAYING);
  427. }
  428. break;
  429. case RT_STATE_BEGIN:
  430. // Should not happen.
  431. TRACE("Critical(): SUX! Problem: this state should not be reached!\n");
  432. sError = -1;
  433. break;
  434. case RT_STATE_PLAYING:
  435. break;
  436. case RT_STATE_PAUSE:
  437. break;
  438. case RT_STATE_ENDING:
  439. // Wait for dispatcher to empty . . .
  440. if (m_dispatch.IsEmpty() == FALSE)
  441. {
  442. break;
  443. }
  444. // Intentional fall through to RT_STATE_ABORTING.
  445. case RT_STATE_ABORTING:
  446. // Try to end as soon as possible.
  447. if (m_dispatch.SendHandlerMessage(RT_STATE_STOPPED) == 0)
  448. {
  449. // Attempt to stop dispatcher . . .
  450. if (m_dispatch.Suspend() == 0)
  451. {
  452. }
  453. else
  454. {
  455. TRACE("Critical(): Unable to suspend dispatcher.\n");
  456. }
  457. SetState(RT_STATE_STOPPED);
  458. }
  459. break;
  460. }
  461. if (sError != 0)
  462. {
  463. Abort();
  464. }
  465. }
  466. //////////////////////////////////////////////////////////////////////////////
  467. // Public methods.
  468. //////////////////////////////////////////////////////////////////////////////
  469. //////////////////////////////////////////////////////////////////////////////
  470. //
  471. // Opens a stream file for play.
  472. // Returns 0 on success.
  473. //
  474. //////////////////////////////////////////////////////////////////////////////
  475. short CRtPlay::Open(char* pszFileName)
  476. {
  477. short sRes = 0; // Assume success.
  478. if (Close() == 0)
  479. {
  480. // Attempt to open file window . . .
  481. if (m_filewin.Open(pszFileName) == 0)
  482. {
  483. // Attempt to set window and pane sizes . . .
  484. if (m_filewin.SetSize(m_lWindowSize, m_lInputPaneSize,
  485. m_lFilterPaneSize) == 0)
  486. {
  487. // Successfully opened.
  488. }
  489. else
  490. {
  491. TRACE("Open(\"%s\"): Unable to set file window and pane sizes.\n",
  492. pszFileName);
  493. sRes = -3;
  494. }
  495. // If any errors occur after opening file . . .
  496. if (sRes != 0)
  497. {
  498. // Close it.
  499. Close();
  500. }
  501. }
  502. else
  503. {
  504. TRACE("Open(\"%s\"): Unable to open file window.\n", pszFileName);
  505. sRes = -2;
  506. }
  507. }
  508. else
  509. {
  510. TRACE("Open(\"%s\"): Unable to close currently open stream file.\n", pszFileName);
  511. sRes = -1;
  512. }
  513. return sRes;
  514. }
  515. //////////////////////////////////////////////////////////////////////////////
  516. //
  517. // Closes an open stream file.
  518. // Returns 0 on success.
  519. //
  520. //////////////////////////////////////////////////////////////////////////////
  521. short CRtPlay::Close(void)
  522. {
  523. short sRes = 0; // Assume success.
  524. // If stopped . . .
  525. if (m_usState == RT_STATE_STOPPED)
  526. {
  527. if (m_filewin.Close() == 0)
  528. {
  529. // Successfully closed.
  530. // Tell resource manager to free unused resources.
  531. m_res.FreeAll();
  532. }
  533. else
  534. {
  535. TRACE("Close(): Failed to close the file window!\n");
  536. sRes = -2;
  537. }
  538. }
  539. else
  540. {
  541. TRACE("Close(): The stream file is not stopped!\n");
  542. sRes = -1;
  543. }
  544. return sRes;
  545. }
  546. //////////////////////////////////////////////////////////////////////////////
  547. //
  548. // Starts play.
  549. // Returns 0 on success.
  550. //
  551. //////////////////////////////////////////////////////////////////////////////
  552. short CRtPlay::Play(void)
  553. {
  554. short sRes = 0; // Assume success.
  555. // If stopped . . .
  556. if (m_usState == RT_STATE_STOPPED)
  557. {
  558. // Set the time to 0.
  559. m_rttime.SetTime(0L);
  560. // Start with no channels done.
  561. m_ulChannelsDone = 0;
  562. // Attempt to start the file window . . .
  563. if (m_filewin.Start() == 0)
  564. {
  565. // Attempt to start the dispatching . . .
  566. if (m_dispatch.Start() == 0)
  567. {
  568. // Attempt to start critical handler . . .
  569. if (Blu_AddCritical(CriticalStatic, (long)this) == 0)
  570. {
  571. if (SetState(RT_STATE_STARTING) == 0)
  572. {
  573. // Successfully changed to starting state.
  574. }
  575. else
  576. {
  577. TRACE("Play(): At least one handler rejected starting.\n");
  578. sRes = -4;
  579. }
  580. // If any errors occurred after we started the critical handler . . .
  581. if (sRes != 0)
  582. {
  583. Blu_RemoveCritical(CriticalStatic);
  584. }
  585. }
  586. else
  587. {
  588. TRACE("Play(): Unable to add critical handler.\n");
  589. sRes = -5;
  590. }
  591. // If any errors occurred after we started the dispatcher . . .
  592. if (sRes != 0)
  593. {
  594. m_dispatch.Suspend();
  595. }
  596. }
  597. else
  598. {
  599. TRACE("Play(): The dispatcher did not start!\n");
  600. sRes = -3;
  601. }
  602. // If any errors occurred after we started the file window . . .
  603. if (sRes != 0)
  604. {
  605. m_filewin.Suspend();
  606. }
  607. }
  608. else
  609. {
  610. TRACE("Play(): The file window did not start!\n");
  611. sRes = -2;
  612. }
  613. // If any errors occurred after we started the file window . . .
  614. if (sRes != 0)
  615. {
  616. m_filewin.Suspend();
  617. }
  618. }
  619. else
  620. {
  621. TRACE("Play(): The stream file is not stopped!\n");
  622. sRes = -1;
  623. }
  624. return sRes;
  625. }
  626. //////////////////////////////////////////////////////////////////////////////
  627. //
  628. // Aborts current play.
  629. // Returns 0 on success.
  630. //
  631. //////////////////////////////////////////////////////////////////////////////
  632. short CRtPlay::Abort(void)
  633. {
  634. short sRes = 0; // Assume success.
  635. // If not stopped . . .
  636. if (m_usState != RT_STATE_STOPPED)
  637. {
  638. if (m_filewin.IsActive() == TRUE)
  639. {
  640. // Suspend file window processing . . .
  641. if (m_filewin.Suspend() == 0)
  642. {
  643. }
  644. else
  645. {
  646. TRACE("Abort(): Unable to suspend file window.\n");
  647. sRes = -2;
  648. }
  649. }
  650. if (m_dispatch.IsActive() == TRUE)
  651. {
  652. // Suspend dispatching . . .
  653. if (m_dispatch.Suspend() == 0)
  654. {
  655. }
  656. else
  657. {
  658. TRACE("Abort(): Unable to suspend dispatcher.\n");
  659. sRes = -3;
  660. }
  661. }
  662. // If completed successfully . . .
  663. if (sRes == 0)
  664. {
  665. // Change state.
  666. if (SetState(RT_STATE_ABORTING) != 0)
  667. {
  668. TRACE("Abort(): At least one handler responded with an error.\n");
  669. }
  670. }
  671. }
  672. else
  673. {
  674. TRACE("Abort(): The stream file is already stopped!\n");
  675. sRes = -1;
  676. }
  677. return sRes;
  678. }
  679. //////////////////////////////////////////////////////////////////////////////
  680. //
  681. // Pauses play.
  682. // Returns 0 on success.
  683. //
  684. //////////////////////////////////////////////////////////////////////////////
  685. short CRtPlay::Pause(void)
  686. {
  687. short sRes = 0; // Assume success.
  688. // If playing . . .
  689. if (m_usState == RT_STATE_PLAYING)
  690. {
  691. // This should suspend any timer based stuff.
  692. m_rttime.Suspend();
  693. // If completed successfully . . .
  694. if (sRes == 0)
  695. {
  696. // Change state.
  697. if (SetState(RT_STATE_PAUSE) == 0)
  698. {
  699. }
  700. else
  701. {
  702. TRACE("Pause(): At least one handler responded with an error to "
  703. "entering the PAUSE state.\n");
  704. sRes = -3;
  705. }
  706. }
  707. }
  708. else
  709. {
  710. TRACE("Pause(): The stream file is stopped!\n");
  711. sRes = -1;
  712. }
  713. return sRes;
  714. }
  715. //////////////////////////////////////////////////////////////////////////////
  716. //
  717. // Resumes play (after Pause()).
  718. // Returns 0 on success.
  719. //
  720. //////////////////////////////////////////////////////////////////////////////
  721. short CRtPlay::Resume(void)
  722. {
  723. short sRes = 0; // Assume success.
  724. if (m_usState == RT_STATE_PAUSE)
  725. {
  726. // This should resume any timer based stuff.
  727. m_rttime.Resume();
  728. // Change state.
  729. if (SetState(RT_STATE_PLAYING) == 0)
  730. {
  731. }
  732. else
  733. {
  734. TRACE("Resume(): At least one handler responded with an "
  735. "error to entering the PLAYING state.\n");
  736. sRes = -4;
  737. if (Abort() != 0)
  738. {
  739. TRACE("Resume(): Unable to abort after failed resume.\n");
  740. }
  741. }
  742. }
  743. else
  744. {
  745. TRACE("Resume(): The stream file is not paused!\n");
  746. sRes = -1;
  747. }
  748. return sRes;
  749. }
  750. //////////////////////////////////////////////////////////////////////////////
  751. // EOF
  752. //////////////////////////////////////////////////////////////////////////////