Use media player image proxy for roku media browser (#43070)
This commit is contained in:
parent
d8b067ebf9
commit
df5a8c4dac
4 changed files with 34 additions and 22 deletions
|
@ -900,6 +900,9 @@ class MediaPlayerEntity(Entity):
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if content is None:
|
||||||
|
_LOGGER.warning("Error retrieving proxied image from %s", url)
|
||||||
|
|
||||||
return content, content_type
|
return content, content_type
|
||||||
|
|
||||||
def get_browse_image_url(
|
def get_browse_image_url(
|
||||||
|
@ -910,15 +913,12 @@ class MediaPlayerEntity(Entity):
|
||||||
f"/api/media_player_proxy/{self.entity_id}/browse_media"
|
f"/api/media_player_proxy/{self.entity_id}/browse_media"
|
||||||
f"/{media_content_type}/{media_content_id}"
|
f"/{media_content_type}/{media_content_id}"
|
||||||
)
|
)
|
||||||
url = str(
|
|
||||||
URL(url_path).with_query(
|
url_query = {"token": self.access_token}
|
||||||
{
|
if media_image_id:
|
||||||
"token": self.access_token,
|
url_query["media_image_id"] = media_image_id
|
||||||
"media_image_id": media_image_id,
|
|
||||||
}
|
return str(URL(url_path).with_query(url_query))
|
||||||
)
|
|
||||||
)
|
|
||||||
return url
|
|
||||||
|
|
||||||
|
|
||||||
class MediaPlayerImageView(HomeAssistantView):
|
class MediaPlayerImageView(HomeAssistantView):
|
||||||
|
|
|
@ -34,7 +34,7 @@ EXPANDABLE_MEDIA_TYPES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def build_item_response(coordinator, payload):
|
def build_item_response(coordinator, payload, get_thumbnail_url=None):
|
||||||
"""Create response payload for the provided media query."""
|
"""Create response payload for the provided media query."""
|
||||||
search_id = payload["search_id"]
|
search_id = payload["search_id"]
|
||||||
search_type = payload["search_type"]
|
search_type = payload["search_type"]
|
||||||
|
@ -75,13 +75,13 @@ def build_item_response(coordinator, payload):
|
||||||
title=title,
|
title=title,
|
||||||
can_play=search_type in PLAYABLE_MEDIA_TYPES and search_id,
|
can_play=search_type in PLAYABLE_MEDIA_TYPES and search_id,
|
||||||
can_expand=True,
|
can_expand=True,
|
||||||
children=[item_payload(item, coordinator) for item in media],
|
children=[item_payload(item, coordinator, get_thumbnail_url) for item in media],
|
||||||
children_media_class=children_media_class,
|
children_media_class=children_media_class,
|
||||||
thumbnail=thumbnail,
|
thumbnail=thumbnail,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def item_payload(item, coordinator):
|
def item_payload(item, coordinator, get_thumbnail_url=None):
|
||||||
"""
|
"""
|
||||||
Create response payload for a single media item.
|
Create response payload for a single media item.
|
||||||
|
|
||||||
|
@ -92,7 +92,8 @@ def item_payload(item, coordinator):
|
||||||
if "app_id" in item:
|
if "app_id" in item:
|
||||||
media_content_type = MEDIA_TYPE_APP
|
media_content_type = MEDIA_TYPE_APP
|
||||||
media_content_id = item["app_id"]
|
media_content_id = item["app_id"]
|
||||||
thumbnail = coordinator.roku.app_icon_url(item["app_id"])
|
if get_thumbnail_url:
|
||||||
|
thumbnail = get_thumbnail_url(media_content_type, media_content_id)
|
||||||
elif "channel_number" in item:
|
elif "channel_number" in item:
|
||||||
media_content_type = MEDIA_TYPE_CHANNEL
|
media_content_type = MEDIA_TYPE_CHANNEL
|
||||||
media_content_id = item["channel_number"]
|
media_content_id = item["channel_number"]
|
||||||
|
@ -115,7 +116,7 @@ def item_payload(item, coordinator):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def library_payload(coordinator):
|
def library_payload(coordinator, get_thumbnail_url=None):
|
||||||
"""
|
"""
|
||||||
Create response payload to describe contents of a specific library.
|
Create response payload to describe contents of a specific library.
|
||||||
|
|
||||||
|
@ -147,6 +148,7 @@ def library_payload(coordinator):
|
||||||
item_payload(
|
item_payload(
|
||||||
{"title": item["title"], "type": item["type"]},
|
{"title": item["title"], "type": item["type"]},
|
||||||
coordinator,
|
coordinator,
|
||||||
|
get_thumbnail_url,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -238,16 +238,30 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity):
|
||||||
"""Emulate opening the search screen and entering the search keyword."""
|
"""Emulate opening the search screen and entering the search keyword."""
|
||||||
await self.coordinator.roku.search(keyword)
|
await self.coordinator.roku.search(keyword)
|
||||||
|
|
||||||
|
async def async_get_browse_image(
|
||||||
|
self, media_content_type, media_content_id, media_image_id=None
|
||||||
|
):
|
||||||
|
"""Fetch media browser image to serve via proxy."""
|
||||||
|
if media_content_type == MEDIA_TYPE_APP and media_content_id:
|
||||||
|
image_url = self.coordinator.roku.app_icon_url(media_content_id)
|
||||||
|
return await self._async_fetch_image(image_url)
|
||||||
|
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
async def async_browse_media(self, media_content_type=None, media_content_id=None):
|
async def async_browse_media(self, media_content_type=None, media_content_id=None):
|
||||||
"""Implement the websocket media browsing helper."""
|
"""Implement the websocket media browsing helper."""
|
||||||
|
|
||||||
|
def _get_thumbnail_url(*args, **kwargs):
|
||||||
|
return self.get_browse_image_url(*args, **kwargs)
|
||||||
|
|
||||||
if media_content_type in [None, "library"]:
|
if media_content_type in [None, "library"]:
|
||||||
return library_payload(self.coordinator)
|
return library_payload(self.coordinator, _get_thumbnail_url)
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"search_type": media_content_type,
|
"search_type": media_content_type,
|
||||||
"search_id": media_content_id,
|
"search_id": media_content_id,
|
||||||
}
|
}
|
||||||
response = build_item_response(self.coordinator, payload)
|
response = build_item_response(self.coordinator, payload, _get_thumbnail_url)
|
||||||
|
|
||||||
if response is None:
|
if response is None:
|
||||||
raise BrowseError(
|
raise BrowseError(
|
||||||
|
|
|
@ -539,18 +539,14 @@ async def test_media_browse(hass, aioclient_mock, hass_ws_client):
|
||||||
assert msg["result"]["children"][0]["media_content_type"] == MEDIA_TYPE_APP
|
assert msg["result"]["children"][0]["media_content_type"] == MEDIA_TYPE_APP
|
||||||
assert msg["result"]["children"][0]["media_content_id"] == "tvinput.hdmi2"
|
assert msg["result"]["children"][0]["media_content_id"] == "tvinput.hdmi2"
|
||||||
assert (
|
assert (
|
||||||
msg["result"]["children"][0]["thumbnail"]
|
"/browse_media/app/tvinput.hdmi2" in msg["result"]["children"][0]["thumbnail"]
|
||||||
== "http://192.168.1.161:8060/query/icon/tvinput.hdmi2"
|
|
||||||
)
|
)
|
||||||
assert msg["result"]["children"][0]["can_play"]
|
assert msg["result"]["children"][0]["can_play"]
|
||||||
|
|
||||||
assert msg["result"]["children"][3]["title"] == "Roku Channel Store"
|
assert msg["result"]["children"][3]["title"] == "Roku Channel Store"
|
||||||
assert msg["result"]["children"][3]["media_content_type"] == MEDIA_TYPE_APP
|
assert msg["result"]["children"][3]["media_content_type"] == MEDIA_TYPE_APP
|
||||||
assert msg["result"]["children"][3]["media_content_id"] == "11"
|
assert msg["result"]["children"][3]["media_content_id"] == "11"
|
||||||
assert (
|
assert "/browse_media/app/11" in msg["result"]["children"][3]["thumbnail"]
|
||||||
msg["result"]["children"][3]["thumbnail"]
|
|
||||||
== "http://192.168.1.161:8060/query/icon/11"
|
|
||||||
)
|
|
||||||
assert msg["result"]["children"][3]["can_play"]
|
assert msg["result"]["children"][3]["can_play"]
|
||||||
|
|
||||||
# test channels
|
# test channels
|
||||||
|
|
Loading…
Add table
Reference in a new issue