Committer:
FrankWeissenborn
Date:
Wed Feb 02 20:08:24 2011 +0000
Revision:
6:e269a1b3bf4f
Parent:
5:36d14584e42f

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
FrankWeissenborn 1:25ceaa587f6b 1 #include "ShoutcastConnector.h"
FrankWeissenborn 1:25ceaa587f6b 2
FrankWeissenborn 3:87023c28aff5 3
FrankWeissenborn 1:25ceaa587f6b 4 enum wSTATE {NOP,PUT_HEADER} WriteState;
FrankWeissenborn 1:25ceaa587f6b 5 enum rSTATE {GET_RESPONSE,GET_STREAM} ReadState;
FrankWeissenborn 1:25ceaa587f6b 6
FrankWeissenborn 1:25ceaa587f6b 7 bool play;
FrankWeissenborn 1:25ceaa587f6b 8
FrankWeissenborn 1:25ceaa587f6b 9
FrankWeissenborn 1:25ceaa587f6b 10 int kb = 0;
FrankWeissenborn 3:87023c28aff5 11 int readed = 0;
FrankWeissenborn 3:87023c28aff5 12 int size = 0;
FrankWeissenborn 1:25ceaa587f6b 13 int metaint=0; // metadate interval
FrankWeissenborn 1:25ceaa587f6b 14
FrankWeissenborn 1:25ceaa587f6b 15
FrankWeissenborn 1:25ceaa587f6b 16
FrankWeissenborn 1:25ceaa587f6b 17
FrankWeissenborn 3:87023c28aff5 18
FrankWeissenborn 5:36d14584e42f 19 ShoutcastConnector::ShoutcastConnector(VS1053* mp3, myCallBack_pfn callback, char *buffer, int buffer_size) {
FrankWeissenborn 1:25ceaa587f6b 20 _mp3 = mp3;
FrankWeissenborn 1:25ceaa587f6b 21 _callback = callback;
FrankWeissenborn 5:36d14584e42f 22 _buffer = buffer;
FrankWeissenborn 5:36d14584e42f 23 _buffer_size = buffer_size;
FrankWeissenborn 3:87023c28aff5 24 ReadState=GET_RESPONSE;
FrankWeissenborn 3:87023c28aff5 25 WriteState=PUT_HEADER;
FrankWeissenborn 3:87023c28aff5 26
FrankWeissenborn 1:25ceaa587f6b 27 }
FrankWeissenborn 1:25ceaa587f6b 28
FrankWeissenborn 6:e269a1b3bf4f 29 int ShoutcastConnector::Connect(IpAddr address, int port, const char * path) {
FrankWeissenborn 3:87023c28aff5 30
FrankWeissenborn 3:87023c28aff5 31 if ((ReadState!=GET_RESPONSE)||(WriteState!=PUT_HEADER)) {
FrankWeissenborn 3:87023c28aff5 32 Disconnect();
FrankWeissenborn 3:87023c28aff5 33 //wait
FrankWeissenborn 3:87023c28aff5 34 wait_ms(500);
FrankWeissenborn 3:87023c28aff5 35 }
FrankWeissenborn 5:36d14584e42f 36 _path = path;
FrankWeissenborn 3:87023c28aff5 37
FrankWeissenborn 1:25ceaa587f6b 38 kb = 0;
FrankWeissenborn 1:25ceaa587f6b 39 readed = 0;
FrankWeissenborn 1:25ceaa587f6b 40 size = 0;
FrankWeissenborn 1:25ceaa587f6b 41 metaint=0; // metadate interval
FrankWeissenborn 1:25ceaa587f6b 42 play=false;
FrankWeissenborn 3:87023c28aff5 43
FrankWeissenborn 5:36d14584e42f 44 for(int i=0; i< _buffer_size; i++)
FrankWeissenborn 5:36d14584e42f 45 _buffer[i] = 0; // IP input buffer
FrankWeissenborn 1:25ceaa587f6b 46
FrankWeissenborn 3:87023c28aff5 47 Host server(address, port); // 128k mp3
FrankWeissenborn 3:87023c28aff5 48 IpAddr serverIp = server.getIp();
FrankWeissenborn 3:87023c28aff5 49
FrankWeissenborn 3:87023c28aff5 50 DEBUGOUT("ShoutcastConnector: Connecting... %d.%d.%d.%d:%d\r\n",
FrankWeissenborn 1:25ceaa587f6b 51 serverIp[0],serverIp[1],serverIp[2],serverIp[3],port);
FrankWeissenborn 1:25ceaa587f6b 52
FrankWeissenborn 1:25ceaa587f6b 53
FrankWeissenborn 5:36d14584e42f 54 _sock.setOnEvent(this, &ShoutcastConnector::onTCPSocketEvent);
FrankWeissenborn 5:36d14584e42f 55 TCPSocketErr bindErr = _sock.connect(server);
FrankWeissenborn 1:25ceaa587f6b 56
FrankWeissenborn 1:25ceaa587f6b 57 if (TCPSOCKET_OK != bindErr) {
FrankWeissenborn 3:87023c28aff5 58 DEBUGOUT("ShoutcastConnector: Error %d in sock.connect().\r\n", bindErr);
FrankWeissenborn 1:25ceaa587f6b 59 return -1;
FrankWeissenborn 1:25ceaa587f6b 60 }
FrankWeissenborn 1:25ceaa587f6b 61 return 0;
FrankWeissenborn 1:25ceaa587f6b 62 }
FrankWeissenborn 1:25ceaa587f6b 63
FrankWeissenborn 3:87023c28aff5 64 int ShoutcastConnector::Disconnect() {
FrankWeissenborn 5:36d14584e42f 65 TCPSocketErr err = _sock.close();
FrankWeissenborn 3:87023c28aff5 66
FrankWeissenborn 3:87023c28aff5 67
FrankWeissenborn 1:25ceaa587f6b 68 if (TCPSOCKET_OK != err) {
FrankWeissenborn 3:87023c28aff5 69 DEBUGOUT("ShoutcastConnector: Error %d in Disconnect().\r\n", err);
FrankWeissenborn 1:25ceaa587f6b 70 return -1;
FrankWeissenborn 3:87023c28aff5 71 } else {
FrankWeissenborn 3:87023c28aff5 72 DEBUGOUT("ShoutcastConnector: disconnected");
FrankWeissenborn 1:25ceaa587f6b 73 }
FrankWeissenborn 3:87023c28aff5 74
FrankWeissenborn 3:87023c28aff5 75 _mp3->stop();
FrankWeissenborn 3:87023c28aff5 76
FrankWeissenborn 3:87023c28aff5 77 ReadState=GET_RESPONSE;
FrankWeissenborn 3:87023c28aff5 78 WriteState=PUT_HEADER;
FrankWeissenborn 3:87023c28aff5 79
FrankWeissenborn 1:25ceaa587f6b 80 return 0;
FrankWeissenborn 1:25ceaa587f6b 81 }
FrankWeissenborn 1:25ceaa587f6b 82
FrankWeissenborn 1:25ceaa587f6b 83 void ShoutcastConnector::onTCPSocketEvent(TCPSocketEvent e) {
FrankWeissenborn 1:25ceaa587f6b 84 switch (e) {
FrankWeissenborn 1:25ceaa587f6b 85 case TCPSOCKET_CONNECTED:
FrankWeissenborn 3:87023c28aff5 86 // DEBUGOUT("TCP Socket Connected\r\n"); // this printf disturb socket work correctly
FrankWeissenborn 1:25ceaa587f6b 87 Writeable();
FrankWeissenborn 1:25ceaa587f6b 88 break; // we must comment out ?
FrankWeissenborn 1:25ceaa587f6b 89 case TCPSOCKET_WRITEABLE:
FrankWeissenborn 3:87023c28aff5 90 // DEBUGOUT("TCP Socket Writeable\r\n");
FrankWeissenborn 1:25ceaa587f6b 91 break;
FrankWeissenborn 1:25ceaa587f6b 92 case TCPSOCKET_READABLE:
FrankWeissenborn 1:25ceaa587f6b 93 //Can now read some data...
FrankWeissenborn 3:87023c28aff5 94 // DEBUGOUT("TCP Socket Readable\r\n");
FrankWeissenborn 1:25ceaa587f6b 95 Readable();
FrankWeissenborn 1:25ceaa587f6b 96 break;//
FrankWeissenborn 1:25ceaa587f6b 97 case TCPSOCKET_CONTIMEOUT:
FrankWeissenborn 3:87023c28aff5 98 DEBUGOUT("ShoutcastConnector: TCP Socket Timeout\r\n");
FrankWeissenborn 3:87023c28aff5 99
FrankWeissenborn 3:87023c28aff5 100 ReadState=GET_RESPONSE;
FrankWeissenborn 3:87023c28aff5 101 WriteState=PUT_HEADER;
FrankWeissenborn 1:25ceaa587f6b 102 break;
FrankWeissenborn 1:25ceaa587f6b 103 case TCPSOCKET_CONRST:
FrankWeissenborn 3:87023c28aff5 104 DEBUGOUT("ShoutcastConnector: TCP Socket CONRST\r\n");
FrankWeissenborn 3:87023c28aff5 105
FrankWeissenborn 3:87023c28aff5 106 ReadState=GET_RESPONSE;
FrankWeissenborn 3:87023c28aff5 107 WriteState=PUT_HEADER;
FrankWeissenborn 1:25ceaa587f6b 108 break;
FrankWeissenborn 1:25ceaa587f6b 109 case TCPSOCKET_CONABRT:
FrankWeissenborn 3:87023c28aff5 110 DEBUGOUT("ShoutcastConnector: TCP Socket CONABRT\r\n");
FrankWeissenborn 3:87023c28aff5 111 DEBUGOUT("ShoutcastConnector: Maybe Server Down...\r\n");
FrankWeissenborn 3:87023c28aff5 112
FrankWeissenborn 3:87023c28aff5 113 ReadState=GET_RESPONSE;
FrankWeissenborn 3:87023c28aff5 114 WriteState=PUT_HEADER;
FrankWeissenborn 1:25ceaa587f6b 115 break;
FrankWeissenborn 1:25ceaa587f6b 116 case TCPSOCKET_ERROR:
FrankWeissenborn 3:87023c28aff5 117 DEBUGOUT("ShoutcastConnector: TCP Socket Error\r\n");
FrankWeissenborn 1:25ceaa587f6b 118 break;
FrankWeissenborn 1:25ceaa587f6b 119 case TCPSOCKET_DISCONNECTED:
FrankWeissenborn 1:25ceaa587f6b 120 //Close socket...
FrankWeissenborn 3:87023c28aff5 121 DEBUGOUT("ShoutcastConnector: Disconnected\r\n");
FrankWeissenborn 5:36d14584e42f 122 _sock.close();
FrankWeissenborn 1:25ceaa587f6b 123 break;
FrankWeissenborn 1:25ceaa587f6b 124 }// switch(e)
FrankWeissenborn 1:25ceaa587f6b 125 }
FrankWeissenborn 1:25ceaa587f6b 126
FrankWeissenborn 1:25ceaa587f6b 127 void ShoutcastConnector::Writeable() {
FrankWeissenborn 5:36d14584e42f 128
FrankWeissenborn 1:25ceaa587f6b 129 switch (WriteState) {
FrankWeissenborn 5:36d14584e42f 130 case PUT_HEADER:
FrankWeissenborn 5:36d14584e42f 131 strcpy(_buffer,"GET ");
FrankWeissenborn 5:36d14584e42f 132 strcat(_buffer,_path);
FrankWeissenborn 5:36d14584e42f 133 strcat(_buffer, " HTTP/1.0\r\nHost: gw\r\nAccept: */*\r\nUser-Agent: mbed\r\nIcy-MetaData: 1\r\n\r\n");
FrankWeissenborn 5:36d14584e42f 134
FrankWeissenborn 5:36d14584e42f 135 DEBUGOUT("\r\nShoutcastConnector: HEADER:\r\n%s\r\n", _buffer); // display PUT_HEADER
FrankWeissenborn 5:36d14584e42f 136
FrankWeissenborn 5:36d14584e42f 137 _sock.send(_buffer, strlen(_buffer));
FrankWeissenborn 5:36d14584e42f 138
FrankWeissenborn 1:25ceaa587f6b 139 WriteState=NOP;
FrankWeissenborn 1:25ceaa587f6b 140 ReadState=GET_RESPONSE;
FrankWeissenborn 1:25ceaa587f6b 141 break;
FrankWeissenborn 1:25ceaa587f6b 142 case NOP:
FrankWeissenborn 1:25ceaa587f6b 143 break;
FrankWeissenborn 1:25ceaa587f6b 144 } // switch(WriteState)
FrankWeissenborn 1:25ceaa587f6b 145 }
FrankWeissenborn 1:25ceaa587f6b 146
FrankWeissenborn 1:25ceaa587f6b 147
FrankWeissenborn 1:25ceaa587f6b 148 void ShoutcastConnector::Readable() {
FrankWeissenborn 1:25ceaa587f6b 149 int len = 0, i=0;
FrankWeissenborn 3:87023c28aff5 150 char* cp;
FrankWeissenborn 3:87023c28aff5 151
FrankWeissenborn 1:25ceaa587f6b 152 switch (ReadState) {
FrankWeissenborn 1:25ceaa587f6b 153 case GET_RESPONSE:
FrankWeissenborn 5:36d14584e42f 154 for(int j=0; j<_buffer_size; j++)
FrankWeissenborn 5:36d14584e42f 155 _buffer[j] = 0x00;
FrankWeissenborn 5:36d14584e42f 156
FrankWeissenborn 5:36d14584e42f 157 len=_sock.recv(_buffer, _buffer_size);
FrankWeissenborn 5:36d14584e42f 158 cp=strstr(_buffer,"\r\n\r\n");
FrankWeissenborn 1:25ceaa587f6b 159 if (cp==NULL) {
FrankWeissenborn 5:36d14584e42f 160 _buffer[len]=0;
FrankWeissenborn 5:36d14584e42f 161 DEBUGOUT("%s", _buffer); // debug
FrankWeissenborn 1:25ceaa587f6b 162 return; // still read response again
FrankWeissenborn 1:25ceaa587f6b 163 }
FrankWeissenborn 1:25ceaa587f6b 164 //
FrankWeissenborn 1:25ceaa587f6b 165 *cp=0;
FrankWeissenborn 5:36d14584e42f 166
FrankWeissenborn 5:36d14584e42f 167 DEBUGOUT("ShoutcastConnector: RESPONSE:\r\n%s",_buffer);
FrankWeissenborn 1:25ceaa587f6b 168 // get metaint value
FrankWeissenborn 5:36d14584e42f 169 cp=strstr(_buffer,"icy-metaint:");
FrankWeissenborn 1:25ceaa587f6b 170 if (cp==NULL) metaint=0;
FrankWeissenborn 1:25ceaa587f6b 171 else sscanf(cp+strlen("icy-metaint:"),"%d",&metaint);
FrankWeissenborn 3:87023c28aff5 172 DEBUGOUT("\r\nShoutcastConnector: metaint: %d\r\n\r\n",metaint); //debug
FrankWeissenborn 1:25ceaa587f6b 173 //
FrankWeissenborn 1:25ceaa587f6b 174
FrankWeissenborn 3:87023c28aff5 175 DEBUGOUT("ShoutcastConnector: HeaderLen:%d\r\n",len);
FrankWeissenborn 1:25ceaa587f6b 176
FrankWeissenborn 5:36d14584e42f 177 i=strlen(_buffer)+4; // bump bitstream right after response
FrankWeissenborn 1:25ceaa587f6b 178 ReadState=GET_STREAM;
FrankWeissenborn 1:25ceaa587f6b 179 //initDec();
FrankWeissenborn 1:25ceaa587f6b 180 //
FrankWeissenborn 1:25ceaa587f6b 181 while (i<len) {
FrankWeissenborn 1:25ceaa587f6b 182 // write one bye
FrankWeissenborn 1:25ceaa587f6b 183 // sbuf.PutByte(inbuf[i]);
FrankWeissenborn 1:25ceaa587f6b 184 i++;
FrankWeissenborn 1:25ceaa587f6b 185 readed++;
FrankWeissenborn 1:25ceaa587f6b 186 };
FrankWeissenborn 1:25ceaa587f6b 187 return;
FrankWeissenborn 1:25ceaa587f6b 188 //
FrankWeissenborn 3:87023c28aff5 189 case GET_STREAM:
FrankWeissenborn 1:25ceaa587f6b 190 // receive data ****repeatedly****
FrankWeissenborn 5:36d14584e42f 191 while ((len=_sock.recv(_buffer, _buffer_size)) != 0x00) {
FrankWeissenborn 3:87023c28aff5 192
FrankWeissenborn 3:87023c28aff5 193
FrankWeissenborn 1:25ceaa587f6b 194 kb += len;
FrankWeissenborn 3:87023c28aff5 195
FrankWeissenborn 3:87023c28aff5 196
FrankWeissenborn 3:87023c28aff5 197 if (metaint > 0) {
FrankWeissenborn 3:87023c28aff5 198 if (readed + len > metaint) {
FrankWeissenborn 1:25ceaa587f6b 199 //XXX
FrankWeissenborn 1:25ceaa587f6b 200 int startindex = metaint-readed;
FrankWeissenborn 5:36d14584e42f 201 size = _buffer[startindex];
FrankWeissenborn 1:25ceaa587f6b 202 //Send first part of data
FrankWeissenborn 3:87023c28aff5 203 while (_mp3->bufferFree() < startindex)
FrankWeissenborn 3:87023c28aff5 204 ; // wait
FrankWeissenborn 5:36d14584e42f 205 _mp3->bufferPutStream(_buffer, startindex);
FrankWeissenborn 3:87023c28aff5 206
FrankWeissenborn 3:87023c28aff5 207 if (size>0) {
FrankWeissenborn 3:87023c28aff5 208 //1.Fall : (metaint-readed)+size <= len
FrankWeissenborn 1:25ceaa587f6b 209 //Text ausgeben
FrankWeissenborn 1:25ceaa587f6b 210 //rest an mp3 codec
FrankWeissenborn 3:87023c28aff5 211 if ((metaint-readed)+size <= len) {
FrankWeissenborn 3:87023c28aff5 212 int start =-1;
FrankWeissenborn 3:87023c28aff5 213 int length = -1;
FrankWeissenborn 3:87023c28aff5 214
FrankWeissenborn 3:87023c28aff5 215 for (int i = startindex + 1; i < startindex + 1 + size*16; i++) {
FrankWeissenborn 4:a3b7032f0776 216
FrankWeissenborn 5:36d14584e42f 217 if (_buffer[i] == '\'') {
FrankWeissenborn 3:87023c28aff5 218 if (start == -1)
FrankWeissenborn 3:87023c28aff5 219 start = i+1-(startindex+1);
FrankWeissenborn 4:a3b7032f0776 220 else {
FrankWeissenborn 5:36d14584e42f 221 if(_buffer[i+1] == ';')
FrankWeissenborn 4:a3b7032f0776 222 {
FrankWeissenborn 4:a3b7032f0776 223 length = (i - (startindex+1)) - start; //last indexs - first index
FrankWeissenborn 4:a3b7032f0776 224 break;
FrankWeissenborn 4:a3b7032f0776 225 }
FrankWeissenborn 4:a3b7032f0776 226 }
FrankWeissenborn 4:a3b7032f0776 227
FrankWeissenborn 3:87023c28aff5 228 }
FrankWeissenborn 3:87023c28aff5 229
FrankWeissenborn 3:87023c28aff5 230 }
FrankWeissenborn 5:36d14584e42f 231 _callback(&_buffer[startindex + 1], size*16, start ,length);
FrankWeissenborn 1:25ceaa587f6b 232 //Send last part of data
FrankWeissenborn 3:87023c28aff5 233 while (_mp3->bufferFree() < len-(startindex+1+size*16))
FrankWeissenborn 3:87023c28aff5 234 ; // wait
FrankWeissenborn 1:25ceaa587f6b 235 readed = len-(startindex+1+size*16);
FrankWeissenborn 5:36d14584e42f 236 _mp3->bufferPutStream(&_buffer[startindex+1+size*16], readed);
FrankWeissenborn 3:87023c28aff5 237 } else {
FrankWeissenborn 3:87023c28aff5 238 DEBUGOUT("ShoutcastConnector: Muh")
FrankWeissenborn 1:25ceaa587f6b 239 }
FrankWeissenborn 3:87023c28aff5 240 } else {
FrankWeissenborn 1:25ceaa587f6b 241 //Send second part of data
FrankWeissenborn 1:25ceaa587f6b 242 //XXX
FrankWeissenborn 3:87023c28aff5 243 while (_mp3->bufferFree() < len-(startindex+1))
FrankWeissenborn 3:87023c28aff5 244 ; // wait
FrankWeissenborn 1:25ceaa587f6b 245 //XXX
FrankWeissenborn 1:25ceaa587f6b 246 readed = len-(startindex+1);
FrankWeissenborn 5:36d14584e42f 247 _mp3->bufferPutStream(&_buffer[startindex+1], len-(startindex+1));
FrankWeissenborn 3:87023c28aff5 248
FrankWeissenborn 3:87023c28aff5 249 }
FrankWeissenborn 3:87023c28aff5 250 } else {
FrankWeissenborn 1:25ceaa587f6b 251 readed += len;
FrankWeissenborn 3:87023c28aff5 252 while (_mp3->bufferFree() < len)
FrankWeissenborn 3:87023c28aff5 253 ; // wait
FrankWeissenborn 5:36d14584e42f 254 _mp3->bufferPutStream(_buffer, len);
FrankWeissenborn 1:25ceaa587f6b 255 }
FrankWeissenborn 3:87023c28aff5 256 } else {
FrankWeissenborn 3:87023c28aff5 257 while (_mp3->bufferFree() < len)
FrankWeissenborn 3:87023c28aff5 258 ; // wait
FrankWeissenborn 5:36d14584e42f 259 _mp3->bufferPutStream(_buffer, len);
FrankWeissenborn 1:25ceaa587f6b 260 }
FrankWeissenborn 3:87023c28aff5 261
FrankWeissenborn 3:87023c28aff5 262
FrankWeissenborn 3:87023c28aff5 263
FrankWeissenborn 3:87023c28aff5 264 if (!play && _mp3->bufferCount() > 0.8 * _mp3->bufferLength()) {
FrankWeissenborn 1:25ceaa587f6b 265 _mp3->play();
FrankWeissenborn 1:25ceaa587f6b 266 play = true;
FrankWeissenborn 1:25ceaa587f6b 267 }
FrankWeissenborn 3:87023c28aff5 268
FrankWeissenborn 3:87023c28aff5 269 if (play && _mp3->bufferCount() < 0.1 * _mp3->bufferLength()) {
FrankWeissenborn 1:25ceaa587f6b 270 _mp3->pause();
FrankWeissenborn 1:25ceaa587f6b 271 play = false;
FrankWeissenborn 1:25ceaa587f6b 272 }
FrankWeissenborn 3:87023c28aff5 273
FrankWeissenborn 3:87023c28aff5 274
FrankWeissenborn 1:25ceaa587f6b 275 } // while (len=sock...)
FrankWeissenborn 3:87023c28aff5 276
FrankWeissenborn 3:87023c28aff5 277
FrankWeissenborn 3:87023c28aff5 278
FrankWeissenborn 1:25ceaa587f6b 279 return; // get more strea
FrankWeissenborn 1:25ceaa587f6b 280 } // switch (ReadState)
FrankWeissenborn 1:25ceaa587f6b 281 }