File content as of revision 6:e269a1b3bf4f:
#include "ShoutcastConnector.h"
enum wSTATE {NOP,PUT_HEADER} WriteState;
enum rSTATE {GET_RESPONSE,GET_STREAM} ReadState;
bool play;
int kb = 0;
int readed = 0;
int size = 0;
int metaint=0; // metadate interval
ShoutcastConnector::ShoutcastConnector(VS1053* mp3, myCallBack_pfn callback, char *buffer, int buffer_size) {
_mp3 = mp3;
_callback = callback;
_buffer = buffer;
_buffer_size = buffer_size;
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
}
int ShoutcastConnector::Connect(IpAddr address, int port, const char * path) {
if ((ReadState!=GET_RESPONSE)||(WriteState!=PUT_HEADER)) {
Disconnect();
//wait
wait_ms(500);
}
_path = path;
kb = 0;
readed = 0;
size = 0;
metaint=0; // metadate interval
play=false;
for(int i=0; i< _buffer_size; i++)
_buffer[i] = 0; // IP input buffer
Host server(address, port); // 128k mp3
IpAddr serverIp = server.getIp();
DEBUGOUT("ShoutcastConnector: Connecting... %d.%d.%d.%d:%d\r\n",
serverIp[0],serverIp[1],serverIp[2],serverIp[3],port);
_sock.setOnEvent(this, &ShoutcastConnector::onTCPSocketEvent);
TCPSocketErr bindErr = _sock.connect(server);
if (TCPSOCKET_OK != bindErr) {
DEBUGOUT("ShoutcastConnector: Error %d in sock.connect().\r\n", bindErr);
return -1;
}
return 0;
}
int ShoutcastConnector::Disconnect() {
TCPSocketErr err = _sock.close();
if (TCPSOCKET_OK != err) {
DEBUGOUT("ShoutcastConnector: Error %d in Disconnect().\r\n", err);
return -1;
} else {
DEBUGOUT("ShoutcastConnector: disconnected");
}
_mp3->stop();
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
return 0;
}
void ShoutcastConnector::onTCPSocketEvent(TCPSocketEvent e) {
switch (e) {
case TCPSOCKET_CONNECTED:
// DEBUGOUT("TCP Socket Connected\r\n"); // this printf disturb socket work correctly
Writeable();
break; // we must comment out ?
case TCPSOCKET_WRITEABLE:
// DEBUGOUT("TCP Socket Writeable\r\n");
break;
case TCPSOCKET_READABLE:
//Can now read some data...
// DEBUGOUT("TCP Socket Readable\r\n");
Readable();
break;//
case TCPSOCKET_CONTIMEOUT:
DEBUGOUT("ShoutcastConnector: TCP Socket Timeout\r\n");
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
break;
case TCPSOCKET_CONRST:
DEBUGOUT("ShoutcastConnector: TCP Socket CONRST\r\n");
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
break;
case TCPSOCKET_CONABRT:
DEBUGOUT("ShoutcastConnector: TCP Socket CONABRT\r\n");
DEBUGOUT("ShoutcastConnector: Maybe Server Down...\r\n");
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
break;
case TCPSOCKET_ERROR:
DEBUGOUT("ShoutcastConnector: TCP Socket Error\r\n");
break;
case TCPSOCKET_DISCONNECTED:
//Close socket...
DEBUGOUT("ShoutcastConnector: Disconnected\r\n");
_sock.close();
break;
}// switch(e)
}
void ShoutcastConnector::Writeable() {
switch (WriteState) {
case PUT_HEADER:
strcpy(_buffer,"GET ");
strcat(_buffer,_path);
strcat(_buffer, " HTTP/1.0\r\nHost: gw\r\nAccept: */*\r\nUser-Agent: mbed\r\nIcy-MetaData: 1\r\n\r\n");
DEBUGOUT("\r\nShoutcastConnector: HEADER:\r\n%s\r\n", _buffer); // display PUT_HEADER
_sock.send(_buffer, strlen(_buffer));
WriteState=NOP;
ReadState=GET_RESPONSE;
break;
case NOP:
break;
} // switch(WriteState)
}
void ShoutcastConnector::Readable() {
int len = 0, i=0;
char* cp;
switch (ReadState) {
case GET_RESPONSE:
for(int j=0; j<_buffer_size; j++)
_buffer[j] = 0x00;
len=_sock.recv(_buffer, _buffer_size);
cp=strstr(_buffer,"\r\n\r\n");
if (cp==NULL) {
_buffer[len]=0;
DEBUGOUT("%s", _buffer); // debug
return; // still read response again
}
//
*cp=0;
DEBUGOUT("ShoutcastConnector: RESPONSE:\r\n%s",_buffer);
// get metaint value
cp=strstr(_buffer,"icy-metaint:");
if (cp==NULL) metaint=0;
else sscanf(cp+strlen("icy-metaint:"),"%d",&metaint);
DEBUGOUT("\r\nShoutcastConnector: metaint: %d\r\n\r\n",metaint); //debug
//
DEBUGOUT("ShoutcastConnector: HeaderLen:%d\r\n",len);
i=strlen(_buffer)+4; // bump bitstream right after response
ReadState=GET_STREAM;
//initDec();
//
while (i<len) {
// write one bye
// sbuf.PutByte(inbuf[i]);
i++;
readed++;
};
return;
//
case GET_STREAM:
// receive data ****repeatedly****
while ((len=_sock.recv(_buffer, _buffer_size)) != 0x00) {
kb += len;
if (metaint > 0) {
if (readed + len > metaint) {
//XXX
int startindex = metaint-readed;
size = _buffer[startindex];
//Send first part of data
while (_mp3->bufferFree() < startindex)
; // wait
_mp3->bufferPutStream(_buffer, startindex);
if (size>0) {
//1.Fall : (metaint-readed)+size <= len
//Text ausgeben
//rest an mp3 codec
if ((metaint-readed)+size <= len) {
int start =-1;
int length = -1;
for (int i = startindex + 1; i < startindex + 1 + size*16; i++) {
if (_buffer[i] == '\'') {
if (start == -1)
start = i+1-(startindex+1);
else {
if(_buffer[i+1] == ';')
{
length = (i - (startindex+1)) - start; //last indexs - first index
break;
}
}
}
}
_callback(&_buffer[startindex + 1], size*16, start ,length);
//Send last part of data
while (_mp3->bufferFree() < len-(startindex+1+size*16))
; // wait
readed = len-(startindex+1+size*16);
_mp3->bufferPutStream(&_buffer[startindex+1+size*16], readed);
} else {
DEBUGOUT("ShoutcastConnector: Muh")
}
} else {
//Send second part of data
//XXX
while (_mp3->bufferFree() < len-(startindex+1))
; // wait
//XXX
readed = len-(startindex+1);
_mp3->bufferPutStream(&_buffer[startindex+1], len-(startindex+1));
}
} else {
readed += len;
while (_mp3->bufferFree() < len)
; // wait
_mp3->bufferPutStream(_buffer, len);
}
} else {
while (_mp3->bufferFree() < len)
; // wait
_mp3->bufferPutStream(_buffer, len);
}
if (!play && _mp3->bufferCount() > 0.8 * _mp3->bufferLength()) {
_mp3->play();
play = true;
}
if (play && _mp3->bufferCount() < 0.1 * _mp3->bufferLength()) {
_mp3->pause();
play = false;
}
} // while (len=sock...)
return; // get more strea
} // switch (ReadState)
}