3 #include "AudioBasic/Debouncer.h"
4 #include "AudioBasic/Str.h"
5 #include "AudioConfig.h"
6 #include "AudioHttp/AudioHttp.h"
7 #include "AudioTools/AudioLogger.h"
8 #include "AudioTools/AudioSource.h"
9 #include "AudioTools/AudioStreams.h"
10 #include "AudioTools/AudioTypes.h"
11 #include "AudioTools/BaseConverter.h"
12 #include "AudioTools/Buffers.h"
13 #include "AudioTools/Fade.h"
14 #include "AudioTools/StreamCopy.h"
18 #include "AudioLibs/AudioSourceSDFAT.h"
58 this->p_source = &source;
59 this->p_decoder = &decoder;
78 this->p_source = &source;
79 this->p_decoder = &decoder;
95 this->p_source = &source;
96 this->p_decoder = &decoder;
111 out_decoding.setDecoder(p_decoder);
114 out_decoding.setDecoder(p_decoder);
116 this->p_final_print = &output;
117 this->p_final_stream =
nullptr;
120 void setOutput(Print &output) {
125 out_decoding.setDecoder(p_decoder);
128 out_decoding.setDecoder(p_decoder);
130 this->p_final_print =
nullptr;
131 this->p_final_stream =
nullptr;
134 void setOutput(AudioStream &output) {
139 out_decoding.setDecoder(p_decoder);
142 out_decoding.setDecoder(p_decoder);
144 this->p_final_print =
nullptr;
145 this->p_final_stream = &output;
156 if (current_volume == -1.0f) {
169 out_decoding.
begin();
175 if (p_input_stream !=
nullptr) {
179 copier.
begin(out_decoding, *p_input_stream);
184 LOGW(
"-> begin: no data found");
189 LOGW(
"-> begin: no stream selected");
202 if (p_decoder !=
nullptr) {
214 this->p_decoder = &decoder;
215 out_decoding.setDecoder(p_decoder);
220 this->p_final_notify = notify;
222 if (p_decoder !=
nullptr) {
232 LOGI(
"channels: %d", (
int) info.
channels);
238 if (p_final_print !=
nullptr)
240 if (p_final_stream !=
nullptr)
242 if (p_final_notify !=
nullptr)
262 virtual bool next(
int offset = 1) {
265 stream_increment = offset >= 0 ? 1 : -1;
274 stream_increment = 1;
283 stream_increment = 1;
292 stream_increment = -1;
300 out_decoding.
begin();
301 p_input_stream = input;
302 if (p_input_stream !=
nullptr) {
303 LOGD(
"open selected stream");
305 copier.
begin(out_decoding, *p_input_stream);
307 return p_input_stream !=
nullptr;
323 fade.setFadeInActive(
true);
325 fade.setFadeOutActive(
true);
337 if (abs(
volume - current_volume) > 0.01f) {
338 LOGI(
"setVolume(%f)",
volume);
343 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
350 float volume()
override {
return current_volume; }
365 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
366 p_final_print->availableForWrite() == 0) ||
367 (p_final_stream !=
nullptr &&
368 p_final_stream->availableForWrite() == 0))) {
370 delay(delay_if_full);
374 result = copier.
copy();
375 if (result > 0 || timeout == 0) {
380 moveToNextFileOnTimeout();
383 if (result == 0 && silence_on_inactive){
388 if (silence_on_inactive) {
397 const char *str,
int len),
401 if (p_source->setMetadataCallback(callback)) {
403 LOGI(
"Using ICY Metadata");
407 meta_out.setCallback(callback);
408 meta_out.setFilter(sel);
432 if (p_final_print !=
nullptr) {
434 }
else if (p_final_stream !=
nullptr) {
446 bool isAutoFade() {
return is_auto_fade; }
450 bool autonext =
true;
451 bool silence_on_inactive =
false;
452 AudioSource *p_source =
nullptr;
453 VolumeStream volume_out;
455 MetaDataID3 meta_out;
456 EncodedAudioOutput out_decoding;
457 CopyDecoder no_decoder{
true};
458 AudioDecoder *p_decoder = &no_decoder;
459 Stream *p_input_stream =
nullptr;
460 AudioOutput *p_final_print =
nullptr;
461 AudioStream *p_final_stream =
nullptr;
462 AudioInfoSupport *p_final_notify =
nullptr;
465 bool meta_active =
false;
466 uint32_t timeout = 0;
467 int stream_increment = 1;
468 float current_volume = -1.0f;
469 int delay_if_full = 100;
470 bool is_auto_fade =
true;
473 if (p_final_print !=
nullptr) {
474 fade.setAudioInfo(p_final_print->audioInfo());
475 }
else if (p_final_stream !=
nullptr) {
476 fade.setAudioInfo(p_final_stream->audioInfo());
480 virtual void moveToNextFileOnTimeout() {
483 if (p_final_stream ==
nullptr)
485 if (p_final_stream->availableForWrite() == 0)
487 if (p_input_stream ==
nullptr ||
millis() > timeout) {
489 fade.setFadeInActive(
true);
491 LOGI(
"-> timeout - moving by %d", stream_increment);
493 if (!
next(stream_increment)) {
494 LOGD(
"stream is null");
499 timeout =
millis() + p_source->timeoutAutoNext();
507 fade.setFadeOutActive(
true);
510 fade.setFadeInActive(
true);
519 LOGD(
"%s, %zu", LOG_METHOD, len);
521 if (p->meta_active) {
522 p->meta_out.
write((
const uint8_t *)data, len);