3#include "AudioTools/AudioCodecs/AudioCodecs.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/AudioMetaData/MetaData.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"
14#include "AudioTools/CoreAudio/VolumeStream.h"
15#include "AudioTools/Disk/AudioSource.h"
16#include "AudioToolsConfig.h"
54 this->p_source = &source;
55 this->p_decoder = &decoder;
74 this->p_source = &source;
75 this->p_decoder = &decoder;
91 this->p_source = &source;
92 this->p_decoder = &decoder;
107 out_decoding.setDecoder(p_decoder);
110 out_decoding.setDecoder(p_decoder);
112 this->p_final_print = &output;
113 this->p_final_stream =
nullptr;
116 void setOutput(Print &output) {
121 out_decoding.setDecoder(p_decoder);
124 out_decoding.setDecoder(p_decoder);
126 this->p_final_print =
nullptr;
127 this->p_final_stream =
nullptr;
130 void setOutput(AudioStream &output) {
135 out_decoding.setDecoder(p_decoder);
138 out_decoding.setDecoder(p_decoder);
140 this->p_final_print =
nullptr;
141 this->p_final_stream = &output;
153 if (current_volume == -1.0f) {
166 out_decoding.
begin();
173 if (p_input_stream !=
nullptr) {
177 copier.
begin(out_decoding, *p_input_stream);
182 LOGW(
"-> begin: no data found");
187 LOGW(
"-> begin: no stream selected");
200 if (p_decoder !=
nullptr) {
215 this->p_decoder = &decoder;
216 out_decoding.setDecoder(p_decoder);
221 this->p_final_notify = notify;
223 if (p_decoder !=
nullptr) {
233 LOGI(
"channels: %d", (
int)info.
channels);
239 if (p_final_print !=
nullptr) p_final_print->
setAudioInfo(info);
240 if (p_final_stream !=
nullptr) p_final_stream->
setAudioInfo(info);
241 if (p_final_notify !=
nullptr) p_final_notify->
setAudioInfo(info);
258 LOGW(
"Could not open file: %s", path);
262 LOGI(
"Playing %s", path);
268 LOGI(
"%s has finished playing", path);
287 stream_increment = offset >= 0 ? 1 : -1;
296 stream_increment = 1;
305 stream_increment = 1;
314 stream_increment = -1;
322 out_decoding.
begin();
323 p_input_stream = input;
324 if (p_input_stream !=
nullptr) {
325 LOGD(
"open selected stream");
327 copier.
begin(out_decoding, *p_input_stream);
330 if (on_stream_change_callback !=
nullptr)
331 on_stream_change_callback(p_input_stream, p_reference);
332 return p_input_stream !=
nullptr;
348 fade.setFadeInActive(
true);
350 fade.setFadeOutActive(
true);
362 if (abs(
volume - current_volume) > 0.01f) {
363 LOGI(
"setVolume(%f)",
volume);
368 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
375 float volume()
override {
return current_volume; }
392 size_t step =
copy();
406 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
407 p_final_print->availableForWrite() == 0) ||
408 (p_final_stream !=
nullptr &&
409 p_final_stream->availableForWrite() == 0))) {
411 delay(delay_if_full);
416 if (result > 0 || timeout == 0) {
421 moveToNextFileOnTimeout();
424 if (result < bytes && silence_on_inactive) {
430 if (silence_on_inactive) {
454 if (p_final_print !=
nullptr) {
456 }
else if (p_final_stream !=
nullptr) {
471 bool isAutoFade() {
return is_auto_fade; }
485 if (p_source->setMetadataCallback(callback)) {
487 LOGI(
"Using ICY Metadata");
491 meta_out.setCallback(callback);
492 meta_out.setFilter(sel);
500 on_stream_change_callback = callback;
501 if (p_input_stream!=
nullptr) callback(p_input_stream, p_reference);
506 bool autonext =
true;
507 bool silence_on_inactive =
false;
514 AudioDecoder *p_decoder = &no_decoder;
515 Stream *p_input_stream =
nullptr;
516 AudioOutput *p_final_print =
nullptr;
517 AudioStream *p_final_stream =
nullptr;
518 AudioInfoSupport *p_final_notify =
nullptr;
521 bool meta_active =
false;
522 uint32_t timeout = 0;
523 int stream_increment = 1;
524 float current_volume = -1.0f;
525 int delay_if_full = 100;
526 bool is_auto_fade =
true;
527 void *p_reference =
nullptr;
528 void (*on_stream_change_callback)(Stream *stream_ptr,
529 void *reference) =
nullptr;
532 if (p_final_print !=
nullptr) {
534 }
else if (p_final_stream !=
nullptr) {
539 void moveToNextFileOnTimeout() {
540 if (p_final_stream !=
nullptr && p_final_stream->availableForWrite() == 0)
542 if (p_input_stream ==
nullptr ||
millis() > timeout) {
543 if (is_auto_fade) fade.setFadeInActive(
true);
545 LOGI(
"-> timeout - moving by %d", stream_increment);
547 if (!
next(stream_increment)) {
548 LOGD(
"stream is null");
561 fade.setFadeOutActive(
true);
564 fade.setFadeInActive(
true);
573 LOGD(
"%s, %zu", LOG_METHOD, len);
575 if (p->meta_active) {
576 p->meta_out.
write((
const uint8_t *)data, len);