3 #include "AudioConfig.h"
4 #include "AudioTools/CoreAudio/AudioBasic/Debouncer.h"
5 #include "AudioTools/CoreAudio/AudioHttp/AudioHttp.h"
6 #include "AudioTools/CoreAudio/AudioLogger.h"
7 #include "AudioTools/CoreAudio/AudioSource.h"
8 #include "AudioTools/CoreAudio/AudioStreams.h"
9 #include "AudioTools/CoreAudio/AudioTypes.h"
10 #include "AudioTools/CoreAudio/BaseConverter.h"
11 #include "AudioTools/CoreAudio/Buffers.h"
12 #include "AudioTools/CoreAudio/Fade.h"
13 #include "AudioTools/CoreAudio/StreamCopy.h"
52 this->p_source = &source;
53 this->p_decoder = &decoder;
72 this->p_source = &source;
73 this->p_decoder = &decoder;
89 this->p_source = &source;
90 this->p_decoder = &decoder;
105 out_decoding.setDecoder(p_decoder);
108 out_decoding.setDecoder(p_decoder);
110 this->p_final_print = &output;
111 this->p_final_stream =
nullptr;
114 void setOutput(Print &output) {
119 out_decoding.setDecoder(p_decoder);
122 out_decoding.setDecoder(p_decoder);
124 this->p_final_print =
nullptr;
125 this->p_final_stream =
nullptr;
128 void setOutput(AudioStream &output) {
133 out_decoding.setDecoder(p_decoder);
136 out_decoding.setDecoder(p_decoder);
138 this->p_final_print =
nullptr;
139 this->p_final_stream = &output;
150 if (current_volume == -1.0f) {
163 out_decoding.
begin();
170 if (p_input_stream !=
nullptr) {
174 copier.
begin(out_decoding, *p_input_stream);
179 LOGW(
"-> begin: no data found");
184 LOGW(
"-> begin: no stream selected");
197 if (p_decoder !=
nullptr) {
209 this->p_decoder = &decoder;
210 out_decoding.setDecoder(p_decoder);
215 this->p_final_notify = notify;
217 if (p_decoder !=
nullptr) {
227 LOGI(
"channels: %d", (
int) info.
channels);
233 if (p_final_print !=
nullptr)
235 if (p_final_stream !=
nullptr)
237 if (p_final_notify !=
nullptr)
257 virtual bool next(
int offset = 1) {
260 stream_increment = offset >= 0 ? 1 : -1;
269 stream_increment = 1;
278 stream_increment = 1;
287 stream_increment = -1;
295 out_decoding.
begin();
296 p_input_stream = input;
297 if (p_input_stream !=
nullptr) {
298 LOGD(
"open selected stream");
300 copier.
begin(out_decoding, *p_input_stream);
302 return p_input_stream !=
nullptr;
318 fade.setFadeInActive(
true);
320 fade.setFadeOutActive(
true);
332 if (abs(
volume - current_volume) > 0.01f) {
333 LOGI(
"setVolume(%f)",
volume);
338 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
345 float volume()
override {
return current_volume; }
355 virtual size_t copy() {
360 virtual size_t copy(
size_t bytes) {
364 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
365 p_final_print->availableForWrite() == 0) ||
366 (p_final_stream !=
nullptr &&
367 p_final_stream->availableForWrite() == 0))) {
369 delay(delay_if_full);
374 if (result > 0 || timeout == 0) {
379 moveToNextFileOnTimeout();
382 if (result < bytes && 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) {
449 bool isAutoFade() {
return is_auto_fade; }
453 bool autonext =
true;
454 bool silence_on_inactive =
false;
455 AudioSource *p_source =
nullptr;
456 VolumeStream volume_out;
458 MetaDataID3 meta_out;
459 EncodedAudioOutput out_decoding;
460 CopyDecoder no_decoder{
true};
461 AudioDecoder *p_decoder = &no_decoder;
462 Stream *p_input_stream =
nullptr;
463 AudioOutput *p_final_print =
nullptr;
464 AudioStream *p_final_stream =
nullptr;
465 AudioInfoSupport *p_final_notify =
nullptr;
468 bool meta_active =
false;
469 uint32_t timeout = 0;
470 int stream_increment = 1;
471 float current_volume = -1.0f;
472 int delay_if_full = 100;
473 bool is_auto_fade =
true;
476 if (p_final_print !=
nullptr) {
477 fade.setAudioInfo(p_final_print->audioInfo());
478 }
else if (p_final_stream !=
nullptr) {
479 fade.setAudioInfo(p_final_stream->audioInfo());
483 virtual void moveToNextFileOnTimeout() {
486 if (p_final_stream !=
nullptr && p_final_stream->availableForWrite() == 0)
488 if (p_input_stream ==
nullptr ||
millis() > timeout) {
490 fade.setFadeInActive(
true);
492 LOGI(
"-> timeout - moving by %d", stream_increment);
494 if (!
next(stream_increment)) {
495 LOGD(
"stream is null");
500 timeout =
millis() + p_source->timeoutAutoNext();
508 fade.setFadeOutActive(
true);
511 fade.setFadeInActive(
true);
520 LOGD(
"%s, %zu", LOG_METHOD, len);
522 if (p->meta_active) {
523 p->meta_out.
write((
const uint8_t *)data, len);