From 533d0e44440cd106bdf649571336a0f2458fbfa2 Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Sat, 15 Jan 2022 01:49:33 -0600 Subject: [PATCH] Add play media URL support to roku (#64021) --- homeassistant/components/roku/const.py | 1 + homeassistant/components/roku/media_player.py | 23 +++++++++++++--- tests/components/roku/test_media_player.py | 27 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roku/const.py b/homeassistant/components/roku/const.py index eb2d5040b50..e399f6e0558 100644 --- a/homeassistant/components/roku/const.py +++ b/homeassistant/components/roku/const.py @@ -3,6 +3,7 @@ DOMAIN = "roku" # Attributes ATTR_CONTENT_ID = "content_id" +ATTR_FORMAT = "format" ATTR_KEYWORD = "keyword" ATTR_MEDIA_TYPE = "media_type" diff --git a/homeassistant/components/roku/media_player.py b/homeassistant/components/roku/media_player.py index 570d5456d5d..0cb03869cf8 100644 --- a/homeassistant/components/roku/media_player.py +++ b/homeassistant/components/roku/media_player.py @@ -16,6 +16,7 @@ from homeassistant.components.media_player.const import ( ATTR_MEDIA_EXTRA, MEDIA_TYPE_APP, MEDIA_TYPE_CHANNEL, + MEDIA_TYPE_URL, SUPPORT_BROWSE_MEDIA, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, @@ -31,6 +32,7 @@ from homeassistant.components.media_player.const import ( from homeassistant.components.media_player.errors import BrowseError from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( + ATTR_NAME, STATE_HOME, STATE_IDLE, STATE_ON, @@ -47,6 +49,7 @@ from . import roku_exception_handler from .browse_media import build_item_response, library_payload from .const import ( ATTR_CONTENT_ID, + ATTR_FORMAT, ATTR_KEYWORD, ATTR_MEDIA_TYPE, DOMAIN, @@ -76,6 +79,11 @@ ATTRS_TO_LAUNCH_PARAMS = { ATTR_MEDIA_TYPE: "MediaType", } +ATTRS_TO_PLAY_VIDEO_PARAMS = { + ATTR_NAME: "videoName", + ATTR_FORMAT: "videoFormat", +} + SEARCH_SCHEMA = {vol.Required(ATTR_KEYWORD): str} @@ -367,25 +375,34 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity): """Tune to channel.""" extra: dict[str, Any] = kwargs.get(ATTR_MEDIA_EXTRA) or {} - if media_type not in (MEDIA_TYPE_APP, MEDIA_TYPE_CHANNEL): + if media_type not in (MEDIA_TYPE_APP, MEDIA_TYPE_CHANNEL, MEDIA_TYPE_URL): _LOGGER.error( - "Invalid media type %s. Only %s and %s are supported", + "Invalid media type %s. Only %s, %s and %s are supported", media_type, MEDIA_TYPE_APP, MEDIA_TYPE_CHANNEL, + MEDIA_TYPE_URL, ) return if media_type == MEDIA_TYPE_APP: params = { param: extra[attr] - for (attr, param) in ATTRS_TO_LAUNCH_PARAMS.items() + for attr, param in ATTRS_TO_LAUNCH_PARAMS.items() if attr in extra } await self.coordinator.roku.launch(media_id, params) elif media_type == MEDIA_TYPE_CHANNEL: await self.coordinator.roku.tune(media_id) + elif media_type == MEDIA_TYPE_URL: + params = { + param: extra[attr] + for (attr, param) in ATTRS_TO_PLAY_VIDEO_PARAMS.items() + if attr in extra + } + + await self.coordinator.roku.play_video(media_id, params) await self.coordinator.async_request_refresh() diff --git a/tests/components/roku/test_media_player.py b/tests/components/roku/test_media_player.py index d0e0388dde1..4da59050b08 100644 --- a/tests/components/roku/test_media_player.py +++ b/tests/components/roku/test_media_player.py @@ -25,6 +25,7 @@ from homeassistant.components.media_player.const import ( MEDIA_TYPE_APPS, MEDIA_TYPE_CHANNEL, MEDIA_TYPE_CHANNELS, + MEDIA_TYPE_URL, SERVICE_PLAY_MEDIA, SERVICE_SELECT_SOURCE, SUPPORT_BROWSE_MEDIA, @@ -41,6 +42,7 @@ from homeassistant.components.media_player.const import ( ) from homeassistant.components.roku.const import ( ATTR_CONTENT_ID, + ATTR_FORMAT, ATTR_KEYWORD, ATTR_MEDIA_TYPE, DOMAIN, @@ -50,6 +52,7 @@ from homeassistant.components.websocket_api.const import TYPE_RESULT from homeassistant.config import async_process_ha_core_config from homeassistant.const import ( ATTR_ENTITY_ID, + ATTR_NAME, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, @@ -481,6 +484,30 @@ async def test_services( }, ) + with patch("homeassistant.components.roku.coordinator.Roku.play_video") as pv_mock: + await hass.services.async_call( + MP_DOMAIN, + SERVICE_PLAY_MEDIA, + { + ATTR_ENTITY_ID: MAIN_ENTITY_ID, + ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_URL, + ATTR_MEDIA_CONTENT_ID: "https://awesome.tld/media.mp4", + ATTR_MEDIA_EXTRA: { + ATTR_NAME: "Sent from HA", + ATTR_FORMAT: "mp4", + }, + }, + blocking=True, + ) + + pv_mock.assert_called_once_with( + "https://awesome.tld/media.mp4", + { + "videoName": "Sent from HA", + "videoFormat": "mp4", + }, + ) + with patch("homeassistant.components.roku.coordinator.Roku.remote") as remote_mock: await hass.services.async_call( MP_DOMAIN,