Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ShoutcastConnector.cpp
- Committer:
- FrankWeissenborn
- Date:
- 2011-01-13
- Revision:
- 3:87023c28aff5
- Parent:
- 2:9abcdc65c5b5
- Child:
- 4:a3b7032f0776
File content as of revision 3:87023c28aff5:
#include "ShoutcastConnector.h"
enum wSTATE {NOP,PUT_HEADER} WriteState;
enum rSTATE {GET_RESPONSE,GET_STREAM} ReadState;
char inbuf[BUFFER_Z]; // IP input buffer
char sResponse[800]; // keeps Stream Response
bool play;
int kb = 0;
int readed = 0;
int size = 0;
int metaint=0; // metadate interval
ShoutcastConnector::ShoutcastConnector(VS1053* mp3, myCallBack_pfn callback) {
_mp3 = mp3;
_callback = callback;
ReadState=GET_RESPONSE;
WriteState=PUT_HEADER;
}
int ShoutcastConnector::Connect(IpAddr address, int port) {
if ((ReadState!=GET_RESPONSE)||(WriteState!=PUT_HEADER)) {
Disconnect();
//wait
wait_ms(500);
}
kb = 0;
readed = 0;
size = 0;
metaint=0; // metadate interval
play=false;
for(int i=0; i< BUFFER_Z; i++)
inbuf[i] = 0; // IP input buffer
for(int i=0; i< 800; i++)
sResponse[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:
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"
"Icy-MetaData: 1\r\n" // send this if you want Metadata
// "Connection: close\r\n"
"\r\n"
;
sock.send(str, strlen(str));
DEBUGOUT("\r\nShoutcastConnector: HEADER:\r\n%s\r\n", str); // display PUT_HEADER
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:
len=sock.recv(inbuf, sizeof inbuf);
cp=strstr(inbuf,"\r\n\r\n");
if (cp==NULL) {
inbuf[len]=0;
DEBUGOUT("%s",inbuf); // debug
//sprintf(sResponse,"%s",inbuf);
return; // still read response again
}
//
*cp=0;
sprintf(sResponse+strlen(sResponse),"%s\r\n\r\n",inbuf);
DEBUGOUT("ShoutcastConnector: 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);
DEBUGOUT("\r\nShoutcastConnector: metaint: %d\r\n\r\n",metaint); //debug
//
DEBUGOUT("ShoutcastConnector: HeaderLen:%d\r\n",len);
i=strlen(inbuf)+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(inbuf, sizeof inbuf)) {
kb += len;
if (metaint > 0) {
if (readed + len > metaint) {
//XXX
int startindex = metaint-readed;
size = inbuf[startindex];
//Send first part of data
while (_mp3->bufferFree() < startindex)
; // wait
_mp3->bufferPutStream(inbuf, 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 (inbuf[i] == '\'') {
if (start == -1)
start = i+1-(startindex+1);
else
length = (i - (startindex+1)) - start; //last indexs - first index
}
}
_callback(&inbuf[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(&inbuf[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(&inbuf[startindex+1], len-(startindex+1));
}
} else {
readed += len;
while (_mp3->bufferFree() < len)
; // wait
_mp3->bufferPutStream(inbuf, len);
}
} else {
while (_mp3->bufferFree() < len)
; // wait
_mp3->bufferPutStream(inbuf, 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)
}