2#include "AudioToolsConfig.h"
3#include "AbstractMetaData.h"
4#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
5#include "AudioTools/Communication/HTTP/AbstractURLStream.h"
7#ifndef AUDIOTOOLS_METADATA_ICY_ASCII_ONLY
8#define AUDIOTOOLS_METADATA_ICY_ASCII_ONLY true
29 enum Status { ProcessData, ProcessMetaData, SetupSize };
41 this->mp3_blocksize = value;
52 int bufferLen = 1024) {
53 dataBuffer =
new uint8_t[bufferLen];
62 LOGI(
"mp3_blocksize: %d", mp3_blocksize);
67 virtual void end()
override { clear(); }
71 virtual size_t write(
const uint8_t* data,
size_t len)
override {
72 if (callback !=
nullptr) {
73 for (
size_t j = 0; j < len; j++) {
81 virtual Status
status() {
return currentStatus; }
84 virtual bool isData() {
return currentStatus == ProcessData; }
87 virtual bool hasMetaData() {
return this->mp3_blocksize > 0; }
90 virtual int metaInt() {
return mp3_blocksize; }
96 currentStatus = ProcessData;
101 if (totalData >= mp3_blocksize) {
104 nextStatus = SetupSize;
109 currentStatus = SetupSize;
113 LOGI(
"metaDataLen: %d", metaDataLen);
114 if (metaDataLen > 0) {
115 if (metaDataLen > 200) {
116 LOGI(
"Unexpected metaDataLen -> processed as data");
117 nextStatus = ProcessData;
119 LOGI(
"Metadata found");
121 nextStatus = ProcessMetaData;
125 nextStatus = ProcessData;
129 case ProcessMetaData:
130 currentStatus = ProcessMetaData;
131 metaData[metaDataPos++] = ch;
132 if (metaDataPos >= metaDataLen) {
134 LOGI(
"Metadata ended")
135 nextStatus = ProcessData;
142 Status nextStatus = ProcessData;
143 Status currentStatus = ProcessData;
144 void (*callback)(
MetaDataType info,
const char* str,
int len) =
nullptr;
147 int mp3_blocksize = 0;
148 int metaDataMaxLen = 0;
153 uint8_t* dataBuffer =
nullptr;
154 void (*dataCallback)(
const uint8_t* str,
int len) =
nullptr;
158 virtual void clear() {
159 nextStatus = ProcessData;
174 for (
int j = 0; j < l; j++) {
177 if (ch < 0x80 || ch > 0xbf)
return false;
181 if (ch !=
'\n' && ch !=
'\r' && ch !=
'\t' && ch < 32 || ch == 127)
184#if !AUDIOTOOLS_METADATA_ICY_ASCII_ONLY
185 else if (ch >= 0xc2 && ch <= 0xdf) remain = 1;
186 else if (ch >= 0xe0 && ch <= 0xef) remain = 2;
187 else if (ch >= 0xf0 && ch <= 0xf4) remain = 3;
198 metaData.resize(meta_size + 1);
199 metaDataMaxLen = meta_size;
200 memset(metaData.data(), 0, meta_size + 1);
210 LOGI(
"%s", metaData);
211 StrView meta(metaData, len + 1, len);
212 int start = meta.
indexOf(
"StreamTitle=");
217 if (start >= 0 &&
end > start) {
219 if (callback !=
nullptr) {
220 callback(Title, (
const char*)metaData + start + 1,
end - start);
227 LOGW(
"Unexpected Data: corrupted metadata block rejected (len=%d)", len);
229 if (callback !=
nullptr) {
230 callback(Corrupted,
nullptr, len);
238 if (dataBuffer !=
nullptr) {
239 dataBuffer[dataPos++] = ch;
241 if (dataPos >= dataLen) {
242 dataCallback(dataBuffer, dataLen);
265 LOGI(
"icy-metaint: %s", iceMetaintStr);
267 LOGE(
"icy-metaint not defined");
270 int iceMetaint = value.
toInt();
279 if (callback ==
nullptr) {
280 LOGW(
"callback not defined")
282 if (p_url ==
nullptr) {
283 LOGW(
"http not defined")
286 if (callback !=
nullptr && p_url !=
nullptr) {
295 callback(Description, descr.
c_str(), descr.
length());