Add media_player.repeat_set service (#41435)

pull/41736/head
Anders Melchiorsen 2020-10-12 23:29:28 +02:00 committed by GitHub
parent a6393fb36c
commit d00655810f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 0 deletions

View File

@ -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."""

View File

@ -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):

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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(