diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py index c98b32137c7..1678547bee7 100644 --- a/homeassistant/components/media_player/gpmdp.py +++ b/homeassistant/components/media_player/gpmdp.py @@ -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() diff --git a/homeassistant/components/media_player/itunes.py b/homeassistant/components/media_player/itunes.py index 4dc41c7e085..c208990cb67 100644 --- a/homeassistant/components/media_player/itunes.py +++ b/homeassistant/components/media_player/itunes.py @@ -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) diff --git a/homeassistant/components/media_player/squeezebox.py b/homeassistant/components/media_player/squeezebox.py index 852ce522559..65a543781aa 100644 --- a/homeassistant/components/media_player/squeezebox.py +++ b/homeassistant/components/media_player/squeezebox.py @@ -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) diff --git a/homeassistant/components/media_player/universal.py b/homeassistant/components/media_player/universal.py index e01717f5693..f1bd61fd007 100644 --- a/homeassistant/components/media_player/universal.py +++ b/homeassistant/components/media_player/universal.py @@ -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, - config[CONF_NAME], - config[CONF_CHILDREN], - config[CONF_COMMANDS], - config[CONF_ATTRS]) + player = UniversalMediaPlayer( + hass, + config[CONF_NAME], + config[CONF_CHILDREN], + config[CONF_COMMANDS], + 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, - allow_override=False): + @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) diff --git a/tests/components/media_player/test_universal.py b/tests/components/media_player/test_universal.py index 4a06d989ce2..76fca3fb6ed 100644 --- a/tests/components/media_player/test_universal.py +++ b/tests/components/media_player/test_universal.py @@ -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))