Frank Weissenborn / ShoutCastConnector
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ShoutcastConnector.cpp Source File

ShoutcastConnector.cpp

00001 #include "ShoutcastConnector.h"
00002 
00003 
00004 enum wSTATE {NOP,PUT_HEADER} WriteState;
00005 enum rSTATE {GET_RESPONSE,GET_STREAM} ReadState;
00006 
00007 bool play;
00008 
00009 
00010 int kb = 0;
00011 int readed = 0;
00012 int size = 0;
00013 int metaint=0; // metadate interval
00014 
00015 
00016 
00017 
00018 
00019 ShoutcastConnector::ShoutcastConnector(VS1053* mp3, myCallBack_pfn callback, char *buffer, int buffer_size) {
00020     _mp3 = mp3;
00021     _callback = callback;
00022     _buffer = buffer;
00023     _buffer_size = buffer_size;
00024     ReadState=GET_RESPONSE;
00025     WriteState=PUT_HEADER;
00026 
00027 }
00028 
00029 int ShoutcastConnector::Connect(IpAddr address, int port, const char * path) {
00030 
00031     if ((ReadState!=GET_RESPONSE)||(WriteState!=PUT_HEADER)) {
00032         Disconnect();
00033         //wait
00034         wait_ms(500);
00035     }
00036     _path = path;
00037 
00038     kb = 0;
00039     readed = 0;
00040     size = 0;
00041     metaint=0; // metadate interval
00042     play=false;
00043     
00044     for(int i=0; i< _buffer_size; i++) 
00045         _buffer[i] = 0; // IP input buffer
00046 
00047     Host server(address, port);                  // 128k mp3
00048     IpAddr serverIp = server.getIp();
00049 
00050     DEBUGOUT("ShoutcastConnector: Connecting... %d.%d.%d.%d:%d\r\n",
00051            serverIp[0],serverIp[1],serverIp[2],serverIp[3],port);
00052 
00053 
00054     _sock.setOnEvent(this, &ShoutcastConnector::onTCPSocketEvent);
00055     TCPSocketErr bindErr = _sock.connect(server);
00056 
00057     if (TCPSOCKET_OK != bindErr) {
00058         DEBUGOUT("ShoutcastConnector: Error %d in sock.connect().\r\n", bindErr);
00059         return -1;
00060     }
00061     return 0;
00062 }
00063 
00064 int ShoutcastConnector::Disconnect() {
00065     TCPSocketErr err = _sock.close();
00066 
00067 
00068     if (TCPSOCKET_OK != err) {
00069         DEBUGOUT("ShoutcastConnector: Error %d in Disconnect().\r\n", err);
00070         return -1;
00071     } else {
00072         DEBUGOUT("ShoutcastConnector: disconnected");
00073     }
00074 
00075     _mp3->stop();
00076 
00077     ReadState=GET_RESPONSE;
00078     WriteState=PUT_HEADER;
00079 
00080     return 0;
00081 }
00082 
00083 void ShoutcastConnector::onTCPSocketEvent(TCPSocketEvent e) {
00084     switch (e) {
00085         case TCPSOCKET_CONNECTED:
00086             // DEBUGOUT("TCP Socket Connected\r\n"); // this printf disturb socket work correctly
00087             Writeable();
00088             break; // we must comment out ?
00089         case TCPSOCKET_WRITEABLE:
00090             // DEBUGOUT("TCP Socket Writeable\r\n");
00091             break;
00092         case TCPSOCKET_READABLE:
00093             //Can now read some data...
00094             // DEBUGOUT("TCP Socket Readable\r\n");
00095             Readable();
00096             break;//
00097         case TCPSOCKET_CONTIMEOUT:
00098             DEBUGOUT("ShoutcastConnector: TCP Socket Timeout\r\n");
00099                     
00100             ReadState=GET_RESPONSE;
00101             WriteState=PUT_HEADER;
00102             break;
00103         case TCPSOCKET_CONRST:
00104             DEBUGOUT("ShoutcastConnector: TCP Socket CONRST\r\n");
00105                     
00106             ReadState=GET_RESPONSE;
00107             WriteState=PUT_HEADER;
00108             break;
00109         case TCPSOCKET_CONABRT:
00110             DEBUGOUT("ShoutcastConnector: TCP Socket CONABRT\r\n");
00111             DEBUGOUT("ShoutcastConnector: Maybe Server Down...\r\n");
00112                     
00113             ReadState=GET_RESPONSE;
00114             WriteState=PUT_HEADER;
00115             break;
00116         case TCPSOCKET_ERROR:
00117             DEBUGOUT("ShoutcastConnector: TCP Socket Error\r\n");
00118             break;
00119         case TCPSOCKET_DISCONNECTED:
00120             //Close socket...
00121             DEBUGOUT("ShoutcastConnector: Disconnected\r\n");
00122             _sock.close();
00123             break;
00124     }// switch(e)
00125 }
00126 
00127 void ShoutcastConnector::Writeable() {
00128    
00129     switch (WriteState) {
00130         case PUT_HEADER:  
00131              strcpy(_buffer,"GET ");
00132              strcat(_buffer,_path);
00133              strcat(_buffer, " HTTP/1.0\r\nHost: gw\r\nAccept: */*\r\nUser-Agent: mbed\r\nIcy-MetaData: 1\r\n\r\n");   
00134              
00135             DEBUGOUT("\r\nShoutcastConnector: HEADER:\r\n%s\r\n", _buffer); // display PUT_HEADER
00136                  
00137             _sock.send(_buffer, strlen(_buffer));
00138             
00139             WriteState=NOP;
00140             ReadState=GET_RESPONSE;
00141             break;
00142         case NOP:
00143             break;
00144     } // switch(WriteState)
00145 }
00146 
00147 
00148 void ShoutcastConnector::Readable() {
00149     int len = 0, i=0;
00150     char* cp;
00151 
00152     switch (ReadState) {
00153         case GET_RESPONSE:
00154         for(int j=0; j<_buffer_size; j++)
00155             _buffer[j] = 0x00;
00156             
00157          len=_sock.recv(_buffer, _buffer_size);
00158             cp=strstr(_buffer,"\r\n\r\n");
00159             if (cp==NULL) {
00160                 _buffer[len]=0;
00161                  DEBUGOUT("%s", _buffer); // debug
00162                 return;  // still read response again
00163             }
00164             //
00165             *cp=0;
00166             
00167             DEBUGOUT("ShoutcastConnector: RESPONSE:\r\n%s",_buffer);
00168             // get metaint value
00169             cp=strstr(_buffer,"icy-metaint:");
00170             if (cp==NULL) metaint=0;
00171             else sscanf(cp+strlen("icy-metaint:"),"%d",&metaint);
00172             DEBUGOUT("\r\nShoutcastConnector: metaint: %d\r\n\r\n",metaint); //debug
00173             //
00174             
00175             DEBUGOUT("ShoutcastConnector: HeaderLen:%d\r\n",len);
00176             
00177             i=strlen(_buffer)+4; // bump bitstream right after response
00178             ReadState=GET_STREAM;
00179             //initDec();
00180             //
00181             while (i<len) {
00182                 // write one bye
00183                // sbuf.PutByte(inbuf[i]);
00184                 i++;
00185                 readed++;
00186             };
00187             return;
00188             //
00189         case GET_STREAM:
00190             // receive data ****repeatedly****
00191             while ((len=_sock.recv(_buffer, _buffer_size)) != 0x00) {
00192 
00193 
00194                 kb += len;
00195 
00196 
00197                 if (metaint > 0) {
00198                     if (readed + len > metaint) {
00199                         //XXX
00200                         int startindex = metaint-readed;
00201                         size = _buffer[startindex];
00202                         //Send first part of data
00203                         while (_mp3->bufferFree() < startindex)
00204                             ;                                   // wait
00205                         _mp3->bufferPutStream(_buffer, startindex);
00206 
00207                         if (size>0) {
00208                             //1.Fall : (metaint-readed)+size <= len
00209                             //Text ausgeben
00210                             //rest an mp3 codec
00211                             if ((metaint-readed)+size <= len) {
00212                                 int start =-1;
00213                                 int length = -1;
00214 
00215                                 for (int i = startindex + 1; i < startindex + 1 + size*16; i++) {
00216                                 
00217                                     if (_buffer[i] == '\'') {
00218                                         if (start == -1)
00219                                             start = i+1-(startindex+1);
00220                                         else {
00221                                             if(_buffer[i+1] == ';')
00222                                                 {
00223                                                     length = (i - (startindex+1)) - start; //last indexs - first index
00224                                                     break;
00225                                                 }
00226                                         }
00227                                         
00228                                     }
00229 
00230                                 }
00231                                 _callback(&_buffer[startindex + 1], size*16, start ,length);
00232                                 //Send last part of data
00233                                 while (_mp3->bufferFree() < len-(startindex+1+size*16))
00234                                     ;                                   // wait
00235                                 readed = len-(startindex+1+size*16);
00236                                 _mp3->bufferPutStream(&_buffer[startindex+1+size*16], readed);
00237                             } else {
00238                                 DEBUGOUT("ShoutcastConnector: Muh")
00239                             }
00240                         } else {
00241                             //Send second part of data
00242                             //XXX
00243                             while (_mp3->bufferFree() < len-(startindex+1))
00244                                 ;                                   // wait
00245                             //XXX
00246                             readed = len-(startindex+1);
00247                             _mp3->bufferPutStream(&_buffer[startindex+1], len-(startindex+1));
00248 
00249                         }
00250                     } else {
00251                         readed += len;
00252                         while (_mp3->bufferFree() < len)
00253                             ;                                   // wait
00254                         _mp3->bufferPutStream(_buffer, len);
00255                     }
00256                 } else {
00257                     while (_mp3->bufferFree() < len)
00258                         ;                                   // wait
00259                     _mp3->bufferPutStream(_buffer, len);
00260                 }
00261 
00262 
00263 
00264                 if (!play && _mp3->bufferCount() > 0.8 * _mp3->bufferLength()) {
00265                     _mp3->play();
00266                     play = true;
00267                 }
00268 
00269                 if (play &&  _mp3->bufferCount() < 0.1 * _mp3->bufferLength()) {
00270                     _mp3->pause();
00271                     play = false;
00272                 }
00273 
00274 
00275             } // while (len=sock...)
00276 
00277 
00278 
00279             return; // get more strea
00280     } // switch (ReadState)
00281 }