httpstream.c 6.3 KB

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