Skip to content

Commit a169f66

Browse files
committed
Addresses ending in .m3u do not work #1139
1 parent 8ad8822 commit a169f66

File tree

1 file changed

+58
-51
lines changed

1 file changed

+58
-51
lines changed

src/Audio.cpp

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
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
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
32623265
bool 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

33493355
exit:
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
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
33563361
const 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
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
64526459
bool Audio::readID3V1Tag() {
64536460
if (m_codec != CODEC_MP3) return false;

0 commit comments

Comments
 (0)