ShoutcastConnector.cpp

Committer:
FrankWeissenborn
Date:
2011-02-02
Revision:
6:e269a1b3bf4f
Parent:
5:36d14584e42f

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)
}