46static const uint32_t MEDIA_CONTROLS_QUEUE_LENGTH = 20;
48static const UBaseType_t MEDIA_PIPELINE_TASK_PRIORITY = 1;
49static const UBaseType_t ANNOUNCEMENT_PIPELINE_TASK_PRIORITY = 1;
51static const char *
const TAG =
"speaker_media_player";
54#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
64 VolumeRestoreState volume_restore_state;
65 if (this->
pref_.
load(&volume_restore_state)) {
73#ifdef USE_OTA_STATE_LISTENER
79 ANNOUNCEMENT_PIPELINE_TASK_PRIORITY);
82 ESP_LOGE(TAG,
"Failed to create announcement pipeline");
91 ESP_LOGE(TAG,
"Failed to create media pipeline");
96 ESP_LOGI(TAG,
"Set up speaker media player");
100 switch (pipeline_type) {
129 MediaCallCommand media_command;
132 bool enqueue = media_command.enqueue.has_value() && media_command.enqueue.value();
134 if (media_command.url.has_value() || media_command.file.has_value()) {
135#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
141 PlaylistItem playlist_item;
142 if (media_command.url.has_value()) {
143 playlist_item.url = *media_command.url.value();
144 delete media_command.url.value();
146 if (media_command.file.has_value()) {
147 playlist_item.file = media_command.file;
150 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
155 if (media_command.file.has_value()) {
157 }
else if (media_command.url.has_value()) {
174 if (media_command.file.has_value()) {
176 }
else if (media_command.url.has_value()) {
189 if (media_command.volume.has_value()) {
194 if (media_command.command.has_value()) {
195 switch (media_command.command.value()) {
197#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
214#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
228#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
229 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value()) ||
232 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
287 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
294 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
301 if (this->
single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
318#ifdef USE_OTA_STATE_LISTENER
320 ota::OTAComponent *comp) {
351 ESP_LOGE(TAG,
"The media pipeline's file reader encountered an error.");
353 ESP_LOGE(TAG,
"The media pipeline's audio decoder encountered an error.");
362 ESP_LOGE(TAG,
"The announcement pipeline's file reader encountered an error.");
364 ESP_LOGE(TAG,
"The announcement pipeline's audio decoder encountered an error.");
385 if (playlist_item.url.has_value()) {
387 }
else if (playlist_item.file.has_value()) {
391 if (timeout_ms > 0) {
401#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
424 if (playlist_item.url.has_value()) {
426 }
else if (playlist_item.file.has_value()) {
430 if (timeout_ms > 0) {
440#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
452 if (this->state != old_state) {
456#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
478 MediaCallCommand media_command;
480 media_command.file = media_file;
482 media_command.announce =
true;
484 media_command.announce =
false;
486 media_command.enqueue = enqueue;
496 MediaCallCommand media_command;
498 auto ann =
call.get_announcement();
500 media_command.announce =
true;
502 media_command.announce =
false;
505 auto media_url =
call.get_media_url();
506 if (media_url.has_value()) {
508 new std::string(*media_url);
510 auto cmd =
call.get_command();
511 if (cmd.has_value()) {
513 media_command.enqueue =
true;
521 auto vol =
call.get_volume();
522 if (vol.has_value()) {
523 media_command.volume = vol;
529 auto cmd =
call.get_command();
530 if (cmd.has_value()) {
531 media_command.command = cmd;
532 TickType_t ticks_to_wait = portMAX_DELAY;
543 auto traits = media_player::MediaPlayerTraits();
545 traits.set_supports_pause(
true);
547#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF
548 traits.set_supports_turn_off_on(
true);
555 traits.get_supported_formats().push_back(this->
media_format_.value());
560 traits.get_supported_formats().push_back(media_format);
567 VolumeRestoreState volume_restore_state;
568 volume_restore_state.volume = this->
volume;
569 volume_restore_state.is_muted = this->
is_muted_;
586 if (old_mute_state != mute_state) {
613 if (volume < 0.001) {
void mark_failed()
Mark this component as failed.
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std voi defer)(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(const std boo cancel_timeout)(const char *name)
Cancel a timeout function.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(const std boo cancel_interval)(const char *name)
Cancel an interval function.
ESPPreferenceObject make_entity_preference(uint32_t version=0)
Create a preference object for storing this entity's state/settings.
void trigger(const Ts &...x)
Inform the parent automation that the event has triggered.
void add_global_state_listener(OTAGlobalStateListener *listener)
virtual void set_volume(float volume)
virtual void set_mute_state(bool mute_state)
OTAGlobalCallback * get_global_ota_callback()
Providing packet encoding functions for exchanging data with a remote host.
T remap(U value, U min, U max, T min_out, T max_out)
Remap value from the range (min, max) to (min_out, max_out).