![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Stream Ripper This program will download MP3 data from SHOUTcast stream and save mp3 file in microSD card. Metadata also will be saved as another file when stream includes metadata.
Dependencies: EthernetNetIf mbed SDFileSystem
Revision 0:5490b791ee3d, committed 2010-09-20
- Comitter:
- xshige
- Date:
- Mon Sep 20 06:47:33 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetNetIf.lib Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_unsupported/code/fatfilesystem/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient/.meta Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<root> + <global/> + <data> + <created_ts>1284931111</created_ts> + <last_mod_ts>1284931789</last_mod_ts> + <is_archive>0</is_archive> + <is_published>0</is_published> + <is_svn>0</is_svn> + <is_module>0</is_module> + <is_lib>1</is_lib> + <url>http://mbed.org/users/donatien/programs/NTPClient</url> + <rev>5z0s7</rev> + <url_full>http://mbed.org/users/donatien/programs/NTPClient/5z0s7</url_full> + </data> +</root>
Binary file NTPClient/LPC1768/NTPClient.ar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient/LPC1768/dbg/dbg.h Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,94 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file +Debugging helpers header file +*/ + +//#ifdef DBG_H +//#define DBG_H + +#ifdef __LWIP_DEBUG +#define __DEBUG +#endif + +/*! + \def __DEBUG + To define to enable debugging in one file +*/ + +#ifdef __DEBUG + +#ifndef __DEBUGSTREAM +#define __DEBUGSTREAM + + +class DebugStream +{ +public: +static void debug(const char* format, ...); +static void release(); +static void breakPoint(const char* file, int line); +private: + +}; + +#undef DBG +#undef DBG_END +#undef BREAK + +///Debug output (if enabled), same syntax as printf, with heading info +#define DBG(...) do{ DebugStream::debug("[%s:%s@%d] ", __FILE__, __FUNCTION__, __LINE__); DebugStream::debug(__VA_ARGS__); } while(0); + +///Debug output (if enabled), same syntax as printf, no heading info +#define DBGL(...) do{ DebugStream::debug(__VA_ARGS__); } while(0); +#define DBG_END DebugStream::release + +///Break point usin serial debug interface (if debug enbaled) +#define BREAK() DebugStream::breakPoint(__FILE__, __LINE__) +#endif + +#else +#undef DBG +#undef DBG_END +#undef BREAK +#define DBG(...) +#define DBG_END() +#define BREAK() +#endif + +#ifdef __LWIP_DEBUG +#ifndef __SNPRINTF +#define __SNPRINTF +#include "mbed.h" + +//int snprintf(char *str, int size, const char *format, ...); +#endif +#endif + +#ifdef __LWIP_DEBUG +#undef __DEBUG +#endif + +//#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient/LPC1768/services/ntp/NTPClient.h Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,200 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file +NTP Client header file +*/ + +#ifndef NTP_CLIENT_H +#define NTP_CLIENT_H + +#include "core/net.h" +#include "core/netservice.h" +#include "api/UDPSocket.h" +#include "api/DNSRequest.h" +#include "mbed.h" + +///NTP Client results +enum NTPResult +{ + NTP_OK, ///<Success + NTP_PROCESSING, ///<Processing + NTP_PRTCL, ///<Protocol error + NTP_TIMEOUT, ///<Connection timeout + NTP_DNS ///<Could not resolve DNS hostname +}; + +///A NTP Client +/** +The NTP client is a simple UDP client that will update the mbed's RTC +*/ +class NTPClient : protected NetService +{ +public: + /** + Instantiates the NTP client + */ + NTPClient(); + virtual ~NTPClient(); + + //High level setup functions + + ///Gets current time (blocking) + /** + Updates the time using the server host + Blocks until completion + @param host : NTP server + */ + NTPResult setTime(const Host& host); //Blocking + + ///Gets current time (non-blocking) + /** + Updates the time using the server host + The function returns immediately and calls the callback on completion or error + @param host : NTP server + @param pMethod : callback function + */ + NTPResult setTime(const Host& host, void (*pMethod)(NTPResult)); //Non blocking + + ///Gets current time (non-blocking) + /** + Updates the time + @param host : NTP server + @param pItem : instance of class on which to execute the callback method + @param pMethod : callback method + The function returns immediately and calls the callback on completion or error + */ + template<class T> + NTPResult setTime(const Host& host, T* pItem, void (T::*pMethod)(NTPResult)) //Non blocking + { + setOnResult(pItem, pMethod); + doSetTime(host); + return NTP_PROCESSING; + } + + ///Gets current time (non-blocking) + /** + Updates the time using the server host + The function returns immediately and calls the previously set callback on completion or error + @param host : NTP server + */ + void doSetTime(const Host& host); + + ///Setups the result callback + /** + @param pMethod : callback function + */ + void setOnResult( void (*pMethod)(NTPResult) ); + + ///Setups the result callback + /** + @param pItem : instance of class on which to execute the callback method + @param pMethod : callback method + */ + class CDummy; + template<class T> + void setOnResult( T* pItem, void (T::*pMethod)(NTPResult) ) + { + m_pCbItem = (CDummy*) pItem; + m_pCbMeth = (void (CDummy::*)(NTPResult)) pMethod; + } + + void close(); + +protected: + virtual void poll(); //Called by NetServices + +private: + void init(); + void open(); + + __packed struct NTPPacket //See RFC 4330 for Simple NTP + { + //WARN: We are in LE! Network is BE! + //LSb first + unsigned mode : 3; + unsigned vn : 3; + unsigned li : 2; + + uint8_t stratum; + uint8_t poll; + uint8_t precision; + //32 bits header + + uint32_t rootDelay; + uint32_t rootDispersion; + uint32_t refId; + + uint32_t refTm_s; + uint32_t refTm_f; + uint32_t origTm_s; + uint32_t origTm_f; + uint32_t rxTm_s; + uint32_t rxTm_f; + uint32_t txTm_s; + uint32_t txTm_f; + }; + + void process(); //Main state-machine + + void setTimeout(int ms); + void resetTimeout(); + + void onTimeout(); //Connection has timed out + void onDNSReply(DNSReply r); + void onUDPSocketEvent(UDPSocketEvent e); + void onResult(NTPResult r); //Called when exchange completed or on failure + + NTPResult blockingProcess(); //Called in blocking mode, calls Net::poll() until return code is available + + UDPSocket* m_pUDPSocket; + + enum NTPStep + { + NTP_PING, + NTP_PONG + }; + + NTPStep m_state; + + NTPPacket m_pkt; + + CDummy* m_pCbItem; + void (CDummy::*m_pCbMeth)(NTPResult); + + void (*m_pCb)(NTPResult); + + Timer m_watchdog; + int m_timeout; + + bool m_closed; + + Host m_host; + + DNSRequest* m_pDnsReq; + + NTPResult m_blockingResult; //Result if blocking mode + +}; + +#endif
Binary file NTPClient/LPC2368/NTPClient.ar has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient/LPC2368/dbg/dbg.h Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,94 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file +Debugging helpers header file +*/ + +//#ifdef DBG_H +//#define DBG_H + +#ifdef __LWIP_DEBUG +#define __DEBUG +#endif + +/*! + \def __DEBUG + To define to enable debugging in one file +*/ + +#ifdef __DEBUG + +#ifndef __DEBUGSTREAM +#define __DEBUGSTREAM + + +class DebugStream +{ +public: +static void debug(const char* format, ...); +static void release(); +static void breakPoint(const char* file, int line); +private: + +}; + +#undef DBG +#undef DBG_END +#undef BREAK + +///Debug output (if enabled), same syntax as printf, with heading info +#define DBG(...) do{ DebugStream::debug("[%s:%s@%d] ", __FILE__, __FUNCTION__, __LINE__); DebugStream::debug(__VA_ARGS__); } while(0); + +///Debug output (if enabled), same syntax as printf, no heading info +#define DBGL(...) do{ DebugStream::debug(__VA_ARGS__); } while(0); +#define DBG_END DebugStream::release + +///Break point usin serial debug interface (if debug enbaled) +#define BREAK() DebugStream::breakPoint(__FILE__, __LINE__) +#endif + +#else +#undef DBG +#undef DBG_END +#undef BREAK +#define DBG(...) +#define DBG_END() +#define BREAK() +#endif + +#ifdef __LWIP_DEBUG +#ifndef __SNPRINTF +#define __SNPRINTF +#include "mbed.h" + +//int snprintf(char *str, int size, const char *format, ...); +#endif +#endif + +#ifdef __LWIP_DEBUG +#undef __DEBUG +#endif + +//#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NTPClient/LPC2368/services/ntp/NTPClient.h Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,200 @@ + +/* +Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** \file +NTP Client header file +*/ + +#ifndef NTP_CLIENT_H +#define NTP_CLIENT_H + +#include "core/net.h" +#include "core/netservice.h" +#include "api/UDPSocket.h" +#include "api/DNSRequest.h" +#include "mbed.h" + +///NTP Client results +enum NTPResult +{ + NTP_OK, ///<Success + NTP_PROCESSING, ///<Processing + NTP_PRTCL, ///<Protocol error + NTP_TIMEOUT, ///<Connection timeout + NTP_DNS ///<Could not resolve DNS hostname +}; + +///A NTP Client +/** +The NTP client is a simple UDP client that will update the mbed's RTC +*/ +class NTPClient : protected NetService +{ +public: + /** + Instantiates the NTP client + */ + NTPClient(); + virtual ~NTPClient(); + + //High level setup functions + + ///Gets current time (blocking) + /** + Updates the time using the server host + Blocks until completion + @param host : NTP server + */ + NTPResult setTime(const Host& host); //Blocking + + ///Gets current time (non-blocking) + /** + Updates the time using the server host + The function returns immediately and calls the callback on completion or error + @param host : NTP server + @param pMethod : callback function + */ + NTPResult setTime(const Host& host, void (*pMethod)(NTPResult)); //Non blocking + + ///Gets current time (non-blocking) + /** + Updates the time + @param host : NTP server + @param pItem : instance of class on which to execute the callback method + @param pMethod : callback method + The function returns immediately and calls the callback on completion or error + */ + template<class T> + NTPResult setTime(const Host& host, T* pItem, void (T::*pMethod)(NTPResult)) //Non blocking + { + setOnResult(pItem, pMethod); + doSetTime(host); + return NTP_PROCESSING; + } + + ///Gets current time (non-blocking) + /** + Updates the time using the server host + The function returns immediately and calls the previously set callback on completion or error + @param host : NTP server + */ + void doSetTime(const Host& host); + + ///Setups the result callback + /** + @param pMethod : callback function + */ + void setOnResult( void (*pMethod)(NTPResult) ); + + ///Setups the result callback + /** + @param pItem : instance of class on which to execute the callback method + @param pMethod : callback method + */ + class CDummy; + template<class T> + void setOnResult( T* pItem, void (T::*pMethod)(NTPResult) ) + { + m_pCbItem = (CDummy*) pItem; + m_pCbMeth = (void (CDummy::*)(NTPResult)) pMethod; + } + + void close(); + +protected: + virtual void poll(); //Called by NetServices + +private: + void init(); + void open(); + + __packed struct NTPPacket //See RFC 4330 for Simple NTP + { + //WARN: We are in LE! Network is BE! + //LSb first + unsigned mode : 3; + unsigned vn : 3; + unsigned li : 2; + + uint8_t stratum; + uint8_t poll; + uint8_t precision; + //32 bits header + + uint32_t rootDelay; + uint32_t rootDispersion; + uint32_t refId; + + uint32_t refTm_s; + uint32_t refTm_f; + uint32_t origTm_s; + uint32_t origTm_f; + uint32_t rxTm_s; + uint32_t rxTm_f; + uint32_t txTm_s; + uint32_t txTm_f; + }; + + void process(); //Main state-machine + + void setTimeout(int ms); + void resetTimeout(); + + void onTimeout(); //Connection has timed out + void onDNSReply(DNSReply r); + void onUDPSocketEvent(UDPSocketEvent e); + void onResult(NTPResult r); //Called when exchange completed or on failure + + NTPResult blockingProcess(); //Called in blocking mode, calls Net::poll() until return code is available + + UDPSocket* m_pUDPSocket; + + enum NTPStep + { + NTP_PING, + NTP_PONG + }; + + NTPStep m_state; + + NTPPacket m_pkt; + + CDummy* m_pCbItem; + void (CDummy::*m_pCbMeth)(NTPResult); + + void (*m_pCb)(NTPResult); + + Timer m_watchdog; + int m_timeout; + + bool m_closed; + + Host m_host; + + DNSRequest* m_pDnsReq; + + NTPResult m_blockingResult; //Result if blocking mode + +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/simon/code/SDFileSystem/#b1ddfc9a9b25
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,645 @@ + +// Stream Ripper +// +// This program will download MP3 data from SHOUTcast stream +// and save mp3 file in microSD card. +// Metadata also will be saved as another file +// when stream includes metadata. +// +// written by: xshige + +// 2010/9/20 version 0.5 + +// Set Recording Size for Downloading +// 1MB means around 1 minutes play (assume 128kbps) +#define RECSIZE (15*1000000) + +// define this if you want metadata stream +#define METADATA + +#include "mbed.h" +#include "EthernetNetIf.h" +#include "TCPSocket.h" +#include "NTPClient.h" + +// define this if you use DHCP +#define DHCP + +// define this if you use time&date as output file name +#define TDFILE + +#define WRTFILE +#ifdef WRTFILE +#include "SDFileSystem.h" +SDFileSystem sd(p5, p6, p7, p8, "sd"); +#endif + + +// maybe we need 4KB at least +#define SBUFSIZE (1024*4) +//#define SBUFSIZE (1024*8) +//#define SBUFSIZE (1024*16) //NG +//#define SBUFSIZE (1024*10) //NG + +//#define TICK_DRIVEN + +NTPClient ntp; +time_t ctTime; + +/* +---------------- + +Message Smaples + +*/ + +// Client Side: + +// GET /live HTTP/1.0 +// Host: gw +// Accept: */* +// User-Agent: mbed +// Icy-MetaData: 1 +// Connection: close + + +/* + +Server#0 Resopose: + +HTTP/1.0 200 OK +Content-Type: audio/mpeg +icy-br:96 +ice-audio-info: ice-samplerate=44100;ice-bitrate=96;ice-channels=2 +icy-br:96 +icy-description:www.SoloPianoRadio.com +icy-genre:Classical +icy-name:Whisperings: Solo Piano Radio +icy-pub:1 +icy-url:http://www.solopianoradio.com +Server: Icecast 2.3.1 +icy-metaint:16000 + + +Server#1 Resopose: + +ICY 200 OK +icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR> +icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.8<BR> +icy-name:SMOOTHJAZZ.COM - The Internet's Original Smooth Jazz Radio Station - Live from the Monterey Bay +icy-genre:Smooth Jazz +icy-url:http://www.smoothjazz.com +content-type:audio/mpeg +icy-pub:1 +icy-metaint:32768 +icy-br:128 + +------------------------ +Notes: + +* icy-metadata:1 +a client can request to have metadata +(information about the music - ) included in the stream, +by adding this. + +* ICY [CODE] +whereas code refers to http status code +(200 - ok, 404 - resource not found, 401 - service unavailable, etc.). + +* icy-pub + - Not sure, believe it indicates if the stream is public or private + +* icy-metaint + - an interval (in bytes) that specifies how often metadata updates + will be sent to the client. + +* icy-br + - BitRate, seems mostly informational as most clients + encountered seem to support VBR (Variable BitRate). + +------------------------- +*/ + +#ifdef DHCP +EthernetNetIf eth; +#else +EthernetNetIf eth( + IpAddr(192,168,0,25), //IP Address + IpAddr(255,255,255,0), //Network Mask + IpAddr(192,168,0,1), //Gateway + IpAddr(192,168,0,1) //DNS +); +#endif + +DigitalOut led1(LED1, "led1"); +DigitalOut led2(LED2, "led2"); +DigitalOut led3(LED3, "led3"); +DigitalOut led4(LED4, "led4"); + +TCPSocket sock; +char inbuf[2048]; // IP input buffer +char* cp; + +// stream +int slen; // stream length +unsigned long int tlen=0; // total lenth of downloaded file + + +//------------------------------------------------- + +class RingBuffer +{ + protected: + unsigned char *buffer; + int buffersize; + int rp; // read index + int wp; // write index + + public: + RingBuffer(int bufsiz) + { + buffersize = bufsiz; + + buffer = new unsigned char[buffersize]; + // memset(buffer, 0, sizeof(char) * buffersize); + + // reset pointer to make empty + rp = 0; + wp = 0; + }; + + ~RingBuffer(void) + { + delete[] buffer; + }; + + int GetByte(unsigned char *cp); + int PutByte(unsigned char c); + int IsEmpty(void); +}; + + +int RingBuffer::GetByte(unsigned char *cp ) +{ + if( rp != wp ) { // not empty + *cp = buffer[rp]; + rp = (rp + 1) % buffersize; + return 0; + } else { // empty + return -1; + } +} + + +int RingBuffer::PutByte(unsigned char c ) +{ + int next = (wp + 1) % buffersize; + if( next == rp ) { + printf("*** Buffer Full ***\r\n" ); +// printf("*");//debug + return -1; + } + buffer[wp] = c; + wp = next; + return 0; +} + + +int RingBuffer::IsEmpty(void) +{ + return (rp==wp)?(true):(false); +} + +//----------------- + + +// create RingBuffer +RingBuffer sbuf(SBUFSIZE); // + + +char sResponse[800]; // keeps Stream Response +char sMetadata[200]; // keeps Stream Metadata +char sPrevMetadata[200]; // keeps Previous Stream Metadata + +// client state +enum wSTATE{NOP,PUT_HEADER} WriteState; +enum rSTATE{GET_RESPONSE,GET_STREAM} ReadState; + +// metadata +char mbuf[512]; +int mbyte; // lenth byte, -1 means this value is not effective +int mlen; // metadata length +int metaint=0; // metadate interval + +void initDec(void); // prototype + + +void onTCPSocketEvent(TCPSocketEvent e) { + int i,len; + switch (e) { + case TCPSOCKET_CONNECTED: + printf("TCP Socket Connected\r\n"); // this printf disturb socket work correctly +// break; // we must comment out ? + case TCPSOCKET_WRITEABLE: + //Can now write some data... +// printf("TCP Socket Writable\r\n"); // debug + switch(WriteState) { + case PUT_HEADER: + const char* str = +// "GET /live HTTP/1.0\r\n" // use this if solopiano + "GET / HTTP/1.0\r\n" + "Host: gw\r\n" + "Accept: */*\r\n" + "User-Agent: mbed\r\n" +#ifdef METADATA + "Icy-MetaData: 1\r\n" // send this if you want Metadata +#endif +// "Connection: close\r\n" + "\r\n" + ; + sock.send(str, strlen(str)); + printf("\r\nHEADER:\r\n%s\r\n", str); // display PUT_HEADER + WriteState=NOP; + ReadState=GET_RESPONSE; + break; + case NOP: + break; + } // switch(WriteState) + break; + case TCPSOCKET_READABLE: + //Can now read some data... +// printf("TCP Socket Readable\r\n"); // debug + switch(ReadState) { + case GET_RESPONSE: + len=sock.recv(inbuf, sizeof inbuf); + cp=strstr(inbuf,"\r\n\r\n"); + if (cp==NULL) { + inbuf[len]=0; + // printf("%s",inbuf); // debug + sprintf(sResponse,"%s",inbuf); + return; // still read response again + } + // + *cp=0; + sprintf(sResponse+strlen(sResponse),"%s\r\n\r\n",inbuf); + printf("RESPONSE:\r\n%s",sResponse); + // get metaint value + cp=strstr(sResponse,"icy-metaint:"); + if (cp==NULL) metaint=0; else sscanf(cp+strlen("icy-metaint:"),"%d",&metaint); + printf("\r\nmetaint: %d\r\n\r\n",metaint); //debug + // + i=strlen(inbuf)+4; // bump bitstream right after response + ReadState=GET_STREAM; + initDec(); + // + while(i<len) { + // write one bye + sbuf.PutByte(inbuf[i]);i++; + }; + return; + break; + // + case GET_STREAM: + // receive data ****repeatedly**** + while(len=sock.recv(inbuf, sizeof inbuf)) { + i=0; + // save len bytes + while (i<len) { + sbuf.PutByte(inbuf[i]);i++; + } + } // while (len=sock...) + return; // get more stream + break; + // + } // switch (ReadState) + break;// + case TCPSOCKET_CONTIMEOUT: + printf("TCP Socket Timeout\r\n"); + break; + case TCPSOCKET_CONRST: + printf("TCP Socket CONRST\r\n"); + break; + case TCPSOCKET_CONABRT: + printf("TCP Socket CONABRT\r\n"); + printf("Maybe Server Down...\r\n"); + break; + case TCPSOCKET_ERROR: + printf("TCP Socket Error\r\n"); + break; + case TCPSOCKET_DISCONNECTED: + //Close socket... + printf("TCP Socket Disconnected\r\n"); + sock.close(); + break; + }// switch(e) +} + + +//-------------------------------- + + +#ifdef WRTFILE +FILE *fp, *fp2; +char outfile1[32]; +char outfile2[32]; +#endif + +void initDec(void) { + slen=0;mbyte=-1;mlen=0; +#ifdef WRTFILE +#ifdef TDFILE +// char outfile[32]; + // make output file for MP3 + ctTime=time(NULL); + struct tm *t=localtime(&ctTime); + sprintf(outfile1,"/sd/%02d%02d%02d%02d.mp3", +// t->tm_year+1900, + t->tm_mon+1, + t->tm_mday, + t->tm_hour, + t->tm_min); +// printf("%s\r\n",outfile); //debug + fp = fopen(outfile1, "wb"); +#else + fp = fopen("/sd/stream.mp3", "wb"); +#endif + if(fp == NULL) { + error("Could not open file for download\n"); + } +#ifdef METADATA +#ifdef TDFILE + // make output file for Metadata + sprintf(outfile2,"/sd/%02d%02d%02d%02d.met", +// t->tm_year+1900, + t->tm_mon+1, + t->tm_mday, + t->tm_hour, + t->tm_min); +// printf("%s\r\n",outfile); //debug + fp2 = fopen(outfile2, "w"); +#else + fp2 = fopen("/sd/stream.met", "w"); +#endif + if(fp2 == NULL) { + error("Could not open file for metadata\n"); + } + ctTime=time(NULL); // get seconds + fprintf(fp2,"%s\n%s\n---------------\n", + sResponse,ctime(&ctTime)); // write stream information on file +#endif + // display time&date + ctTime = time(NULL); // get seconds + printf("%s\r\n", ctime(&ctTime)); + // + float edt=(RECSIZE)/1000000; + if (metaint==0) { + printf("Now Downloading(Metadata-less Stream)...\r\n"); + printf("Estimated Donwload Time: %3.2f minutes\r\n\r\n",edt); + } else { + printf("Now Downloading(Stream with Metadata)...\r\n"); + printf("Estimated Donwload Time: %3.2f minutes\r\n\r\n",edt); + } +#endif + return; +} + +void sendDec(unsigned char sbyte) { + unsigned char wc=sbyte; + if (metaint==0) { + // we have no metadata in a stream + // put one byte to decoder +#ifdef WRTFILE + fwrite(&wc,1,1,fp); +// fputc(sbyte,fp); ///// + tlen++; + if (tlen==RECSIZE) { + fclose(fp); + printf("\r\n*** Download Complete.***\r\n"); + while(true); // dynamic stop + } +#endif + return; + } + // + if (slen==metaint) { + mbyte=sbyte; + mlen=0; + slen++; + return; + } + // + if (mbyte==-1) { + // put one byte to decoder +#ifdef WRTFILE + fwrite(&wc,1,1,fp); +// fputc(sbyte,fp); ///// +#endif +#if 1 + if (0!=strcmp(sMetadata,sPrevMetadata)) { + printf("Metadata: %s\r\n",sMetadata); // display metadata +// printf("mbyte:%d slen:%d tlen:%d\r\n\r\n",mbyte,slen,tlen); // debug + printf("tlen:%d\r\n\r\n",tlen); // display total length + sprintf(sPrevMetadata,"%s",sMetadata); // copy to previous +///// fclose(fp);fp=fopen(outfile1,"ab"); // switch append mode +///// fclose(fp2);fp2=fopen(outfile2,"a"); + fprintf(fp2,"%d\n%s\n",tlen,sMetadata); // save metadata on TXT file + + } +#endif + slen++; + tlen++; + return; + } + // + // comming here when we are in reading metadata + if (slen==(metaint+16*mbyte+1)) { + // we have all bytes for metadata + mbuf[mlen]=0; // make terminator + if (0<mbyte) { + sprintf(sMetadata,"%s",mbuf); // coy new metadata + } +#ifdef WRTFILE + fwrite(&wc,1,1,fp); +// fputc(sbyte,fp); //// + tlen++; + if (tlen>RECSIZE) { + printf("\r\n*** Download Complete.***\r\n"); + fclose(fp);fclose(fp2); + // display time&date + ctTime = time(NULL); // get seconds in UTC + printf("%s\r\n", ctime(&ctTime)); + while(true); // dynamic stop + } +#endif + // printf("metaint: %d slen:%d\r\n",metaint,slen); //debug + mbyte=-1;mlen=0; + slen=1; //OK + return; + } // if (slen==(metaint+16*mbyte+1)) + // + // coming here still reading metadata + // we still read one byte of metadata + mbuf[mlen]=sbyte;mlen++; slen++; + return; +} + + +#ifdef TICK_DRIVEN +void TickProcess(void) { + int x; + for(x=0;x<(SBUFSIEZ/2);x++) { + unsigned char sbyte; + if (-1==sbuf.GetByte(&sbyte)) { + // Net::poll(); + return; + } + sendDec(sbyte); + } + return; +} + +//----------------------- + +Ticker tick; +#endif + +int main() { + +// set_time(); + + // make debug port Fast + Serial pc(USBTX, USBRX); +// pc.baud(9600); + pc.baud(115200); +// pc.baud(230400); + +// init string +sprintf(sResponse,""); + +// init medatadata string +sprintf(sMetadata,"StreamTitle='Currently, Unknown';"); +sprintf(sPrevMetadata,""); + + + + printf("\r\n"); + printf("Setting up...\r\n"); + + EthernetErr ethErr = eth.setup(); + if (ethErr) { + printf("Error %d in setup.\r\n", ethErr); + return -1; + }; + +// Init State for Read/Write + ReadState=GET_RESPONSE; + WriteState=PUT_HEADER; + + +//---------------------------------- +// setup clock for time stamp +// NTPClient ntp; +// time_t ctTime; + + Host timeServer(IpAddr(), 123, "0.uk.pool.ntp.org"); + ntp.setTime(timeServer); + + ctTime = time(NULL); // get seconds in UTC + ctTime = ctTime+(3600*9); // convert JST (please change to fit your localtime) + set_time(ctTime); // re-setup RTC + printf("\r\nTime is setup now (JST): %s\r\n", ctime(&ctTime)); + +#if 0 +// test program for time + ctTime=time(NULL); + struct tm *t=localtime(&ctTime); + printf("%4d %02d/%02d %02d:%02d:%02d\r\n\r\n", + t->tm_year+1900, + t->tm_mon+1, + t->tm_mday, + t->tm_hour, + t->tm_min, + t->tm_sec); +#endif + +//----------------------------- + + printf("Setup OK\r\n"); + + +// ************** STATION DEFINITIONS ************** + +//// http://pianosolo.streamguys.net:80/live +//Host server(IpAddr(216,246,105,11), 80); //solo piano +//Host server(IpAddr(), 80,"pianosolo.streamguys.net"); //solo piano + +// SMOOTHJAZZ.COM - The Internet's Original Smooth Jazz Radio Station +// - Live from the Monterey Bay +// Host server(IpAddr(67,213,217,212), 80); //smooth jazz + +//Folk Alley (( All Folk. All The Time. )) +// http://66.225.205.8:8000 + Host server(IpAddr(66,225,205,8), 8000); + +// 1-ONE NATION FM.COM GOSPEL RADIO +// http://208.85.240.2:8094 +// Host server(IpAddr(208,85,240,2), 8094); + + +// GotRadio - Celti +//http://64.62.164.211:3000 +// Host server(IpAddr(64,62,164,211), 3000); + +// AnimeNfo Radio | Serving you the best Anime music! +//http://216.18.227.252:8000 +// Host server(IpAddr(216,18,227,252), 8000); + +// ************** end of STATION DEFINITIONS ************** + + // display IP address and port# of server + IpAddr serverIp = server.getIp(); + int port = server.getPort(); + printf("Connecting... %d.%d.%d.%d:%d\r\n", + serverIp[0],serverIp[1],serverIp[2],serverIp[3],port); + + + TCPSocketErr bindErr = sock.connect(server); + + sock.setOnEvent(&onTCPSocketEvent); + + Timer tmr; + tmr.start(); + +#ifdef TICK_DRIVEN + tick.attach(&TickProcess,0.1); // 100ms tick, this interval depens on SBUFSIZE +#endif + + while (true) { + Net::poll(); + +#ifndef TICK_DRIVEN + int x; + for(x=0;x<(SBUFSIZE/2);x++) { + unsigned char sbyte; + if (-1==sbuf.GetByte(&sbyte)) { + // Net::poll(); + break; + } + sendDec(sbyte); + } +#endif + if (tmr.read() > 0.05) { + tmr.reset(); + if (metaint>0) { + led4=!led4; //Show that we are alive + if ((metaint/4)<slen) led3=1; else led3=0; + if ((metaint*2/4)<slen) led2=1; else led2=0; + if ((metaint*3/4)<slen) led1=1; else led1=0; + } else { + led1=!led1; // indicate no metadata + led4=0; + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Sep 20 06:47:33 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e