Add general sound mode support (#14729)

* Media player: general sound mode support

* General sound mode support

* White spaces

* Add sound mode support to demo media player

* white space

* remove unnessesary code
pull/14863/head
starkillerOG 2018-06-07 16:57:45 +02:00 committed by Paulus Schoutsen
parent 6b2b92a732
commit f696331563
3 changed files with 88 additions and 5 deletions

View File

@ -57,6 +57,7 @@ ENTITY_IMAGE_CACHE = {
SERVICE_PLAY_MEDIA = 'play_media'
SERVICE_SELECT_SOURCE = 'select_source'
SERVICE_SELECT_SOUND_MODE = 'select_sound_mode'
SERVICE_CLEAR_PLAYLIST = 'clear_playlist'
ATTR_MEDIA_VOLUME_LEVEL = 'volume_level'
@ -81,6 +82,8 @@ ATTR_APP_ID = 'app_id'
ATTR_APP_NAME = 'app_name'
ATTR_INPUT_SOURCE = 'source'
ATTR_INPUT_SOURCE_LIST = 'source_list'
ATTR_SOUND_MODE = 'sound_mode'
ATTR_SOUND_MODE_LIST = 'sound_mode_list'
ATTR_MEDIA_ENQUEUE = 'enqueue'
ATTR_MEDIA_SHUFFLE = 'shuffle'
@ -109,6 +112,7 @@ SUPPORT_STOP = 4096
SUPPORT_CLEAR_PLAYLIST = 8192
SUPPORT_PLAY = 16384
SUPPORT_SHUFFLE_SET = 32768
SUPPORT_SELECT_SOUND_MODE = 65536
# Service call validation schemas
MEDIA_PLAYER_SCHEMA = vol.Schema({
@ -132,6 +136,10 @@ MEDIA_PLAYER_SELECT_SOURCE_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_INPUT_SOURCE): cv.string,
})
MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_SOUND_MODE): cv.string,
})
MEDIA_PLAYER_PLAY_MEDIA_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_MEDIA_CONTENT_TYPE): cv.string,
vol.Required(ATTR_MEDIA_CONTENT_ID): cv.string,
@ -167,6 +175,9 @@ SERVICE_TO_METHOD = {
SERVICE_SELECT_SOURCE: {
'method': 'async_select_source',
'schema': MEDIA_PLAYER_SELECT_SOURCE_SCHEMA},
SERVICE_SELECT_SOUND_MODE: {
'method': 'async_select_sound_mode',
'schema': MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA},
SERVICE_PLAY_MEDIA: {
'method': 'async_play_media',
'schema': MEDIA_PLAYER_PLAY_MEDIA_SCHEMA},
@ -197,6 +208,8 @@ ATTR_TO_PROPERTY = [
ATTR_APP_NAME,
ATTR_INPUT_SOURCE,
ATTR_INPUT_SOURCE_LIST,
ATTR_SOUND_MODE,
ATTR_SOUND_MODE_LIST,
ATTR_MEDIA_SHUFFLE,
]
@ -346,6 +359,17 @@ def select_source(hass, source, entity_id=None):
hass.services.call(DOMAIN, SERVICE_SELECT_SOURCE, data)
@bind_hass
def select_sound_mode(hass, sound_mode, entity_id=None):
"""Send the media player the command to select sound mode."""
data = {ATTR_SOUND_MODE: sound_mode}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_SELECT_SOUND_MODE, data)
@bind_hass
def clear_playlist(hass, entity_id=None):
"""Send the media player the command for clear playlist."""
@ -399,6 +423,8 @@ async def async_setup(hass, config):
params['position'] = service.data.get(ATTR_MEDIA_SEEK_POSITION)
elif service.service == SERVICE_SELECT_SOURCE:
params['source'] = service.data.get(ATTR_INPUT_SOURCE)
elif service.service == SERVICE_SELECT_SOUND_MODE:
params['sound_mode'] = service.data.get(ATTR_SOUND_MODE)
elif service.service == SERVICE_PLAY_MEDIA:
params['media_type'] = \
service.data.get(ATTR_MEDIA_CONTENT_TYPE)
@ -580,6 +606,16 @@ class MediaPlayerDevice(Entity):
"""List of available input sources."""
return None
@property
def sound_mode(self):
"""Name of the current sound mode."""
return None
@property
def sound_mode_list(self):
"""List of available sound modes."""
return None
@property
def shuffle(self):
"""Boolean if shuffle is enabled."""
@ -723,6 +759,17 @@ class MediaPlayerDevice(Entity):
"""
return self.hass.async_add_job(self.select_source, source)
def select_sound_mode(self, sound_mode):
"""Select sound mode."""
raise NotImplementedError()
def async_select_sound_mode(self, sound_mode):
"""Select sound mode.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.async_add_job(self.select_sound_mode, sound_mode)
def clear_playlist(self):
"""Clear players playlist."""
raise NotImplementedError()
@ -796,6 +843,11 @@ class MediaPlayerDevice(Entity):
"""Boolean if select source command supported."""
return bool(self.supported_features & SUPPORT_SELECT_SOURCE)
@property
def support_select_sound_mode(self):
"""Boolean if select sound mode command supported."""
return bool(self.supported_features & SUPPORT_SELECT_SOUND_MODE)
@property
def support_clear_playlist(self):
"""Boolean if clear playlist command supported."""

View File

@ -8,8 +8,8 @@ from homeassistant.components.media_player import (
MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_MOVIE, SUPPORT_NEXT_TRACK,
SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK,
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET,
SUPPORT_SELECT_SOURCE, SUPPORT_CLEAR_PLAYLIST, SUPPORT_PLAY,
SUPPORT_SHUFFLE_SET, MediaPlayerDevice)
SUPPORT_SELECT_SOURCE, SUPPORT_SELECT_SOUND_MODE, SUPPORT_CLEAR_PLAYLIST,
SUPPORT_PLAY, SUPPORT_SHUFFLE_SET, MediaPlayerDevice)
from homeassistant.const import STATE_OFF, STATE_PAUSED, STATE_PLAYING
import homeassistant.util.dt as dt_util
@ -28,22 +28,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
YOUTUBE_COVER_URL_FORMAT = 'https://img.youtube.com/vi/{}/hqdefault.jpg'
SOUND_MODE_LIST = ['Dummy Music', 'Dummy Movie']
DEFAULT_SOUND_MODE = 'Dummy Music'
YOUTUBE_PLAYER_SUPPORT = \
SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PLAY_MEDIA | SUPPORT_PLAY | \
SUPPORT_SHUFFLE_SET
SUPPORT_SHUFFLE_SET | SUPPORT_SELECT_SOUND_MODE
MUSIC_PLAYER_SUPPORT = \
SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_CLEAR_PLAYLIST | \
SUPPORT_PLAY | SUPPORT_SHUFFLE_SET | \
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
SUPPORT_SELECT_SOUND_MODE
NETFLIX_PLAYER_SUPPORT = \
SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \
SUPPORT_SELECT_SOURCE | SUPPORT_PLAY | SUPPORT_SHUFFLE_SET | \
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
SUPPORT_SELECT_SOUND_MODE
class AbstractDemoPlayer(MediaPlayerDevice):
@ -58,6 +62,8 @@ class AbstractDemoPlayer(MediaPlayerDevice):
self._volume_level = 1.0
self._volume_muted = False
self._shuffle = False
self._sound_mode_list = SOUND_MODE_LIST
self._sound_mode = DEFAULT_SOUND_MODE
@property
def should_poll(self):
@ -89,6 +95,16 @@ class AbstractDemoPlayer(MediaPlayerDevice):
"""Boolean if shuffling is enabled."""
return self._shuffle
@property
def sound_mode(self):
"""Return the current sound mode."""
return self._sound_mode
@property
def sound_mode_list(self):
"""Return a list of available sound modes."""
return self._sound_mode_list
def turn_on(self):
"""Turn the media player on."""
self._player_state = STATE_PLAYING
@ -124,6 +140,11 @@ class AbstractDemoPlayer(MediaPlayerDevice):
self._shuffle = shuffle
self.schedule_update_ha_state()
def select_sound_mode(self, sound_mode):
"""Select sound mode."""
self._sound_mode = sound_mode
self.schedule_update_ha_state()
class DemoYoutubePlayer(AbstractDemoPlayer):
"""A Demo media player that only supports YouTube."""

View File

@ -144,6 +144,16 @@ select_source:
description: Name of the source to switch to. Platform dependent.
example: 'video1'
select_sound_mode:
description: Send the media player the command to change sound mode.
fields:
entity_id:
description: Name(s) of entities to change sound mode on.
example: 'media_player.marantz'
sound_mode:
description: Name of the sound mode to switch to.
example: 'Music'
clear_playlist:
description: Send the media player the command to clear players playlist.
fields: