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();
168 if (!p_source->
begin()){
169 LOGE(
"Could not start audio source");
172 if (!meta_out.begin()){
173 LOGE(
"Could not start metadata output");
176 if (!volume_out.begin()){
177 LOGE(
"Could not start volume control");
183 if (p_input_stream !=
nullptr) {
187 copier.
begin(out_decoding, *p_input_stream);
192 LOGW(
"-> begin: no data found");
197 LOGW(
"-> begin: no stream selected");
210 if (p_decoder !=
nullptr) {
225 this->p_decoder = &decoder;
226 out_decoding.setDecoder(p_decoder);
231 this->p_final_notify = notify;
233 if (p_decoder !=
nullptr) {
243 LOGI(
"channels: %d", (
int)info.
channels);
249 if (p_final_print !=
nullptr) p_final_print->
setAudioInfo(info);
250 if (p_final_stream !=
nullptr) p_final_stream->
setAudioInfo(info);
251 if (p_final_notify !=
nullptr) p_final_notify->
setAudioInfo(info);
268 LOGW(
"Could not open file: %s", path);
272 LOGI(
"Playing %s", path);
278 LOGI(
"%s has finished playing", path);
297 stream_increment = offset >= 0 ? 1 : -1;
306 stream_increment = 1;
315 stream_increment = 1;
324 stream_increment = -1;
332 out_decoding.
begin();
333 p_input_stream = input;
334 if (p_input_stream !=
nullptr) {
335 LOGD(
"open selected stream");
337 copier.
begin(out_decoding, *p_input_stream);
340 if (on_stream_change_callback !=
nullptr)
341 on_stream_change_callback(p_input_stream, p_reference);
342 return p_input_stream !=
nullptr;
358 fade.setFadeInActive(
true);
360 fade.setFadeOutActive(
true);
372 if (abs(
volume - current_volume) > 0.01f) {
373 LOGI(
"setVolume(%f)",
volume);
378 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
385 float volume()
override {
return current_volume; }
402 size_t step =
copy();
416 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
417 p_final_print->availableForWrite() == 0) ||
418 (p_final_stream !=
nullptr &&
419 p_final_stream->availableForWrite() == 0))) {
421 delay(delay_if_full);
426 if (result > 0 || timeout == 0) {
431 moveToNextFileOnTimeout();
434 if (result < bytes && silence_on_inactive) {
440 if (silence_on_inactive) {
464 if (p_final_print !=
nullptr) {
466 }
else if (p_final_stream !=
nullptr) {
481 bool isAutoFade() {
return is_auto_fade; }
495 if (p_source->setMetadataCallback(callback)) {
497 LOGI(
"Using ICY Metadata");
501 meta_out.setCallback(callback);
502 meta_out.setFilter(sel);
510 on_stream_change_callback = callback;
511 if (p_input_stream!=
nullptr) callback(p_input_stream, p_reference);
516 bool autonext =
true;
517 bool silence_on_inactive =
false;
524 AudioDecoder *p_decoder = &no_decoder;
525 Stream *p_input_stream =
nullptr;
526 AudioOutput *p_final_print =
nullptr;
527 AudioStream *p_final_stream =
nullptr;
528 AudioInfoSupport *p_final_notify =
nullptr;
531 bool meta_active =
false;
532 uint32_t timeout = 0;
533 int stream_increment = 1;
534 float current_volume = -1.0f;
535 int delay_if_full = 100;
536 bool is_auto_fade =
true;
537 void *p_reference =
nullptr;
538 void (*on_stream_change_callback)(Stream *stream_ptr,
539 void *reference) =
nullptr;
542 if (p_final_print !=
nullptr) {
544 }
else if (p_final_stream !=
nullptr) {
549 void moveToNextFileOnTimeout() {
550 if (p_final_stream !=
nullptr && p_final_stream->availableForWrite() == 0)
552 if (p_input_stream ==
nullptr ||
millis() > timeout) {
553 if (is_auto_fade) fade.setFadeInActive(
true);
555 LOGI(
"-> timeout - moving by %d", stream_increment);
557 if (!
next(stream_increment)) {
558 LOGD(
"stream is null");
571 fade.setFadeOutActive(
true);
574 fade.setFadeInActive(
true);
583 LOGD(
"%s, %zu", LOG_METHOD, len);
585 if (p->meta_active) {
586 p->meta_out.
write((
const uint8_t *)data, len);