1
0

PlaybackBase.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include "PlaybackBase.h"
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #ifdef __ANDROID__
  5. #include <android/log.h> // TODO: replace with generic logging API
  6. #else
  7. #define ANDROID_LOG_INFO 0
  8. #define ANDROID_LOG_ERROR 1
  9. static void __android_log_print(int, const char *, const char *, ...)
  10. {
  11. }
  12. #endif
  13. PlaybackBase::PlaybackBase()
  14. {
  15. wake_flags=0;
  16. last_wake_flags=0;
  17. playback_thread=0;
  18. secondary_parameters=0;
  19. filename=0;
  20. player=0;
  21. queued_seek=0;
  22. output_service=0;
  23. }
  24. int PlaybackBase::Initialize(nx_uri_t filename, ifc_player *player)
  25. {
  26. this->player = player;
  27. this->filename = NXURIRetain(filename);
  28. return NErr_Success;
  29. }
  30. PlaybackBase::~PlaybackBase()
  31. {
  32. if (secondary_parameters)
  33. secondary_parameters->Release();
  34. if (filename)
  35. NXURIRelease(filename);
  36. if (queued_seek)
  37. free(queued_seek);
  38. if (playback_thread)
  39. NXThreadJoin(playback_thread, 0);
  40. }
  41. int PlaybackBase::Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters)
  42. {
  43. if (!playback_thread)
  44. return 1;
  45. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Play");
  46. output_service = output;
  47. threadloop_node_t *apc = thread_loop.GetAPC();
  48. if (apc)
  49. {
  50. this->secondary_parameters = secondary_parameters;
  51. if (secondary_parameters)
  52. secondary_parameters->Retain();
  53. apc->func = APC_Play;
  54. apc->param1 = this;
  55. thread_loop.Schedule(apc);
  56. return NErr_Success;
  57. }
  58. else
  59. return NErr_OutOfMemory;
  60. }
  61. int PlaybackBase::Playback_SeekSeconds(double seconds)
  62. {
  63. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Seek (%f seconds)", seconds);
  64. Agave_Seek *seek = (Agave_Seek *)malloc(sizeof(Agave_Seek));
  65. if (seek)
  66. {
  67. seek->position_type = AGAVE_PLAYPOSITION_SECONDS;
  68. seek->position.seconds = seconds;
  69. threadloop_node_t *apc = thread_loop.GetAPC();
  70. if (apc)
  71. {
  72. apc->func = APC_Seek;
  73. apc->param1 = this;
  74. apc->param2 = seek;
  75. thread_loop.Schedule(apc);
  76. return NErr_Success;
  77. }
  78. }
  79. free(seek);
  80. return NErr_OutOfMemory;
  81. }
  82. int PlaybackBase::Playback_Pause()
  83. {
  84. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Pause");
  85. threadloop_node_t *apc = thread_loop.GetAPC();
  86. if (apc)
  87. {
  88. apc->func = APC_Pause;
  89. apc->param1 = this;
  90. thread_loop.Schedule(apc);
  91. return NErr_Success;
  92. }
  93. else
  94. return NErr_OutOfMemory;
  95. }
  96. int PlaybackBase::Playback_Unpause()
  97. {
  98. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Unpause");
  99. threadloop_node_t *apc = thread_loop.GetAPC();
  100. if (apc)
  101. {
  102. apc->func = APC_Unpause;
  103. apc->param1 = this;
  104. thread_loop.Schedule(apc);
  105. return NErr_Success;
  106. }
  107. else
  108. return NErr_OutOfMemory;
  109. }
  110. int PlaybackBase::Playback_Stop()
  111. {
  112. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Stop");
  113. threadloop_node_t *apc = thread_loop.GetAPC();
  114. if (apc)
  115. {
  116. apc->func = APC_Stop;
  117. apc->param1 = this;
  118. thread_loop.Schedule(apc);
  119. return NErr_Success;
  120. }
  121. else
  122. return NErr_OutOfMemory;
  123. }
  124. int PlaybackBase::Playback_Close()
  125. {
  126. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Close");
  127. threadloop_node_t *apc = thread_loop.GetAPC();
  128. if (apc)
  129. {
  130. apc->func = APC_Close;
  131. apc->param1 = this;
  132. thread_loop.Schedule(apc);
  133. return NErr_Success;
  134. }
  135. else
  136. return NErr_OutOfMemory;
  137. }
  138. int PlaybackBase::FileLockCallback_Interrupt()
  139. {
  140. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Interrupt");
  141. threadloop_node_t *apc = thread_loop.GetAPC();
  142. if (apc)
  143. {
  144. apc->func = APC_Interrupt;
  145. apc->param1 = this;
  146. thread_loop.Schedule(apc);
  147. return NErr_Success;
  148. }
  149. else
  150. return NErr_OutOfMemory;
  151. }
  152. void PlaybackBase::ToggleFlags(int wake_reason)
  153. {
  154. switch(wake_reason)
  155. {
  156. case WAKE_KILL:
  157. last_wake_flags ^= WAKE_KILL; /* toggle kill flag */
  158. break;
  159. case WAKE_STOP:
  160. last_wake_flags ^= WAKE_STOP; /* toggle stop flag */
  161. break;
  162. case WAKE_PLAY:
  163. last_wake_flags ^= WAKE_PLAY; /* toggle play flag */
  164. break;
  165. case WAKE_PAUSE:
  166. case WAKE_UNPAUSE:
  167. last_wake_flags ^= WAKE_PAUSE; /* toggle pause flag */
  168. break;
  169. case WAKE_INTERRUPT:
  170. last_wake_flags ^= WAKE_INTERRUPT; /* toggle interrupt flag */
  171. break;
  172. }
  173. }
  174. int PlaybackBase::WakeReason(int mask) const
  175. {
  176. int reason_awoken = last_wake_flags ^ wake_flags;
  177. reason_awoken = reason_awoken & mask;
  178. if (reason_awoken & WAKE_INTERRUPT)
  179. {
  180. if (wake_flags & WAKE_INTERRUPT)
  181. return WAKE_INTERRUPT;
  182. else
  183. return WAKE_RESUME;
  184. }
  185. if (reason_awoken & WAKE_STOP)
  186. {
  187. return WAKE_STOP;
  188. }
  189. if (reason_awoken & WAKE_KILL)
  190. {
  191. return WAKE_KILL;
  192. }
  193. if (reason_awoken & WAKE_PLAY)
  194. {
  195. if (wake_flags & WAKE_PLAY)
  196. return WAKE_PLAY;
  197. else /* if someone cleared the play flag for whatever reason, just treat it as a 0 */
  198. return 0;
  199. }
  200. if (reason_awoken & WAKE_PAUSE)
  201. {
  202. if (wake_flags & WAKE_PAUSE)
  203. return WAKE_PAUSE;
  204. else
  205. return WAKE_UNPAUSE;
  206. }
  207. return 0;
  208. }
  209. int PlaybackBase::Wake(int mask)
  210. {
  211. assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
  212. assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
  213. for (;;)
  214. {
  215. int reason_awoken = last_wake_flags ^ wake_flags;
  216. reason_awoken = reason_awoken & mask;
  217. if (reason_awoken)
  218. {
  219. int ret = WakeReason(mask);
  220. ToggleFlags(ret); // mark the last-known-state of the wake flags
  221. return ret;
  222. }
  223. if (((mask & WAKE_PLAY) && !(wake_flags & WAKE_PLAY))/* if we're stopped and they asked to be woken up for play */
  224. || ((mask & WAKE_PAUSE) && (wake_flags & WAKE_PAUSE)) /* or waiting to be woken up for unpause */
  225. || ((mask & WAKE_INTERRUPT) && (wake_flags & WAKE_INTERRUPT))) /* or waiting to be woken up for resume */
  226. {
  227. thread_loop.Step();
  228. int ret = WakeReason(mask);
  229. if (ret) /* if ret is !0, it means we gotten woken up for a reason we care about */
  230. {
  231. ToggleFlags(ret); // mark the last-known-state of the wake flags
  232. return ret;
  233. }
  234. }
  235. else /* no reason to sleep, so just return 0 (no change) */
  236. {
  237. return 0;
  238. }
  239. }
  240. }
  241. int PlaybackBase::Check(int mask)
  242. {
  243. assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
  244. assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
  245. int reason_awoken = last_wake_flags ^ wake_flags;
  246. reason_awoken = reason_awoken & mask;
  247. int ret = 0;
  248. if (reason_awoken)
  249. {
  250. ret = WakeReason(mask);
  251. ToggleFlags(ret); // mark the last-known-state of the wake flags
  252. }
  253. return ret;
  254. }
  255. int PlaybackBase::Wait(unsigned int milliseconds, int mask)
  256. {
  257. int reason_awoken = last_wake_flags ^ wake_flags;
  258. reason_awoken = reason_awoken & mask;
  259. if (reason_awoken)
  260. {
  261. int ret = WakeReason(mask);
  262. ToggleFlags(ret); // mark the last-known-state of the wake flags
  263. return ret;
  264. }
  265. thread_loop.Step(milliseconds);
  266. int ret = WakeReason(mask);
  267. ToggleFlags(ret); // mark the last-known-state of the wake flags
  268. return ret;
  269. }
  270. int PlaybackBase::Sleep(unsigned int milliseconds, int mask)
  271. {
  272. int reason_awoken = last_wake_flags ^ wake_flags;
  273. reason_awoken = reason_awoken & mask;
  274. if (reason_awoken)
  275. {
  276. int ret = WakeReason(mask);
  277. assert(ret != 0);
  278. return ret;
  279. }
  280. thread_loop.Step(milliseconds);
  281. int ret = WakeReason(mask);
  282. return ret;
  283. }
  284. void PlaybackBase::OnStopPlaying()
  285. {
  286. // turn off the play flag (also adjust old wake flags so we don't trigger a WAKE_STOP)
  287. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnStopPlaying");
  288. wake_flags &= ~WAKE_PLAY;
  289. last_wake_flags &= ~WAKE_PLAY;
  290. }
  291. void PlaybackBase::OnInterrupted()
  292. {
  293. __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnInterrupted");
  294. wake_flags &= ~WAKE_INTERRUPT;
  295. last_wake_flags &= ~WAKE_INTERRUPT;
  296. }
  297. Agave_Seek *PlaybackBase::GetSeek()
  298. {
  299. Agave_Seek *seek = queued_seek;
  300. queued_seek=0;
  301. return seek;
  302. }
  303. void PlaybackBase::FreeSeek(Agave_Seek *seek)
  304. {
  305. free(seek);
  306. }
  307. bool PlaybackBase::PendingSeek()
  308. {
  309. return !!queued_seek;
  310. }
  311. void PlaybackBase::APC_Play(void *_playback_base, void *param2, double real_value)
  312. {
  313. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  314. playback_base->wake_flags |= WAKE_PLAY;
  315. }
  316. void PlaybackBase::APC_Seek(void *_playback_base, void *_seek, double real_value)
  317. {
  318. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  319. Agave_Seek *seek = (Agave_Seek *)_seek;
  320. free(playback_base->queued_seek);
  321. playback_base->queued_seek = seek;
  322. }
  323. void PlaybackBase::APC_Pause(void *_playback_base, void *param2, double real_value)
  324. {
  325. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  326. playback_base->wake_flags |= WAKE_PAUSE;
  327. }
  328. void PlaybackBase::APC_Unpause(void *_playback_base, void *param2, double real_value)
  329. {
  330. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  331. playback_base->wake_flags &= ~WAKE_PAUSE;
  332. }
  333. void PlaybackBase::APC_Stop(void *_playback_base, void *param2, double real_value)
  334. {
  335. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  336. playback_base->wake_flags |= WAKE_STOP;
  337. }
  338. void PlaybackBase::APC_Close(void *_playback_base, void *param2, double real_value)
  339. {
  340. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  341. playback_base->wake_flags |= WAKE_KILL;
  342. }
  343. void PlaybackBase::APC_Interrupt(void *_playback_base, void *param2, double real_value)
  344. {
  345. PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
  346. playback_base->wake_flags |= WAKE_INTERRUPT;
  347. }