From b8a9d327f05700a6df463202cdc5cfaefbfdc8dd Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Thu, 2 Apr 2026 09:40:19 -0500 Subject: [PATCH] [media_player] Add enqueue action (#14775) --- esphome/components/media_player/__init__.py | 41 +++++++++++++------- esphome/components/media_player/automation.h | 16 +++++--- tests/components/media_player/common.yaml | 5 +++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 767916ad88..842f620dae 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -94,6 +94,9 @@ _STATE_CONDITIONS = [ PlayMediaAction = media_player_ns.class_( "PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer) ) +EnqueueMediaAction = media_player_ns.class_( + "EnqueueMediaAction", automation.Action, cg.Parented.template(MediaPlayer) +) VolumeSetAction = media_player_ns.class_( "VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer) ) @@ -168,20 +171,17 @@ MEDIA_PLAYER_CONDITION_SCHEMA = automation.maybe_simple_id( ) -@automation.register_action( - "media_player.play_media", - PlayMediaAction, - cv.maybe_simple_value( - { - cv.GenerateID(): cv.use_id(MediaPlayer), - cv.Required(CONF_MEDIA_URL): cv.templatable(cv.url), - cv.Optional(CONF_ANNOUNCEMENT, default=False): cv.templatable(cv.boolean), - }, - key=CONF_MEDIA_URL, - ), - synchronous=True, +_MEDIA_URL_ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(MediaPlayer), + cv.Required(CONF_MEDIA_URL): cv.templatable(cv.url), + cv.Optional(CONF_ANNOUNCEMENT, default=False): cv.templatable(cv.boolean), + }, + key=CONF_MEDIA_URL, ) -async def media_player_play_media_action(config, action_id, template_arg, args): + + +async def _media_action_handler(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) media_url = await cg.templatable(config[CONF_MEDIA_URL], args, cg.std_string) @@ -191,6 +191,21 @@ async def media_player_play_media_action(config, action_id, template_arg, args): return var +automation.register_action( + "media_player.play_media", + PlayMediaAction, + _MEDIA_URL_ACTION_SCHEMA, + synchronous=True, +)(_media_action_handler) + +automation.register_action( + "media_player.enqueue", + EnqueueMediaAction, + _MEDIA_URL_ACTION_SCHEMA, + synchronous=True, +)(_media_action_handler) + + def _snake_to_camel(name): return "".join(word.capitalize() for word in name.split("_")) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 658381ef90..14ce3c6aed 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -55,17 +55,23 @@ using GroupJoinAction = MediaPlayerCommandAction using ClearPlaylistAction = MediaPlayerCommandAction; -template class PlayMediaAction : public Action, public Parented { +template +class MediaPlayerMediaAction : public Action, public Parented { TEMPLATABLE_VALUE(std::string, media_url) TEMPLATABLE_VALUE(bool, announcement) void play(const Ts &...x) override { - this->parent_->make_call() - .set_media_url(this->media_url_.value(x...)) - .set_announcement(this->announcement_.value(x...)) - .perform(); + auto call = this->parent_->make_call(); + if constexpr (Command != MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PLAY) + call.set_command(Command); + call.set_media_url(this->media_url_.value(x...)).set_announcement(this->announcement_.value(x...)).perform(); } }; +template +using PlayMediaAction = MediaPlayerMediaAction; +template +using EnqueueMediaAction = MediaPlayerMediaAction; + template class VolumeSetAction : public Action, public Parented { TEMPLATABLE_VALUE(float, volume) void play(const Ts &...x) override { this->parent_->make_call().set_volume(this->volume_.value(x...)).perform(); } diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml index 89600f70f6..88d04d0ff0 100644 --- a/tests/components/media_player/common.yaml +++ b/tests/components/media_player/common.yaml @@ -61,3 +61,8 @@ media_player: - media_player.volume_up: - media_player.volume_down: - media_player.volume_set: 50% + - media_player.enqueue: http://localhost/media.mp3 + - media_player.enqueue: !lambda 'return "http://localhost/media.mp3";' + - media_player.enqueue: + media_url: http://localhost/media.mp3 + announcement: true