Shoutcast.cpp

Committer:
FrankWeissenborn
Date:
2011-01-28
Revision:
6:be954c212733
Parent:
5:d5d16fd31139
Child:
7:f652d1e054e9

File content as of revision 6:be954c212733:

#include "Shoutcast.h"
#include "mbed.h"
#include "HTTPClient.h"

#include "FileDownloader.h"


#define FOLDER          "/sd/mydir/"
#define FILECHANNEL     "/sd/mydir/channel.xml"
#define FILECHANNELMOD  "/sd/mydir/cm.xml"
#define FILETOP500      "/sd/mydir/top500.xml"
#define FILEPLS         "/sd/mydir/currChan.pls"
#define FILEPLSMOD      "/sd/mydir/ChanM"

const char* const GENRE[25] = {"Alternative","Blues","Classical","Country","Decades","Easy Listening","Electronic","Folk","Inspirational","International","Jazz","Latin","Metal","Misc","New Age","Pop","Public Radio","R&B/Urban","Rap","Reggae","Rock","Seasonal/Holiday","Soundtracks","Talk","Themes" };

int completed_dns;


Shoutcast::Shoutcast(const char* devId, char * big_buffer,  int big_buffer_size, char * small_buffer, int small_buffer_size) {
    _devId = devId;
    _big_buffer = big_buffer;
    _big_buffer_size = big_buffer_size;
    _small_buffer = small_buffer;
    _small_buffer_size = small_buffer_size;
    _genreCounter = 0;
    _maxChannel = 0;
    _currentChannel = 0;
    _maxAddress = 0;
    _currentAddress = 0;

    mkdir(FOLDER, 0777);

}

const char* Shoutcast::GetNextGenre() {
    if (_genreCounter < 24) {
        _genreCounter++;
    } else {
        _genreCounter = 0;
    }
    
    _maxChannel = 0;
    _currentChannel = 0;
    _maxAddress = 0;
    _currentAddress = 0;

    return GENRE[_genreCounter];
   
}

const char* Shoutcast::GetPrevGenre() {
    if (_genreCounter > 0) {
        _genreCounter--;
    } else {
        _genreCounter = 24;
    }

    _maxChannel = 0;
    _currentChannel = 0;
    _maxAddress = 0;
    _currentAddress = 0;

    return GENRE[_genreCounter];
}
const char* Shoutcast::GetCurrGenre() {
    return GENRE[_genreCounter];
}

int Shoutcast::GetChannel(char* name, int length) {
    DEBUGOUT("Shoutcast:GetChannel started\r\n");
    DEBUGOUT("Shoutcast: Download channellist:%s started\r\n",GENRE[_genreCounter]);
    
    strcpy (_big_buffer,"http://api.shoutcast.com/legacy/genresearch?k=");
    strcat (_big_buffer,_devId);
    strcat (_big_buffer,"&genre=");
    strcat (_big_buffer,GENRE[_genreCounter]);
    strcat (_big_buffer,"&f=xml");
    DEBUGOUT("Shoutcast: %s\r\n",_big_buffer);

    HTTPResult result = GetFile(_big_buffer,FILECHANNEL,_fpout,_small_buffer,_small_buffer_size);
    if(result != HTTP_OK)
    {
        DEBUGOUT("Shoutcast: Download channellist:%s ended with error %i.\r\n",GENRE[_genreCounter],result);
        return 1;
    }
    DEBUGOUT("Shoutcast: Download channellist:%s successfully completed.\r\n",GENRE[_genreCounter]);
    ParseChannelList(FILECHANNEL);

    _currentChannel = 0;
    return GetChannel(name, length, 0);
}

int Shoutcast::GetTop500(char* name, int length) {

    DEBUGOUT("Shoutcast: Download Top500 started\r\n");
    strcpy (_big_buffer,"http://api.shoutcast.com/legacy/Top500?k=");
    strcat (_big_buffer,_devId);
    DEBUGOUT("%s\n",_big_buffer);
     HTTPResult result = GetFile(_big_buffer,FILETOP500,_fpout,_small_buffer,_small_buffer_size);
    if(result != HTTP_OK)
    {
        DEBUGOUT("Shoutcast: Download Top500 ended with error %i.\r\n",result);
        return 1;
    }
    DEBUGOUT("Shoutcast: Download Top500 successfully completed.\r\n");
    ParseChannelList(FILETOP500);
    _currentChannel = 0;
    return GetChannel(name, length, 0);
}
int Shoutcast::GetPrevChannel(char* name, int length) {
    
    if(_maxChannel == 0){
    return -2;
    }
    
    if(_currentChannel > 0){
        _currentChannel--;
    }
    else {
    _currentChannel = _maxChannel - 1;
    }
    
    if((length == 0) || (name == NULL)) {
        return 0;
    }
    
    _maxAddress = 0;
    _currentAddress = 0;

    return GetChannel(name, length, _currentChannel);
}
int Shoutcast::GetNextChannel(char* name, int length) {
    
    if(_maxChannel == 0){
        return -2;
    }
    
    
    if(_currentChannel < _maxChannel - 1) {
        _currentChannel++;
    }
    else {
    _currentChannel=0;
    }
    
    if((length == 0) || (name == NULL)) {
        return 0;
    }
    
    _maxAddress = 0;
    _currentAddress = 0;

    return GetChannel(name, length, _currentChannel);
}

int Shoutcast::GetCurrChannel(char* name, int length) {
    return GetChannel(name, length, _currentChannel);
}

int Shoutcast::TuneIn(IpAddr* address, int* port) {
    char buf[10];
    sprintf(buf,"%d",GetChannelId(_currentChannel));
     
    strcpy (_big_buffer,"http://yp.shoutcast.com/sbin/tunein-station.pls?&k=");
    strcat (_big_buffer,_devId);
    strcat (_big_buffer,"&id=");
    strcat (_big_buffer,buf); //todo: int to string
    strcat (_big_buffer,"&f=xml");
    DEBUGOUT("Shoutcast: %s\r\n",_big_buffer);
    HTTPResult result = GetFile(_big_buffer,FILEPLS,_fpout,_small_buffer,_small_buffer_size);
    DEBUGOUT("Shoutcast: result PLS: %d\n", result);
    
    if(ParsePls() != 0x00)
    {   
        return 1;
    }
    _currentAddress = 0;
    return GetAddressData(address,port,0);
}



int Shoutcast::ParseChannelList(const char* channelList) {
    
    DEBUGOUT("Shoutcast: Parsing started\r\n");
    _maxChannel = 0;
    
    _fpin = fopen(channelList, "r");
    if (_fpin == NULL) {
        error("Could not open file for write\n");
    } 
    
    _fpout = fopen(FILECHANNELMOD, "w");
    if (_fpout == NULL) {
        error("Could not open file for write\n");
    }
    
    char * cp;
    char * cp2 = NULL;
    char * station1; char * station2 = NULL;

    int i=0;
    bool finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
    _big_buffer[_big_buffer_size-1] = 0x00;
    cp = _big_buffer;

    while (!finished) {
        if (cp==NULL) {
            if (cp2 != NULL) {
                int x = (_big_buffer + _big_buffer_size) - cp2 - 1;
                int read_size = _big_buffer_size-(x-1);

                finished = (fgets(_big_buffer+x-1, read_size,_fpin) == NULL);
                _big_buffer[_big_buffer_size-1] = 0x00;
                cp=_big_buffer;

            } else {
                finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
                _big_buffer[_big_buffer_size-1] = 0x00;
                cp = _big_buffer;
            }
        }

        cp=strstr(cp,"<station ");

        if (cp!=NULL) {
            cp2=strstr(cp,"/>");
            if (cp2 != NULL) {
                i++;
               
                cp2[0] = 0x00;
                
                //name suchen
                station1=strstr(cp,"name=\"");
                if(station1 != NULL)
                {
                  station1 = station1 + strlen("name=\"");
                  station2 = NULL;
                  station2 = strstr(station1,"\"");
                  if(station2 != NULL)
                  {
                    station2[0]=0x00;
                    fprintf(_fpout,"%s<>",station1);
                    _maxChannel++;
                  }
                }
                //id suchen
                station1=strstr(station2+1,"id=\"");
                if(station1 != NULL)
                {
                  station1 = station1 + strlen("id=\"");
                  station2 = NULL;
                  station2 = strstr(station1,"\"");
                  if(station2 != NULL)
                  {
                    station2[0]=0x00;
                    fprintf(_fpout,"%s\r\n",station1);
                  }
                }
                
                cp=cp2+1;
            } else {
                //Kopieren
                strcpy(_big_buffer,cp);
                int x = (_big_buffer + _big_buffer_size) - cp - 1;
                int read_size = _big_buffer_size-(x-1);
                finished = (fgets(_big_buffer+x-1, read_size,_fpin) == NULL);
                _big_buffer[_big_buffer_size-1] = 0x00;
                cp = _big_buffer;
            }
        }

    }
    fclose(_fpin);
    fclose(_fpout);
    DEBUGOUT("Shoutcast: Parsing completed\r\n");
    return true;
}

int Shoutcast::GetChannel(char* name, int length, int channelNumber)
{   
    if(_maxChannel == 0) return -1;
    if(channelNumber > _maxChannel) return -1;

    _fpin = fopen(FILECHANNELMOD, "r");
    if (_fpin == NULL) {
        error("Could not open file for write\n");
    }
    bool finished = false;
    int line = 0;
    char * delimiter;
    
    while(!finished) {
        finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
        if(channelNumber == line)
        {
            delimiter=strstr(_big_buffer,"<>");
            if(delimiter != NULL)
            {
                int i = 0;
                for(i = 0; (i<delimiter-_big_buffer) && (i<length-1); i++)
                {
                   name[i] = _big_buffer[i];
                }
                name[i]=0x00;
                finished = true;
            }
            else
            {
                fclose(_fpin);
                return 1;
            }
        }
        line++;
    }
    
    fclose(_fpin);
    return 0;
}


int Shoutcast::GetChannelId(int channelNumber)
{   
    DEBUGOUT("Shoutcast: GetChannelId started\r\n");
    _fpin = fopen(FILECHANNELMOD, "r");
    if (_fpin == NULL) {
        error("Could not open file for write\n");
    }
    bool finished = false;
    int line = 0;
    char * delimiter;
    
    while(!finished) {
        finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
        if(channelNumber == line)
        {
            DEBUGOUT("Shoutcast: GetChannelId Line found\r\n");
            delimiter=strstr(_big_buffer,"<>");
            int id = -1;
            if(delimiter != NULL)
            {
                 id = atoi(delimiter+strlen("<>"));
                //id = 4;
                fclose(_fpin);
                return id;  
            }
            else
            {
                fclose(_fpin);
                return -1;
            }
        }
        line++;
    }
    fclose(_fpin);
    return -1;
}

int Shoutcast::ParsePls() {
    DEBUGOUT("Shoutcast: start parsing pls\r\n");
    
_fpin = fopen(FILEPLS, "r");
 if (_fpin == NULL) {
        error("Could not open file for read\n");
    }
_fpout = fopen(FILEPLSMOD, "w");
 if (_fpout == NULL) {
        error("Could not open file for write\n");
    }
bool finished = false;
  
    char * cp;
    char * cp2;
    IpAddr addr;
    while(!finished) {
        finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
        
        //suchen nach 
        cp = strstr(_big_buffer,"=http://");
        if(cp!= NULL)
        {   
            cp = cp +strlen("=http://");
            cp2=strstr(cp,":");
            if(cp2 != NULL)
            {
                cp2[0]=0x00;
                int dnserr = ResolveDNSRequest(&addr, cp);
                
                if(dnserr != 0)
                {   
                    DEBUGOUT("Shoutcast: DNS Error - Parsing Pls\r\n");
                    fclose(_fpin);
                    fclose(_fpout);
                    
                    return -1;
                }
                else
                {
                cp = NULL;
                finished = true;
                }
                int port = atoi(cp2+1);
                fprintf(_fpout, "%d %d %d %d %d\r\n",
                       addr[0],addr[1],addr[2],addr[3],port);
                _maxAddress++;
            }
        }
        _big_buffer[_big_buffer_size-1] = 0x00;
        }
    fclose(_fpin);
    fclose(_fpout);
    
    DEBUGOUT("Shoutcast: end parsing pls\r\n");
    return 0;
}
int Shoutcast::ResolveDNSRequest(IpAddr* addr, char * url){
    DNSRequest * request = new DNSRequest();
    request->setOnReply(this, &Shoutcast::onReply);

     completed_dns=0;
     

     DNSRequestErr r = request->resolve(url);
     if (0!=r) {
         request->close();
         return 1;
        
     }
     while (0==completed_dns) {
         Net::poll();
     }

    if(completed_dns == -1) {
       return 1;
    }
     request->getResult(addr);
     request->close();
     return 0;
}

int Shoutcast::GetAddressData(IpAddr* address, int* port, int addressNumber) {

    if(_maxAddress == 0) return -1;
    if(addressNumber > _maxAddress) return -1;

    DEBUGOUT("Shoutcast: start get address data\r\n");
    _fpin = fopen(FILEPLSMOD, "r");
    bool finished = false;
    int line = 0;
    
    while(!finished) {
        finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
        if(line == addressNumber){
            int ip1 = 0;int ip2 = 0;int ip3 = 0;int ip4 = 0;int p = 0;
            sscanf (_big_buffer,"%d %d %d %d %d",&ip1,&ip2,&ip3,&ip4,&p);
            IpAddr server = IpAddr(ip1,ip2,ip3,ip4);
            *address = server;
            *port = p;
            finished = true;
        }
        line++;
    }
    DEBUGOUT("Shoutcast: end get address data\r\n");
    return 0;
}

void Shoutcast::onReply(DNSReply reply) {
         if (reply==DNS_FOUND)
             completed_dns=1;
         else
             completed_dns=-1;
     };

int Shoutcast::GetNextAddress(IpAddr* address, int* port)
{
    if(_currentAddress < _maxAddress - 1 )
    {
        _currentAddress++;
    }
    else
    {
        _currentAddress = 0;
    }
    return GetAddressData(address,port,_currentAddress);
    
}
int Shoutcast::GetCurrAddress(IpAddr* address, int* port)
{
    return GetAddressData(address,port,_currentAddress);
}
int Shoutcast::GetPrevAddress(IpAddr* address, int* port)
{
    if(_currentAddress > 0 )
    {
        _currentAddress--;
    }
    else
    {
        _currentAddress = _maxAddress - 1;
    }
    return GetAddressData(address,port,_currentAddress);
}