13struct AudioSinkAdapter :
public audio::AudioSinkCallback {
17 size_t audio_sink_write(uint8_t *data,
size_t length, TickType_t ticks_to_wait)
override {
18 return this->source->write_output(data,
length, pdTICKS_TO_MS(ticks_to_wait), this->stream_info);
23#if defined(USE_AUDIO_OPUS_SUPPORT)
24static constexpr uint32_t DECODE_TASK_STACK_SIZE = 5 * 1024;
26static constexpr uint32_t DECODE_TASK_STACK_SIZE = 3 * 1024;
29static const char *
const TAG =
"audio_file_media_source";
49 ESP_LOGCONFIG(TAG,
"Audio File Media Source:");
58 ESP_LOGE(TAG,
"Failed to create event group");
65 EventBits_t event_bits = xEventGroupGetBits(this->
event_group_);
77 this->task_stack_in_psram_)) {
78 ESP_LOGE(TAG,
"Failed to create task");
90 ESP_LOGD(TAG,
"Starting");
95 ESP_LOGV(TAG,
"Started");
107 ESP_LOGV(TAG,
"Stopping");
108 xEventGroupClearBits(this->
event_group_, TASK_STOPPING);
117 ESP_LOGD(TAG,
"Stopped");
149 ESP_LOGE(TAG,
"Cannot play '%s': source is busy", uri.c_str());
154 if (!uri.starts_with(
"audio-file://")) {
155 ESP_LOGE(TAG,
"Invalid URI: '%s'", uri.c_str());
160 const char *file_id = uri.c_str() + 13;
163 if (strcmp(named_file.file_id, file_id) == 0) {
171 ESP_LOGE(TAG,
"Unknown file: '%s'", file_id);
204 std::unique_ptr<audio::AudioDecoder> decoder = make_unique<audio::AudioDecoder>(0, 4096);
208 ESP_LOGE(TAG,
"Failed to start decoder: %s", esp_err_to_name(err));
218 AudioSinkAdapter audio_sink;
219 bool has_stream_info =
false;
222 EventBits_t event_bits = xEventGroupGetBits(this_source->
event_group_);
229 decoder->set_pause_output_state(paused);
232 vTaskDelay(pdMS_TO_TICKS(20));
243 ESP_LOGE(TAG,
"Decoder failed");
248 if (!has_stream_info && decoder->get_audio_stream_info().has_value()) {
249 has_stream_info =
true;
253 ESP_LOGD(TAG,
"Bits per sample: %d, Channels: %d, Sample rate: %" PRIu32,
stream_info.get_bits_per_sample(),
257 ESP_LOGE(TAG,
"Incompatible audio stream. Only 16 bits per sample and 1 or 2 channels are supported");
262 audio_sink.source = this_source;
264 esp_err_t err = decoder->add_sink(&audio_sink);
266 ESP_LOGE(TAG,
"Failed to add sink: %s", esp_err_to_name(err));
279 vTaskSuspend(
nullptr);
void mark_failed()
Mark this component as failed.
void status_momentary_error(const char *name, uint32_t length=5000)
Set error status flag and automatically clear it after a timeout.
void enable_loop()
Enable this component's loop.
bool status_has_error() const
void disable_loop()
Disable this component's loop.
bool create(TaskFunction_t fn, const char *name, uint32_t stack_size, void *param, UBaseType_t priority, bool use_psram)
Allocate stack and create task.
bool is_created() const
Check if the task has been created and not yet destroyed.
void deallocate()
Delete the task (if running) and free the stack buffer.
const StaticVector< NamedAudioFile, AUDIO_FILE_MAX_FILES > & get_named_audio_files()