Add volume_step property to MediaPlayerEntity (#105574)
* Add volume_step property to MediaPlayerEntity * Improve tests * Address review comments
This commit is contained in:
parent
4e9b9add29
commit
4f9f548929
2 changed files with 61 additions and 6 deletions
|
@ -454,6 +454,7 @@ class MediaPlayerEntityDescription(EntityDescription):
|
|||
"""A class that describes media player entities."""
|
||||
|
||||
device_class: MediaPlayerDeviceClass | None = None
|
||||
volume_step: float | None = None
|
||||
|
||||
|
||||
class MediaPlayerEntity(Entity):
|
||||
|
@ -505,6 +506,7 @@ class MediaPlayerEntity(Entity):
|
|||
_attr_state: MediaPlayerState | None = None
|
||||
_attr_supported_features: MediaPlayerEntityFeature = MediaPlayerEntityFeature(0)
|
||||
_attr_volume_level: float | None = None
|
||||
_attr_volume_step: float
|
||||
|
||||
# Implement these for your media player
|
||||
@property
|
||||
|
@ -533,6 +535,18 @@ class MediaPlayerEntity(Entity):
|
|||
"""Volume level of the media player (0..1)."""
|
||||
return self._attr_volume_level
|
||||
|
||||
@property
|
||||
def volume_step(self) -> float:
|
||||
"""Return the step to be used by the volume_up and volume_down services."""
|
||||
if hasattr(self, "_attr_volume_step"):
|
||||
return self._attr_volume_step
|
||||
if (
|
||||
hasattr(self, "entity_description")
|
||||
and (volume_step := self.entity_description.volume_step) is not None
|
||||
):
|
||||
return volume_step
|
||||
return 0.1
|
||||
|
||||
@property
|
||||
def is_volume_muted(self) -> bool | None:
|
||||
"""Boolean if volume is currently muted."""
|
||||
|
@ -956,7 +970,9 @@ class MediaPlayerEntity(Entity):
|
|||
and self.volume_level < 1
|
||||
and self.supported_features & MediaPlayerEntityFeature.VOLUME_SET
|
||||
):
|
||||
await self.async_set_volume_level(min(1, self.volume_level + 0.1))
|
||||
await self.async_set_volume_level(
|
||||
min(1, self.volume_level + self.volume_step)
|
||||
)
|
||||
|
||||
async def async_volume_down(self) -> None:
|
||||
"""Turn volume down for media player.
|
||||
|
@ -972,7 +988,9 @@ class MediaPlayerEntity(Entity):
|
|||
and self.volume_level > 0
|
||||
and self.supported_features & MediaPlayerEntityFeature.VOLUME_SET
|
||||
):
|
||||
await self.async_set_volume_level(max(0, self.volume_level - 0.1))
|
||||
await self.async_set_volume_level(
|
||||
max(0, self.volume_level - self.volume_step)
|
||||
)
|
||||
|
||||
async def async_media_play_pause(self) -> None:
|
||||
"""Play or pause the media player."""
|
||||
|
|
|
@ -10,6 +10,7 @@ from homeassistant.const import (
|
|||
STATE_PLAYING,
|
||||
STATE_STANDBY,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
class ExtendedMediaPlayer(mp.MediaPlayerEntity):
|
||||
|
@ -148,28 +149,64 @@ class SimpleMediaPlayer(mp.MediaPlayerEntity):
|
|||
self._state = STATE_STANDBY
|
||||
|
||||
|
||||
class AttrMediaPlayer(SimpleMediaPlayer):
|
||||
"""Media player setting properties via _attr_*."""
|
||||
|
||||
_attr_volume_step = 0.2
|
||||
|
||||
|
||||
class DescrMediaPlayer(SimpleMediaPlayer):
|
||||
"""Media player setting properties via entity description."""
|
||||
|
||||
entity_description = mp.MediaPlayerEntityDescription(key="test", volume_step=0.3)
|
||||
|
||||
|
||||
@pytest.fixture(params=[ExtendedMediaPlayer, SimpleMediaPlayer])
|
||||
def player(hass, request):
|
||||
"""Return a media player."""
|
||||
return request.param(hass)
|
||||
|
||||
|
||||
async def test_volume_up(player) -> None:
|
||||
@pytest.mark.parametrize(
|
||||
("player_class", "volume_step"),
|
||||
[
|
||||
(ExtendedMediaPlayer, 0.1),
|
||||
(SimpleMediaPlayer, 0.1),
|
||||
(AttrMediaPlayer, 0.2),
|
||||
(DescrMediaPlayer, 0.3),
|
||||
],
|
||||
)
|
||||
async def test_volume_up(
|
||||
hass: HomeAssistant, player_class: type[mp.MediaPlayerEntity], volume_step: float
|
||||
) -> None:
|
||||
"""Test the volume_up and set volume methods."""
|
||||
player = player_class(hass)
|
||||
assert player.volume_level == 0
|
||||
await player.async_set_volume_level(0.5)
|
||||
assert player.volume_level == 0.5
|
||||
await player.async_volume_up()
|
||||
assert player.volume_level == 0.6
|
||||
assert player.volume_level == 0.5 + volume_step
|
||||
|
||||
|
||||
async def test_volume_down(player) -> None:
|
||||
@pytest.mark.parametrize(
|
||||
("player_class", "volume_step"),
|
||||
[
|
||||
(ExtendedMediaPlayer, 0.1),
|
||||
(SimpleMediaPlayer, 0.1),
|
||||
(AttrMediaPlayer, 0.2),
|
||||
(DescrMediaPlayer, 0.3),
|
||||
],
|
||||
)
|
||||
async def test_volume_down(
|
||||
hass: HomeAssistant, player_class: type[mp.MediaPlayerEntity], volume_step: float
|
||||
) -> None:
|
||||
"""Test the volume_down and set volume methods."""
|
||||
player = player_class(hass)
|
||||
assert player.volume_level == 0
|
||||
await player.async_set_volume_level(0.5)
|
||||
assert player.volume_level == 0.5
|
||||
await player.async_volume_down()
|
||||
assert player.volume_level == 0.4
|
||||
assert player.volume_level == 0.5 - volume_step
|
||||
|
||||
|
||||
async def test_media_play_pause(player) -> None:
|
||||
|
|
Loading…
Add table
Reference in a new issue