httpstream.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. //
  2. // Created by janco on 10-3-16.
  3. //
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <sys/thread.h>
  7. #include <sys/timer.h>
  8. #include <sys/version.h>
  9. #include <dev/irqreg.h>
  10. #include "vs10xx.h"
  11. #include <sys/socket.h>
  12. #include <netinet/tcp.h>
  13. #include <sys/confnet.h>
  14. #include <net/route.h>
  15. #include <dev/board.h>
  16. #include <pro/httpd.h>
  17. #include <pro/dhcp.h>
  18. #include <pro/asp.h>
  19. #include <pro/discover.h>
  20. #include <dev/nicrtl.h>
  21. #include "ntp.h"
  22. #include "httpstream.h"
  23. bool isStreaming;
  24. TCPSOCKET *sock;
  25. FILE *stream;
  26. u_long metaint;
  27. THREAD(Stream, args)
  28. {
  29. if(stream) {
  30. PlayMp3Stream(stream, metaint);
  31. }
  32. fclose(stream);
  33. NutTcpCloseSocket(sock);
  34. VsPlayerStop();
  35. stopStream();
  36. printf("Stopping http stream..");
  37. NutThreadExit();
  38. }
  39. void playStream(char *ipaddr, u_short port, char *radiourl){
  40. if(isStreaming != true){
  41. ConnectStation(sock, inet_addr(ipaddr), port, radiourl, &metaint);
  42. isStreaming = true;
  43. NutThreadCreate("Stream", Stream, NULL, 512);
  44. }
  45. }
  46. void stopStream(){
  47. isStreaming = false;
  48. }
  49. bool HttpIsStreaming(){
  50. return isStreaming;
  51. }
  52. void ConnectStation(TCPSOCKET *sock, u_long ip, u_short port, char *radiourl, u_long *metaint){
  53. int rc;
  54. u_char *line;
  55. u_char *cp;
  56. /*
  57. * Connect the TCP server.
  58. */
  59. if ((sock = NutTcpCreateSocket()) == 0)
  60. printf("Probleem bij het creereen van tcp socket");
  61. if (NutTcpSetSockOpt(sock, TCP_MAXSEG, MSS, sizeof(MSS)))
  62. printf("Probleem bij het creereen van tcp socket");
  63. if (NutTcpSetSockOpt(sock, SO_RCVTIMEO, RX_TO, sizeof(RX_TO)))
  64. printf("Probleem bij het creereen van tcp socket");
  65. if (NutTcpSetSockOpt(sock, SO_RCVBUF, TCPBUFSIZE, sizeof(TCPBUFSIZE)))
  66. printf("Probleem bij het creereen van tcp socket");
  67. printf("Connecting %s:%u...", inet_ntoa(ip), port);
  68. if ((rc = NutTcpConnect(sock, ip, port))) {
  69. printf("Error: Connect failed with %d\n", ip);
  70. return;
  71. }
  72. puts("OK");
  73. if ((stream = _fdopen((int) sock, "r+b")) == 0) {
  74. printf("Error: Can't create stream");
  75. return;
  76. }
  77. /*
  78. * Send the HTTP request.
  79. */
  80. printf("GET %s HTTP/1.0\n\n", radiourl);
  81. fprintf(stream, "GET %s HTTP/1.0\r\n", radiourl);
  82. fprintf(stream, "Host: %s\r\n", inet_ntoa(ip));
  83. fprintf(stream, "User-Agent: Ethernut\r\n");
  84. fprintf(stream, "Accept: */*\r\n");
  85. fprintf(stream, "Icy-MetaData: 1\r\n");
  86. fprintf(stream, "Connection: close\r\n");
  87. fputs("\r\n", stream);
  88. fflush(stream);
  89. /*
  90. * Receive the HTTP header.
  91. */
  92. line = malloc(MAX_HEADERLINE);
  93. if(line == 0){
  94. printf("Can't malloc memory in httpstream\n");
  95. return;
  96. }
  97. while(fgets(line, MAX_HEADERLINE, stream)) {
  98. /*
  99. * Chop off the carriage return at the end of the line. If none
  100. * was found, then this line was probably too large for our buffer.
  101. */
  102. cp = strchr(line, '\r');
  103. if(cp == 0) {
  104. printf("Warning: Input buffer overflow");
  105. continue;
  106. }
  107. *cp = 0;
  108. /*
  109. * The header is terminated by an empty line.
  110. */
  111. if(*line == 0) {
  112. break;
  113. }
  114. if(strncmp(line, "icy-metaint:", 12) == 0) {
  115. *metaint = atol(line + 12);
  116. }
  117. printf("%s\n", line);
  118. }
  119. putchar('\n');
  120. free(line);
  121. }
  122. int ProcessMetaData(FILE *stream)
  123. {
  124. u_char blks = 0;
  125. u_short cnt;
  126. int got;
  127. int rc = 0;
  128. u_char *mbuf;
  129. /*
  130. * Wait for the lenght byte.
  131. */
  132. got = fread(&blks, 1, 1, stream);
  133. if(got != 1) {
  134. return -1;
  135. }
  136. if (blks) {
  137. if (blks > 32) {
  138. printf("Error: Metadata too large, %u blocks\n", blks);
  139. return -1;
  140. }
  141. cnt = blks * 16;
  142. if ((mbuf = malloc(cnt + 1)) == 0) {
  143. printf("Can't malloc memory for metadata parsing\n");
  144. return -1;
  145. }
  146. /*
  147. * Receive the metadata block.
  148. */
  149. for (;;) {
  150. if ((got = fread(mbuf + rc, 1, cnt, stream)) <= 0) {
  151. return -1;
  152. }
  153. if ((cnt -= got) == 0) {
  154. break;
  155. }
  156. rc += got;
  157. mbuf[rc] = 0;
  158. }
  159. printf("\nMeta='%s'\n", mbuf);
  160. free(mbuf);
  161. }
  162. return 0;
  163. }
  164. void PlayMp3Stream(FILE *stream, u_long metaint)
  165. {
  166. size_t rbytes = 0;
  167. u_char *mp3buf;
  168. u_char ief;
  169. int got = 0;
  170. u_long last;
  171. u_long mp3left = metaint;
  172. /*
  173. * Initialize the MP3 buffer. The NutSegBuf routines provide a global
  174. * system buffer, which works with banked and non-banked systems.
  175. */
  176. if (NutSegBufInit(8192) == 0) {
  177. puts("Error: MP3 buffer init failed");
  178. return;
  179. }
  180. /*
  181. * Initialize the MP3 decoder hardware.
  182. */
  183. if (VsPlayerReset(0)) {
  184. puts("Error: MP3 hardware init failed");
  185. return;
  186. }
  187. /*
  188. * Reset the MP3 buffer.
  189. */
  190. ief = VsPlayerInterrupts(0);
  191. NutSegBufReset();
  192. VsPlayerInterrupts(ief);
  193. last = NutGetSeconds();
  194. while (isStreaming == true) {
  195. /*
  196. * Query number of byte available in MP3 buffer.
  197. */
  198. ief = VsPlayerInterrupts(0);
  199. mp3buf = NutSegBufWriteRequest(&rbytes);
  200. VsPlayerInterrupts(ief);
  201. /*
  202. * If the player is not running, kick it.
  203. */
  204. if (VsGetStatus() != VS_STATUS_RUNNING) {
  205. puts("Not running");
  206. if(rbytes < 1024 || NutGetSeconds() - last > 4UL) {
  207. last = NutGetSeconds();
  208. puts("Kick player");
  209. VsPlayerKick();
  210. }
  211. }
  212. /*
  213. * Do not read pass metadata.
  214. */
  215. if (metaint && rbytes > mp3left) {
  216. rbytes = mp3left;
  217. }
  218. /*
  219. * Read data directly into the MP3 buffer.
  220. */
  221. while (rbytes && (isStreaming == true)) {
  222. if ((got = fread(mp3buf, 1, rbytes, stream)) > 0) {
  223. ief = VsPlayerInterrupts(0);
  224. mp3buf = NutSegBufWriteCommit(got);
  225. VsPlayerInterrupts(ief);
  226. if (metaint) {
  227. mp3left -= got;
  228. if (mp3left == 0) {
  229. ProcessMetaData(stream);
  230. mp3left = metaint;
  231. }
  232. }
  233. if(got < rbytes && got < 512) {
  234. printf("%lu buffered\n", NutSegBufUsed());
  235. NutSleep(250);
  236. }
  237. else {
  238. NutThreadYield();
  239. }
  240. } else {
  241. break;
  242. }
  243. rbytes -= got;
  244. }
  245. if(got <= 0) {
  246. break;
  247. }
  248. }
  249. }