Add media_player.repeat_set service (#41435)
parent
a6393fb36c
commit
d00655810f
|
@ -4,12 +4,14 @@ from homeassistant.components.media_player.const import (
|
|||
MEDIA_TYPE_MOVIE,
|
||||
MEDIA_TYPE_MUSIC,
|
||||
MEDIA_TYPE_TVSHOW,
|
||||
REPEAT_MODE_OFF,
|
||||
SUPPORT_CLEAR_PLAYLIST,
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PAUSE,
|
||||
SUPPORT_PLAY,
|
||||
SUPPORT_PLAY_MEDIA,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_REPEAT_SET,
|
||||
SUPPORT_SEEK,
|
||||
SUPPORT_SELECT_SOUND_MODE,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
|
@ -73,6 +75,7 @@ MUSIC_PLAYER_SUPPORT = (
|
|||
| SUPPORT_CLEAR_PLAYLIST
|
||||
| SUPPORT_PLAY
|
||||
| SUPPORT_SHUFFLE_SET
|
||||
| SUPPORT_REPEAT_SET
|
||||
| SUPPORT_VOLUME_STEP
|
||||
| SUPPORT_PREVIOUS_TRACK
|
||||
| SUPPORT_NEXT_TRACK
|
||||
|
@ -319,6 +322,7 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
"""Initialize the demo device."""
|
||||
super().__init__("Walkman")
|
||||
self._cur_track = 0
|
||||
self._repeat = REPEAT_MODE_OFF
|
||||
|
||||
@property
|
||||
def media_content_id(self):
|
||||
|
@ -360,6 +364,11 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
"""Return the track number of current media (Music track only)."""
|
||||
return self._cur_track + 1
|
||||
|
||||
@property
|
||||
def repeat(self):
|
||||
"""Return current repeat mode."""
|
||||
return self._repeat
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
|
@ -384,6 +393,11 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
self._player_state = STATE_OFF
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def set_repeat(self, repeat):
|
||||
"""Enable/disable repeat mode."""
|
||||
self._repeat = repeat
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
|
||||
class DemoTVShowPlayer(AbstractDemoPlayer):
|
||||
"""A Demo media player that only supports YouTube."""
|
||||
|
|
|
@ -35,6 +35,7 @@ from homeassistant.const import (
|
|||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
SERVICE_MEDIA_SEEK,
|
||||
SERVICE_MEDIA_STOP,
|
||||
SERVICE_REPEAT_SET,
|
||||
SERVICE_SHUFFLE_SET,
|
||||
SERVICE_TOGGLE,
|
||||
SERVICE_TURN_OFF,
|
||||
|
@ -76,6 +77,7 @@ from .const import (
|
|||
ATTR_MEDIA_PLAYLIST,
|
||||
ATTR_MEDIA_POSITION,
|
||||
ATTR_MEDIA_POSITION_UPDATED_AT,
|
||||
ATTR_MEDIA_REPEAT,
|
||||
ATTR_MEDIA_SEASON,
|
||||
ATTR_MEDIA_SEEK_POSITION,
|
||||
ATTR_MEDIA_SERIES_TITLE,
|
||||
|
@ -88,6 +90,7 @@ from .const import (
|
|||
ATTR_SOUND_MODE_LIST,
|
||||
DOMAIN,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
REPEAT_MODES,
|
||||
SERVICE_CLEAR_PLAYLIST,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
SERVICE_SELECT_SOUND_MODE,
|
||||
|
@ -99,6 +102,7 @@ from .const import (
|
|||
SUPPORT_PLAY,
|
||||
SUPPORT_PLAY_MEDIA,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_REPEAT_SET,
|
||||
SUPPORT_SEEK,
|
||||
SUPPORT_SELECT_SOUND_MODE,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
|
@ -167,6 +171,7 @@ ATTR_TO_PROPERTY = [
|
|||
ATTR_INPUT_SOURCE,
|
||||
ATTR_SOUND_MODE,
|
||||
ATTR_MEDIA_SHUFFLE,
|
||||
ATTR_MEDIA_REPEAT,
|
||||
]
|
||||
|
||||
|
||||
|
@ -325,6 +330,13 @@ async def async_setup(hass, config):
|
|||
[SUPPORT_SHUFFLE_SET],
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_REPEAT_SET,
|
||||
{vol.Required(ATTR_MEDIA_REPEAT): vol.In(REPEAT_MODES)},
|
||||
"async_set_repeat",
|
||||
[SUPPORT_REPEAT_SET],
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -508,6 +520,11 @@ class MediaPlayerEntity(Entity):
|
|||
"""Boolean if shuffle is enabled."""
|
||||
return None
|
||||
|
||||
@property
|
||||
def repeat(self):
|
||||
"""Return current repeat mode."""
|
||||
return None
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
|
@ -635,6 +652,14 @@ class MediaPlayerEntity(Entity):
|
|||
"""Enable/disable shuffle mode."""
|
||||
await self.hass.async_add_executor_job(self.set_shuffle, shuffle)
|
||||
|
||||
def set_repeat(self, repeat):
|
||||
"""Set repeat mode."""
|
||||
raise NotImplementedError()
|
||||
|
||||
async def async_set_repeat(self, repeat):
|
||||
"""Set repeat mode."""
|
||||
await self.hass.async_add_job(self.set_repeat, repeat)
|
||||
|
||||
# No need to overwrite these.
|
||||
@property
|
||||
def support_play(self):
|
||||
|
|
|
@ -17,6 +17,7 @@ ATTR_MEDIA_EPISODE = "media_episode"
|
|||
ATTR_MEDIA_PLAYLIST = "media_playlist"
|
||||
ATTR_MEDIA_POSITION = "media_position"
|
||||
ATTR_MEDIA_POSITION_UPDATED_AT = "media_position_updated_at"
|
||||
ATTR_MEDIA_REPEAT = "repeat"
|
||||
ATTR_MEDIA_SEASON = "media_season"
|
||||
ATTR_MEDIA_SEEK_POSITION = "seek_position"
|
||||
ATTR_MEDIA_SERIES_TITLE = "media_series_title"
|
||||
|
@ -78,6 +79,11 @@ SERVICE_PLAY_MEDIA = "play_media"
|
|||
SERVICE_SELECT_SOUND_MODE = "select_sound_mode"
|
||||
SERVICE_SELECT_SOURCE = "select_source"
|
||||
|
||||
REPEAT_MODE_ALL = "all"
|
||||
REPEAT_MODE_OFF = "off"
|
||||
REPEAT_MODE_ONE = "one"
|
||||
REPEAT_MODES = [REPEAT_MODE_ALL, REPEAT_MODE_OFF, REPEAT_MODE_ONE]
|
||||
|
||||
SUPPORT_PAUSE = 1
|
||||
SUPPORT_SEEK = 2
|
||||
SUPPORT_VOLUME_SET = 4
|
||||
|
@ -96,3 +102,4 @@ SUPPORT_PLAY = 16384
|
|||
SUPPORT_SHUFFLE_SET = 32768
|
||||
SUPPORT_SELECT_SOUND_MODE = 65536
|
||||
SUPPORT_BROWSE_MEDIA = 131072
|
||||
SUPPORT_REPEAT_SET = 262144
|
||||
|
|
|
@ -156,3 +156,13 @@ shuffle_set:
|
|||
shuffle:
|
||||
description: True/false for enabling/disabling shuffle.
|
||||
example: true
|
||||
|
||||
repeat_set:
|
||||
description: Set repeat mode.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Name(s) of entities to set.
|
||||
example: "media_player.sonos"
|
||||
repeat:
|
||||
description: Repeat mode to set (off, all, one).
|
||||
example: "off"
|
||||
|
|
|
@ -532,6 +532,7 @@ SERVICE_MEDIA_STOP = "media_stop"
|
|||
SERVICE_MEDIA_NEXT_TRACK = "media_next_track"
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track"
|
||||
SERVICE_MEDIA_SEEK = "media_seek"
|
||||
SERVICE_REPEAT_SET = "repeat_set"
|
||||
SERVICE_SHUFFLE_SET = "shuffle_set"
|
||||
|
||||
SERVICE_ALARM_DISARM = "alarm_disarm"
|
||||
|
|
|
@ -60,6 +60,27 @@ async def test_source_select(hass):
|
|||
assert state.attributes.get(mp.ATTR_INPUT_SOURCE) == "xbox"
|
||||
|
||||
|
||||
async def test_repeat_set(hass):
|
||||
"""Test the repeat set service."""
|
||||
entity_id = "media_player.walkman"
|
||||
|
||||
assert await async_setup_component(
|
||||
hass, mp.DOMAIN, {"media_player": {"platform": "demo"}}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get(mp.ATTR_MEDIA_REPEAT) == mp.const.REPEAT_MODE_OFF
|
||||
|
||||
await hass.services.async_call(
|
||||
mp.DOMAIN,
|
||||
mp.SERVICE_REPEAT_SET,
|
||||
{ATTR_ENTITY_ID: entity_id, mp.ATTR_MEDIA_REPEAT: mp.const.REPEAT_MODE_ALL},
|
||||
blocking=True,
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.attributes.get(mp.ATTR_MEDIA_REPEAT) == mp.const.REPEAT_MODE_ALL
|
||||
|
||||
|
||||
async def test_clear_playlist(hass):
|
||||
"""Test clear playlist."""
|
||||
assert await async_setup_component(
|
||||
|
|
Loading…
Reference in New Issue