Frank Weissenborn / Shoutcast
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Shoutcast.cpp Source File

Shoutcast.cpp

00001 #include "Shoutcast.h"
00002 #include "mbed.h"
00003 #include "HTTPClient.h"
00004 
00005 #include "FileDownloader.h"
00006 
00007 
00008 #define FOLDER          "/sd/mydir/"
00009 #define FILECHANNEL     "/sd/mydir/channel.xml"
00010 #define FILECHANNELMOD  "/sd/mydir/cm.xml"
00011 #define FILETOP500      "/sd/mydir/top500.xml"
00012 #define FILEPLS         "/sd/mydir/currChan.pls"
00013 #define FILEPLSMOD      "/sd/mydir/ChanM"
00014 
00015 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" };
00016 
00017 int completed_dns;
00018 
00019 
00020 Shoutcast::Shoutcast(const char* devId, char * big_buffer,  int big_buffer_size, char * small_buffer, int small_buffer_size) {
00021     _devId = devId;
00022     _big_buffer = big_buffer;
00023     _big_buffer_size = big_buffer_size;
00024     _small_buffer = small_buffer;
00025     _small_buffer_size = small_buffer_size;
00026     _genreCounter = 0;
00027     _maxChannel = 0;
00028     _currentChannel = 0;
00029     _maxAddress = 0;
00030     _currentAddress = 0;
00031 
00032     mkdir(FOLDER, 0777);
00033 
00034 }
00035 
00036 const char* Shoutcast::GetNextGenre() {
00037     if (_genreCounter < 24) {
00038         _genreCounter++;
00039     } else {
00040         _genreCounter = 0;
00041     }
00042     
00043     _maxChannel = 0;
00044     _currentChannel = 0;
00045     _maxAddress = 0;
00046     _currentAddress = 0;
00047 
00048     return GENRE[_genreCounter];
00049    
00050 }
00051 
00052 const char* Shoutcast::GetPrevGenre() {
00053     if (_genreCounter > 0) {
00054         _genreCounter--;
00055     } else {
00056         _genreCounter = 24;
00057     }
00058 
00059     _maxChannel = 0;
00060     _currentChannel = 0;
00061     _maxAddress = 0;
00062     _currentAddress = 0;
00063 
00064     return GENRE[_genreCounter];
00065 }
00066 const char* Shoutcast::GetCurrGenre() {
00067     return GENRE[_genreCounter];
00068 }
00069 
00070 int Shoutcast::GetChannel(char* name, int length) {
00071     DEBUGOUT("Shoutcast:GetChannel started\r\n");
00072     DEBUGOUT("Shoutcast: Download channellist:%s started\r\n",GENRE[_genreCounter]);
00073     
00074     strcpy (_big_buffer,"http://api.shoutcast.com/legacy/genresearch?k=");
00075     strcat (_big_buffer,_devId);
00076     strcat (_big_buffer,"&genre=");
00077     strcat (_big_buffer,GENRE[_genreCounter]);
00078     strcat (_big_buffer,"&f=xml");
00079     DEBUGOUT("Shoutcast: %s\r\n",_big_buffer);
00080 
00081     HTTPResult result = GetFile(_big_buffer,FILECHANNEL,_fpout,_small_buffer,_small_buffer_size);
00082     if(result != HTTP_OK)
00083     {
00084         DEBUGOUT("Shoutcast: Download channellist:%s ended with error %i.\r\n",GENRE[_genreCounter],result);
00085         return 1;
00086     }
00087     DEBUGOUT("Shoutcast: Download channellist:%s successfully completed.\r\n",GENRE[_genreCounter]);
00088     ParseChannelList(FILECHANNEL);
00089 
00090     _currentChannel = 0;
00091     return GetChannel(name, length, 0);
00092 }
00093 
00094 int Shoutcast::GetTop500(char* name, int length) {
00095 
00096     DEBUGOUT("Shoutcast: Download Top500 started\r\n");
00097     strcpy (_big_buffer,"http://api.shoutcast.com/legacy/Top500?k=");
00098     strcat (_big_buffer,_devId);
00099     DEBUGOUT("%s\n",_big_buffer);
00100      HTTPResult result = GetFile(_big_buffer,FILETOP500,_fpout,_small_buffer,_small_buffer_size);
00101     if(result != HTTP_OK)
00102     {
00103         DEBUGOUT("Shoutcast: Download Top500 ended with error %i.\r\n",result);
00104         return 1;
00105     }
00106     DEBUGOUT("Shoutcast: Download Top500 successfully completed.\r\n");
00107     ParseChannelList(FILETOP500);
00108     _currentChannel = 0;
00109     return GetChannel(name, length, 0);
00110 }
00111 int Shoutcast::GetPrevChannel(char* name, int length) {
00112     
00113     if(_maxChannel == 0){
00114     return -2;
00115     }
00116     
00117     if(_currentChannel > 0){
00118         _currentChannel--;
00119     }
00120     else {
00121     _currentChannel = _maxChannel - 1;
00122     }
00123     
00124     if((length == 0) || (name == NULL)) {
00125         return 0;
00126     }
00127     
00128     _maxAddress = 0;
00129     _currentAddress = 0;
00130 
00131     return GetChannel(name, length, _currentChannel);
00132 }
00133 int Shoutcast::GetNextChannel(char* name, int length) {
00134     
00135     if(_maxChannel == 0){
00136         return -2;
00137     }
00138     
00139     
00140     if(_currentChannel < _maxChannel - 1) {
00141         _currentChannel++;
00142     }
00143     else {
00144     _currentChannel=0;
00145     }
00146     
00147     if((length == 0) || (name == NULL)) {
00148         return 0;
00149     }
00150     
00151     _maxAddress = 0;
00152     _currentAddress = 0;
00153 
00154     return GetChannel(name, length, _currentChannel);
00155 }
00156 
00157 int Shoutcast::GetCurrChannel(char* name, int length) {
00158     return GetChannel(name, length, _currentChannel);
00159 }
00160 
00161 int Shoutcast::TuneIn(IpAddr* address, int* port, char * path, const int length) {
00162     char buf[10];
00163     sprintf(buf,"%d",GetChannelId(_currentChannel));
00164      
00165     strcpy (_big_buffer,"http://yp.shoutcast.com/sbin/tunein-station.pls?&k=");
00166     strcat (_big_buffer,_devId);
00167     strcat (_big_buffer,"&id=");
00168     strcat (_big_buffer,buf); //todo: int to string
00169     strcat (_big_buffer,"&f=xml");
00170     DEBUGOUT("Shoutcast: %s\r\n",_big_buffer);
00171     HTTPResult result = GetFile(_big_buffer,FILEPLS,_fpout,_small_buffer,_small_buffer_size);
00172     DEBUGOUT("Shoutcast: result PLS: %d\n", result);
00173     
00174     if(ParsePls() != 0x00)
00175     {   
00176         return 1;
00177     }
00178     _currentAddress = 0;
00179     return GetAddressData(address,port,path,length,0);
00180 }
00181 
00182 
00183 
00184 int Shoutcast::ParseChannelList(const char* channelList) {
00185     
00186     DEBUGOUT("Shoutcast: Parsing started\r\n");
00187     _maxChannel = 0;
00188     
00189     _fpin = fopen(channelList, "r");
00190     if (_fpin == NULL) {
00191         error("Could not open file for write\n");
00192     } 
00193     
00194     _fpout = fopen(FILECHANNELMOD, "w");
00195     if (_fpout == NULL) {
00196         error("Could not open file for write\n");
00197     }
00198     
00199     char * cp;
00200     char * cp2 = NULL;
00201     char * station1; char * station2 = NULL;
00202 
00203     int i=0;
00204     bool finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00205     _big_buffer[_big_buffer_size-1] = 0x00;
00206     cp = _big_buffer;
00207 
00208     while (!finished) {
00209         if (cp==NULL) {
00210             if (cp2 != NULL) {
00211                 int x = (_big_buffer + _big_buffer_size) - cp2 - 1;
00212                 int read_size = _big_buffer_size-(x-1);
00213 
00214                 finished = (fgets(_big_buffer+x-1, read_size,_fpin) == NULL);
00215                 _big_buffer[_big_buffer_size-1] = 0x00;
00216                 cp=_big_buffer;
00217 
00218             } else {
00219                 finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00220                 _big_buffer[_big_buffer_size-1] = 0x00;
00221                 cp = _big_buffer;
00222             }
00223         }
00224 
00225         cp=strstr(cp,"<station ");
00226 
00227         if (cp!=NULL) {
00228             cp2=strstr(cp,"/>");
00229             if (cp2 != NULL) {
00230                 i++;
00231                
00232                 cp2[0] = 0x00;
00233                 
00234                 //name suchen
00235                 station1=strstr(cp,"name=\"");
00236                 if(station1 != NULL)
00237                 {
00238                   station1 = station1 + strlen("name=\"");
00239                   station2 = NULL;
00240                   station2 = strstr(station1,"\"");
00241                   if(station2 != NULL)
00242                   {
00243                     station2[0]=0x00;
00244                     fprintf(_fpout,"%s<>",station1);
00245                     _maxChannel++;
00246                   }
00247                 }
00248                 //id suchen
00249                 station1=strstr(station2+1,"id=\"");
00250                 if(station1 != NULL)
00251                 {
00252                   station1 = station1 + strlen("id=\"");
00253                   station2 = NULL;
00254                   station2 = strstr(station1,"\"");
00255                   if(station2 != NULL)
00256                   {
00257                     station2[0]=0x00;
00258                     fprintf(_fpout,"%s\r\n",station1);
00259                   }
00260                 }
00261                 
00262                 cp=cp2+1;
00263             } else {
00264                 //Kopieren
00265                 strcpy(_big_buffer,cp);
00266                 int x = (_big_buffer + _big_buffer_size) - cp - 1;
00267                 int read_size = _big_buffer_size-(x-1);
00268                 finished = (fgets(_big_buffer+x-1, read_size,_fpin) == NULL);
00269                 _big_buffer[_big_buffer_size-1] = 0x00;
00270                 cp = _big_buffer;
00271             }
00272         }
00273 
00274     }
00275     fclose(_fpin);
00276     fclose(_fpout);
00277     DEBUGOUT("Shoutcast: Parsing completed\r\n");
00278     return true;
00279 }
00280 
00281 int Shoutcast::GetChannel(char* name, int length, int channelNumber)
00282 {   
00283     if(_maxChannel == 0) return -1;
00284     if(channelNumber > _maxChannel) return -1;
00285 
00286     _fpin = fopen(FILECHANNELMOD, "r");
00287     if (_fpin == NULL) {
00288         error("Could not open file for write\n");
00289     }
00290     bool finished = false;
00291     int line = 0;
00292     char * delimiter;
00293     
00294     while(!finished) {
00295         finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00296         if(channelNumber == line)
00297         {
00298             delimiter=strstr(_big_buffer,"<>");
00299             if(delimiter != NULL)
00300             {
00301                 int i = 0;
00302                 for(i = 0; (i<delimiter-_big_buffer) && (i<length-1); i++)
00303                 {
00304                    name[i] = _big_buffer[i];
00305                 }
00306                 name[i]=0x00;
00307                 finished = true;
00308             }
00309             else
00310             {
00311                 fclose(_fpin);
00312                 return 1;
00313             }
00314         }
00315         line++;
00316     }
00317     
00318     fclose(_fpin);
00319     return 0;
00320 }
00321 
00322 
00323 int Shoutcast::GetChannelId(int channelNumber)
00324 {   
00325     DEBUGOUT("Shoutcast: GetChannelId started\r\n");
00326     _fpin = fopen(FILECHANNELMOD, "r");
00327     if (_fpin == NULL) {
00328         error("Could not open file for write\n");
00329     }
00330     bool finished = false;
00331     int line = 0;
00332     char * delimiter;
00333     
00334     while(!finished) {
00335         finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00336         if(channelNumber == line)
00337         {
00338             DEBUGOUT("Shoutcast: GetChannelId Line found\r\n");
00339             delimiter=strstr(_big_buffer,"<>");
00340             int id = -1;
00341             if(delimiter != NULL)
00342             {
00343                  id = atoi(delimiter+strlen("<>"));
00344                 //id = 4;
00345                 fclose(_fpin);
00346                 return id;  
00347             }
00348             else
00349             {
00350                 fclose(_fpin);
00351                 return -1;
00352             }
00353         }
00354         line++;
00355     }
00356     fclose(_fpin);
00357     return -1;
00358 }
00359 
00360 int Shoutcast::ParsePls() {
00361     DEBUGOUT("Shoutcast: start parsing pls\r\n");
00362     
00363 _fpin = fopen(FILEPLS, "r");
00364  if (_fpin == NULL) {
00365         error("Could not open file for read\n");
00366     }
00367 _fpout = fopen(FILEPLSMOD, "w");
00368  if (_fpout == NULL) {
00369         error("Could not open file for write\n");
00370     }
00371 bool finished = false;
00372   
00373     char * cp;
00374     char * cp2;
00375     IpAddr addr;
00376     int k=0;
00377     while(!finished) {
00378         finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00379         //suchen nach 
00380         cp = strstr(_big_buffer,"=http://");
00381         if(cp!= NULL)
00382         {   
00383             cp = cp +strlen("=http://");
00384             cp2=strstr(cp,":");
00385             if(cp2 != NULL)
00386             {
00387                 cp2[0]=0x00;
00388                 int dnserr = ResolveDNSRequest(&addr, cp);
00389                 
00390                 if(dnserr != 0)
00391                 {   
00392                     DEBUGOUT("Shoutcast: DNS Error - Parsing Pls\r\n");
00393                     fclose(_fpin);
00394                     fclose(_fpout);
00395                     
00396                     return -1;
00397                 }
00398                 else
00399                 {
00400                     cp = NULL;
00401                 }
00402                 int port = atoi(cp2+1);
00403                 cp = strstr(cp2+1,"/");
00404                 if(cp == NULL)
00405                 {
00406                     _small_buffer[0] = '/';
00407                     _small_buffer[1] = 0x00;
00408                 }
00409                 else
00410                 {
00411                     int j=0;
00412                     while(cp[j]!=0x0a)
00413                         j++;
00414                     
00415                     cp[j] = 0x00;
00416                     strcpy (_small_buffer,cp);
00417                 }
00418                 fprintf(_fpout, "%d %d %d %d %d %s\r\n",
00419                        addr[0],addr[1],addr[2],addr[3],port,_small_buffer);
00420                 _maxAddress++;
00421             }
00422         }
00423         _big_buffer[_big_buffer_size-1] = 0x00;
00424         }
00425     fclose(_fpin);
00426     fclose(_fpout);
00427     
00428     DEBUGOUT("Shoutcast: end parsing pls\r\n");
00429     return 0;
00430 }
00431 int Shoutcast::ResolveDNSRequest(IpAddr* addr, char * url){
00432 //TODO: instanzvaraible, setOnReplay im Konstruktor
00433     DNSRequest * request = new DNSRequest();
00434     request->setOnReply(this, &Shoutcast::onReply);
00435 
00436      completed_dns=0;
00437      
00438 
00439      DNSRequestErr r = request->resolve(url);
00440      if (0!=r) {
00441          request->close();
00442          return 1;
00443         
00444      }
00445      while (0==completed_dns) {
00446          Net::poll();
00447      }
00448 
00449     if(completed_dns == -1) {
00450        return 1;
00451     }
00452      request->getResult(addr);
00453      request->close();
00454      return 0;
00455 }
00456 
00457 int Shoutcast::GetAddressData(IpAddr* address, int* port, char * path, const int length, int addressNumber) {
00458 
00459     if(_maxAddress == 0) return -1;
00460     if(addressNumber > _maxAddress) return -1;
00461 
00462     DEBUGOUT("Shoutcast: start get address data\r\n");
00463     _fpin = fopen(FILEPLSMOD, "r");
00464     bool finished = false;
00465     int line = 0;
00466     
00467     while(!finished) {
00468         finished = (fgets(_big_buffer, _big_buffer_size-1, _fpin) == NULL);
00469         if(line == addressNumber){
00470             int ip1 = 0;int ip2 = 0;int ip3 = 0;int ip4 = 0;
00471             sscanf (_big_buffer,"%d %d %d %d %d %s",&ip1,&ip2,&ip3,&ip4,port,path);
00472             IpAddr server = IpAddr(ip1,ip2,ip3,ip4);
00473             *address = server;
00474             //*path = _small_buffer[0]; //TODO: Length
00475             finished = true;
00476         }
00477         line++;
00478     }
00479     DEBUGOUT("Shoutcast: end get address data\r\n");
00480     return 0;
00481 }
00482 
00483 void Shoutcast::onReply(DNSReply reply) {
00484          if (reply==DNS_FOUND)
00485              completed_dns=1;
00486          else
00487              completed_dns=-1;
00488      };
00489 
00490 int Shoutcast::GetNextAddress(IpAddr* address, int* port, char * path, const int length)
00491 {
00492     if(_currentAddress < _maxAddress - 1 )
00493     {
00494         _currentAddress++;
00495     }
00496     else
00497     {
00498         _currentAddress = 0;
00499     }
00500     return GetAddressData(address,port,path,length,_currentAddress);
00501     
00502 }
00503 int Shoutcast::GetCurrAddress(IpAddr* address, int* port, char * path, const int length)
00504 {
00505     return GetAddressData(address,port,path,length,_currentAddress);
00506 }
00507 int Shoutcast::GetPrevAddress(IpAddr* address, int* port, char * path, const int length)
00508 {
00509     if(_currentAddress > 0 )
00510     {
00511         _currentAddress--;
00512     }
00513     else
00514     {
00515         _currentAddress = _maxAddress - 1;
00516     }
00517     return GetAddressData(address,port,path,length,_currentAddress);
00518 }