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