mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 17:49:37 +01:00
Add support for Media player Mute/Unmute intents (#150508)
This commit is contained in:
@@ -14,6 +14,7 @@ from homeassistant.const import (
|
||||
SERVICE_MEDIA_PAUSE,
|
||||
SERVICE_MEDIA_PLAY,
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
SERVICE_VOLUME_SET,
|
||||
STATE_PLAYING,
|
||||
)
|
||||
@@ -27,6 +28,7 @@ from .browse_media import SearchMedia
|
||||
from .const import (
|
||||
ATTR_MEDIA_FILTER_CLASSES,
|
||||
ATTR_MEDIA_VOLUME_LEVEL,
|
||||
ATTR_MEDIA_VOLUME_MUTED,
|
||||
DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
SERVICE_SEARCH_MEDIA,
|
||||
@@ -39,6 +41,8 @@ INTENT_MEDIA_PAUSE = "HassMediaPause"
|
||||
INTENT_MEDIA_UNPAUSE = "HassMediaUnpause"
|
||||
INTENT_MEDIA_NEXT = "HassMediaNext"
|
||||
INTENT_MEDIA_PREVIOUS = "HassMediaPrevious"
|
||||
INTENT_PLAYER_MUTE = "HassMediaPlayerMute"
|
||||
INTENT_PLAYER_UNMUTE = "HassMediaPlayerUnmute"
|
||||
INTENT_SET_VOLUME = "HassSetVolume"
|
||||
INTENT_SET_VOLUME_RELATIVE = "HassSetVolumeRelative"
|
||||
INTENT_MEDIA_SEARCH_AND_PLAY = "HassMediaSearchAndPlay"
|
||||
@@ -130,6 +134,8 @@ async def async_setup_intents(hass: HomeAssistant) -> None:
|
||||
),
|
||||
)
|
||||
intent.async_register(hass, MediaSetVolumeRelativeHandler())
|
||||
intent.async_register(hass, MediaPlayerMuteUnmuteHandler(True))
|
||||
intent.async_register(hass, MediaPlayerMuteUnmuteHandler(False))
|
||||
intent.async_register(hass, MediaSearchAndPlayHandler())
|
||||
|
||||
|
||||
@@ -231,6 +237,42 @@ class MediaUnpauseHandler(intent.ServiceIntentHandler):
|
||||
)
|
||||
|
||||
|
||||
class MediaPlayerMuteUnmuteHandler(intent.ServiceIntentHandler):
|
||||
"""Handle Mute/Unmute intents."""
|
||||
|
||||
def __init__(self, is_volume_muted: bool) -> None:
|
||||
"""Initialize the mute/unmute handler objects."""
|
||||
|
||||
super().__init__(
|
||||
(INTENT_PLAYER_MUTE if is_volume_muted else INTENT_PLAYER_UNMUTE),
|
||||
DOMAIN,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
required_domains={DOMAIN},
|
||||
required_features=MediaPlayerEntityFeature.VOLUME_MUTE,
|
||||
optional_slots={
|
||||
ATTR_MEDIA_VOLUME_MUTED: intent.IntentSlotInfo(
|
||||
description="Whether the media player should be muted or unmuted",
|
||||
value_schema=vol.Boolean(),
|
||||
),
|
||||
},
|
||||
description=(
|
||||
"Mutes a media player" if is_volume_muted else "Unmutes a media player"
|
||||
),
|
||||
platforms={DOMAIN},
|
||||
device_classes={MediaPlayerDeviceClass},
|
||||
)
|
||||
self.is_volume_muted = is_volume_muted
|
||||
|
||||
async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
|
||||
"""Handle the intent."""
|
||||
|
||||
intent_obj.slots["is_volume_muted"] = {
|
||||
"value": self.is_volume_muted,
|
||||
"text": str(self.is_volume_muted),
|
||||
}
|
||||
return await super().async_handle(intent_obj)
|
||||
|
||||
|
||||
class MediaSearchAndPlayHandler(intent.IntentHandler):
|
||||
"""Handle HassMediaSearchAndPlay intents."""
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from homeassistant.components.media_player import (
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
SERVICE_SEARCH_MEDIA,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
SERVICE_VOLUME_SET,
|
||||
BrowseMedia,
|
||||
MediaClass,
|
||||
@@ -265,6 +266,88 @@ async def test_volume_media_player_intent(hass: HomeAssistant) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def test_media_player_mute_intent(hass: HomeAssistant) -> None:
|
||||
"""Test HassMediaPlayerMute intent for media players."""
|
||||
await media_player_intent.async_setup_intents(hass)
|
||||
|
||||
entity_id = f"{DOMAIN}.test_media_player"
|
||||
attributes = {ATTR_SUPPORTED_FEATURES: MediaPlayerEntityFeature.VOLUME_MUTE}
|
||||
|
||||
hass.states.async_set(entity_id, STATE_PLAYING, attributes=attributes)
|
||||
calls = async_mock_service(hass, DOMAIN, SERVICE_VOLUME_MUTE)
|
||||
|
||||
response = await intent.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
media_player_intent.INTENT_PLAYER_MUTE,
|
||||
{},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert response.response_type == intent.IntentResponseType.ACTION_DONE
|
||||
assert len(calls) == 1
|
||||
call = calls[0]
|
||||
assert call.domain == DOMAIN
|
||||
assert call.service == SERVICE_VOLUME_MUTE
|
||||
assert call.data == {"entity_id": entity_id, "is_volume_muted": True}
|
||||
|
||||
# Test feature not supported
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_PLAYING,
|
||||
attributes={ATTR_SUPPORTED_FEATURES: MediaPlayerEntityFeature(0)},
|
||||
)
|
||||
|
||||
with pytest.raises(intent.MatchFailedError):
|
||||
response = await intent.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
media_player_intent.INTENT_PLAYER_MUTE,
|
||||
{},
|
||||
)
|
||||
|
||||
|
||||
async def test_media_player_unmute_intent(hass: HomeAssistant) -> None:
|
||||
"""Test HassMediaPlayerMute intent for media players."""
|
||||
await media_player_intent.async_setup_intents(hass)
|
||||
|
||||
entity_id = f"{DOMAIN}.test_media_player"
|
||||
attributes = {ATTR_SUPPORTED_FEATURES: MediaPlayerEntityFeature.VOLUME_MUTE}
|
||||
|
||||
hass.states.async_set(entity_id, STATE_PLAYING, attributes=attributes)
|
||||
calls = async_mock_service(hass, DOMAIN, SERVICE_VOLUME_MUTE)
|
||||
|
||||
response = await intent.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
media_player_intent.INTENT_PLAYER_UNMUTE,
|
||||
{},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert response.response_type == intent.IntentResponseType.ACTION_DONE
|
||||
assert len(calls) == 1
|
||||
call = calls[0]
|
||||
assert call.domain == DOMAIN
|
||||
assert call.service == SERVICE_VOLUME_MUTE
|
||||
assert call.data == {"entity_id": entity_id, "is_volume_muted": False}
|
||||
|
||||
# Test feature not supported
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_PLAYING,
|
||||
attributes={ATTR_SUPPORTED_FEATURES: MediaPlayerEntityFeature(0)},
|
||||
)
|
||||
|
||||
with pytest.raises(intent.MatchFailedError):
|
||||
response = await intent.async_handle(
|
||||
hass,
|
||||
"test",
|
||||
media_player_intent.INTENT_PLAYER_UNMUTE,
|
||||
{},
|
||||
)
|
||||
|
||||
|
||||
async def test_multiple_media_players(
|
||||
hass: HomeAssistant,
|
||||
area_registry: ar.AreaRegistry,
|
||||
|
||||
Reference in New Issue
Block a user