[speaker] Use register_apply_action for the speaker actions (#19535)

This commit is contained in:
J. Nick Koston
2026-09-23 16:51:20 -05:00
committed by GitHub
parent c33ccc7043
commit 4a7fe83a17
6 changed files with 34 additions and 125 deletions
+11 -44
View File
@@ -18,21 +18,6 @@ Speaker = speaker_ns.class_("Speaker")
PlayAction = speaker_ns.class_(
"PlayAction", automation.Action, cg.Parented.template(Speaker)
)
StopAction = speaker_ns.class_(
"StopAction", automation.Action, cg.Parented.template(Speaker)
)
FinishAction = speaker_ns.class_(
"FinishAction", automation.Action, cg.Parented.template(Speaker)
)
VolumeSetAction = speaker_ns.class_(
"VolumeSetAction", automation.Action, cg.Parented.template(Speaker)
)
MuteOnAction = speaker_ns.class_(
"MuteOnAction", automation.Action, cg.Parented.template(Speaker)
)
MuteOffAction = speaker_ns.class_(
"MuteOffAction", automation.Action, cg.Parented.template(Speaker)
)
IsPlayingCondition = speaker_ns.class_("IsPlayingCondition", automation.Condition)
@@ -96,12 +81,15 @@ async def speaker_play_action(config, action_id, template_arg, args):
return var
automation.register_action(
"speaker.stop", StopAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True
)(speaker_action)
automation.register_action(
"speaker.finish", FinishAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True
)(speaker_action)
for _name, _call in (
("speaker.stop", "stop()"),
("speaker.finish", "finish()"),
("speaker.mute_on", "set_mute_state(true)"),
("speaker.mute_off", "set_mute_state(false)"),
):
automation.register_apply_action(
_name, SPEAKER_AUTOMATION_SCHEMA, automation.ApplyCall(_call)
)
automation.register_condition(
"speaker.is_playing", IsPlayingCondition, SPEAKER_AUTOMATION_SCHEMA
@@ -112,9 +100,8 @@ automation.register_condition(
)(speaker_action)
@automation.register_action(
automation.register_apply_action(
"speaker.volume_set",
VolumeSetAction,
cv.maybe_simple_value(
{
cv.GenerateID(): cv.use_id(Speaker),
@@ -122,28 +109,8 @@ automation.register_condition(
},
key=CONF_VOLUME,
),
synchronous=True,
automation.ApplyField(CONF_VOLUME, "set_volume", cg.float_),
)
async def speaker_volume_set_action(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
volume = await cg.templatable(config[CONF_VOLUME], args, cg.float_)
cg.add(var.set_volume(volume))
return var
@automation.register_action(
"speaker.mute_off",
MuteOffAction,
SPEAKER_AUTOMATION_SCHEMA,
synchronous=True,
)
@automation.register_action(
"speaker.mute_on", MuteOnAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True
)
async def speaker_mute_action_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
return cg.new_Pvariable(action_id, template_arg, paren)
@coroutine_with_priority(CoroPriority.CORE)
-35
View File
@@ -38,41 +38,6 @@ template<typename... Ts> class PlayAction final : public Action<Ts...>, public P
} data_;
};
template<typename... Ts> class VolumeSetAction final : public Action<Ts...>, public Parented<Speaker> {
TEMPLATABLE_VALUE(float, volume)
void play(const Ts &...x) override { this->parent_->set_volume(this->volume_.value(x...)); }
};
template<typename... Ts> class MuteOnAction final : public Action<Ts...> {
public:
explicit MuteOnAction(Speaker *speaker) : speaker_(speaker) {}
void play(const Ts &...x) override { this->speaker_->set_mute_state(true); }
protected:
Speaker *speaker_;
};
template<typename... Ts> class MuteOffAction final : public Action<Ts...> {
public:
explicit MuteOffAction(Speaker *speaker) : speaker_(speaker) {}
void play(const Ts &...x) override { this->speaker_->set_mute_state(false); }
protected:
Speaker *speaker_;
};
template<typename... Ts> class StopAction final : public Action<Ts...>, public Parented<Speaker> {
public:
void play(const Ts &...x) override { this->parent_->stop(); }
};
template<typename... Ts> class FinishAction final : public Action<Ts...>, public Parented<Speaker> {
public:
void play(const Ts &...x) override { this->parent_->finish(); }
};
template<typename... Ts> class IsPlayingCondition final : public Condition<Ts...>, public Parented<Speaker> {
public:
bool check(const Ts &...x) override { return this->parent_->is_running(); }
@@ -22,7 +22,6 @@ from esphome.const import (
CONF_BUFFER_SIZE,
CONF_FILES,
CONF_FORMAT,
CONF_ID,
CONF_NUM_CHANNELS,
CONF_ON_TURN_OFF,
CONF_ON_TURN_ON,
@@ -63,11 +62,6 @@ AUDIO_PIPELINE_TYPE_ENUM = {
"ANNOUNCEMENT": AudioPipelineType.ANNOUNCEMENT,
}
PlayOnDeviceMediaAction = speaker_ns.class_(
"PlayOnDeviceMediaAction",
automation.Action,
cg.Parented.template(SpeakerMediaPlayer),
)
StopStreamAction = speaker_ns.class_(
"StopStreamAction", automation.Action, cg.Parented.template(SpeakerMediaPlayer)
)
@@ -239,9 +233,8 @@ async def to_code(config):
audio_file.generate_audio_file_code(file_config)
@automation.register_action(
automation.register_apply_action(
"media_player.speaker.play_on_device_media_file",
PlayOnDeviceMediaAction,
cv.maybe_simple_value(
{
cv.GenerateID(): cv.use_id(SpeakerMediaPlayer),
@@ -251,17 +244,18 @@ async def to_code(config):
},
key=CONF_MEDIA_FILE,
),
synchronous=True,
automation.ApplyCall(
"play_file({}, {}, {})",
(
# The file is a use_id of a global AudioFile pointer; global-scope qualified
# so a trigger arg with the same name cannot shadow it.
(
CONF_MEDIA_FILE,
audio.AudioFile.operator("ptr"),
lambda _, value: f"::{value}",
),
(CONF_ANNOUNCEMENT, cg.bool_),
(CONF_ENQUEUE, cg.bool_),
),
),
)
async def play_on_device_media_media_action(config, action_id, template_arg, args):
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])
media_file = await cg.get_variable(config[CONF_MEDIA_FILE])
announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_)
enqueue = await cg.templatable(config[CONF_ENQUEUE], args, cg.bool_)
template_ = await cg.templatable(media_file, args, audio.AudioFile.operator("ptr"))
cg.add(var.set_audio_file(template_))
cg.add(var.set_announcement(announcement))
cg.add(var.set_enqueue(enqueue))
return var
@@ -1,25 +0,0 @@
#pragma once
#include "speaker_media_player.h"
#ifdef USE_ESP32
#include "esphome/components/audio/audio.h"
#include "esphome/core/automation.h"
namespace esphome::speaker {
template<typename... Ts>
class PlayOnDeviceMediaAction final : public Action<Ts...>, public Parented<SpeakerMediaPlayer> {
TEMPLATABLE_VALUE(audio::AudioFile *, audio_file)
TEMPLATABLE_VALUE(bool, announcement)
TEMPLATABLE_VALUE(bool, enqueue)
void play(const Ts &...x) override {
this->parent_->play_file(this->audio_file_.value(x...), this->announcement_.value(x...),
this->enqueue_.value(x...));
}
};
} // namespace esphome::speaker
#endif
@@ -30,3 +30,8 @@ script:
id: speaker_media_player_id
media_file: speaker_test_audio
announcement: true
- media_player.speaker.play_on_device_media_file:
id: speaker_media_player_id
media_file: speaker_test_audio
announcement: !lambda return id(speaker_my_number).state > 50;
enqueue: !lambda return id(speaker_my_number).state < 50;
+3
View File
@@ -25,6 +25,9 @@ esphome:
- speaker.volume_set:
id: speaker_id
volume: 0.9
- speaker.volume_set:
id: speaker_id
volume: !lambda return id(speaker_my_number).state / 100.0f;
- if:
condition:
speaker.is_playing: