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;
182 if (ch !=
'\n' && ch !=
'\r' && ch !=
'\t' && ch != 0 && (ch < 32 || ch == 127))
185#if !AUDIOTOOLS_METADATA_ICY_ASCII_ONLY
186 else if (ch >= 0xc2 && ch <= 0xdf) remain = 1;
187 else if (ch >= 0xe0 && ch <= 0xef) remain = 2;
188 else if (ch >= 0xf0 && ch <= 0xf4) remain = 3;
199 metaData.resize(meta_size + 1);
200 metaDataMaxLen = meta_size;
201 memset(metaData.data(), 0, meta_size + 1);
211 LOGI(
"%s", metaData);
212 StrView meta(metaData, len + 1, len);
213 int start = meta.
indexOf(
"StreamTitle=");
218 if (start >= 0 &&
end > start) {
220 if (callback !=
nullptr) {
221 callback(Title, (
const char*)metaData + start + 1,
end - start);
228 LOGW(
"Unexpected Data: corrupted metadata block rejected (len=%d)", len);
230 if (callback !=
nullptr) {
231 callback(Corrupted,
nullptr, len);
239 if (dataBuffer !=
nullptr) {
240 dataBuffer[dataPos++] = ch;
242 if (dataPos >= dataLen) {
243 dataCallback(dataBuffer, dataLen);
266 LOGI(
"icy-metaint: %s", iceMetaintStr);
268 LOGE(
"icy-metaint not defined");
271 int iceMetaint = value.
toInt();
280 if (callback ==
nullptr) {
281 LOGW(
"callback not defined")
283 if (p_url ==
nullptr) {
284 LOGW(
"http not defined")
287 if (callback !=
nullptr && p_url !=
nullptr) {
296 callback(Description, descr.
c_str(), descr.
length());