@@ -19,6 +19,9 @@ namespace audio_tools {
1919 */
2020class MultiDecoder : public AudioDecoder {
2121 public:
22+ MultiDecoder () = default ;
23+ MultiDecoder (AbstractURLStream& url) { setMimeSource (url); }
24+
2225 // / Enables the automatic mime type determination
2326 bool begin () override {
2427 mime_detector.begin ();
@@ -43,21 +46,25 @@ class MultiDecoder : public AudioDecoder {
4346 decoder.addNotifyAudioChange (*this );
4447 decoders.push_back (info);
4548 }
46-
47- // / Adds a decoder that will be selected by it's mime type and defines the mime checking logic
48- void addDecoder (AudioDecoder& decoder, const char * mime, bool (*check)(uint8_t *data, size_t len)) {
49+
50+ // / Adds a decoder that will be selected by it's mime type and defines the
51+ // / mime checking logic
52+ void addDecoder (AudioDecoder& decoder, const char * mime,
53+ bool (*check)(uint8_t * data, size_t len)) {
4954 addDecoder (decoder, mime);
5055 mime_detector.setCheck (mime, check);
5156 }
5257
53-
54- virtual void setOutput (Print &out_stream) override {
55- p_print = &out_stream;
58+ virtual void setOutput (Print& out_stream) override {
59+ p_print = &out_stream;
5660 for (int j = 0 ; j < decoders.size (); j++) {
5761 decoders[j].decoder ->setOutput (out_stream);
5862 }
5963 }
60-
64+
65+ // / Defines url stream from which we determine the mime type from the reply header
66+ void setMimeSource (AbstractURLStream& url) { p_url_stream = &url; }
67+
6168 // / selects the actual decoder by mime type - this is usually called
6269 // / automatically from the determined mime type
6370 bool selectDecoder (const char * mime) {
@@ -77,8 +84,8 @@ class MultiDecoder : public AudioDecoder {
7784 LOGI (" New decoder found for %s (%s)" , info.mime , mime);
7885 actual_decoder = info;
7986 // define output if it has not been defined
80- if (p_print!= nullptr
81- && actual_decoder.decoder ->getOutput ()== nullptr ){
87+ if (p_print != nullptr &&
88+ actual_decoder.decoder ->getOutput () == nullptr ) {
8289 actual_decoder.decoder ->setOutput (*p_print);
8390 }
8491 actual_decoder.decoder ->begin ();
@@ -91,10 +98,18 @@ class MultiDecoder : public AudioDecoder {
9198
9299 size_t write (const uint8_t * data, size_t len) override {
93100 if (is_first) {
94- // select the decoder based on the detemined mime type
95- mime_detector.write ((uint8_t *)data, len);
96- const char * mime = mime_detector.mime ();
101+ const char * mime = nullptr ;
102+ if (p_url_stream != nullptr ) {
103+ // get content type from http header
104+ mime = p_url_stream->getReplyHeader (CONTENT_TYPE);
105+ }
106+ if (mime != nullptr ) {
107+ // use the mime detector
108+ mime_detector.write ((uint8_t *)data, len);
109+ mime = mime_detector.mime ();
110+ }
97111 if (mime != nullptr ) {
112+ // select the decoder based on the detemined mime type
98113 if (!selectDecoder (mime)) {
99114 LOGE (" The decoder could not be found for %s" , mime);
100115 actual_decoder.decoder = &nop;
@@ -109,9 +124,9 @@ class MultiDecoder : public AudioDecoder {
109124 return actual_decoder.decoder ->write (data, len);
110125 }
111126
112- virtual operator bool () {
127+ virtual operator bool () {
113128 if (actual_decoder.decoder == &nop) return false ;
114- return is_first || actual_decoder.is_open ;
129+ return is_first || actual_decoder.is_open ;
115130 };
116131
117132 protected:
@@ -120,14 +135,15 @@ class MultiDecoder : public AudioDecoder {
120135 AudioDecoder* decoder = nullptr ;
121136 bool is_open = false ;
122137 DecoderInfo () = default ;
123- DecoderInfo (const char * mime, AudioDecoder* decoder){
138+ DecoderInfo (const char * mime, AudioDecoder* decoder) {
124139 this ->mime = mime;
125140 this ->decoder = decoder;
126141 }
127142 } actual_decoder;
128143 Vector<DecoderInfo> decoders{0 };
129144 MimeDetector mime_detector;
130145 CodecNOP nop;
146+ AbstractURLStream* p_url_stream = nullptr ;
131147 bool is_first = true ;
132148};
133149
0 commit comments