Cleanup media_player universal platform / blocking platform. (#5671)

* Cleanup media_player universal platform / blocking platform.

* fix comments

* fix unittest

* fix lint

* fix unittest lint

* fix coro

* fix test

* fix tests part 2
This commit is contained in:
Pascal Vizeli 2017-02-02 06:45:19 +01:00 committed by Paulus Schoutsen
parent 10a104271e
commit eefb603f17
5 changed files with 299 additions and 181 deletions

View file

@ -311,13 +311,13 @@ class GPMDP(MediaPlayerDevice):
"""Send media_play command to media player."""
self.send_gpmdp_msg('playback', 'playPause', False)
self._status = STATE_PLAYING
self.update_ha_state()
self.schedule_update_ha_state()
def media_pause(self):
"""Send media_pause command to media player."""
self.send_gpmdp_msg('playback', 'playPause', False)
self._status = STATE_PAUSED
self.update_ha_state()
self.schedule_update_ha_state()
def media_seek(self, position):
"""Send media_seek command to media player."""
@ -327,7 +327,7 @@ class GPMDP(MediaPlayerDevice):
websocket.send(json.dumps({'namespace': 'playback',
'method': 'setCurrentTime',
'arguments': [position*1000]}))
self.update_ha_state()
self.schedule_update_ha_state()
def volume_up(self):
"""Send volume_up command to media player."""
@ -335,7 +335,7 @@ class GPMDP(MediaPlayerDevice):
if websocket is None:
return
websocket.send('{"namespace": "volume", "method": "increaseVolume"}')
self.update_ha_state()
self.schedule_update_ha_state()
def volume_down(self):
"""Send volume_down command to media player."""
@ -343,7 +343,7 @@ class GPMDP(MediaPlayerDevice):
if websocket is None:
return
websocket.send('{"namespace": "volume", "method": "decreaseVolume"}')
self.update_ha_state()
self.schedule_update_ha_state()
def set_volume_level(self, volume):
"""Set volume on media player, range(0..1)."""
@ -353,4 +353,4 @@ class GPMDP(MediaPlayerDevice):
websocket.send(json.dumps({'namespace': 'volume',
'method': 'setVolume',
'arguments': [volume*100]}))
self.update_ha_state()
self.schedule_update_ha_state()

View file

@ -438,13 +438,13 @@ class AirPlayDevice(MediaPlayerDevice):
def turn_on(self):
"""Select AirPlay."""
self.update_state({"selected": True})
self.update_ha_state()
self.schedule_update_ha_state()
response = self.client.toggle_airplay_device(self._id, True)
self.update_state(response)
def turn_off(self):
"""Deselect AirPlay."""
self.update_state({"selected": False})
self.update_ha_state()
self.schedule_update_ha_state()
response = self.client.toggle_airplay_device(self._id, False)
self.update_state(response)

View file

@ -201,10 +201,6 @@ class SqueezeBoxDevice(MediaPlayerDevice):
return self._lms.async_query(
*parameters, player=self._id)
def query(self, *parameters):
"""Queue up a command to send the LMS."""
self.hass.loop.create_task(self.async_query(*parameters))
@asyncio.coroutine
def async_update(self):
"""Retrieve the current state of the player."""
@ -310,85 +306,108 @@ class SqueezeBoxDevice(MediaPlayerDevice):
"""Flag of media commands that are supported."""
return SUPPORT_SQUEEZEBOX
def turn_off(self):
"""Turn off media player."""
self.query('power', '0')
self.update_ha_state()
def async_turn_off(self):
"""Turn off media player.
def volume_up(self):
"""Volume up media player."""
self.query('mixer', 'volume', '+5')
self.update_ha_state()
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('power', '0')
def volume_down(self):
"""Volume down media player."""
self.query('mixer', 'volume', '-5')
self.update_ha_state()
def async_volume_up(self):
"""Volume up media player.
def set_volume_level(self, volume):
"""Set volume level, range 0..1."""
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('mixer', 'volume', '+5')
def async_volume_down(self):
"""Volume down media player.
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('mixer', 'volume', '-5')
def async_set_volume_level(self, volume):
"""Set volume level, range 0..1.
This method must be run in the event loop and returns a coroutine.
"""
volume_percent = str(int(volume*100))
self.query('mixer', 'volume', volume_percent)
self.update_ha_state()
return self.async_query('mixer', 'volume', volume_percent)
def mute_volume(self, mute):
"""Mute (true) or unmute (false) media player."""
def async_mute_volume(self, mute):
"""Mute (true) or unmute (false) media player.
This method must be run in the event loop and returns a coroutine.
"""
mute_numeric = '1' if mute else '0'
self.query('mixer', 'muting', mute_numeric)
self.update_ha_state()
return self.async_query('mixer', 'muting', mute_numeric)
def media_play_pause(self):
"""Send pause command to media player."""
self.query('pause')
self.update_ha_state()
def async_media_play_pause(self):
"""Send pause command to media player.
def media_play(self):
"""Send play command to media player."""
self.query('play')
self.update_ha_state()
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('pause')
def media_pause(self):
"""Send pause command to media player."""
self.query('pause', '1')
self.update_ha_state()
def async_media_play(self):
"""Send play command to media player.
def media_next_track(self):
"""Send next track command."""
self.query('playlist', 'index', '+1')
self.update_ha_state()
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('play')
def media_previous_track(self):
"""Send next track command."""
self.query('playlist', 'index', '-1')
self.update_ha_state()
def async_media_pause(self):
"""Send pause command to media player.
def media_seek(self, position):
"""Send seek command."""
self.query('time', position)
self.update_ha_state()
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('pause', '1')
def turn_on(self):
"""Turn the media player on."""
self.query('power', '1')
self.update_ha_state()
def async_media_next_track(self):
"""Send next track command.
def play_media(self, media_type, media_id, **kwargs):
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('playlist', 'index', '+1')
def async_media_previous_track(self):
"""Send next track command.
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('playlist', 'index', '-1')
def async_media_seek(self, position):
"""Send seek command.
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('time', position)
def async_turn_on(self):
"""Turn the media player on.
This method must be run in the event loop and returns a coroutine.
"""
return self.async_query('power', '1')
def async_play_media(self, media_type, media_id, **kwargs):
"""
Send the play_media command to the media player.
If ATTR_MEDIA_ENQUEUE is True, add `media_id` to the current playlist.
This method must be run in the event loop and returns a coroutine.
"""
if kwargs.get(ATTR_MEDIA_ENQUEUE):
self._add_uri_to_playlist(media_id)
else:
self._play_uri(media_id)
return self._add_uri_to_playlist(media_id)
return self._play_uri(media_id)
def _play_uri(self, media_id):
"""Replace the current play list with the uri."""
self.query('playlist', 'play', media_id)
self.update_ha_state()
return self.async_query('playlist', 'play', media_id)
def _add_uri_to_playlist(self, media_id):
"""Add a items to the existing playlist."""
self.query('playlist', 'add', media_id)
self.update_ha_state()
return self.async_query('playlist', 'add', media_id)

View file

@ -4,10 +4,12 @@ Combination of multiple media players into one for a universal controller.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.universal/
"""
import asyncio
import logging
# pylint: disable=import-error
from copy import copy
from homeassistant.core import callback
from homeassistant.components.media_player import (
ATTR_APP_ID, ATTR_APP_NAME, ATTR_MEDIA_ALBUM_ARTIST, ATTR_MEDIA_ALBUM_NAME,
ATTR_MEDIA_ARTIST, ATTR_MEDIA_CHANNEL, ATTR_MEDIA_CONTENT_ID,
@ -28,8 +30,8 @@ from homeassistant.const import (
SERVICE_TURN_ON, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_SET, SERVICE_VOLUME_UP, STATE_IDLE, STATE_OFF, STATE_ON,
SERVICE_MEDIA_STOP)
from homeassistant.helpers.event import track_state_change
from homeassistant.helpers.service import call_from_config
from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers.service import async_call_from_config
ATTR_ACTIVE_CHILD = 'active_child'
@ -47,18 +49,21 @@ REQUIREMENTS = []
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the universal media players."""
if not validate_config(config):
return
player = UniversalMediaPlayer(hass,
player = UniversalMediaPlayer(
hass,
config[CONF_NAME],
config[CONF_CHILDREN],
config[CONF_COMMANDS],
config[CONF_ATTRS])
config[CONF_ATTRS]
)
add_devices([player])
yield from async_add_devices([player])
def validate_config(config):
@ -143,15 +148,16 @@ class UniversalMediaPlayer(MediaPlayerDevice):
self._attrs = attributes
self._child_state = None
def on_dependency_update(*_):
@callback
def async_on_dependency_update(*_):
"""Update ha state when dependencies update."""
self.update_ha_state(True)
self.hass.add_job(self.async_update_ha_state(True))
depend = copy(children)
for entity in attributes.values():
depend.append(entity[0])
track_state_change(hass, depend, on_dependency_update)
async_track_state_change(hass, depend, async_on_dependency_update)
def _entity_lkp(self, entity_id, state_attr=None):
"""Look up an entity state."""
@ -177,14 +183,15 @@ class UniversalMediaPlayer(MediaPlayerDevice):
active_child = self._child_state
return active_child.attributes.get(attr_name) if active_child else None
def _call_service(self, service_name, service_data=None,
@asyncio.coroutine
def _async_call_service(self, service_name, service_data=None,
allow_override=False):
"""Call either a specified or active child's service."""
if service_data is None:
service_data = {}
if allow_override and service_name in self._cmds:
call_from_config(
yield from async_call_from_config(
self.hass, self._cmds[service_name],
variables=service_data, blocking=True)
return
@ -196,8 +203,8 @@ class UniversalMediaPlayer(MediaPlayerDevice):
service_data[ATTR_ENTITY_ID] = active_child.entity_id
self.hass.services.call(DOMAIN, service_name, service_data,
blocking=True)
yield from self.hass.services.async_call(
DOMAIN, service_name, service_data, blocking=True)
@property
def should_poll(self):
@ -395,77 +402,130 @@ class UniversalMediaPlayer(MediaPlayerDevice):
"""When was the position of the current playing media valid."""
return self._child_attr(ATTR_MEDIA_POSITION_UPDATED_AT)
def turn_on(self):
"""Turn the media player on."""
self._call_service(SERVICE_TURN_ON, allow_override=True)
def async_turn_on(self):
"""Turn the media player on.
def turn_off(self):
"""Turn the media player off."""
self._call_service(SERVICE_TURN_OFF, allow_override=True)
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_TURN_ON, allow_override=True)
def mute_volume(self, is_volume_muted):
"""Mute the volume."""
def async_turn_off(self):
"""Turn the media player off.
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_TURN_OFF, allow_override=True)
def async_mute_volume(self, is_volume_muted):
"""Mute the volume.
This method must be run in the event loop and returns a coroutine.
"""
data = {ATTR_MEDIA_VOLUME_MUTED: is_volume_muted}
self._call_service(SERVICE_VOLUME_MUTE, data, allow_override=True)
return self._async_call_service(
SERVICE_VOLUME_MUTE, data, allow_override=True)
def set_volume_level(self, volume_level):
"""Set volume level, range 0..1."""
def async_set_volume_level(self, volume_level):
"""Set volume level, range 0..1.
This method must be run in the event loop and returns a coroutine.
"""
data = {ATTR_MEDIA_VOLUME_LEVEL: volume_level}
self._call_service(SERVICE_VOLUME_SET, data, allow_override=True)
return self._async_call_service(
SERVICE_VOLUME_SET, data, allow_override=True)
def media_play(self):
"""Send play commmand."""
self._call_service(SERVICE_MEDIA_PLAY)
def async_media_play(self):
"""Send play commmand.
def media_pause(self):
"""Send pause command."""
self._call_service(SERVICE_MEDIA_PAUSE)
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_PLAY)
def media_stop(self):
"""Send stop command."""
self._call_service(SERVICE_MEDIA_STOP)
def async_media_pause(self):
"""Send pause command.
def media_previous_track(self):
"""Send previous track command."""
self._call_service(SERVICE_MEDIA_PREVIOUS_TRACK)
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_PAUSE)
def media_next_track(self):
"""Send next track command."""
self._call_service(SERVICE_MEDIA_NEXT_TRACK)
def async_media_stop(self):
"""Send stop command.
def media_seek(self, position):
"""Send seek command."""
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_STOP)
def async_media_previous_track(self):
"""Send previous track command.
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_PREVIOUS_TRACK)
def async_media_next_track(self):
"""Send next track command.
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_NEXT_TRACK)
def async_media_seek(self, position):
"""Send seek command.
This method must be run in the event loop and returns a coroutine.
"""
data = {ATTR_MEDIA_SEEK_POSITION: position}
self._call_service(SERVICE_MEDIA_SEEK, data)
return self._async_call_service(SERVICE_MEDIA_SEEK, data)
def play_media(self, media_type, media_id, **kwargs):
"""Play a piece of media."""
def async_play_media(self, media_type, media_id, **kwargs):
"""Play a piece of media.
This method must be run in the event loop and returns a coroutine.
"""
data = {ATTR_MEDIA_CONTENT_TYPE: media_type,
ATTR_MEDIA_CONTENT_ID: media_id}
self._call_service(SERVICE_PLAY_MEDIA, data)
return self._async_call_service(SERVICE_PLAY_MEDIA, data)
def volume_up(self):
"""Turn volume up for media player."""
self._call_service(SERVICE_VOLUME_UP, allow_override=True)
def async_volume_up(self):
"""Turn volume up for media player.
def volume_down(self):
"""Turn volume down for media player."""
self._call_service(SERVICE_VOLUME_DOWN, allow_override=True)
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_VOLUME_UP, allow_override=True)
def media_play_pause(self):
"""Play or pause the media player."""
self._call_service(SERVICE_MEDIA_PLAY_PAUSE)
def async_volume_down(self):
"""Turn volume down for media player.
def select_source(self, source):
"""Set the input source."""
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(
SERVICE_VOLUME_DOWN, allow_override=True)
def async_media_play_pause(self):
"""Play or pause the media player.
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_MEDIA_PLAY_PAUSE)
def async_select_source(self, source):
"""Set the input source.
This method must be run in the event loop and returns a coroutine.
"""
data = {ATTR_INPUT_SOURCE: source}
self._call_service(SERVICE_SELECT_SOURCE, data, allow_override=True)
return self._async_call_service(
SERVICE_SELECT_SOURCE, data, allow_override=True)
def clear_playlist(self):
"""Clear players playlist."""
self._call_service(SERVICE_CLEAR_PLAYLIST)
def async_clear_playlist(self):
"""Clear players playlist.
def update(self):
This method must be run in the event loop and returns a coroutine.
"""
return self._async_call_service(SERVICE_CLEAR_PLAYLIST)
@asyncio.coroutine
def async_update(self):
"""Update state in HA."""
for child_name in self._children:
child_state = self.hass.states.get(child_name)

View file

@ -1,4 +1,5 @@
"""The tests for the Universal Media player platform."""
import asyncio
from copy import copy
import unittest
@ -9,6 +10,7 @@ import homeassistant.components.input_slider as input_slider
import homeassistant.components.input_select as input_select
import homeassistant.components.media_player as media_player
import homeassistant.components.media_player.universal as universal
from homeassistant.util.async import run_coroutine_threadsafe
from tests.common import mock_service, get_test_home_assistant
@ -256,15 +258,20 @@ class TestMediaPlayer(unittest.TestCase):
bad_config = {'platform': 'universal'}
entities = []
@asyncio.coroutine
def add_devices(new_entities):
"""Add devices to list."""
for dev in new_entities:
entities.append(dev)
universal.setup_platform(self.hass, bad_config, add_devices)
run_coroutine_threadsafe(
universal.async_setup_platform(self.hass, bad_config, add_devices),
self.hass.loop).result()
self.assertEqual(0, len(entities))
universal.setup_platform(self.hass, config, add_devices)
run_coroutine_threadsafe(
universal.async_setup_platform(self.hass, config, add_devices),
self.hass.loop).result()
self.assertEqual(1, len(entities))
self.assertEqual('test', entities[0].name)
@ -305,25 +312,25 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(None, ump._child_state)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(self.mock_mp_1.entity_id,
ump._child_state.entity_id)
self.mock_mp_2._state = STATE_PLAYING
self.mock_mp_2.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(self.mock_mp_1.entity_id,
ump._child_state.entity_id)
self.mock_mp_1._state = STATE_OFF
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(self.mock_mp_2.entity_id,
ump._child_state.entity_id)
@ -352,13 +359,13 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertTrue(ump.state, STATE_OFF)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(STATE_PLAYING, ump.state)
def test_state_with_children_and_attrs(self):
@ -368,21 +375,21 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(STATE_OFF, ump.state)
self.hass.states.set(self.mock_state_switch_id, STATE_ON)
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(STATE_ON, ump.state)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(STATE_PLAYING, ump.state)
self.hass.states.set(self.mock_state_switch_id, STATE_OFF)
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(STATE_OFF, ump.state)
def test_volume_level(self):
@ -392,18 +399,18 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(None, ump.volume_level)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(0, ump.volume_level)
self.mock_mp_1._volume_level = 1
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(1, ump.volume_level)
def test_media_image_url(self):
@ -414,14 +421,14 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(None, ump.media_image_url)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1._media_image_url = TEST_URL
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
# mock_mp_1 will convert the url to the api proxy url. This test
# ensures ump passes through the same url without an additional proxy.
self.assertEqual(self.mock_mp_1.entity_picture, ump.entity_picture)
@ -433,18 +440,18 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertFalse(ump.is_volume_muted)
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertFalse(ump.is_volume_muted)
self.mock_mp_1._is_volume_muted = True
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertTrue(ump.is_volume_muted)
def test_source_list_children_and_attr(self):
@ -502,14 +509,14 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(0, ump.supported_media_commands)
self.mock_mp_1._supported_media_commands = 512
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.assertEqual(512, ump.supported_media_commands)
def test_supported_media_commands_children_and_cmds(self):
@ -526,11 +533,11 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.mock_mp_1._state = STATE_PLAYING
self.mock_mp_1.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
check_flags = universal.SUPPORT_TURN_ON | universal.SUPPORT_TURN_OFF \
| universal.SUPPORT_VOLUME_STEP | universal.SUPPORT_VOLUME_MUTE \
@ -545,15 +552,17 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.mock_mp_1._state = STATE_OFF
self.mock_mp_1.update_ha_state()
self.mock_mp_2._state = STATE_OFF
self.mock_mp_2.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
ump.turn_off()
run_coroutine_threadsafe(
ump.async_turn_off(),
self.hass.loop).result()
self.assertEqual(0, len(self.mock_mp_1.service_calls['turn_off']))
self.assertEqual(0, len(self.mock_mp_2.service_calls['turn_off']))
@ -564,60 +573,90 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.mock_mp_2._state = STATE_PLAYING
self.mock_mp_2.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
ump.turn_off()
run_coroutine_threadsafe(
ump.async_turn_off(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['turn_off']))
ump.turn_on()
run_coroutine_threadsafe(
ump.async_turn_on(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['turn_on']))
ump.mute_volume(True)
run_coroutine_threadsafe(
ump.async_mute_volume(True),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['mute_volume']))
ump.set_volume_level(0.5)
run_coroutine_threadsafe(
ump.async_set_volume_level(0.5),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['set_volume_level']))
ump.media_play()
run_coroutine_threadsafe(
ump.async_media_play(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_play']))
ump.media_pause()
run_coroutine_threadsafe(
ump.async_media_pause(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_pause']))
ump.media_previous_track()
run_coroutine_threadsafe(
ump.async_media_previous_track(),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['media_previous_track']))
ump.media_next_track()
run_coroutine_threadsafe(
ump.async_media_next_track(),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['media_next_track']))
ump.media_seek(100)
run_coroutine_threadsafe(
ump.async_media_seek(100),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_seek']))
ump.play_media('movie', 'batman')
run_coroutine_threadsafe(
ump.async_play_media('movie', 'batman'),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['play_media']))
ump.volume_up()
run_coroutine_threadsafe(
ump.async_volume_up(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['volume_up']))
ump.volume_down()
run_coroutine_threadsafe(
ump.async_volume_down(),
self.hass.loop).result()
self.assertEqual(1, len(self.mock_mp_2.service_calls['volume_down']))
ump.media_play_pause()
run_coroutine_threadsafe(
ump.async_media_play_pause(),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['media_play_pause']))
ump.select_source('dvd')
run_coroutine_threadsafe(
ump.async_select_source('dvd'),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['select_source']))
ump.clear_playlist()
run_coroutine_threadsafe(
ump.async_clear_playlist(),
self.hass.loop).result()
self.assertEqual(
1, len(self.mock_mp_2.service_calls['clear_playlist']))
@ -632,11 +671,11 @@ class TestMediaPlayer(unittest.TestCase):
ump = universal.UniversalMediaPlayer(self.hass, **config)
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
self.mock_mp_2._state = STATE_PLAYING
self.mock_mp_2.update_ha_state()
ump.update()
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
ump.turn_off()
run_coroutine_threadsafe(ump.async_turn_off(), self.hass.loop).result()
self.assertEqual(1, len(service))