7#include <freertos/FreeRTOS.h>
8#include <freertos/task.h>
14static const char *
const TAG =
"audio_file_media_source";
16static constexpr uint32_t AUDIO_WRITE_TIMEOUT_MS = 50;
17static constexpr size_t DECODER_TASK_STACK_SIZE = 5120;
18static constexpr uint8_t DECODER_TASK_PRIORITY = 2;
19static constexpr uint32_t PAUSE_POLL_DELAY_MS = 20;
20static constexpr char URI_PREFIX[] =
"audio-file://";
30#ifdef USE_AUDIO_FLAC_SUPPORT
32 return micro_decoder::AudioFileType::FLAC;
34#ifdef USE_AUDIO_MP3_SUPPORT
36 return micro_decoder::AudioFileType::MP3;
38#ifdef USE_AUDIO_OPUS_SUPPORT
40 return micro_decoder::AudioFileType::OPUS;
42#ifdef USE_AUDIO_WAV_SUPPORT
44 return micro_decoder::AudioFileType::WAV;
47 return micro_decoder::AudioFileType::NONE;
55 "Audio File Media Source:\n"
56 " Decoder Task Stack in PSRAM: %s",
63 micro_decoder::DecoderConfig config;
64 config.audio_write_timeout_ms = AUDIO_WRITE_TIMEOUT_MS;
65 config.decoder_priority = DECODER_TASK_PRIORITY;
66 config.decoder_stack_size = DECODER_TASK_STACK_SIZE;
69 this->
decoder_ = std::make_unique<micro_decoder::DecoderSource>(config);
71 ESP_LOGE(TAG,
"Failed to allocate decoder");
89 ESP_LOGE(TAG,
"Cannot play '%s': source is busy", uri.c_str());
93 if (!uri.starts_with(URI_PREFIX)) {
94 ESP_LOGE(TAG,
"Invalid URI: '%s'", uri.c_str());
98 const char *file_id = uri.c_str() +
sizeof(URI_PREFIX) - 1;
101 if (strcmp(named_file.file_id, file_id) == 0) {
108 ESP_LOGE(TAG,
"Unknown file: '%s'", file_id);
113 if (this->
decoder_->play_buffer(this->current_file_->data, this->current_file_->length,
type)) {
114 this->
pause_.store(
false, std::memory_order_relaxed);
119 ESP_LOGE(TAG,
"Failed to start playback of '%s'", file_id);
139 this->
pause_.store(
true, std::memory_order_relaxed);
145 this->
pause_.store(
false, std::memory_order_relaxed);
155 if (this->
pause_.load(std::memory_order_relaxed)) {
156 vTaskDelay(pdMS_TO_TICKS(PAUSE_POLL_DELAY_MS));
171 case micro_decoder::DecoderState::IDLE:
175 case micro_decoder::DecoderState::PLAYING:
178 case micro_decoder::DecoderState::FAILED:
void mark_failed()
Mark this component as failed.
void enable_loop()
Enable this component's loop.
bool status_has_error() const
void disable_loop()
Disable this component's loop.
const StaticVector< NamedAudioFile, AUDIO_FILE_MAX_FILES > & get_named_audio_files()