player.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (C) 2003-2006 by egnite Software GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*!
  35. * $Id: player.c 4115 2012-04-12 21:06:13Z olereinhardt $
  36. */
  37. #include <sys/heap.h>
  38. #include <sys/event.h>
  39. #include <sys/timer.h>
  40. #include <sys/thread.h>
  41. #include <dev/vs1001k.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <stdio.h>
  45. #include "player.h"
  46. #include <sys/bankmem.h>
  47. #define MAX_WAITSTREAM 20
  48. #define BIGBUF_WATERMARK 65535UL
  49. PLAYERINFO player;
  50. #if defined(__AVR__)
  51. /*
  52. * Process embedded meta data.
  53. */
  54. static void ClearMetaData(void)
  55. {
  56. if (player.psi_metatitle) {
  57. free(player.psi_metatitle);
  58. player.psi_metatitle = 0;
  59. }
  60. if (player.psi_metaurl) {
  61. free(player.psi_metaurl);
  62. player.psi_metaurl = 0;
  63. }
  64. }
  65. /*
  66. * Process embedded meta data.
  67. */
  68. static int ProcessMetaData(void)
  69. {
  70. uint8_t blks = 0;
  71. uint16_t cnt;
  72. int got;
  73. int rc = 0;
  74. uint8_t to_cnt = 0;
  75. char *mbuf;
  76. char *mn1;
  77. char *mn2;
  78. char *md1;
  79. char *md2;
  80. /*
  81. * Wait for the lenght byte.
  82. */
  83. while (player.psi_status == PSI_RUNNING) {
  84. if ((got = NutTcpReceive(player.psi_sock, &blks, 1)) == 1)
  85. break;
  86. if (got < 0 || to_cnt++ > MAX_WAITSTREAM) {
  87. printf("[NoLen]");
  88. return -1;
  89. }
  90. }
  91. if (blks) {
  92. if (blks > 32) {
  93. printf("[Blks=%u]", blks);
  94. return -1;
  95. }
  96. cnt = blks * 16;
  97. if ((mbuf = malloc(cnt + 1)) == 0) {
  98. printf("[NoMem]");
  99. return -1;
  100. }
  101. /*
  102. * Receive the metadata block.
  103. */
  104. while (player.psi_status == PSI_RUNNING) {
  105. if ((got = NutTcpReceive(player.psi_sock, mbuf + rc, cnt)) < 0) {
  106. printf("[RxFail]");
  107. return -1;
  108. }
  109. if (got) {
  110. to_cnt = 0;
  111. if ((cnt -= got) == 0)
  112. break;
  113. rc += got;
  114. mbuf[rc] = 0;
  115. } else if (to_cnt++ > MAX_WAITSTREAM) {
  116. printf("[RxTo]");
  117. return -1;
  118. }
  119. }
  120. ClearMetaData();
  121. printf("\nMeta='%s'\n", mbuf);
  122. mn1 = mbuf;
  123. while (mn1) {
  124. if ((mn2 = strchr(mn1, ';')) != 0)
  125. *mn2++ = 0;
  126. if ((md1 = strchr(mn1, '=')) != 0) {
  127. *md1++ = 0;
  128. while (*md1 == ' ' || *md1 == '\'')
  129. md1++;
  130. if ((md2 = strrchr(md1, '\'')) != 0)
  131. *md2 = 0;
  132. if (strcasecmp(mn1, "StreamTitle") == 0 && player.psi_metatitle == 0) {
  133. player.psi_metatitle = malloc(strlen(md1) + 1);
  134. strcpy(player.psi_metatitle, md1);
  135. } else if (strcasecmp(mn1, "StreamUrl") == 0 && player.psi_metaurl == 0) {
  136. player.psi_metaurl = malloc(strlen(md1) + 1);
  137. strcpy(player.psi_metaurl, md1);
  138. }
  139. }
  140. mn1 = mn2;
  141. }
  142. free(mbuf);
  143. player.psi_metaupdate = 1;
  144. }
  145. return 0;
  146. }
  147. /*
  148. * Background thread for playing stream.
  149. */
  150. THREAD(Player, arg)
  151. {
  152. size_t rbytes;
  153. char *mp3buf;
  154. uint8_t to_cnt = 0;
  155. int got;
  156. uint8_t ief;
  157. /*
  158. * Nut/OS threads run forever.
  159. */
  160. for (;;) {
  161. /*
  162. * Idle loop.
  163. */
  164. for (;;) {
  165. /* Broadcast idle status. */
  166. printf("[IDLE]");
  167. ClearMetaData();
  168. player.psi_status = PSI_IDLE;
  169. NutEventBroadcast(&player.psi_stsevt);
  170. /* Wait for start event. */
  171. NutEventWait(&player.psi_cmdevt, 0);
  172. printf("[EVT%u]", player.psi_status);
  173. if (player.psi_status == PSI_START)
  174. break;
  175. }
  176. /* Broadcast running event. */
  177. printf("[RUN]");
  178. player.psi_status = PSI_RUNNING;
  179. player.psi_mp3left = player.psi_metaint;
  180. NutEventBroadcast(&player.psi_stsevt);
  181. /* Reset decoder buffer. */
  182. ief = VsPlayerInterrupts(0);
  183. NutSegBufReset();
  184. VsPlayerInterrupts(ief);
  185. /*
  186. * Running loop.
  187. */
  188. while (player.psi_status == PSI_RUNNING) {
  189. /*
  190. * Query number of byte available in MP3 buffer. If it is
  191. * zero, then the player may have stopped running.
  192. */
  193. ief = VsPlayerInterrupts(0);
  194. mp3buf = NutSegBufWriteRequest(&rbytes);
  195. VsPlayerInterrupts(ief);
  196. if (rbytes < 1024) {
  197. if (VsGetStatus() != VS_STATUS_RUNNING)
  198. VsPlayerKick();
  199. if (rbytes == 0) {
  200. NutSleep(125);
  201. continue;
  202. }
  203. }
  204. /* Do not read pass metadata. */
  205. if (player.psi_metaint && rbytes > player.psi_mp3left)
  206. rbytes = player.psi_mp3left;
  207. /*
  208. * Loop until MP3 buffer space is filled.
  209. */
  210. while (rbytes) {
  211. /* Read data directly into the MP3 buffer. */
  212. if ((got = NutTcpReceive(player.psi_sock, mp3buf, rbytes)) < 0) {
  213. /* This is fatal. Return to idle state. */
  214. printf("[RXFAIL]");
  215. player.psi_status = PSI_IDLE;
  216. break;
  217. }
  218. /*
  219. * Got some MP3 data.
  220. */
  221. if (got) {
  222. /* Commit the buffer. */
  223. ief = VsPlayerInterrupts(0);
  224. mp3buf = NutSegBufWriteCommit(got);
  225. VsPlayerInterrupts(ief);
  226. /* Reset timeout counter and reduce number of buffer bytes. */
  227. to_cnt = 0;
  228. rbytes -= got;
  229. /* Process meta data. */
  230. if (player.psi_metaint) {
  231. player.psi_mp3left -= got;
  232. if (player.psi_mp3left == 0) {
  233. if (ProcessMetaData()) {
  234. printf("[METAFAIL]");
  235. //player.psi_status = PSI_IDLE;
  236. //break;
  237. }
  238. player.psi_mp3left = player.psi_metaint;
  239. }
  240. }
  241. /* Start early with large buffers. */
  242. if (VsGetStatus() != VS_STATUS_RUNNING) {
  243. ief = VsPlayerInterrupts(0);
  244. if ((NutSegBufUsed() > 2048 && player.psi_start) ||
  245. (NutSegBufUsed() > BIGBUF_WATERMARK && NutSegBufAvailable() < BIGBUF_WATERMARK))
  246. VsPlayerKick();
  247. else
  248. VsPlayerInterrupts(ief);
  249. }
  250. player.psi_start = 0;
  251. }
  252. /*
  253. * Got no MP3 data.
  254. */
  255. else {
  256. printf("[T%u, %u]", to_cnt, NutHeapAvailable());
  257. NutSleep(100);
  258. if (to_cnt++ > MAX_WAITSTREAM) {
  259. /* If timeouts reach our limit, go back to idle state. */
  260. printf("[RXTO]");
  261. player.psi_status = PSI_IDLE;
  262. break;
  263. }
  264. }
  265. /*
  266. * If we won't yield the CPU, we may consume the complete
  267. * TCP buffer before being stopped in NutTcpReceive. That
  268. * would result in bumpy feeding.
  269. */
  270. NutThreadYield();
  271. }
  272. /* If play loop is not entered, we may omit the watchdog
  273. update here and force a system reset. */
  274. NutThreadYield();
  275. }
  276. /* Flush decoder and wait until finished. */
  277. printf("[FLUSH]");
  278. VsPlayerFlush();
  279. while (VsGetStatus() == VS_STATUS_RUNNING) {
  280. NutSleep(63);
  281. }
  282. /* Reset the decoder. */
  283. printf("[RESET]");
  284. VsPlayerReset(0);
  285. }
  286. }
  287. /*!
  288. * \brief Initialize the MP3 player.
  289. *
  290. * Initializes the decoder and the decoder buffer and starts the
  291. * player background thread.
  292. */
  293. int PlayerInit(void)
  294. {
  295. /* Init decoder. */
  296. if (VsPlayerInit() || VsPlayerReset(0))
  297. return -1;
  298. /* Start player thread. */
  299. if (NutThreadCreate("player", Player, 0, 512) == 0)
  300. return -1;
  301. return 0;
  302. }
  303. /*!
  304. * \brief Stop MP3 player.
  305. *
  306. * Force player into idle mode.
  307. */
  308. int PlayerStop(uint32_t tmo)
  309. {
  310. while (player.psi_status != PSI_IDLE) {
  311. printf("[STOP]");
  312. player.psi_status = PSI_STOP;
  313. NutEventPost(&player.psi_cmdevt);
  314. if (NutEventWait(&player.psi_stsevt, tmo)) {
  315. printf("[TOP]");
  316. return -1;
  317. }
  318. }
  319. printf("[STOPPED]");
  320. return 0;
  321. }
  322. /*!
  323. * \brief Start MP3 player.
  324. *
  325. * If the player is currently running, it will be stopped first.
  326. */
  327. int PlayerStart(TCPSOCKET * sock, uint32_t metaint, uint32_t tmo)
  328. {
  329. if (PlayerStop(tmo))
  330. return -1;
  331. /* Clear event queue and send start command. */
  332. NutEventBroadcast(&player.psi_stsevt);
  333. printf("[START]");
  334. player.psi_status = PSI_START;
  335. player.psi_sock = sock;
  336. player.psi_metaint = metaint;
  337. NutEventPost(&player.psi_cmdevt);
  338. /* The next event will be the result of our start command. */
  339. if (NutEventWait(&player.psi_stsevt, tmo) || player.psi_status != PSI_RUNNING) {
  340. printf("[TOS]");
  341. return -1;
  342. }
  343. return 0;
  344. }
  345. #endif /* __AVR__ */