Unverified Commit 1037680b authored by Wolle's avatar Wolle Committed by GitHub

readMetadata() rewritten

parent beb5ea49
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* *
* Created on: Oct 26.2018 * Created on: Oct 26.2018
* *
* Version 2.0.4d * Version 2.0.4e
* Updated on: Jul 11.2022 * Updated on: Jul 16.2022
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
* *
*/ */
...@@ -440,7 +440,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) { ...@@ -440,7 +440,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
strcat(rqh, "GET "); strcat(rqh, "GET ");
strcat(rqh, extension); strcat(rqh, extension);
strcat(rqh, " HTTP/1.0\r\n"); strcat(rqh, " HTTP/1.1\r\n");
strcat(rqh, "Host: "); strcat(rqh, "Host: ");
strcat(rqh, hostwoext); strcat(rqh, hostwoext);
strcat(rqh, "\r\n"); strcat(rqh, "\r\n");
...@@ -2338,7 +2338,7 @@ const char* Audio::parsePlaylist_M3U(){ ...@@ -2338,7 +2338,7 @@ const char* Audio::parsePlaylist_M3U(){
// AUDIO_INFO("Entry in playlist found: %s", pl); // AUDIO_INFO("Entry in playlist found: %s", pl);
pos = indexOf(m_playlistContent[i], "http", 0); // Search for "http" pos = indexOf(m_playlistContent[i], "http", 0); // Search for "http"
if(pos >= 0) { // Does URL contain "http://"? if(pos >= 0) { // Does URL contain "http://"?
log_e("%s pos=%i", m_playlistContent[i], pos); // log_e("%s pos=%i", m_playlistContent[i], pos);
host = m_playlistContent[i] + pos; // Yes, set new host host = m_playlistContent[i] + pos; // Yes, set new host
break; break;
} }
...@@ -2755,7 +2755,7 @@ void Audio::processLocalFile() { ...@@ -2755,7 +2755,7 @@ void Audio::processLocalFile() {
void Audio::processWebStream() { void Audio::processWebStream() {
const uint16_t maxFrameSize = InBuff.getMaxBlockSize(); // every mp3/aac frame is not bigger const uint16_t maxFrameSize = InBuff.getMaxBlockSize(); // every mp3/aac frame is not bigger
int32_t availableBytes; // available bytes in stream uint32_t availableBytes; // available bytes in stream
static bool f_tmr_1s; static bool f_tmr_1s;
static bool f_stream; // first audio data received static bool f_stream; // first audio data received
static bool f_webFileDataComplete; // all file data received static bool f_webFileDataComplete; // all file data received
...@@ -2765,7 +2765,6 @@ void Audio::processWebStream() { ...@@ -2765,7 +2765,6 @@ void Audio::processWebStream() {
static uint32_t chunksize; // chunkcount read from stream static uint32_t chunksize; // chunkcount read from stream
static uint32_t tmr_1s; // timer 1 sec static uint32_t tmr_1s; // timer 1 sec
static uint32_t loopCnt; // count loops if clientbuffer is empty static uint32_t loopCnt; // count loops if clientbuffer is empty
static uint32_t metacount; // counts down bytes between metadata
static size_t audioDataCount; // counts the decoded audiodata only static size_t audioDataCount; // counts the decoded audiodata only
// first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // first call, set some values to default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
...@@ -2781,7 +2780,7 @@ void Audio::processWebStream() { ...@@ -2781,7 +2780,7 @@ void Audio::processWebStream() {
audioDataCount = 0; audioDataCount = 0;
tmr_1s = millis(); tmr_1s = millis();
m_t0 = millis(); m_t0 = millis();
metacount = m_metaint; m_metacount = m_metaint;
readMetadata(0, true); // reset all static vars readMetadata(0, true); // reset all static vars
} }
...@@ -2840,51 +2839,14 @@ void Audio::processWebStream() { ...@@ -2840,51 +2839,14 @@ void Audio::processWebStream() {
} }
// if we have metadata: get them - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // if we have metadata: get them - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(!metacount && !m_f_swm && availableBytes){ if(!m_metacount && !m_f_swm){
static uint16_t pos_ml = 0; // determines the current position in metaline int bytes = 0;
static uint16_t metalen = 0; int res = 0;
if(m_f_chunked) bytes = min(m_chunkcount, availableBytes);
if(!metalen) { // First byte of metadata? else bytes = availableBytes;
int b = _client->read(); res = readMetadata(bytes);
if(m_f_chunked) m_chunkcount--; if(m_f_chunked) m_chunkcount -= res;
metalen = b * 16; // New count for metadata including length byte if(!m_metacount) return;
if(metalen >512){
AUDIO_INFO("Metadata block to long! Skipping all Metadata from now on.");
m_f_swm = true; // expect stream without metadata
}
pos_ml = 0; chbuf[pos_ml] = 0; // Prepare for new line
}
int i = 0;
if(m_f_chunked) i = min((uint32_t)metalen, m_chunkcount);
else i = metalen;
int bytes = _client->readBytes(&chbuf[pos_ml], i);
if(m_f_chunked) m_chunkcount -= bytes;
pos_ml += bytes;
if(pos_ml == metalen) {
metalen = 0;
chbuf[pos_ml] = '\0';
pos_ml = 0;
metacount = m_metaint;
if(strlen(chbuf)) { // Any info present?
// metaline contains artist and song name. For example:
// "StreamTitle='Don McLean - American Pie';StreamUrl='';"
// Sometimes it is just other info like:
// "StreamTitle='60s 03 05 Magic60s';StreamUrl='';"
// Isolate the StreamTitle, remove leading and trailing quotes if present.
// log_i("ST %s", metaline);
latinToUTF8(chbuf, sizeof(chbuf)); // convert to UTF-8 if necessary
int pos = indexOf(chbuf, "song_spot", 0); // remove some irrelevant infos
if(pos > 3) { // e.g. song_spot="T" MediaBaseId="0" itunesTrackId="0"
chbuf[pos] = 0;
}
log_e("%s", chbuf);
if(!m_f_localfile) showstreamtitle(chbuf); // Show artist and title if present in metadata
}
}
return;
} }
// if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // if the buffer is often almost empty issue a warning - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
...@@ -2913,7 +2875,7 @@ void Audio::processWebStream() { ...@@ -2913,7 +2875,7 @@ void Audio::processWebStream() {
// buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // buffer fill routine - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(true) { // statement has no effect if(true) { // statement has no effect
uint32_t bytesCanBeWritten = InBuff.writeSpace(); uint32_t bytesCanBeWritten = InBuff.writeSpace();
if(!m_f_swm) bytesCanBeWritten = min(metacount, bytesCanBeWritten); if(!m_f_swm) bytesCanBeWritten = min(m_metacount, bytesCanBeWritten);
if(m_f_chunked) bytesCanBeWritten = min(m_chunkcount, bytesCanBeWritten); if(m_f_chunked) bytesCanBeWritten = min(m_chunkcount, bytesCanBeWritten);
int16_t bytesAddedToBuffer = 0; int16_t bytesAddedToBuffer = 0;
...@@ -2942,7 +2904,7 @@ void Audio::processWebStream() { ...@@ -2942,7 +2904,7 @@ void Audio::processWebStream() {
if(bytesAddedToBuffer > 0) { if(bytesAddedToBuffer > 0) {
if(m_f_webfile) byteCounter += bytesAddedToBuffer; // Pull request #42 if(m_f_webfile) byteCounter += bytesAddedToBuffer; // Pull request #42
if(!m_f_swm) metacount -= bytesAddedToBuffer; if(!m_f_swm) m_metacount -= bytesAddedToBuffer;
if(m_f_chunked) m_chunkcount -= bytesAddedToBuffer; if(m_f_chunked) m_chunkcount -= bytesAddedToBuffer;
InBuff.bytesWritten(bytesAddedToBuffer); InBuff.bytesWritten(bytesAddedToBuffer);
} }
...@@ -3032,7 +2994,7 @@ void Audio::processWebStream() { ...@@ -3032,7 +2994,7 @@ void Audio::processWebStream() {
if(byteCounter == m_contentlength){ if(byteCounter == m_contentlength){
if(m_playlistFormat == FORMAT_M3U8){ if(m_playlistFormat == FORMAT_M3U8){
byteCounter = 0; byteCounter = 0;
metacount = m_metaint; m_metacount = m_metaint;
m_f_continue = true; m_f_continue = true;
return; return;
} }
...@@ -3130,7 +3092,7 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque ...@@ -3130,7 +3092,7 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque
idx = indexOf(rhl, "content-type:", 0); // content-type: text/html; charset=UTF-8 idx = indexOf(rhl, "content-type:", 0); // content-type: text/html; charset=UTF-8
if(idx >= 0) { if(idx >= 0) {
AUDIO_INFO("%s", rhl); // AUDIO_INFO("%s", rhl);
idx = indexOf(rhl + 13, ";"); idx = indexOf(rhl + 13, ";");
if(idx >0) rhl[13 + idx] = '\0'; if(idx >0) rhl[13 + idx] = '\0';
if(parseContentType(rhl + 13)) ct_seen = true; if(parseContentType(rhl + 13)) ct_seen = true;
...@@ -3250,7 +3212,6 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque ...@@ -3250,7 +3212,6 @@ bool Audio::parseHttpResponseHeader() { // this is the response to a GET / reque
} // outer while } // outer while
exit: // termination condition exit: // termination condition
log_e("exit");
if(audio_showstation) audio_showstation(""); if(audio_showstation) audio_showstation("");
if(audio_icydescription) audio_icydescription(""); if(audio_icydescription) audio_icydescription("");
if(audio_icyurl) audio_icyurl(""); if(audio_icyurl) audio_icyurl("");
...@@ -3325,34 +3286,39 @@ bool Audio:: initializeDecoder(){ ...@@ -3325,34 +3286,39 @@ bool Audio:: initializeDecoder(){
return false; return false;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::readMetadata(uint8_t b, bool first) { uint16_t Audio::readMetadata(uint16_t maxBytes, bool first) {
static uint16_t pos_ml = 0; // determines the current position in metaline static uint16_t pos_ml = 0; // determines the current position in metaline
static uint16_t metalen = 0; static uint16_t metalen = 0;
uint16_t res = 0;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(first){ if(first){
pos_ml = 0; pos_ml = 0;
metalen = 0; metalen = 0;
return true; return 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if(!metalen) { // First byte of metadata? if(!maxBytes) return 0; // guard
int b = _client->read();
metalen = b * 16 + 1; // New count for metadata including length byte if(!metalen) {
if(metalen >512){ int b = _client->read(); // First byte of metadata?
metalen = b * 16 ; // New count for metadata including length byte
if(metalen > 512){
AUDIO_INFO("Metadata block to long! Skipping all Metadata from now on."); AUDIO_INFO("Metadata block to long! Skipping all Metadata from now on.");
m_f_swm = true; // expect stream without metadata m_f_swm = true; // expect stream without metadata
} }
pos_ml = 0; chbuf[pos_ml] = 0; // Prepare for new line pos_ml = 0; chbuf[pos_ml] = 0; // Prepare for new line
res = 1;
} }
chbuf[pos_ml] = (char) b; // Put new char in +++++ if(!metalen) {m_metacount = m_metaint; return res;}
if(pos_ml < 510) pos_ml ++;
chbuf[pos_ml] = 0;
if(pos_ml == 509) { log_e("metaline overflow in AUDIO_METADATA! metaline=%s", chbuf); }
if(pos_ml == 510) { ; /* last current char in b */}
if(--metalen == 0) { uint16_t a = _client->readBytes(&chbuf[pos_ml], min(metalen, (uint16_t)(maxBytes -1)));
res += a;
pos_ml += a;
if(pos_ml == metalen) {
metalen = 0;
chbuf[pos_ml] = '\0';
m_metacount = m_metaint;
if(strlen(chbuf)) { // Any info present? if(strlen(chbuf)) { // Any info present?
// metaline contains artist and song name. For example: // metaline contains artist and song name. For example:
// "StreamTitle='Don McLean - American Pie';StreamUrl='';" // "StreamTitle='Don McLean - American Pie';StreamUrl='';"
...@@ -3360,18 +3326,16 @@ bool Audio::readMetadata(uint8_t b, bool first) { ...@@ -3360,18 +3326,16 @@ bool Audio::readMetadata(uint8_t b, bool first) {
// "StreamTitle='60s 03 05 Magic60s';StreamUrl='';" // "StreamTitle='60s 03 05 Magic60s';StreamUrl='';"
// Isolate the StreamTitle, remove leading and trailing quotes if present. // Isolate the StreamTitle, remove leading and trailing quotes if present.
// log_i("ST %s", metaline); // log_i("ST %s", metaline);
latinToUTF8(chbuf, sizeof(chbuf)); // convert to UTF-8 if necessary latinToUTF8(chbuf, sizeof(chbuf)); // convert to UTF-8 if necessary
int pos = indexOf(chbuf, "song_spot", 0); // remove some irrelevant infos int pos = indexOf(chbuf, "song_spot", 0); // remove some irrelevant infos
if(pos > 3) { // e.g. song_spot="T" MediaBaseId="0" itunesTrackId="0" if(pos > 3) { // e.g. song_spot="T" MediaBaseId="0" itunesTrackId="0"
chbuf[pos] = 0; chbuf[pos] = 0;
} }
if(!m_f_localfile) showstreamtitle(chbuf); // Show artist and title if present in metadata showstreamtitle(chbuf); // Show artist and title if present in metadata
} }
return true ; pos_ml = 0;
} }
return false;// end_METADATA return res;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::parseContentType(char* ct) { bool Audio::parseContentType(char* ct) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Audio.h * Audio.h
* *
* Created on: Oct 26,2018 * Created on: Oct 26,2018
* Updated on: Jul 11,2022 * Updated on: Jul 16,2022
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
*/ */
...@@ -248,7 +248,7 @@ private: ...@@ -248,7 +248,7 @@ private:
bool parseContentType(char* ct); bool parseContentType(char* ct);
bool parseHttpResponseHeader(); bool parseHttpResponseHeader();
bool initializeDecoder(); bool initializeDecoder();
bool readMetadata(uint8_t b, bool first = false); uint16_t readMetadata(uint16_t b, bool first = false);
esp_err_t I2Sstart(uint8_t i2s_num); esp_err_t I2Sstart(uint8_t i2s_num);
esp_err_t I2Sstop(uint8_t i2s_num); esp_err_t I2Sstop(uint8_t i2s_num);
void urlencode(char* buff, uint16_t buffLen, bool spacesOnly = false); void urlencode(char* buff, uint16_t buffLen, bool spacesOnly = false);
...@@ -459,13 +459,13 @@ private: ...@@ -459,13 +459,13 @@ private:
uint32_t m_sampleRate=16000; uint32_t m_sampleRate=16000;
uint32_t m_bitRate=0; // current bitrate given fom decoder uint32_t m_bitRate=0; // current bitrate given fom decoder
uint32_t m_avr_bitrate = 0; // average bitrate, median computed by VBR uint32_t m_avr_bitrate = 0; // average bitrate, median computed by VBR
int m_readbytes=0; // bytes read int m_readbytes = 0; // bytes read
int m_metalen=0; // Number of bytes in metadata uint32_t m_metacount = 0; // counts down bytes between metadata
int m_controlCounter = 0; // Status within readID3data() and readWaveHeader() int m_controlCounter = 0; // Status within readID3data() and readWaveHeader()
int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right) int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right)
uint8_t m_vol=64; // volume uint8_t m_vol=64; // volume
uint8_t m_bitsPerSample = 16; // bitsPerSample uint8_t m_bitsPerSample = 16; // bitsPerSample
uint8_t m_channels=2; uint8_t m_channels = 2;
uint8_t m_i2s_num = I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1 uint8_t m_i2s_num = I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1
uint8_t m_playlistFormat = 0; // M3U, PLS, ASX uint8_t m_playlistFormat = 0; // M3U, PLS, ASX
uint8_t m_m3u8codec = CODEC_NONE; // M4A uint8_t m_m3u8codec = CODEC_NONE; // M4A
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment