mirror of
https://github.com/esphome/esphome.git
synced 2026-02-23 17:58:23 -07:00
[media_player] Add more commands to support Sendspin (#12258)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick+github@koston.org>
This commit is contained in:
@@ -35,86 +35,73 @@ MEDIA_PLAYER_FORMAT_PURPOSE_ENUM = {
|
||||
"announcement": MediaPlayerFormatPurpose.PURPOSE_ANNOUNCEMENT,
|
||||
}
|
||||
|
||||
|
||||
PlayAction = media_player_ns.class_(
|
||||
"PlayAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
PlayMediaAction = media_player_ns.class_(
|
||||
"PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
ToggleAction = media_player_ns.class_(
|
||||
"ToggleAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
PauseAction = media_player_ns.class_(
|
||||
"PauseAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
StopAction = media_player_ns.class_(
|
||||
"StopAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeUpAction = media_player_ns.class_(
|
||||
"VolumeUpAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeDownAction = media_player_ns.class_(
|
||||
"VolumeDownAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeSetAction = media_player_ns.class_(
|
||||
"VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
TurnOnAction = media_player_ns.class_(
|
||||
"TurnOnAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
TurnOffAction = media_player_ns.class_(
|
||||
"TurnOffAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
|
||||
# Local config key constants
|
||||
CONF_ANNOUNCEMENT = "announcement"
|
||||
CONF_ON_PLAY = "on_play"
|
||||
CONF_ON_PAUSE = "on_pause"
|
||||
CONF_ON_ANNOUNCEMENT = "on_announcement"
|
||||
CONF_MEDIA_URL = "media_url"
|
||||
|
||||
StateTrigger = media_player_ns.class_("StateTrigger", automation.Trigger.template())
|
||||
IdleTrigger = media_player_ns.class_("IdleTrigger", automation.Trigger.template())
|
||||
PlayTrigger = media_player_ns.class_("PlayTrigger", automation.Trigger.template())
|
||||
PauseTrigger = media_player_ns.class_("PauseTrigger", automation.Trigger.template())
|
||||
AnnoucementTrigger = media_player_ns.class_(
|
||||
"AnnouncementTrigger", automation.Trigger.template()
|
||||
# Command actions that all share the same schema and codegen handler
|
||||
_COMMAND_ACTIONS = [
|
||||
"play",
|
||||
"pause",
|
||||
"stop",
|
||||
"toggle",
|
||||
"volume_up",
|
||||
"volume_down",
|
||||
"turn_on",
|
||||
"turn_off",
|
||||
"next",
|
||||
"previous",
|
||||
"mute",
|
||||
"unmute",
|
||||
"repeat_off",
|
||||
"repeat_one",
|
||||
"repeat_all",
|
||||
"shuffle",
|
||||
"unshuffle",
|
||||
"group_join",
|
||||
"clear_playlist",
|
||||
]
|
||||
|
||||
# State triggers: (config_key, C++ class name)
|
||||
_STATE_TRIGGERS = [
|
||||
(CONF_ON_STATE, "StateTrigger"),
|
||||
(CONF_ON_IDLE, "IdleTrigger"),
|
||||
(CONF_ON_PLAY, "PlayTrigger"),
|
||||
(CONF_ON_PAUSE, "PauseTrigger"),
|
||||
(CONF_ON_ANNOUNCEMENT, "AnnouncementTrigger"),
|
||||
(CONF_ON_TURN_ON, "OnTrigger"),
|
||||
(CONF_ON_TURN_OFF, "OffTrigger"),
|
||||
]
|
||||
|
||||
# State conditions that all share the same schema and codegen handler
|
||||
_STATE_CONDITIONS = [
|
||||
"idle",
|
||||
"paused",
|
||||
"playing",
|
||||
"announcing",
|
||||
"on",
|
||||
"off",
|
||||
"muted",
|
||||
]
|
||||
|
||||
# Special action classes with custom schemas/handlers
|
||||
PlayMediaAction = media_player_ns.class_(
|
||||
"PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
OnTrigger = media_player_ns.class_("OnTrigger", automation.Trigger.template())
|
||||
OffTrigger = media_player_ns.class_("OffTrigger", automation.Trigger.template())
|
||||
IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition)
|
||||
IsPausedCondition = media_player_ns.class_("IsPausedCondition", automation.Condition)
|
||||
IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition)
|
||||
IsAnnouncingCondition = media_player_ns.class_(
|
||||
"IsAnnouncingCondition", automation.Condition
|
||||
VolumeSetAction = media_player_ns.class_(
|
||||
"VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
IsOnCondition = media_player_ns.class_("IsOnCondition", automation.Condition)
|
||||
IsOffCondition = media_player_ns.class_("IsOffCondition", automation.Condition)
|
||||
|
||||
|
||||
async def setup_media_player_core_(var, config):
|
||||
await setup_entity(var, config, "media_player")
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_IDLE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_PLAY, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_PAUSE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_ANNOUNCEMENT, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_TURN_ON, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_TURN_OFF, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf_key, _ in _STATE_TRIGGERS:
|
||||
for conf in config.get(conf_key, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
||||
|
||||
async def register_media_player(var, config):
|
||||
@@ -133,41 +120,14 @@ async def new_media_player(config, *args):
|
||||
|
||||
_MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||
cv.Optional(conf_key): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
media_player_ns.class_(class_name, automation.Trigger.template())
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_IDLE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PLAY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PlayTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PAUSE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ANNOUNCEMENT): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(AnnoucementTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_TURN_ON): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OffTrigger),
|
||||
}
|
||||
),
|
||||
)
|
||||
for conf_key, class_name in _STATE_TRIGGERS
|
||||
}
|
||||
)
|
||||
|
||||
@@ -228,56 +188,48 @@ async def media_player_play_media_action(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action("media_player.play", PlayAction, MEDIA_PLAYER_ACTION_SCHEMA)
|
||||
@automation.register_action(
|
||||
"media_player.toggle", ToggleAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"media_player.pause", PauseAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action("media_player.stop", StopAction, MEDIA_PLAYER_ACTION_SCHEMA)
|
||||
@automation.register_action(
|
||||
"media_player.volume_up", VolumeUpAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"media_player.volume_down", VolumeDownAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"media_player.turn_on", TurnOnAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"media_player.turn_off", TurnOffAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
async def media_player_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_)
|
||||
cg.add(var.set_announcement(announcement))
|
||||
return var
|
||||
def _snake_to_camel(name):
|
||||
return "".join(word.capitalize() for word in name.split("_"))
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
"media_player.is_idle", IsIdleCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_paused", IsPausedCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_playing", IsPlayingCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_announcing", IsAnnouncingCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_on", IsOnCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_off", IsOffCondition, MEDIA_PLAYER_CONDITION_SCHEMA
|
||||
)
|
||||
async def media_player_condition(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
def _register_command_actions():
|
||||
async def handler(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_)
|
||||
cg.add(var.set_announcement(announcement))
|
||||
return var
|
||||
|
||||
for action_name in _COMMAND_ACTIONS:
|
||||
class_name = f"{_snake_to_camel(action_name)}Action"
|
||||
action_class = media_player_ns.class_(
|
||||
class_name, automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
automation.register_action(
|
||||
f"media_player.{action_name}", action_class, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)(handler)
|
||||
|
||||
|
||||
_register_command_actions()
|
||||
|
||||
|
||||
def _register_state_conditions():
|
||||
async def handler(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
for condition_name in _STATE_CONDITIONS:
|
||||
class_name = f"Is{_snake_to_camel(condition_name)}Condition"
|
||||
condition_class = media_player_ns.class_(class_name, automation.Condition)
|
||||
automation.register_condition(
|
||||
f"media_player.is_{condition_name}",
|
||||
condition_class,
|
||||
MEDIA_PLAYER_CONDITION_SCHEMA,
|
||||
)(handler)
|
||||
|
||||
|
||||
_register_state_conditions()
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -32,6 +32,28 @@ template<typename... Ts>
|
||||
using TurnOnAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_TURN_ON, Ts...>;
|
||||
template<typename... Ts>
|
||||
using TurnOffAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_TURN_OFF, Ts...>;
|
||||
template<typename... Ts>
|
||||
using NextAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_NEXT, Ts...>;
|
||||
template<typename... Ts>
|
||||
using PreviousAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PREVIOUS, Ts...>;
|
||||
template<typename... Ts>
|
||||
using MuteAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_MUTE, Ts...>;
|
||||
template<typename... Ts>
|
||||
using UnmuteAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_UNMUTE, Ts...>;
|
||||
template<typename... Ts>
|
||||
using RepeatOffAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF, Ts...>;
|
||||
template<typename... Ts>
|
||||
using RepeatOneAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE, Ts...>;
|
||||
template<typename... Ts>
|
||||
using RepeatAllAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ALL, Ts...>;
|
||||
template<typename... Ts>
|
||||
using ShuffleAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_SHUFFLE, Ts...>;
|
||||
template<typename... Ts>
|
||||
using UnshuffleAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_UNSHUFFLE, Ts...>;
|
||||
template<typename... Ts>
|
||||
using GroupJoinAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_GROUP_JOIN, Ts...>;
|
||||
template<typename... Ts>
|
||||
using ClearPlaylistAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST, Ts...>;
|
||||
|
||||
template<typename... Ts> class PlayMediaAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
TEMPLATABLE_VALUE(std::string, media_url)
|
||||
@@ -105,5 +127,10 @@ template<typename... Ts> class IsOffCondition : public Condition<Ts...>, public
|
||||
bool check(const Ts &...x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_OFF; }
|
||||
};
|
||||
|
||||
template<typename... Ts> class IsMutedCondition : public Condition<Ts...>, public Parented<MediaPlayer> {
|
||||
public:
|
||||
bool check(const Ts &...x) override { return this->parent_->is_muted(); }
|
||||
};
|
||||
|
||||
} // namespace media_player
|
||||
} // namespace esphome
|
||||
|
||||
@@ -60,11 +60,39 @@ const char *media_player_command_to_string(MediaPlayerCommand command) {
|
||||
return "TURN_ON";
|
||||
case MEDIA_PLAYER_COMMAND_TURN_OFF:
|
||||
return "TURN_OFF";
|
||||
case MEDIA_PLAYER_COMMAND_NEXT:
|
||||
return "NEXT";
|
||||
case MEDIA_PLAYER_COMMAND_PREVIOUS:
|
||||
return "PREVIOUS";
|
||||
case MEDIA_PLAYER_COMMAND_REPEAT_ALL:
|
||||
return "REPEAT_ALL";
|
||||
case MEDIA_PLAYER_COMMAND_SHUFFLE:
|
||||
return "SHUFFLE";
|
||||
case MEDIA_PLAYER_COMMAND_UNSHUFFLE:
|
||||
return "UNSHUFFLE";
|
||||
case MEDIA_PLAYER_COMMAND_GROUP_JOIN:
|
||||
return "GROUP_JOIN";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayerTraits::set_supports_pause(bool supports_pause) {
|
||||
if (supports_pause) {
|
||||
this->feature_flags_ |= MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY;
|
||||
} else {
|
||||
this->feature_flags_ &= ~(MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayerTraits::set_supports_turn_off_on(bool supports_turn_off_on) {
|
||||
if (supports_turn_off_on) {
|
||||
this->feature_flags_ |= MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON;
|
||||
} else {
|
||||
this->feature_flags_ &= ~(MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayerCall::validate_() {
|
||||
if (this->media_url_.has_value()) {
|
||||
if (this->command_.has_value() && this->command_.value() != MEDIA_PLAYER_COMMAND_ENQUEUE) {
|
||||
@@ -125,6 +153,30 @@ MediaPlayerCall &MediaPlayerCall::set_command(const char *command) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_TURN_ON);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TURN_OFF")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_TURN_OFF);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("VOLUME_UP")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_VOLUME_UP);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("VOLUME_DOWN")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_VOLUME_DOWN);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("ENQUEUE")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_ENQUEUE);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_ONE")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_ONE);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_OFF")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_OFF);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_ALL")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_ALL);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("CLEAR_PLAYLIST")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("NEXT")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_NEXT);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("PREVIOUS")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_PREVIOUS);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("SHUFFLE")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_SHUFFLE);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("UNSHUFFLE")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_UNSHUFFLE);
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("GROUP_JOIN")) == 0) {
|
||||
this->set_command(MEDIA_PLAYER_COMMAND_GROUP_JOIN);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ enum MediaPlayerCommand : uint8_t {
|
||||
MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST = 11,
|
||||
MEDIA_PLAYER_COMMAND_TURN_ON = 12,
|
||||
MEDIA_PLAYER_COMMAND_TURN_OFF = 13,
|
||||
MEDIA_PLAYER_COMMAND_NEXT = 14,
|
||||
MEDIA_PLAYER_COMMAND_PREVIOUS = 15,
|
||||
MEDIA_PLAYER_COMMAND_REPEAT_ALL = 16,
|
||||
MEDIA_PLAYER_COMMAND_SHUFFLE = 17,
|
||||
MEDIA_PLAYER_COMMAND_UNSHUFFLE = 18,
|
||||
MEDIA_PLAYER_COMMAND_GROUP_JOIN = 19,
|
||||
};
|
||||
const char *media_player_command_to_string(MediaPlayerCommand command);
|
||||
|
||||
@@ -74,38 +80,40 @@ struct MediaPlayerSupportedFormat {
|
||||
uint32_t sample_bytes;
|
||||
};
|
||||
|
||||
// Base features always reported for all media players
|
||||
static constexpr uint32_t BASE_MEDIA_PLAYER_FEATURES =
|
||||
MediaPlayerEntityFeature::PLAY_MEDIA | MediaPlayerEntityFeature::BROWSE_MEDIA | MediaPlayerEntityFeature::STOP |
|
||||
MediaPlayerEntityFeature::VOLUME_SET | MediaPlayerEntityFeature::VOLUME_MUTE |
|
||||
MediaPlayerEntityFeature::MEDIA_ANNOUNCE;
|
||||
|
||||
class MediaPlayer;
|
||||
|
||||
class MediaPlayerTraits {
|
||||
public:
|
||||
MediaPlayerTraits() = default;
|
||||
|
||||
void set_supports_pause(bool supports_pause) { this->supports_pause_ = supports_pause; }
|
||||
bool get_supports_pause() const { return this->supports_pause_; }
|
||||
|
||||
void set_supports_turn_off_on(bool supports_turn_off_on) { this->supports_turn_off_on_ = supports_turn_off_on; }
|
||||
bool get_supports_turn_off_on() const { return this->supports_turn_off_on_; }
|
||||
uint32_t get_feature_flags() const { return this->feature_flags_; }
|
||||
void add_feature_flags(uint32_t feature_flags) { this->feature_flags_ |= feature_flags; }
|
||||
void clear_feature_flags(uint32_t feature_flags) { this->feature_flags_ &= ~feature_flags; }
|
||||
// Returns true only if all specified flags are set
|
||||
bool has_feature_flags(uint32_t feature_flags) const {
|
||||
return (this->feature_flags_ & feature_flags) == feature_flags;
|
||||
}
|
||||
|
||||
std::vector<MediaPlayerSupportedFormat> &get_supported_formats() { return this->supported_formats_; }
|
||||
|
||||
uint32_t get_feature_flags() const {
|
||||
uint32_t flags = 0;
|
||||
flags |= MediaPlayerEntityFeature::PLAY_MEDIA | MediaPlayerEntityFeature::BROWSE_MEDIA |
|
||||
MediaPlayerEntityFeature::STOP | MediaPlayerEntityFeature::VOLUME_SET |
|
||||
MediaPlayerEntityFeature::VOLUME_MUTE | MediaPlayerEntityFeature::MEDIA_ANNOUNCE;
|
||||
if (this->get_supports_pause()) {
|
||||
flags |= MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY;
|
||||
}
|
||||
if (this->get_supports_turn_off_on()) {
|
||||
flags |= MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON;
|
||||
}
|
||||
return flags;
|
||||
// Legacy setters/getters are kept for backward compatibility
|
||||
void set_supports_pause(bool supports_pause);
|
||||
bool get_supports_pause() const { return this->has_feature_flags(MediaPlayerEntityFeature::PAUSE); }
|
||||
|
||||
void set_supports_turn_off_on(bool supports_turn_off_on);
|
||||
bool get_supports_turn_off_on() const {
|
||||
return this->has_feature_flags(MediaPlayerEntityFeature::TURN_ON | MediaPlayerEntityFeature::TURN_OFF);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<MediaPlayerSupportedFormat> supported_formats_{};
|
||||
bool supports_pause_{false};
|
||||
bool supports_turn_off_on_{false};
|
||||
uint32_t feature_flags_{BASE_MEDIA_PLAYER_FEATURES};
|
||||
};
|
||||
|
||||
class MediaPlayerCall {
|
||||
|
||||
@@ -23,8 +23,27 @@ media_player:
|
||||
- media_player.stop:
|
||||
- media_player.stop:
|
||||
announcement: true
|
||||
on_announcement:
|
||||
- media_player.play:
|
||||
on_turn_on:
|
||||
- media_player.play:
|
||||
on_turn_off:
|
||||
- media_player.stop:
|
||||
on_pause:
|
||||
- media_player.toggle:
|
||||
- media_player.turn_on:
|
||||
- media_player.turn_off:
|
||||
- media_player.next:
|
||||
- media_player.previous:
|
||||
- media_player.mute:
|
||||
- media_player.unmute:
|
||||
- media_player.repeat_off:
|
||||
- media_player.repeat_one:
|
||||
- media_player.repeat_all:
|
||||
- media_player.shuffle:
|
||||
- media_player.unshuffle:
|
||||
- media_player.group_join:
|
||||
- media_player.clear_playlist:
|
||||
- wait_until:
|
||||
media_player.is_idle:
|
||||
- wait_until:
|
||||
@@ -33,6 +52,12 @@ media_player:
|
||||
media_player.is_announcing:
|
||||
- wait_until:
|
||||
media_player.is_paused:
|
||||
- wait_until:
|
||||
media_player.is_on:
|
||||
- wait_until:
|
||||
media_player.is_off:
|
||||
- wait_until:
|
||||
media_player.is_muted:
|
||||
- media_player.volume_up:
|
||||
- media_player.volume_down:
|
||||
- media_player.volume_set: 50%
|
||||
|
||||
Reference in New Issue
Block a user