@@ -19,6 +19,9 @@ namespace audio_tools {
19
19
*/
20
20
class MultiDecoder : public AudioDecoder {
21
21
public:
22
+ MultiDecoder () = default ;
23
+ MultiDecoder (AbstractURLStream& url) { setMimeSource (url); }
24
+
22
25
// / Enables the automatic mime type determination
23
26
bool begin () override {
24
27
mime_detector.begin ();
@@ -43,21 +46,25 @@ class MultiDecoder : public AudioDecoder {
43
46
decoder.addNotifyAudioChange (*this );
44
47
decoders.push_back (info);
45
48
}
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)) {
49
54
addDecoder (decoder, mime);
50
55
mime_detector.setCheck (mime, check);
51
56
}
52
57
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;
56
60
for (int j = 0 ; j < decoders.size (); j++) {
57
61
decoders[j].decoder ->setOutput (out_stream);
58
62
}
59
63
}
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
+
61
68
// / selects the actual decoder by mime type - this is usually called
62
69
// / automatically from the determined mime type
63
70
bool selectDecoder (const char * mime) {
@@ -77,8 +84,8 @@ class MultiDecoder : public AudioDecoder {
77
84
LOGI (" New decoder found for %s (%s)" , info.mime , mime);
78
85
actual_decoder = info;
79
86
// 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 ) {
82
89
actual_decoder.decoder ->setOutput (*p_print);
83
90
}
84
91
actual_decoder.decoder ->begin ();
@@ -91,10 +98,18 @@ class MultiDecoder : public AudioDecoder {
91
98
92
99
size_t write (const uint8_t * data, size_t len) override {
93
100
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
+ }
97
111
if (mime != nullptr ) {
112
+ // select the decoder based on the detemined mime type
98
113
if (!selectDecoder (mime)) {
99
114
LOGE (" The decoder could not be found for %s" , mime);
100
115
actual_decoder.decoder = &nop;
@@ -109,9 +124,9 @@ class MultiDecoder : public AudioDecoder {
109
124
return actual_decoder.decoder ->write (data, len);
110
125
}
111
126
112
- virtual operator bool () {
127
+ virtual operator bool () {
113
128
if (actual_decoder.decoder == &nop) return false ;
114
- return is_first || actual_decoder.is_open ;
129
+ return is_first || actual_decoder.is_open ;
115
130
};
116
131
117
132
protected:
@@ -120,14 +135,15 @@ class MultiDecoder : public AudioDecoder {
120
135
AudioDecoder* decoder = nullptr ;
121
136
bool is_open = false ;
122
137
DecoderInfo () = default ;
123
- DecoderInfo (const char * mime, AudioDecoder* decoder){
138
+ DecoderInfo (const char * mime, AudioDecoder* decoder) {
124
139
this ->mime = mime;
125
140
this ->decoder = decoder;
126
141
}
127
142
} actual_decoder;
128
143
Vector<DecoderInfo> decoders{0 };
129
144
MimeDetector mime_detector;
130
145
CodecNOP nop;
146
+ AbstractURLStream* p_url_stream = nullptr ;
131
147
bool is_first = true ;
132
148
};
133
149
0 commit comments