1
0
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:
anishsane
2025-10-01 01:07:19 +05:30
committed by GitHub
parent 1ca701dda4
commit 6d940f476a
2 changed files with 125 additions and 0 deletions
@@ -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,