33 audio.cpp
44
55 Created on: Oct 28.2018 */ char audioI2SVers[] =" \
6- Version 3.4.1l " ;
6+ Version 3.4.1m " ;
77/* Updated on: Aug 18.2025
88
99 Author: Wolle (schreibfaul1)
@@ -686,9 +686,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
686686 rqh.assign (" GET /" );
687687 rqh.append (path.get ());
688688 rqh.append (" HTTP/1.1\r\n " );
689- rqh.append (" Host: " );
690- rqh.append (hwoe.get ());
691- rqh.append (" \r\n " );
689+ rqh.appendf (" Host: %s:%u\r\n " , hwoe.get (), port);
692690 rqh.append (" Icy-MetaData:1\r\n " );
693691 rqh.append (" Icy-MetaData:2\r\n " );
694692 rqh.append (" Pragma: no-cache\r\n " );
@@ -801,9 +799,7 @@ bool Audio::httpPrint(const char* host) {
801799 rqh.assign (" GET /" );
802800 rqh.append (path.get ());
803801 rqh.append (" HTTP/1.1\r\n " );
804- rqh.append (" Host: " );
805- rqh.append (hwoe.get ());
806- rqh.append (" \r\n " );
802+ rqh.appendf (" Host: %s:%u\r\n " , hwoe.get (), port);
807803 rqh.append (" Icy-MetaData:1\r\n " );
808804 rqh.append (" Icy-MetaData:2\r\n " );
809805 rqh.append (" Accept:*/*\r\n " );
@@ -898,7 +894,7 @@ bool Audio::httpRange(uint32_t seek, uint32_t length){
898894 else range.assignf (" Range: bytes=%li-%li\r\n " ,seek, length);
899895
900896 rqh.assignf (" GET /%s HTTP/1.1\r\n " , path.get ());
901- rqh.appendf (" Host: %s\r\n " , hwoe.get ());
897+ rqh.appendf (" Host: %s:%u \r\n " , hwoe.get (), port );
902898 rqh.append (" Accept: */*\r\n " );
903899 rqh.append (" Accept-Encoding: identity;q=1,*;q=0\r\n " );
904900 rqh.append (" Cache-Control: no-cache\r\n " );
@@ -3229,7 +3225,14 @@ void Audio::loop() {
32293225 m_f_firstCall = true ;
32303226 }
32313227 break ;
3232- case AUDIO_PLAYLISTINIT: readPlayListData (); break ;
3228+ case AUDIO_PLAYLISTINIT:
3229+ if (readPlayListData ()) break ;
3230+ else { // readPlayListData == false means connect to m3u8 URL
3231+ if (m_lastM3U8host.valid ()) {m_f_reset_m3u8Codec = false ; httpPrint (m_lastM3U8host.get ());}
3232+ else {httpPrint (m_lastHost.get ());} // if url has no first redirection
3233+ m_dataMode = HTTP_RESPONSE_HEADER; // we have a new playlist now
3234+ break ;
3235+ }
32333236 case AUDIO_PLAYLISTDATA:
32343237 host = parsePlaylist_M3U8 ();
32353238 if (!host.valid ()) m_lVar.no_host_cnt ++;
@@ -3260,18 +3263,38 @@ void Audio::loop() {
32603263}
32613264// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
32623265bool Audio::readPlayListData () {
3263- if (m_dataMode != AUDIO_PLAYLISTINIT) return false ;
3264- if (m_client->available () == 0 ) return false ;
32653266
3266- uint32_t chunksize = 0 ;
3267- uint8_t readedBytes = 0 ;
3267+ uint32_t chunksize = 0 ;
3268+ uint8_t readedBytes = 0 ;
3269+ ps_ptr<char > pl (" pl" );
3270+ uint32_t ctl = 0 ;
3271+ int lines = 0 ;
3272+ uint16_t plSize = 0 ;
3273+
3274+ auto detectTimeout = [&]() -> bool {
3275+ uint32_t t = millis ();
3276+ while (!m_client->available ()) {
3277+ vTaskDelay (50 );
3278+ if (t + 1000 < millis ()) {
3279+ AUDIO_LOG_WARN (" Playlist is incomplete, fetch again" );
3280+ if (m_f_chunked) getChunkSize (0 , true );
3281+ return true ;
3282+ }
3283+ }
3284+ return false ;
3285+ };
3286+
3287+ if (m_dataMode != AUDIO_PLAYLISTINIT) {AUDIO_LOG_ERROR (" wrong datamode %s" , dataModeStr[m_dataMode]); goto exit;}
3288+
32683289 getChunkSize (0 , true );
32693290 if (m_f_chunked) chunksize = getChunkSize (&readedBytes);
3270- uint16_t plSize = max (m_audioFileSize, chunksize);
3291+ plSize = max (m_audioFileSize, chunksize);
3292+
3293+ if (!plSize){ // maybe playlist without contentLength or chunkSize
3294+ if (detectTimeout ()) goto exit;
3295+ plSize = m_client->available ();
3296+ }
32713297
3272- ps_ptr<char >pl (" pl" );
3273- uint32_t ctl = 0 ;
3274- int lines = 0 ;
32753298 // delete all memory in m_playlistContent
32763299 if (m_playlistFormat == FORMAT_M3U8 && !psramFound ()) { AUDIO_LOG_ERROR (" m3u8 playlists requires PSRAM enabled!" ); }
32773300 vector_clear_and_shrink (m_playlistContent);
@@ -3283,42 +3306,24 @@ bool Audio::readPlayListData() {
32833306
32843307 while (true ) { // inner while
32853308 uint16_t pos = 0 ;
3286- while (m_client->available ()) { // super inner while :-))
3309+ while (true ) { // super inner while :-))
3310+ uint32_t t = millis ();
32873311 if (ctl == plSize) break ;
3312+ if (detectTimeout ()) goto exit;
32883313 pl[pos] = audioFileRead ();
32893314 ctl++;
3290- if (pl[pos] == ' \n ' ) {
3291- pl[pos] = ' \0 ' ;
3292- pos++;
3293- break ;
3294- }
3295- if (pl[pos] == ' \r ' ) {
3296- pl[pos] = ' \0 ' ;
3297- pos++;
3298- continue ;
3299- ;
3300- }
3315+ if (pl[pos] == ' \n ' ) {pl[pos] = ' \0 ' ; pos++; break ;}
3316+ if (pl[pos] == ' \r ' ) {pl[pos] = ' \0 ' ; pos++; continue ;}
33013317 pos++;
3302- if (pos == 1022 ) {
3303- pos--;
3304- continue ;
3305- }
3306- if (ctl == plSize) {
3307- pl[pos] = ' \0 ' ;
3308- break ;
3309- }
3318+ if (pos == 1022 ) {pos--; continue ;}
3319+ if (ctl == plSize) {pl[pos] = ' \0 ' ; break ;}
33103320 }
3311- if (ctl == plSize) break ;
33123321 if (pos) {
33133322 pl[pos] = ' \0 ' ;
33143323 break ;
33153324 }
3316-
3317- if (ctime + timeout < millis ()) {
3318- AUDIO_LOG_ERROR (" timeout" );
3319- for (int i = 0 ; i < m_playlistContent.size (); i++) AUDIO_LOG_ERROR (" pl%i = %s" , i, m_playlistContent[i].get ());
3320- goto exit;
3321- }
3325+ if (ctl == plSize) break ;
3326+ if (detectTimeout ()) goto exit;
33223327 } // inner while
33233328
33243329 if (pl.starts_with_icase (" <!DOCTYPE" )) {
@@ -3342,23 +3347,25 @@ bool Audio::readPlayListData() {
33423347 }
33433348 } // outer while
33443349 lines = m_playlistContent.size ();
3345- if (m_f_chunked) getChunkSize (&readedBytes);
3350+
3351+ if (m_f_chunked) getChunkSize (&readedBytes); // expected: "\r\n\0\r\n\r\n"
33463352 m_dataMode = AUDIO_PLAYLISTDATA;
33473353 return true ;
33483354
33493355exit:
33503356 vector_clear_and_shrink (m_playlistContent);
3351- m_f_running = false ;
3352- m_dataMode = AUDIO_NONE;
3357+ getChunkSize (0 , true );
33533358 return false ;
33543359}
33553360// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
33563361const char * Audio::parsePlaylist_M3U () {
3362+
33573363 uint8_t lines = m_playlistContent.size ();
33583364 int pos = 0 ;
33593365 char * host = nullptr ;
33603366
33613367 for (int i = 0 ; i < lines; i++) {
3368+ // m_playlistContent[i].println();
33623369 if (m_playlistContent[i].contains (" #EXTINF:" )) { // Info?
33633370 pos = m_playlistContent[i].index_of (" ," ); // Comma in this line?
33643371 if (pos > 0 ) {
@@ -6380,9 +6387,11 @@ int32_t Audio::getChunkSize(uint8_t *readedBytes, bool first) {
63806387
63816388 // skip CRLF from the previous chunk (only http-chunked)
63826389 if (m_gchs.f_skipCRLF ) {
6383- if (m_client->available () < 2 ) {
6390+ uint32_t t = millis ();
6391+ while (m_client->available () < 2 ) {
6392+ if (t + 500 > millis ()){vTaskDelay (100 ); continue ;}
63846393 AUDIO_LOG_WARN (" Not enough bytes for CRLF" );
6385- return 0 ;
6394+ return - 1 ;
63866395 }
63876396 int a = audioFileRead ();
63886397 int b = audioFileRead ();
@@ -6444,10 +6453,8 @@ int32_t Audio::getChunkSize(uint8_t *readedBytes, bool first) {
64446453 idx++;
64456454 }
64466455 }
6447-
64486456 return chunksize;
64496457}
6450-
64516458// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
64526459bool Audio::readID3V1Tag () {
64536460 if (m_codec != CODEC_MP3) return false ;
0 commit comments