1 """Support for media browsing."""
15 PLAYABLE_MEDIA_TYPES = [
21 CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS = {
22 MediaType.ALBUM: MediaClass.ALBUM,
23 MediaType.ARTIST: MediaClass.ARTIST,
24 MediaType.PLAYLIST: MediaClass.PLAYLIST,
25 MediaType.SEASON: MediaClass.SEASON,
26 MediaType.TVSHOW: MediaClass.TV_SHOW,
29 CHILD_TYPE_MEDIA_CLASS = {
30 MediaType.SEASON: MediaClass.SEASON,
31 MediaType.ALBUM: MediaClass.ALBUM,
32 MediaType.ARTIST: MediaClass.ARTIST,
33 MediaType.MOVIE: MediaClass.MOVIE,
34 MediaType.PLAYLIST: MediaClass.PLAYLIST,
35 MediaType.TRACK: MediaClass.TRACK,
36 MediaType.TVSHOW: MediaClass.TV_SHOW,
37 MediaType.CHANNEL: MediaClass.CHANNEL,
38 MediaType.EPISODE: MediaClass.EPISODE,
41 _LOGGER = logging.getLogger(__name__)
45 """Unknown media type."""
49 """Create response payload for the provided media query."""
50 search_id = payload[
"search_id"]
51 search_type = payload[
"search_type"]
53 _, title, media = await
get_media_info(media_library, search_id, search_type)
54 thumbnail = await get_thumbnail_url(search_type, search_id)
59 children = await asyncio.gather(
60 *(
item_payload(item, get_thumbnail_url)
for item
in media)
63 if search_type
in (MediaType.TVSHOW, MediaType.MOVIE)
and search_id ==
"":
64 children.sort(key=
lambda x: x.title.replace(
"The ",
"", 1), reverse=
False)
66 response = BrowseMedia(
67 media_class=CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS.get(
68 search_type, MediaClass.DIRECTORY
70 media_content_id=search_id,
71 media_content_type=search_type,
73 can_play=search_type
in PLAYABLE_MEDIA_TYPES
and search_id,
79 if search_type ==
"library_music":
80 response.children_media_class = MediaClass.MUSIC
82 response.calculate_children_class()
88 """Create response payload for a single media item.
90 Used by async_browse_media.
97 media_content_type = MediaType.TRACK
98 media_content_id = f
"{item['songid']}"
101 elif "albumid" in item:
102 media_content_type = MediaType.ALBUM
103 media_content_id = f
"{item['albumid']}"
106 elif "artistid" in item:
107 media_content_type = MediaType.ARTIST
108 media_content_id = f
"{item['artistid']}"
111 elif "movieid" in item:
112 media_content_type = MediaType.MOVIE
113 media_content_id = f
"{item['movieid']}"
116 elif "episodeid" in item:
117 media_content_type = MediaType.EPISODE
118 media_content_id = f
"{item['episodeid']}"
121 elif "seasonid" in item:
122 media_content_type = MediaType.SEASON
123 media_content_id = f
"{item['tvshowid']}/{item['season']}"
126 elif "tvshowid" in item:
127 media_content_type = MediaType.TVSHOW
128 media_content_id = f
"{item['tvshowid']}"
131 elif "channelid" in item:
132 media_content_type = MediaType.CHANNEL
133 media_content_id = f
"{item['channelid']}"
134 if broadcasting := item.get(
"broadcastnow"):
135 show = broadcasting.get(
"title")
136 title = f
"{title} - {show}"
142 media_class = MediaClass.DIRECTORY
143 media_content_type = item[
"type"]
144 media_content_id =
""
148 if media_class
is None:
150 media_class = CHILD_TYPE_MEDIA_CLASS[media_content_type]
151 except KeyError
as err:
152 _LOGGER.debug(
"Unknown media type received: %s", media_content_type)
153 raise UnknownMediaType
from err
155 thumbnail = item.get(
"thumbnail")
156 if thumbnail
is not None and get_thumbnail_url
is not None:
157 thumbnail = await get_thumbnail_url(
158 media_content_type, media_content_id, thumbnail_url=thumbnail
163 media_class=media_class,
164 media_content_type=media_content_type,
165 media_content_id=media_content_id,
167 can_expand=can_expand,
173 """Content filter for media sources."""
176 item.media_content_id.startswith(
"media-source://camera/")
177 and item.media_content_type ==
"image/png"
182 """Create response payload to describe contents of a specific library.
184 Used by async_browse_media.
186 library_info = BrowseMedia(
187 media_class=MediaClass.DIRECTORY,
188 media_content_id=
"library",
189 media_content_type=
"library",
190 title=
"Media Library",
197 "library_music":
"Music",
198 MediaType.MOVIE:
"Movies",
199 MediaType.TVSHOW:
"TV shows",
200 MediaType.CHANNEL:
"Channels",
203 library_info.children = await asyncio.gather(
207 "label": item[
"label"],
208 "type": item[
"type"],
213 {
"label": name,
"type": type_}
for type_, name
in library.items()
218 for child
in library_info.children:
219 child.thumbnail =
"https://brands.home-assistant.io/_/kodi/logo.png"
222 item = await media_source.async_browse_media(
223 hass,
None, content_filter=media_source_content_filter
226 if item.domain
is None:
227 library_info.children.extend(item.children)
229 library_info.children.append(item)
235 """Fetch media/album."""
240 properties = [
"thumbnail"]
241 if search_type == MediaType.ALBUM:
243 album = await media_library.get_album_details(
244 album_id=
int(search_id), properties=properties
246 thumbnail = media_library.thumbnail_url(
247 album[
"albumdetails"].
get(
"thumbnail")
249 title = album[
"albumdetails"][
"label"]
250 media = await media_library.get_songs(
251 album_id=
int(search_id),
261 media = media.get(
"songs")
263 media = await media_library.get_albums(properties=properties)
264 media = media.get(
"albums")
267 elif search_type == MediaType.ARTIST:
269 media = await media_library.get_albums(
270 artist_id=
int(search_id), properties=properties
272 media = media.get(
"albums")
273 artist = await media_library.get_artist_details(
274 artist_id=
int(search_id), properties=properties
276 thumbnail = media_library.thumbnail_url(
277 artist[
"artistdetails"].
get(
"thumbnail")
279 title = artist[
"artistdetails"][
"label"]
281 media = await media_library.get_artists(properties)
282 media = media.get(
"artists")
285 elif search_type ==
"library_music":
286 library = {MediaType.ALBUM:
"Albums", MediaType.ARTIST:
"Artists"}
287 media = [{
"label": name,
"type": type_}
for type_, name
in library.items()]
288 title =
"Music Library"
290 elif search_type == MediaType.MOVIE:
292 movie = await media_library.get_movie_details(
293 movie_id=
int(search_id), properties=properties
295 thumbnail = media_library.thumbnail_url(
296 movie[
"moviedetails"].
get(
"thumbnail")
298 title = movie[
"moviedetails"][
"label"]
300 media = await media_library.get_movies(properties)
301 media = media.get(
"movies")
304 elif search_type == MediaType.TVSHOW:
306 media = await media_library.get_seasons(
307 tv_show_id=
int(search_id),
308 properties=[
"thumbnail",
"season",
"tvshowid"],
310 media = media.get(
"seasons")
311 tvshow = await media_library.get_tv_show_details(
312 tv_show_id=
int(search_id), properties=properties
314 thumbnail = media_library.thumbnail_url(
315 tvshow[
"tvshowdetails"].
get(
"thumbnail")
317 title = tvshow[
"tvshowdetails"][
"label"]
319 media = await media_library.get_tv_shows(properties)
320 media = media.get(
"tvshows")
323 elif search_type == MediaType.SEASON:
324 tv_show_id, season_id = search_id.split(
"/", 1)
325 media = await media_library.get_episodes(
326 tv_show_id=
int(tv_show_id),
327 season_id=
int(season_id),
328 properties=[
"thumbnail",
"tvshowid",
"seasonid"],
330 media = media.get(
"episodes")
332 season = await media_library.get_season_details(
333 season_id=
int(media[0][
"seasonid"]), properties=properties
335 thumbnail = media_library.thumbnail_url(
336 season[
"seasondetails"].
get(
"thumbnail")
338 title = season[
"seasondetails"][
"label"]
340 elif search_type == MediaType.CHANNEL:
341 media = await media_library.get_channels(
342 channel_group_id=
"alltv",
343 properties=[
"thumbnail",
"channeltype",
"channel",
"broadcastnow"],
345 media = media.get(
"channels")
348 return thumbnail, title, media
web.Response get(self, web.Request request, str config_key)