1 """Support for media browsing."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from functools
import partial
18 from .coordinator
import RokuDataUpdateCoordinator
19 from .helpers
import format_channel_name
21 CONTENT_TYPE_MEDIA_CLASS = {
22 MediaType.APP: MediaClass.APP,
23 MediaType.APPS: MediaClass.APP,
24 MediaType.CHANNEL: MediaClass.CHANNEL,
25 MediaType.CHANNELS: MediaClass.CHANNEL,
28 CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS = {
29 MediaType.APPS: MediaClass.DIRECTORY,
30 MediaType.CHANNELS: MediaClass.DIRECTORY,
33 PLAYABLE_MEDIA_TYPES = [
38 EXPANDABLE_MEDIA_TYPES = [
43 type GetBrowseImageUrlType = Callable[[str, str, str |
None], str |
None]
47 coordinator: RokuDataUpdateCoordinator,
49 get_browse_image_url: GetBrowseImageUrlType,
50 media_content_type: str,
51 media_content_id: str,
52 media_image_id: str |
None =
None,
54 """Get thumbnail URL."""
56 if media_content_type == MediaType.APP
and media_content_id:
57 return coordinator.roku.app_icon_url(media_content_id)
60 return get_browse_image_url(
69 coordinator: RokuDataUpdateCoordinator,
70 get_browse_image_url: GetBrowseImageUrlType,
71 media_content_id: str |
None,
72 media_content_type: str |
None,
75 if media_content_id
is None:
82 if media_source.is_media_source_id(media_content_id):
83 return await media_source.async_browse_media(hass, media_content_id)
86 "search_type": media_content_type,
87 "search_id": media_content_id,
90 response = await hass.async_add_executor_job(
95 get_thumbnail_url_full,
103 raise BrowseError(f
"Media not found: {media_content_type} / {media_content_id}")
110 coordinator: RokuDataUpdateCoordinator,
111 get_browse_image_url: GetBrowseImageUrlType,
113 """Return root payload for Roku."""
114 device = coordinator.data
118 {
"title":
"Apps",
"type": MediaType.APPS},
120 get_browse_image_url,
124 if device.info.device_type ==
"tv" and len(device.channels) > 0:
127 {
"title":
"TV Channels",
"type": MediaType.CHANNELS},
129 get_browse_image_url,
133 for child
in children:
134 child.thumbnail =
"https://brands.home-assistant.io/_/roku/logo.png"
137 browse_item = await media_source.async_browse_media(hass,
None)
140 if browse_item.domain
is None:
141 if browse_item.children
is not None:
142 children.extend(browse_item.children)
144 children.append(browse_item)
148 if len(children) == 1:
152 get_browse_image_url,
153 children[0].media_content_id,
154 children[0].media_content_type,
159 media_class=MediaClass.DIRECTORY,
161 media_content_type=
"root",
169 coordinator: RokuDataUpdateCoordinator,
171 get_browse_image_url: GetBrowseImageUrlType,
172 ) -> BrowseMedia |
None:
173 """Create response payload for the provided media query."""
174 search_id = payload[
"search_id"]
175 search_type = payload[
"search_type"]
180 children_media_class =
None
182 if search_type == MediaType.APPS:
185 {
"app_id": item.app_id,
"title": item.name,
"type": MediaType.APP}
186 for item
in coordinator.data.apps
188 children_media_class = MediaClass.APP
189 elif search_type == MediaType.CHANNELS:
190 title =
"TV Channels"
193 "channel_number": channel.number,
195 "type": MediaType.CHANNEL,
197 for channel
in coordinator.data.channels
199 children_media_class = MediaClass.CHANNEL
201 if title
is None or media
is None:
205 media_class=CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS.get(
206 search_type, MediaClass.DIRECTORY
208 media_content_id=search_id,
209 media_content_type=search_type,
211 can_play=search_type
in PLAYABLE_MEDIA_TYPES
and search_id,
214 item_payload(item, coordinator, get_browse_image_url)
for item
in media
216 children_media_class=children_media_class,
223 coordinator: RokuDataUpdateCoordinator,
224 get_browse_image_url: GetBrowseImageUrlType,
226 """Create response payload for a single media item.
228 Used by async_browse_media.
233 media_content_type = MediaType.APP
234 media_content_id = item[
"app_id"]
235 thumbnail = get_browse_image_url(media_content_type, media_content_id,
None)
236 elif "channel_number" in item:
237 media_content_type = MediaType.CHANNEL
238 media_content_id = item[
"channel_number"]
240 media_content_type = item[
"type"]
241 media_content_id =
""
243 title = item[
"title"]
244 can_play = media_content_type
in PLAYABLE_MEDIA_TYPES
and media_content_id
245 can_expand = media_content_type
in EXPANDABLE_MEDIA_TYPES
249 media_class=CONTENT_TYPE_MEDIA_CLASS[media_content_type],
250 media_content_type=media_content_type,
251 media_content_id=media_content_id,
253 can_expand=can_expand,
str format_channel_name(str channel_number, str|None channel_name=None)
bool is_internal_request(HomeAssistant hass)