Fix for media content type case in Squeezebox (#143099)

This commit is contained in:
peteS-UK 2025-04-17 17:56:28 +01:00 committed by GitHub
parent c7290908cc
commit 8355727eb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 66 additions and 64 deletions

View File

@ -22,34 +22,34 @@ from homeassistant.helpers.network import is_internal_request
from .const import UNPLAYABLE_TYPES from .const import UNPLAYABLE_TYPES
LIBRARY = [ LIBRARY = [
"Favorites", "favorites",
"Artists", "artists",
"Albums", "albums",
"Tracks", "tracks",
"Playlists", "playlists",
"Genres", "genres",
"New Music", "new music",
"Album Artists", "album artists",
"Apps", "apps",
"Radios", "radios",
] ]
MEDIA_TYPE_TO_SQUEEZEBOX: dict[str | MediaType, str] = { MEDIA_TYPE_TO_SQUEEZEBOX: dict[str | MediaType, str] = {
"Favorites": "favorites", "favorites": "favorites",
"Artists": "artists", "artists": "artists",
"Albums": "albums", "albums": "albums",
"Tracks": "titles", "tracks": "titles",
"Playlists": "playlists", "playlists": "playlists",
"Genres": "genres", "genres": "genres",
"New Music": "new music", "new music": "new music",
"Album Artists": "album artists", "album artists": "album artists",
MediaType.ALBUM: "album", MediaType.ALBUM: "album",
MediaType.ARTIST: "artist", MediaType.ARTIST: "artist",
MediaType.TRACK: "title", MediaType.TRACK: "title",
MediaType.PLAYLIST: "playlist", MediaType.PLAYLIST: "playlist",
MediaType.GENRE: "genre", MediaType.GENRE: "genre",
"Apps": "apps", MediaType.APPS: "apps",
"Radios": "radios", "radios": "radios",
} }
SQUEEZEBOX_ID_BY_TYPE: dict[str | MediaType, str] = { SQUEEZEBOX_ID_BY_TYPE: dict[str | MediaType, str] = {
@ -58,22 +58,20 @@ SQUEEZEBOX_ID_BY_TYPE: dict[str | MediaType, str] = {
MediaType.TRACK: "track_id", MediaType.TRACK: "track_id",
MediaType.PLAYLIST: "playlist_id", MediaType.PLAYLIST: "playlist_id",
MediaType.GENRE: "genre_id", MediaType.GENRE: "genre_id",
"Favorites": "item_id", "favorites": "item_id",
MediaType.APPS: "item_id", MediaType.APPS: "item_id",
} }
CONTENT_TYPE_MEDIA_CLASS: dict[str | MediaType, dict[str, MediaClass | str]] = { CONTENT_TYPE_MEDIA_CLASS: dict[str | MediaType, dict[str, MediaClass | str]] = {
"Favorites": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK}, "favorites": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
"Apps": {"item": MediaClass.DIRECTORY, "children": MediaClass.APP}, "radios": {"item": MediaClass.DIRECTORY, "children": MediaClass.APP},
"Radios": {"item": MediaClass.DIRECTORY, "children": MediaClass.APP}, "artists": {"item": MediaClass.DIRECTORY, "children": MediaClass.ARTIST},
"App": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK}, "albums": {"item": MediaClass.DIRECTORY, "children": MediaClass.ALBUM},
"Artists": {"item": MediaClass.DIRECTORY, "children": MediaClass.ARTIST}, "tracks": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
"Albums": {"item": MediaClass.DIRECTORY, "children": MediaClass.ALBUM}, "playlists": {"item": MediaClass.DIRECTORY, "children": MediaClass.PLAYLIST},
"Tracks": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK}, "genres": {"item": MediaClass.DIRECTORY, "children": MediaClass.GENRE},
"Playlists": {"item": MediaClass.DIRECTORY, "children": MediaClass.PLAYLIST}, "new music": {"item": MediaClass.DIRECTORY, "children": MediaClass.ALBUM},
"Genres": {"item": MediaClass.DIRECTORY, "children": MediaClass.GENRE}, "album artists": {"item": MediaClass.DIRECTORY, "children": MediaClass.ARTIST},
"New Music": {"item": MediaClass.DIRECTORY, "children": MediaClass.ALBUM},
"Album Artists": {"item": MediaClass.DIRECTORY, "children": MediaClass.ARTIST},
MediaType.ALBUM: {"item": MediaClass.ALBUM, "children": MediaClass.TRACK}, MediaType.ALBUM: {"item": MediaClass.ALBUM, "children": MediaClass.TRACK},
MediaType.ARTIST: {"item": MediaClass.ARTIST, "children": MediaClass.ALBUM}, MediaType.ARTIST: {"item": MediaClass.ARTIST, "children": MediaClass.ALBUM},
MediaType.TRACK: {"item": MediaClass.TRACK, "children": ""}, MediaType.TRACK: {"item": MediaClass.TRACK, "children": ""},
@ -91,17 +89,15 @@ CONTENT_TYPE_TO_CHILD_TYPE: dict[
MediaType.PLAYLIST: MediaType.PLAYLIST, MediaType.PLAYLIST: MediaType.PLAYLIST,
MediaType.ARTIST: MediaType.ALBUM, MediaType.ARTIST: MediaType.ALBUM,
MediaType.GENRE: MediaType.ARTIST, MediaType.GENRE: MediaType.ARTIST,
"Artists": MediaType.ARTIST, "artists": MediaType.ARTIST,
"Albums": MediaType.ALBUM, "albums": MediaType.ALBUM,
"Tracks": MediaType.TRACK, "tracks": MediaType.TRACK,
"Playlists": MediaType.PLAYLIST, "playlists": MediaType.PLAYLIST,
"Genres": MediaType.GENRE, "genres": MediaType.GENRE,
"Favorites": None, # can only be determined after inspecting the item "favorites": None, # can only be determined after inspecting the item
"Apps": MediaClass.APP, "radios": MediaClass.APP,
"Radios": MediaClass.APP, "new music": MediaType.ALBUM,
"App": None, # can only be determined after inspecting the item "album artists": MediaType.ARTIST,
"New Music": MediaType.ALBUM,
"Album Artists": MediaType.ARTIST,
MediaType.APPS: MediaType.APP, MediaType.APPS: MediaType.APP,
MediaType.APP: MediaType.TRACK, MediaType.APP: MediaType.TRACK,
} }
@ -173,7 +169,7 @@ def _build_response_known_app(
def _build_response_favorites(item: dict[str, Any]) -> BrowseMedia: def _build_response_favorites(item: dict[str, Any]) -> BrowseMedia:
"""Build item for Favorites.""" """Build item for favorites."""
if "album_id" in item: if "album_id" in item:
return BrowseMedia( return BrowseMedia(
media_content_id=str(item["album_id"]), media_content_id=str(item["album_id"]),
@ -183,21 +179,21 @@ def _build_response_favorites(item: dict[str, Any]) -> BrowseMedia:
can_expand=True, can_expand=True,
can_play=True, can_play=True,
) )
if item["hasitems"] and not item["isaudio"]: if item.get("hasitems") and not item.get("isaudio"):
return BrowseMedia( return BrowseMedia(
media_content_id=item["id"], media_content_id=item["id"],
title=item["title"], title=item["title"],
media_content_type="Favorites", media_content_type="favorites",
media_class=CONTENT_TYPE_MEDIA_CLASS["Favorites"]["item"], media_class=CONTENT_TYPE_MEDIA_CLASS["favorites"]["item"],
can_expand=True, can_expand=True,
can_play=False, can_play=False,
) )
return BrowseMedia( return BrowseMedia(
media_content_id=item["id"], media_content_id=item["id"],
title=item["title"], title=item["title"],
media_content_type="Favorites", media_content_type="favorites",
media_class=CONTENT_TYPE_MEDIA_CLASS[MediaType.TRACK]["item"], media_class=CONTENT_TYPE_MEDIA_CLASS[MediaType.TRACK]["item"],
can_expand=item["hasitems"], can_expand=bool(item.get("hasitems")),
can_play=bool(item["isaudio"] and item.get("url")), can_play=bool(item["isaudio"] and item.get("url")),
) )
@ -220,7 +216,7 @@ def _get_item_thumbnail(
item_type, item["id"], artwork_track_id item_type, item["id"], artwork_track_id
) )
elif search_type in ["Apps", "Radios"]: elif search_type in ["apps", "radios"]:
item_thumbnail = player.generate_image_url(item["icon"]) item_thumbnail = player.generate_image_url(item["icon"])
if item_thumbnail is None: if item_thumbnail is None:
item_thumbnail = item.get("image_url") # will not be proxied by HA item_thumbnail = item.get("image_url") # will not be proxied by HA
@ -265,10 +261,10 @@ async def build_item_response(
for item in result["items"]: for item in result["items"]:
# Force the item id to a string in case it's numeric from some lms # Force the item id to a string in case it's numeric from some lms
item["id"] = str(item.get("id", "")) item["id"] = str(item.get("id", ""))
if search_type == "Favorites": if search_type == "favorites":
child_media = _build_response_favorites(item) child_media = _build_response_favorites(item)
elif search_type in ["Apps", "Radios"]: elif search_type in ["apps", "radios"]:
# item["cmd"] contains the name of the command to use with the cli for the app # item["cmd"] contains the name of the command to use with the cli for the app
# add the command to the dictionaries # add the command to the dictionaries
if item["title"] == "Search" or item.get("type") in UNPLAYABLE_TYPES: if item["title"] == "Search" or item.get("type") in UNPLAYABLE_TYPES:
@ -364,11 +360,11 @@ async def library_payload(
assert media_class["children"] is not None assert media_class["children"] is not None
library_info["children"].append( library_info["children"].append(
BrowseMedia( BrowseMedia(
title=item, title=item.title(),
media_class=media_class["children"], media_class=media_class["children"],
media_content_id=item, media_content_id=item,
media_content_type=item, media_content_type=item,
can_play=item not in ["Favorites", "Apps", "Radios"], can_play=item not in ["favorites", "apps", "radios"],
can_expand=True, can_expand=True,
) )
) )

View File

@ -446,6 +446,9 @@ class SqueezeBoxMediaPlayerEntity(SqueezeboxEntity, MediaPlayerEntity):
"""Send the play_media command to the media player.""" """Send the play_media command to the media player."""
index = None index = None
if media_type:
media_type = media_type.lower()
enqueue: MediaPlayerEnqueue | None = kwargs.get(ATTR_MEDIA_ENQUEUE) enqueue: MediaPlayerEnqueue | None = kwargs.get(ATTR_MEDIA_ENQUEUE)
if enqueue == MediaPlayerEnqueue.ADD: if enqueue == MediaPlayerEnqueue.ADD:
@ -617,6 +620,9 @@ class SqueezeBoxMediaPlayerEntity(SqueezeboxEntity, MediaPlayerEntity):
media_content_id, media_content_id,
) )
if media_content_type:
media_content_type = media_content_type.lower()
if media_content_type in [None, "library"]: if media_content_type in [None, "library"]:
return await library_payload(self.hass, self._player, self._browse_data) return await library_payload(self.hass, self._player, self._browse_data)

View File

@ -65,21 +65,21 @@ async def test_async_browse_media_root(
assert response["success"] assert response["success"]
result = response["result"] result = response["result"]
for idx, item in enumerate(result["children"]): for idx, item in enumerate(result["children"]):
assert item["title"] == LIBRARY[idx] assert item["title"].lower() == LIBRARY[idx]
@pytest.mark.parametrize( @pytest.mark.parametrize(
("category", "child_count"), ("category", "child_count"),
[ [
("Favorites", 4), ("favorites", 4),
("Artists", 4), ("artists", 4),
("Albums", 4), ("albums", 4),
("Playlists", 4), ("playlists", 4),
("Genres", 4), ("genres", 4),
("New Music", 4), ("new music", 4),
("Album Artists", 4), ("album artists", 4),
("Apps", 3), ("apps", 3),
("Radios", 3), ("radios", 3),
], ],
) )
async def test_async_browse_media_with_subitems( async def test_async_browse_media_with_subitems(