33 *
44 * Created on: Oct 26.2018
55 *
6- * Version 2.0.5g
7- * Updated on: Aug 12 .2022
6+ * Version 2.0.5h
7+ * Updated on: Aug 17 .2022
88 * Author: Wolle (schreibfaul1)
99 *
1010 */
@@ -316,7 +316,7 @@ void Audio::setDefaults() {
316316 m_f_firstmetabyte = false ;
317317 m_f_playing = false ;
318318 m_f_ssl = false ;
319- m_f_swm = true ; // Assume no metaint (stream without metadata)
319+ m_f_metadata = false ;
320320 m_f_tts = false ;
321321 m_f_firstCall = true ; // InitSequence for processWebstream and processLokalFile
322322 m_f_running = false ;
@@ -2389,7 +2389,8 @@ void Audio::loop() {
23892389 if (m_playlistFormat == FORMAT_ASX) connecttohost (parsePlaylist_ASX ());
23902390 break ;
23912391 case AUDIO_DATA:
2392- processWebStream ();
2392+ if (m_streamType == ST_WEBSTREAM) processWebStream ();
2393+ if (m_streamType == ST_WEBFILE) processWebFile ();
23932394 break ;
23942395 }
23952396 }
@@ -2444,12 +2445,20 @@ void Audio::loop() {
24442445 }
24452446}
24462447// ---------------------------------------------------------------------------------------------------------------------
2447- size_t Audio::chunkedDataTransfer (){
2448+ size_t Audio::chunkedDataTransfer (uint8_t * bytes ){
24482449 size_t chunksize = 0 ;
24492450 int b = 0 ;
2451+ uint32_t ctime = millis ();
2452+ uint32_t timeout = 2000 ; // ms
24502453 while (true ){
2454+ if (ctime + timeout < millis ()) {
2455+ log_e (" timeout" );
2456+ stopSong ();
2457+ return 0 ;
2458+ }
24512459 b = _client->read ();
2452- if (b < 0 ) break ;
2460+ *bytes++;
2461+ if (b < 0 ) continue ; // -1 no data available
24532462 if (b == ' \n ' ) break ;
24542463 if (b < ' 0' ) continue ;
24552464 // We have received a hexadecimal character. Decode it and add to the result.
@@ -2466,8 +2475,8 @@ bool Audio::readPlayListData() {
24662475 if (getDatamode () != AUDIO_PLAYLISTINIT) return false ;
24672476 if (_client->available () == 0 ) return false ;
24682477
2469- uint32_t chunksize = 0 ;
2470- if (m_f_chunked) chunksize = chunkedDataTransfer ();
2478+ uint32_t chunksize = 0 ; uint8_t readedBytes = 0 ;
2479+ if (m_f_chunked) chunksize = chunkedDataTransfer (&readedBytes );
24712480
24722481 // reads the content of the playlist and stores it in the vector m_contentlength
24732482 // m_contentlength is a table of pointers to the lines
@@ -2956,9 +2965,90 @@ void Audio::processLocalFile() {
29562965 if (afn) {free (afn); afn = NULL ;}
29572966 }
29582967}
2959- // ---------------------------------------------------------------------------------------------------------------------
2968+ // ----------------------------------------------------------------------------------------------------------------------
29602969void Audio::processWebStream () {
29612970
2971+ const uint16_t maxFrameSize = InBuff.getMaxBlockSize (); // every mp3/aac frame is not bigger
2972+ static bool f_tmr_1s;
2973+ static bool f_stream; // first audio data received
2974+ static uint8_t cnt_slow;
2975+ static uint32_t chunkSize; // chunkcount read from stream
2976+ static uint32_t tmr_1s; // timer 1 sec
2977+ static uint32_t loopCnt; // count loops if clientbuffer is empty
2978+
2979+ // first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2980+ if (m_f_firstCall) { // runs only ont time per connection, prepare for start
2981+ m_f_firstCall = false ;
2982+ f_stream = false ;
2983+ cnt_slow = 0 ;
2984+ chunkSize = 0 ;
2985+ loopCnt = 0 ;
2986+ tmr_1s = millis ();
2987+ m_metacount = m_metaint;
2988+ readMetadata (0 , true ); // reset all static vars
2989+ }
2990+
2991+ if (getDatamode () != AUDIO_DATA) return ; // guard
2992+ uint32_t availableBytes = _client->available (); // available from stream
2993+ // chunked data tramsfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2994+ if (m_f_chunked){
2995+ uint8_t readedBytes = 0 ;
2996+ if (!chunkSize) chunkSize = chunkedDataTransfer (&readedBytes);
2997+ availableBytes = min (availableBytes, chunkSize);
2998+ }
2999+ // we have metadata - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3000+ if (m_f_metadata){
3001+ if (availableBytes) if (m_metacount == 0 ) {chunkSize -= readMetadata (availableBytes); return ;}
3002+ availableBytes = min (availableBytes, m_metacount);
3003+ }
3004+ // timer, triggers every second - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3005+ if ((tmr_1s + 1000 ) < millis ()) {
3006+ f_tmr_1s = true ; // flag will be set every second for one loop only
3007+ tmr_1s = millis ();
3008+ }
3009+ // if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3010+ if (InBuff.bufferFilled () > maxFrameSize) {f_tmr_1s = false ; cnt_slow = 0 ; loopCnt = 0 ;}
3011+ if (f_tmr_1s){
3012+ cnt_slow ++;
3013+ if (cnt_slow > 25 ){cnt_slow = 0 ; AUDIO_INFO (" slow stream, dropouts are possible" );}
3014+ }
3015+ // if the buffer can't filled for several seconds try a new connection - - - - - - - - - - - - - - - - - - - - - - -
3016+ if (f_stream && !availableBytes){
3017+ loopCnt++;
3018+ if (loopCnt > 200000 ) { // wait several seconds
3019+ AUDIO_INFO (" Stream lost -> try new connection" );
3020+ connecttohost (m_lastHost);
3021+ return ;
3022+ }
3023+ }
3024+ // buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3025+ if (availableBytes) {
3026+ availableBytes = min (availableBytes, InBuff.writeSpace ());
3027+ int16_t bytesAddedToBuffer = _client->read (InBuff.getWritePtr (), availableBytes);
3028+
3029+ if (bytesAddedToBuffer > 0 ) {
3030+ if (m_f_metadata) m_metacount -= bytesAddedToBuffer;
3031+ if (m_f_chunked) chunkSize -= bytesAddedToBuffer;
3032+ InBuff.bytesWritten (bytesAddedToBuffer);
3033+ }
3034+
3035+ if (InBuff.bufferFilled () > maxFrameSize && !f_stream) { // waiting for buffer filled
3036+ f_stream = true ; // ready to play the audio data
3037+ AUDIO_INFO (" stream ready" );
3038+ }
3039+ if (!f_stream) return ;
3040+ }
3041+
3042+ // play audio data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3043+ if (f_stream){
3044+ static uint8_t cnt = 0 ;
3045+ cnt++;
3046+ if (cnt == 3 ){playAudioData (); cnt = 0 ;}
3047+ }
3048+ }
3049+ // ---------------------------------------------------------------------------------------------------------------------
3050+ void Audio::processWebFile () {
3051+
29623052 const uint16_t maxFrameSize = InBuff.getMaxBlockSize (); // every mp3/aac frame is not bigger
29633053 uint32_t availableBytes; // available bytes in stream
29643054 static bool f_tmr_1s;
@@ -3044,15 +3134,15 @@ void Audio::processWebStream() {
30443134 }
30453135
30463136 // if we have metadata: get them - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3047- if (!m_metacount && !m_f_swm){
3048- int bytes = 0 ;
3049- int res = 0 ;
3050- if (m_f_chunked) bytes = min (m_chunkcount, availableBytes);
3051- else bytes = availableBytes;
3052- res = readMetadata (bytes);
3053- if (m_f_chunked) m_chunkcount -= res;
3054- if (!m_metacount) return ;
3055- }
3137+ // if(!m_metacount && !m_f_swm){
3138+ // int bytes = 0;
3139+ // int res = 0;
3140+ // if(m_f_chunked) bytes = min(m_chunkcount, availableBytes);
3141+ // else bytes = availableBytes;
3142+ // res = readMetadata(bytes);
3143+ // if(m_f_chunked) m_chunkcount -= res;
3144+ // if(!m_metacount) return;
3145+ // }
30563146
30573147 // if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30583148 if (InBuff.bufferFilled () < maxFrameSize && f_stream && !f_webFileDataComplete){
@@ -3080,7 +3170,7 @@ void Audio::processWebStream() {
30803170 // buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30813171 if (true ) { // statement has no effect
30823172 uint32_t bytesCanBeWritten = InBuff.writeSpace ();
3083- if (!m_f_swm) bytesCanBeWritten = min (m_metacount, bytesCanBeWritten);
3173+ // if(!m_f_swm) bytesCanBeWritten = min(m_metacount, bytesCanBeWritten);
30843174 if (m_f_chunked) bytesCanBeWritten = min (m_chunkcount, bytesCanBeWritten);
30853175
30863176 int16_t bytesAddedToBuffer = 0 ;
@@ -3109,7 +3199,7 @@ void Audio::processWebStream() {
31093199
31103200 if (bytesAddedToBuffer > 0 ) {
31113201 if (m_streamType == ST_WEBFILE) byteCounter += bytesAddedToBuffer; // Pull request #42
3112- if (!m_f_swm) m_metacount -= bytesAddedToBuffer;
3202+ // if(!m_f_swm) m_metacount -= bytesAddedToBuffer;
31133203 if (m_f_chunked) m_chunkcount -= bytesAddedToBuffer;
31143204 InBuff.bytesWritten (bytesAddedToBuffer);
31153205 }
@@ -3279,7 +3369,8 @@ void Audio::processWebStreamTS() {
32793369
32803370 availableBytes = _client->available ();
32813371 if (availableBytes){
3282- if (m_f_chunked) chunkSize = chunkedDataTransfer ();
3372+ uint8_t readedBytes = 0 ;
3373+ if (m_f_chunked) chunkSize = chunkedDataTransfer (&readedBytes);
32833374 int res = _client->read (ts_packet + ts_packetPtr, ts_packetsize - ts_packetPtr);
32843375 if (res > 0 ){
32853376 ts_packetPtr += res;
@@ -3401,7 +3492,8 @@ void Audio::processWebStreamHLS() {
34013492
34023493 availableBytes = _client->available ();
34033494 if (availableBytes){
3404- if (m_f_chunked) chunkSize = chunkedDataTransfer ();
3495+ uint8_t readedBytes = 0 ;
3496+ if (m_f_chunked) chunkSize = chunkedDataTransfer (&readedBytes);
34053497 size_t bytesWasWritten = 0 ;
34063498 if (InBuff.writeSpace () >= availableBytes){
34073499 bytesWasWritten = _client->read (InBuff.getWritePtr (), availableBytes);
@@ -3623,7 +3715,7 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque
36233715 const char * c_metaint = (rhl + 12 );
36243716 int32_t i_metaint = atoi (c_metaint);
36253717 m_metaint = i_metaint;
3626- if (m_metaint) m_f_swm = false ; // Multimediastream
3718+ if (m_metaint) m_f_metadata = true ; // Multimediastream
36273719 }
36283720
36293721 else if (startsWith (rhl, " icy-name:" )) {
@@ -3768,20 +3860,18 @@ uint16_t Audio::readMetadata(uint16_t maxBytes, bool first) {
37683860 metalen = b * 16 ; // New count for metadata including length byte
37693861 if (metalen > 512 ){
37703862 AUDIO_INFO (" Metadata block to long! Skipping all Metadata from now on." );
3771- m_f_swm = true ; // expect stream without metadata
3863+ m_f_metadata = false ; // expect stream without metadata
3864+ return 1 ;
37723865 }
37733866 pos_ml = 0 ; chbuf[pos_ml] = 0 ; // Prepare for new line
37743867 res = 1 ;
37753868 }
3776- if (!metalen) {m_metacount = m_metaint; return res;}
3777-
3869+ if (!metalen) {m_metacount = m_metaint; return res;} // metalen is 0
37783870 uint16_t a = _client->readBytes (&chbuf[pos_ml], min ((uint16_t )(metalen - pos_ml), (uint16_t )(maxBytes -1 )));
37793871 res += a;
37803872 pos_ml += a;
37813873 if (pos_ml == metalen) {
3782- metalen = 0 ;
37833874 chbuf[pos_ml] = ' \0 ' ;
3784- m_metacount = m_metaint;
37853875 if (strlen (chbuf)) { // Any info present?
37863876 // metaline contains artist and song name. For example:
37873877 // "StreamTitle='Don McLean - American Pie';StreamUrl='';"
@@ -3796,6 +3886,8 @@ uint16_t Audio::readMetadata(uint16_t maxBytes, bool first) {
37963886 }
37973887 showstreamtitle (chbuf); // Show artist and title if present in metadata
37983888 }
3889+ m_metacount = m_metaint;
3890+ metalen = 0 ;
37993891 pos_ml = 0 ;
38003892 }
38013893 return res;
0 commit comments