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