3#include "AudioToolsConfig.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/AudioStreams.h"
8#include "AudioTools/CoreAudio/AudioTypes.h"
9#include "AudioTools/CoreAudio/BaseConverter.h"
10#include "AudioTools/CoreAudio/Buffers.h"
11#include "AudioTools/CoreAudio/Fade.h"
12#include "AudioTools/CoreAudio/StreamCopy.h"
13#include "AudioTools/CoreAudio/AudioMetaData/MetaData.h"
14#include "AudioTools/CoreAudio/VolumeStream.h"
15#include "AudioTools/Disk/AudioSource.h"
16#include "AudioTools/AudioCodecs/AudioCodecs.h"
55 this->p_source = &source;
56 this->p_decoder = &decoder;
75 this->p_source = &source;
76 this->p_decoder = &decoder;
92 this->p_source = &source;
93 this->p_decoder = &decoder;
108 out_decoding.setDecoder(p_decoder);
111 out_decoding.setDecoder(p_decoder);
113 this->p_final_print = &output;
114 this->p_final_stream =
nullptr;
117 void setOutput(Print &output) {
122 out_decoding.setDecoder(p_decoder);
125 out_decoding.setDecoder(p_decoder);
127 this->p_final_print =
nullptr;
128 this->p_final_stream =
nullptr;
131 void setOutput(AudioStream &output) {
136 out_decoding.setDecoder(p_decoder);
139 out_decoding.setDecoder(p_decoder);
141 this->p_final_print =
nullptr;
142 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)
241 if (p_final_stream !=
nullptr)
243 if (p_final_notify !=
nullptr)
261 LOGW(
"Could not open file: %s", filePath);
265 LOGI(
"Playing %s", filePath);
269 size_t bytes_copied =
copy();
271 if (bytes_copied == 0) {
277 LOGI(
"%s has finished playing", filePath);
292 stream_increment = offset >= 0 ? 1 : -1;
301 stream_increment = 1;
310 stream_increment = 1;
319 stream_increment = -1;
327 out_decoding.
begin();
328 p_input_stream = input;
329 if (p_input_stream !=
nullptr) {
330 LOGD(
"open selected stream");
332 copier.
begin(out_decoding, *p_input_stream);
334 return p_input_stream !=
nullptr;
350 fade.setFadeInActive(
true);
352 fade.setFadeOutActive(
true);
364 if (abs(
volume - current_volume) > 0.01f) {
365 LOGI(
"setVolume(%f)",
volume);
370 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
377 float volume()
override {
return current_volume; }
395 size_t step =
copy();
408 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
409 p_final_print->availableForWrite() == 0) ||
410 (p_final_stream !=
nullptr &&
411 p_final_stream->availableForWrite() == 0))) {
413 delay(delay_if_full);
418 if (result > 0 || timeout == 0) {
423 moveToNextFileOnTimeout();
426 if (result < bytes && silence_on_inactive){
432 if (silence_on_inactive) {
441 const char *str,
int len),
445 if (p_source->setMetadataCallback(callback)) {
447 LOGI(
"Using ICY Metadata");
451 meta_out.setCallback(callback);
452 meta_out.setFilter(sel);
476 if (p_final_print !=
nullptr) {
478 }
else if (p_final_stream !=
nullptr) {
493 bool isAutoFade() {
return is_auto_fade; }
503 bool autonext =
true;
504 bool silence_on_inactive =
false;
511 AudioDecoder *p_decoder = &no_decoder;
512 Stream *p_input_stream =
nullptr;
513 AudioOutput *p_final_print =
nullptr;
514 AudioStream *p_final_stream =
nullptr;
515 AudioInfoSupport *p_final_notify =
nullptr;
518 bool meta_active =
false;
519 uint32_t timeout = 0;
520 int stream_increment = 1;
521 float current_volume = -1.0f;
522 int delay_if_full = 100;
523 bool is_auto_fade =
true;
526 if (p_final_print !=
nullptr) {
528 }
else if (p_final_stream !=
nullptr) {
533 void moveToNextFileOnTimeout() {
536 if (p_final_stream !=
nullptr && p_final_stream->availableForWrite() == 0)
538 if (p_input_stream ==
nullptr ||
millis() > timeout) {
540 fade.setFadeInActive(
true);
542 LOGI(
"-> timeout - moving by %d", stream_increment);
544 if (!
next(stream_increment)) {
545 LOGD(
"stream is null");
558 fade.setFadeOutActive(
true);
561 fade.setFadeInActive(
true);
570 LOGD(
"%s, %zu", LOG_METHOD, len);
572 if (p->meta_active) {
573 p->meta_out.
write((
const uint8_t *)data, len);