Add children media class (#39902)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>pull/39974/head
parent
e208aac834
commit
e96fed20c8
homeassistant/components
kodi
media_player
media_source
netatmo
philips_js
plex
roku
sonos
spotify
tests/components
|
@ -29,8 +29,15 @@ PLAYABLE_MEDIA_TYPES = [
|
|||
MEDIA_TYPE_TRACK,
|
||||
]
|
||||
|
||||
CONTENT_TYPE_MEDIA_CLASS = {
|
||||
"library_music": MEDIA_CLASS_MUSIC,
|
||||
CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS = {
|
||||
MEDIA_TYPE_ALBUM: MEDIA_CLASS_ALBUM,
|
||||
MEDIA_TYPE_ARTIST: MEDIA_CLASS_ARTIST,
|
||||
MEDIA_TYPE_PLAYLIST: MEDIA_CLASS_PLAYLIST,
|
||||
MEDIA_TYPE_SEASON: MEDIA_CLASS_SEASON,
|
||||
MEDIA_TYPE_TVSHOW: MEDIA_CLASS_TV_SHOW,
|
||||
}
|
||||
|
||||
CHILD_TYPE_MEDIA_CLASS = {
|
||||
MEDIA_TYPE_SEASON: MEDIA_CLASS_SEASON,
|
||||
MEDIA_TYPE_ALBUM: MEDIA_CLASS_ALBUM,
|
||||
MEDIA_TYPE_ARTIST: MEDIA_CLASS_ARTIST,
|
||||
|
@ -151,8 +158,10 @@ async def build_item_response(media_library, payload):
|
|||
except UnknownMediaType:
|
||||
pass
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=CONTENT_TYPE_MEDIA_CLASS[search_type],
|
||||
response = BrowseMedia(
|
||||
media_class=CONTAINER_TYPES_SPECIFIC_MEDIA_CLASS.get(
|
||||
search_type, MEDIA_CLASS_DIRECTORY
|
||||
),
|
||||
media_content_id=search_id,
|
||||
media_content_type=search_type,
|
||||
title=title,
|
||||
|
@ -162,6 +171,13 @@ async def build_item_response(media_library, payload):
|
|||
thumbnail=thumbnail,
|
||||
)
|
||||
|
||||
if search_type == "library_music":
|
||||
response.children_media_class = MEDIA_CLASS_MUSIC
|
||||
else:
|
||||
response.calculate_children_class()
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def item_payload(item, media_library):
|
||||
"""
|
||||
|
@ -170,11 +186,12 @@ def item_payload(item, media_library):
|
|||
Used by async_browse_media.
|
||||
"""
|
||||
title = item["label"]
|
||||
|
||||
thumbnail = item.get("thumbnail")
|
||||
if thumbnail:
|
||||
thumbnail = media_library.thumbnail_url(thumbnail)
|
||||
|
||||
media_class = None
|
||||
|
||||
if "songid" in item:
|
||||
media_content_type = MEDIA_TYPE_TRACK
|
||||
media_content_id = f"{item['songid']}"
|
||||
|
@ -213,16 +230,18 @@ def item_payload(item, media_library):
|
|||
else:
|
||||
# this case is for the top folder of each type
|
||||
# possible content types: album, artist, movie, library_music, tvshow
|
||||
media_class = MEDIA_CLASS_DIRECTORY
|
||||
media_content_type = item["type"]
|
||||
media_content_id = ""
|
||||
can_play = False
|
||||
can_expand = True
|
||||
|
||||
try:
|
||||
media_class = CONTENT_TYPE_MEDIA_CLASS[media_content_type]
|
||||
except KeyError as err:
|
||||
_LOGGER.debug("Unknown media type received: %s", media_content_type)
|
||||
raise UnknownMediaType from err
|
||||
if media_class is None:
|
||||
try:
|
||||
media_class = CHILD_TYPE_MEDIA_CLASS[media_content_type]
|
||||
except KeyError as err:
|
||||
_LOGGER.debug("Unknown media type received: %s", media_content_type)
|
||||
raise UnknownMediaType from err
|
||||
|
||||
return BrowseMedia(
|
||||
title=title,
|
||||
|
|
|
@ -85,6 +85,7 @@ from .const import (
|
|||
ATTR_SOUND_MODE,
|
||||
ATTR_SOUND_MODE_LIST,
|
||||
DOMAIN,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
SERVICE_CLEAR_PLAYLIST,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
SERVICE_SELECT_SOUND_MODE,
|
||||
|
@ -816,24 +817,10 @@ class MediaPlayerEntity(Entity):
|
|||
media_content_type: Optional[str] = None,
|
||||
media_content_id: Optional[str] = None,
|
||||
) -> "BrowseMedia":
|
||||
"""
|
||||
Return a payload for the "media_player/browse_media" websocket command.
|
||||
"""Return a BrowseMedia instance.
|
||||
|
||||
Payload should follow this format:
|
||||
{
|
||||
"title": str - Title of the item
|
||||
"media_class": str - Media class
|
||||
"media_content_type": str - see below
|
||||
"media_content_id": str - see below
|
||||
- Can be passed back in to browse further
|
||||
- Can be used as-is with media_player.play_media service
|
||||
"can_play": bool - If item is playable
|
||||
"can_expand": bool - If item contains other media
|
||||
"thumbnail": str (Optional) - URL to image thumbnail for item
|
||||
"children": list (Optional) - [{<item_with_keys_above>}, ...]
|
||||
}
|
||||
|
||||
Note: Children should omit the children key.
|
||||
The BrowseMedia instance will be used by the
|
||||
"media_player/browse_media" websocket command.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
@ -1054,6 +1041,7 @@ class BrowseMedia:
|
|||
can_play: bool,
|
||||
can_expand: bool,
|
||||
children: Optional[List["BrowseMedia"]] = None,
|
||||
children_media_class: Optional[str] = None,
|
||||
thumbnail: Optional[str] = None,
|
||||
):
|
||||
"""Initialize browse media item."""
|
||||
|
@ -1064,10 +1052,14 @@ class BrowseMedia:
|
|||
self.can_play = can_play
|
||||
self.can_expand = can_expand
|
||||
self.children = children
|
||||
self.children_media_class = children_media_class
|
||||
self.thumbnail = thumbnail
|
||||
|
||||
def as_dict(self, *, parent: bool = True) -> dict:
|
||||
"""Convert Media class to browse media dictionary."""
|
||||
if self.children_media_class is None:
|
||||
self.calculate_children_class()
|
||||
|
||||
response = {
|
||||
"title": self.title,
|
||||
"media_class": self.media_class,
|
||||
|
@ -1075,6 +1067,7 @@ class BrowseMedia:
|
|||
"media_content_id": self.media_content_id,
|
||||
"can_play": self.can_play,
|
||||
"can_expand": self.can_expand,
|
||||
"children_media_class": self.children_media_class,
|
||||
"thumbnail": self.thumbnail,
|
||||
}
|
||||
|
||||
|
@ -1089,3 +1082,14 @@ class BrowseMedia:
|
|||
response["children"] = []
|
||||
|
||||
return response
|
||||
|
||||
def calculate_children_class(self) -> None:
|
||||
"""Count the children media classes and calculate the correct class."""
|
||||
if self.children is None or len(self.children) == 0:
|
||||
return
|
||||
|
||||
self.children_media_class = MEDIA_CLASS_DIRECTORY
|
||||
|
||||
proposed_class = self.children[0].media_class
|
||||
if all(child.media_class == proposed_class for child in self.children):
|
||||
self.children_media_class = proposed_class
|
||||
|
|
|
@ -6,6 +6,7 @@ from typing import List, Optional, Tuple
|
|||
from homeassistant.components.media_player import BrowseMedia
|
||||
from homeassistant.components.media_player.const import (
|
||||
MEDIA_CLASS_CHANNEL,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_TYPE_CHANNEL,
|
||||
MEDIA_TYPE_CHANNELS,
|
||||
)
|
||||
|
@ -53,11 +54,12 @@ class MediaSourceItem:
|
|||
base = BrowseMediaSource(
|
||||
domain=None,
|
||||
identifier=None,
|
||||
media_class=MEDIA_CLASS_CHANNEL,
|
||||
media_class=MEDIA_CLASS_DIRECTORY,
|
||||
media_content_type=MEDIA_TYPE_CHANNELS,
|
||||
title="Media Sources",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=MEDIA_CLASS_CHANNEL,
|
||||
)
|
||||
base.children = [
|
||||
BrowseMediaSource(
|
||||
|
|
|
@ -5,6 +5,7 @@ import re
|
|||
from typing import Optional, Tuple
|
||||
|
||||
from homeassistant.components.media_player.const import (
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_CLASS_VIDEO,
|
||||
MEDIA_TYPE_VIDEO,
|
||||
)
|
||||
|
@ -91,10 +92,12 @@ class NetatmoSource(MediaSource):
|
|||
else:
|
||||
path = f"{source}/{camera_id}"
|
||||
|
||||
media_class = MEDIA_CLASS_DIRECTORY if event_id is None else MEDIA_CLASS_VIDEO
|
||||
|
||||
media = BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=path,
|
||||
media_class=MEDIA_CLASS_VIDEO,
|
||||
media_class=media_class,
|
||||
media_content_type=MEDIA_TYPE_VIDEO,
|
||||
title=title,
|
||||
can_play=bool(
|
||||
|
|
|
@ -12,6 +12,7 @@ from homeassistant.components.media_player import (
|
|||
)
|
||||
from homeassistant.components.media_player.const import (
|
||||
MEDIA_CLASS_CHANNEL,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_TYPE_CHANNEL,
|
||||
MEDIA_TYPE_CHANNELS,
|
||||
SUPPORT_BROWSE_MEDIA,
|
||||
|
@ -289,7 +290,7 @@ class PhilipsTVMediaPlayer(MediaPlayerEntity):
|
|||
|
||||
return BrowseMedia(
|
||||
title="Channels",
|
||||
media_class=MEDIA_CLASS_CHANNEL,
|
||||
media_class=MEDIA_CLASS_DIRECTORY,
|
||||
media_content_id="",
|
||||
media_content_type=MEDIA_TYPE_CHANNELS,
|
||||
can_play=False,
|
||||
|
|
|
@ -26,7 +26,7 @@ class UnknownMediaType(BrowseError):
|
|||
EXPANDABLES = ["album", "artist", "playlist", "season", "show"]
|
||||
PLAYLISTS_BROWSE_PAYLOAD = {
|
||||
"title": "Playlists",
|
||||
"media_class": MEDIA_CLASS_PLAYLIST,
|
||||
"media_class": MEDIA_CLASS_DIRECTORY,
|
||||
"media_content_id": "all",
|
||||
"media_content_type": "playlists",
|
||||
"can_play": False,
|
||||
|
@ -94,10 +94,21 @@ def browse_media(
|
|||
if special_folder:
|
||||
if media_content_type == "server":
|
||||
library_or_section = plex_server.library
|
||||
children_media_class = MEDIA_CLASS_DIRECTORY
|
||||
title = plex_server.friendly_name
|
||||
elif media_content_type == "library":
|
||||
library_or_section = plex_server.library.sectionByID(media_content_id)
|
||||
title = library_or_section.title
|
||||
try:
|
||||
children_media_class = ITEM_TYPE_MEDIA_CLASS[library_or_section.TYPE]
|
||||
except KeyError as err:
|
||||
raise BrowseError(
|
||||
f"Media not found: {media_content_type} / {media_content_id}"
|
||||
) from err
|
||||
else:
|
||||
raise BrowseError(
|
||||
f"Media not found: {media_content_type} / {media_content_id}"
|
||||
)
|
||||
|
||||
payload = {
|
||||
"title": title,
|
||||
|
@ -107,6 +118,7 @@ def browse_media(
|
|||
"can_play": False,
|
||||
"can_expand": True,
|
||||
"children": [],
|
||||
"children_media_class": children_media_class,
|
||||
}
|
||||
|
||||
method = SPECIAL_METHODS[special_folder]
|
||||
|
@ -116,13 +128,20 @@ def browse_media(
|
|||
payload["children"].append(item_payload(item))
|
||||
except UnknownMediaType:
|
||||
continue
|
||||
|
||||
return BrowseMedia(**payload)
|
||||
|
||||
if media_content_type in ["server", None]:
|
||||
return server_payload(plex_server)
|
||||
try:
|
||||
if media_content_type in ["server", None]:
|
||||
return server_payload(plex_server)
|
||||
|
||||
if media_content_type == "library":
|
||||
return library_payload(plex_server, media_content_id)
|
||||
if media_content_type == "library":
|
||||
return library_payload(plex_server, media_content_id)
|
||||
|
||||
except UnknownMediaType as err:
|
||||
raise BrowseError(
|
||||
f"Media not found: {media_content_type} / {media_content_id}"
|
||||
) from err
|
||||
|
||||
if media_content_type == "playlists":
|
||||
return playlists_payload(plex_server)
|
||||
|
@ -160,6 +179,11 @@ def item_payload(item):
|
|||
|
||||
def library_section_payload(section):
|
||||
"""Create response payload for a single library section."""
|
||||
try:
|
||||
children_media_class = ITEM_TYPE_MEDIA_CLASS[section.TYPE]
|
||||
except KeyError as err:
|
||||
_LOGGER.debug("Unknown type received: %s", section.TYPE)
|
||||
raise UnknownMediaType from err
|
||||
return BrowseMedia(
|
||||
title=section.title,
|
||||
media_class=MEDIA_CLASS_DIRECTORY,
|
||||
|
@ -167,6 +191,7 @@ def library_section_payload(section):
|
|||
media_content_type="library",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=children_media_class,
|
||||
)
|
||||
|
||||
|
||||
|
@ -194,6 +219,7 @@ def server_payload(plex_server):
|
|||
can_expand=True,
|
||||
)
|
||||
server_info.children = []
|
||||
server_info.children_media_class = MEDIA_CLASS_DIRECTORY
|
||||
server_info.children.append(special_library_payload(server_info, "On Deck"))
|
||||
server_info.children.append(special_library_payload(server_info, "Recently Added"))
|
||||
for library in plex_server.library.sections():
|
||||
|
@ -229,4 +255,6 @@ def playlists_payload(plex_server):
|
|||
playlists_info["children"].append(item_payload(playlist))
|
||||
except UnknownMediaType:
|
||||
continue
|
||||
return BrowseMedia(**playlists_info)
|
||||
response = BrowseMedia(**playlists_info)
|
||||
response.children_media_class = MEDIA_CLASS_PLAYLIST
|
||||
return response
|
||||
|
|
|
@ -13,9 +13,9 @@ from homeassistant.components.media_player.const import (
|
|||
|
||||
CONTENT_TYPE_MEDIA_CLASS = {
|
||||
MEDIA_TYPE_APP: MEDIA_CLASS_APP,
|
||||
MEDIA_TYPE_APPS: MEDIA_CLASS_APP,
|
||||
MEDIA_TYPE_APPS: MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_TYPE_CHANNEL: MEDIA_CLASS_CHANNEL,
|
||||
MEDIA_TYPE_CHANNELS: MEDIA_CLASS_CHANNEL,
|
||||
MEDIA_TYPE_CHANNELS: MEDIA_CLASS_DIRECTORY,
|
||||
}
|
||||
|
||||
PLAYABLE_MEDIA_TYPES = [
|
||||
|
@ -59,7 +59,7 @@ def build_item_response(coordinator, payload):
|
|||
return None
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=CONTENT_TYPE_MEDIA_CLASS[search_type],
|
||||
media_class=MEDIA_CLASS_DIRECTORY,
|
||||
media_content_id=search_id,
|
||||
media_content_type=search_type,
|
||||
title=title,
|
||||
|
@ -139,4 +139,16 @@ def library_payload(coordinator):
|
|||
)
|
||||
)
|
||||
|
||||
if all(
|
||||
child.media_content_type == MEDIA_TYPE_APPS for child in library_info.children
|
||||
):
|
||||
library_info.children_media_class = MEDIA_CLASS_APP
|
||||
elif all(
|
||||
child.media_content_type == MEDIA_TYPE_CHANNELS
|
||||
for child in library_info.children
|
||||
):
|
||||
library_info.children_media_class = MEDIA_CLASS_CHANNEL
|
||||
else:
|
||||
library_info.children_media_class = MEDIA_CLASS_DIRECTORY
|
||||
|
||||
return library_info
|
||||
|
|
|
@ -222,6 +222,10 @@ ATTR_STATUS_LIGHT = "status_light"
|
|||
UNAVAILABLE_VALUES = {"", "NOT_IMPLEMENTED", None}
|
||||
|
||||
|
||||
class UnknownMediaType(BrowseError):
|
||||
"""Unknown media type."""
|
||||
|
||||
|
||||
class SonosData:
|
||||
"""Storage class for platform global data."""
|
||||
|
||||
|
@ -1487,7 +1491,20 @@ def build_item_response(media_library, payload):
|
|||
except IndexError:
|
||||
title = LIBRARY_TITLES_MAPPING[payload["idstring"]]
|
||||
|
||||
media_class = SONOS_TO_MEDIA_CLASSES[MEDIA_TYPES_TO_SONOS[payload["search_type"]]]
|
||||
try:
|
||||
media_class = SONOS_TO_MEDIA_CLASSES[
|
||||
MEDIA_TYPES_TO_SONOS[payload["search_type"]]
|
||||
]
|
||||
except KeyError:
|
||||
_LOGGER.debug("Unknown media type received %s", payload["search_type"])
|
||||
return None
|
||||
|
||||
children = []
|
||||
for item in media:
|
||||
try:
|
||||
children.append(item_payload(item))
|
||||
except UnknownMediaType:
|
||||
pass
|
||||
|
||||
return BrowseMedia(
|
||||
title=title,
|
||||
|
@ -1495,7 +1512,7 @@ def build_item_response(media_library, payload):
|
|||
media_class=media_class,
|
||||
media_content_id=payload["idstring"],
|
||||
media_content_type=payload["search_type"],
|
||||
children=[item_payload(item) for item in media],
|
||||
children=children,
|
||||
can_play=can_play(payload["search_type"]),
|
||||
can_expand=can_expand(payload["search_type"]),
|
||||
)
|
||||
|
@ -1507,12 +1524,18 @@ def item_payload(item):
|
|||
|
||||
Used by async_browse_media.
|
||||
"""
|
||||
media_type = get_media_type(item)
|
||||
try:
|
||||
media_class = SONOS_TO_MEDIA_CLASSES[media_type]
|
||||
except KeyError as err:
|
||||
_LOGGER.debug("Unknown media type received %s", media_type)
|
||||
raise UnknownMediaType from err
|
||||
return BrowseMedia(
|
||||
title=item.title,
|
||||
thumbnail=getattr(item, "album_art_uri", None),
|
||||
media_class=SONOS_TO_MEDIA_CLASSES[get_media_type(item)],
|
||||
media_class=media_class,
|
||||
media_content_id=get_content_id(item),
|
||||
media_content_type=SONOS_TO_MEDIA_TYPES[get_media_type(item)],
|
||||
media_content_type=SONOS_TO_MEDIA_TYPES[media_type],
|
||||
can_play=can_play(item.item_class),
|
||||
can_expand=can_expand(item),
|
||||
)
|
||||
|
@ -1524,6 +1547,13 @@ def library_payload(media_library):
|
|||
|
||||
Used by async_browse_media.
|
||||
"""
|
||||
children = []
|
||||
for item in media_library.browse():
|
||||
try:
|
||||
children.append(item_payload(item))
|
||||
except UnknownMediaType:
|
||||
pass
|
||||
|
||||
return BrowseMedia(
|
||||
title="Music Library",
|
||||
media_class=MEDIA_CLASS_DIRECTORY,
|
||||
|
@ -1531,7 +1561,7 @@ def library_payload(media_library):
|
|||
media_content_type="library",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children=[item_payload(item) for item in media_library.browse()],
|
||||
children=children,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -105,18 +105,18 @@ LIBRARY_MAP = {
|
|||
}
|
||||
|
||||
CONTENT_TYPE_MEDIA_CLASS = {
|
||||
"current_user_playlists": MEDIA_CLASS_PLAYLIST,
|
||||
"current_user_followed_artists": MEDIA_CLASS_ARTIST,
|
||||
"current_user_saved_albums": MEDIA_CLASS_ALBUM,
|
||||
"current_user_saved_tracks": MEDIA_CLASS_TRACK,
|
||||
"current_user_saved_shows": MEDIA_CLASS_PODCAST,
|
||||
"current_user_recently_played": MEDIA_CLASS_TRACK,
|
||||
"current_user_top_artists": MEDIA_CLASS_ARTIST,
|
||||
"current_user_top_tracks": MEDIA_CLASS_TRACK,
|
||||
"featured_playlists": MEDIA_CLASS_PLAYLIST,
|
||||
"categories": MEDIA_CLASS_GENRE,
|
||||
"category_playlists": MEDIA_CLASS_PLAYLIST,
|
||||
"new_releases": MEDIA_CLASS_ALBUM,
|
||||
"current_user_playlists": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_followed_artists": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_saved_albums": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_saved_tracks": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_saved_shows": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_recently_played": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_top_artists": MEDIA_CLASS_DIRECTORY,
|
||||
"current_user_top_tracks": MEDIA_CLASS_DIRECTORY,
|
||||
"featured_playlists": MEDIA_CLASS_DIRECTORY,
|
||||
"categories": MEDIA_CLASS_DIRECTORY,
|
||||
"category_playlists": MEDIA_CLASS_DIRECTORY,
|
||||
"new_releases": MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_TYPE_PLAYLIST: MEDIA_CLASS_PLAYLIST,
|
||||
MEDIA_TYPE_ALBUM: MEDIA_CLASS_ALBUM,
|
||||
MEDIA_TYPE_ARTIST: MEDIA_CLASS_ARTIST,
|
||||
|
@ -567,6 +567,7 @@ def build_item_response(spotify, user, payload):
|
|||
can_expand=True,
|
||||
)
|
||||
)
|
||||
media_item.children_media_class = MEDIA_CLASS_GENRE
|
||||
return media_item
|
||||
|
||||
if title is None:
|
||||
|
@ -575,7 +576,7 @@ def build_item_response(spotify, user, payload):
|
|||
else:
|
||||
title = LIBRARY_MAP.get(payload["media_content_id"])
|
||||
|
||||
response = {
|
||||
params = {
|
||||
"title": title,
|
||||
"media_class": media_class,
|
||||
"media_content_id": media_content_id,
|
||||
|
@ -586,16 +587,16 @@ def build_item_response(spotify, user, payload):
|
|||
}
|
||||
for item in items:
|
||||
try:
|
||||
response["children"].append(item_payload(item))
|
||||
params["children"].append(item_payload(item))
|
||||
except (MissingMediaInformation, UnknownMediaType):
|
||||
continue
|
||||
|
||||
if "images" in media:
|
||||
response["thumbnail"] = fetch_image_url(media)
|
||||
params["thumbnail"] = fetch_image_url(media)
|
||||
elif image:
|
||||
response["thumbnail"] = image
|
||||
params["thumbnail"] = image
|
||||
|
||||
return BrowseMedia(**response)
|
||||
return BrowseMedia(**params)
|
||||
|
||||
|
||||
def item_payload(item):
|
||||
|
@ -624,17 +625,13 @@ def item_payload(item):
|
|||
|
||||
payload = {
|
||||
"title": item.get("name"),
|
||||
"media_class": media_class,
|
||||
"media_content_id": media_id,
|
||||
"media_content_type": media_type,
|
||||
"can_play": media_type in PLAYABLE_MEDIA_TYPES,
|
||||
"can_expand": can_expand,
|
||||
}
|
||||
|
||||
payload = {
|
||||
**payload,
|
||||
"media_class": media_class,
|
||||
}
|
||||
|
||||
if "images" in item:
|
||||
payload["thumbnail"] = fetch_image_url(item)
|
||||
elif MEDIA_TYPE_ALBUM in item:
|
||||
|
@ -665,7 +662,9 @@ def library_payload():
|
|||
{"name": item["name"], "type": item["type"], "uri": item["type"]}
|
||||
)
|
||||
)
|
||||
return BrowseMedia(**library_info)
|
||||
response = BrowseMedia(**library_info)
|
||||
response.children_media_class = MEDIA_CLASS_DIRECTORY
|
||||
return response
|
||||
|
||||
|
||||
def fetch_image_url(item, key="images"):
|
||||
|
|
|
@ -17,6 +17,7 @@ async def test_browse_media_as_dict():
|
|||
title="media/",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=MEDIA_CLASS_MUSIC,
|
||||
)
|
||||
base.children = [
|
||||
models.BrowseMediaSource(
|
||||
|
@ -37,6 +38,7 @@ async def test_browse_media_as_dict():
|
|||
assert item["media_content_id"] == f"{const.URI_SCHEME}{const.DOMAIN}/media"
|
||||
assert not item["can_play"]
|
||||
assert item["can_expand"]
|
||||
assert item["children_media_class"] == MEDIA_CLASS_MUSIC
|
||||
assert len(item["children"]) == 1
|
||||
assert item["children"][0]["title"] == "test.mp3"
|
||||
assert item["children"][0]["media_class"] == MEDIA_CLASS_MUSIC
|
||||
|
@ -62,6 +64,7 @@ async def test_browse_media_parent_no_children():
|
|||
assert not item["can_play"]
|
||||
assert item["can_expand"]
|
||||
assert len(item["children"]) == 0
|
||||
assert item["children_media_class"] is None
|
||||
|
||||
|
||||
async def test_media_source_default_name():
|
||||
|
|
|
@ -409,6 +409,11 @@ class MockPlexLibrarySection:
|
|||
if self.title == "Photos":
|
||||
return "photo"
|
||||
|
||||
@property
|
||||
def TYPE(self):
|
||||
"""Return the library type."""
|
||||
return self.type
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""Mock the key identifier property."""
|
||||
|
|
|
@ -16,6 +16,9 @@ from homeassistant.components.media_player.const import (
|
|||
ATTR_MEDIA_TITLE,
|
||||
ATTR_MEDIA_VOLUME_MUTED,
|
||||
DOMAIN as MP_DOMAIN,
|
||||
MEDIA_CLASS_APP,
|
||||
MEDIA_CLASS_CHANNEL,
|
||||
MEDIA_CLASS_DIRECTORY,
|
||||
MEDIA_TYPE_APP,
|
||||
MEDIA_TYPE_APPS,
|
||||
MEDIA_TYPE_CHANNEL,
|
||||
|
@ -499,6 +502,7 @@ async def test_media_browse(hass, aioclient_mock, hass_ws_client):
|
|||
|
||||
assert msg["result"]
|
||||
assert msg["result"]["title"] == "Media Library"
|
||||
assert msg["result"]["media_class"] == MEDIA_CLASS_DIRECTORY
|
||||
assert msg["result"]["media_content_type"] == "library"
|
||||
assert msg["result"]["can_expand"]
|
||||
assert not msg["result"]["can_play"]
|
||||
|
@ -523,10 +527,12 @@ async def test_media_browse(hass, aioclient_mock, hass_ws_client):
|
|||
|
||||
assert msg["result"]
|
||||
assert msg["result"]["title"] == "Apps"
|
||||
assert msg["result"]["media_class"] == MEDIA_CLASS_DIRECTORY
|
||||
assert msg["result"]["media_content_type"] == MEDIA_TYPE_APPS
|
||||
assert msg["result"]["can_expand"]
|
||||
assert not msg["result"]["can_play"]
|
||||
assert len(msg["result"]["children"]) == 11
|
||||
assert msg["result"]["children_media_class"] == MEDIA_CLASS_APP
|
||||
|
||||
assert msg["result"]["children"][0]["title"] == "Satellite TV"
|
||||
assert msg["result"]["children"][0]["media_content_type"] == MEDIA_TYPE_APP
|
||||
|
@ -565,10 +571,12 @@ async def test_media_browse(hass, aioclient_mock, hass_ws_client):
|
|||
|
||||
assert msg["result"]
|
||||
assert msg["result"]["title"] == "Channels"
|
||||
assert msg["result"]["media_class"] == MEDIA_CLASS_DIRECTORY
|
||||
assert msg["result"]["media_content_type"] == MEDIA_TYPE_CHANNELS
|
||||
assert msg["result"]["can_expand"]
|
||||
assert not msg["result"]["can_play"]
|
||||
assert len(msg["result"]["children"]) == 2
|
||||
assert msg["result"]["children_media_class"] == MEDIA_CLASS_CHANNEL
|
||||
|
||||
assert msg["result"]["children"][0]["title"] == "WhatsOn"
|
||||
assert msg["result"]["children"][0]["media_content_type"] == MEDIA_TYPE_CHANNEL
|
||||
|
|
Loading…
Reference in New Issue