3#include "AudioTools/AudioCodecs/AudioCodecs.h"
4#include "AudioTools/CoreAudio/AudioBasic/Debouncer.h"
5#include "AudioTools/CoreAudio/AudioLogger.h"
6#include "AudioTools/CoreAudio/AudioMetaData/MetaData.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/VolumeStream.h"
14#include "AudioTools/Disk/AudioSource.h"
15#include "AudioToolsConfig.h"
67 this->p_source = &source;
68 this->p_decoder = &decoder;
87 this->p_source = &source;
88 this->p_decoder = &decoder;
104 this->p_source = &source;
105 this->p_decoder = &decoder;
123 out_decoding.setDecoder(p_decoder);
126 out_decoding.setDecoder(p_decoder);
128 this->p_final_print = &output;
129 this->p_final_stream =
nullptr;
138 out_decoding.setDecoder(p_decoder);
141 out_decoding.setDecoder(p_decoder);
143 this->p_final_print =
nullptr;
144 this->p_final_stream =
nullptr;
153 out_decoding.setDecoder(p_decoder);
156 out_decoding.setDecoder(p_decoder);
158 this->p_final_print =
nullptr;
159 this->p_final_stream = &output;
170 if (current_volume == -1.0f) {
183 out_decoding.
begin();
185 if (!p_source->
begin()) {
186 LOGE(
"Could not start audio source");
189 if (!meta_out.begin()) {
190 LOGE(
"Could not start metadata output");
193 if (!volume_out.begin()) {
194 LOGE(
"Could not start volume control");
200 if (p_input_stream !=
nullptr) {
204 copier.
begin(out_decoding, *p_input_stream);
209 LOGW(
"-> begin: no data found");
214 LOGW(
"-> begin: no stream selected");
229 if (p_decoder !=
nullptr) {
244 this->p_decoder = &decoder;
245 out_decoding.setDecoder(p_decoder);
250 this->p_final_notify = notify;
252 if (p_decoder !=
nullptr) {
262 LOGI(
"channels: %d", (
int)info.
channels);
268 if (p_final_print !=
nullptr) p_final_print->
setAudioInfo(info);
269 if (p_final_stream !=
nullptr) p_final_stream->
setAudioInfo(info);
270 if (p_final_notify !=
nullptr) p_final_notify->
setAudioInfo(info);
289 LOGW(
"Could not open file: %s", path);
293 LOGI(
"Playing %s", path);
299 LOGI(
"%s has finished playing", path);
316 stream_increment = offset >= 0 ? 1 : -1;
325 stream_increment = 1;
334 stream_increment = 1;
343 stream_increment = -1;
351 out_decoding.
begin();
352 p_input_stream = input;
354 if (p_input_stream !=
nullptr) {
355 LOGD(
"open selected stream");
357 copier.
begin(out_decoding, *p_input_stream);
360 if (on_stream_change_callback !=
nullptr)
361 on_stream_change_callback(p_input_stream, p_reference);
362 return p_input_stream !=
nullptr;
378 fade.setFadeInActive(
true);
380 fade.setFadeOutActive(
true);
392 if (abs(
volume - current_volume) > 0.01f) {
393 LOGI(
"setVolume(%f)",
volume);
398 LOGE(
"setVolume value '%f' out of range (0.0 -1.0)",
volume);
405 float volume()
override {
return current_volume; }
420 size_t step =
copy();
432 if (delay_if_full != 0 && ((p_final_print !=
nullptr &&
433 p_final_print->availableForWrite() == 0) ||
434 (p_final_stream !=
nullptr &&
435 p_final_stream->availableForWrite() == 0))) {
437 delay(delay_if_full);
438 LOGD(
"copy: %d -> 0", (
int)bytes);
444 if (result > 0 || timeout == 0) {
450 moveToNextFileOnTimeout();
453 if (result < bytes && silence_on_inactive) {
459 if (silence_on_inactive) {
463 LOGD(
"copy: %d -> %d", (
int)bytes, (
int)result);
483 if (p_final_print !=
nullptr) {
485 }
else if (p_final_stream !=
nullptr) {
511 if (p_source->setMetadataCallback(callback)) {
513 LOGI(
"Using ICY Metadata");
517 meta_out.setCallback(callback);
518 meta_out.setFilter(sel);
526 on_stream_change_callback = callback;
527 if (p_input_stream !=
nullptr) callback(p_input_stream, p_reference);
534 on_eof_callback = callback;
540 if (current_volume > 0.0f) {
541 muted_volume = current_volume;
545 if (muted_volume > 0.0f) {
554 bool isMuted() {
return current_volume == 0.0f; }
558 bool autonext =
true;
559 bool silence_on_inactive =
false;
566 AudioDecoder* p_decoder = &no_decoder;
567 Stream* p_input_stream =
nullptr;
568 AudioOutput* p_final_print =
nullptr;
569 AudioStream* p_final_stream =
nullptr;
570 AudioInfoSupport* p_final_notify =
nullptr;
573 bool meta_active =
false;
574 uint32_t timeout = 0;
575 int stream_increment = 1;
576 float current_volume = -1.0f;
577 float muted_volume = 0.0f;
578 int delay_if_full = 100;
579 bool is_auto_fade =
true;
580 void* p_reference =
nullptr;
581 void (*on_stream_change_callback)(Stream* stream_ptr,
582 void* reference) =
nullptr;
584 void (*on_eof_callback)(
AudioPlayer& player) =
nullptr;
585 bool eof_called =
false;
588 if (p_final_print !=
nullptr) {
590 }
else if (p_final_stream !=
nullptr) {
595 void moveToNextFileOnTimeout() {
596 if (p_final_stream !=
nullptr && p_final_stream->availableForWrite() == 0)
598 if (p_input_stream ==
nullptr ||
millis() > timeout) {
599 if (is_auto_fade) fade.setFadeInActive(
true);
604 if (on_eof_callback !=
nullptr) {
605 on_eof_callback(*
this);
610 LOGI(
"-> timeout - moving by %d", stream_increment);
612 if (!
next(stream_increment)) {
613 LOGD(
"stream is null");
626 fade.setFadeOutActive(
true);
629 fade.setFadeInActive(
true);
639 LOGD(
"%s, %zu", LOG_METHOD, len);
641 if (p->meta_active) {
642 p->meta_out.
write((
const uint8_t*)data, len);