Update Music Assistant browse media types (#143249)

* Update Music Assistant browse media types

* changes based on review comments
This commit is contained in:
Jozef Kruszynski 2025-04-25 18:32:48 +02:00 committed by GitHub
parent d61e39743b
commit 09ad14bc28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 105 additions and 43 deletions

View File

@ -21,12 +21,16 @@ if TYPE_CHECKING:
from music_assistant_client import MusicAssistantClient
MEDIA_TYPE_RADIO = "radio"
MEDIA_TYPE_PODCAST_EPISODE = "podcast_episode"
MEDIA_TYPE_AUDIOBOOK = "audiobook"
PLAYABLE_MEDIA_TYPES = [
MediaType.PLAYLIST,
MediaType.ALBUM,
MediaType.ARTIST,
MEDIA_TYPE_RADIO,
MediaType.PODCAST,
MEDIA_TYPE_AUDIOBOOK,
MediaType.TRACK,
]
@ -35,6 +39,8 @@ LIBRARY_ALBUMS = "albums"
LIBRARY_TRACKS = "tracks"
LIBRARY_PLAYLISTS = "playlists"
LIBRARY_RADIO = "radio"
LIBRARY_PODCASTS = "podcasts"
LIBRARY_AUDIOBOOKS = "audiobooks"
LIBRARY_TITLE_MAP = {
@ -43,6 +49,8 @@ LIBRARY_TITLE_MAP = {
LIBRARY_TRACKS: "Tracks",
LIBRARY_PLAYLISTS: "Playlists",
LIBRARY_RADIO: "Radio stations",
LIBRARY_PODCASTS: "Podcasts",
LIBRARY_AUDIOBOOKS: "Audiobooks",
}
LIBRARY_MEDIA_CLASS_MAP = {
@ -51,10 +59,13 @@ LIBRARY_MEDIA_CLASS_MAP = {
LIBRARY_TRACKS: MediaClass.TRACK,
LIBRARY_PLAYLISTS: MediaClass.PLAYLIST,
LIBRARY_RADIO: MediaClass.MUSIC, # radio is not accepted by HA
LIBRARY_PODCASTS: MediaClass.PODCAST,
LIBRARY_AUDIOBOOKS: MediaClass.DIRECTORY, # audiobook is not accepted by HA
}
MEDIA_CONTENT_TYPE_FLAC = "audio/flac"
THUMB_SIZE = 200
SORT_NAME_DESC = "sort_name_desc"
def media_source_filter(item: BrowseMedia) -> bool:
@ -89,13 +100,16 @@ async def async_browse_media(
return await build_playlists_listing(mass)
if media_content_id == LIBRARY_RADIO:
return await build_radio_listing(mass)
if media_content_id == LIBRARY_PODCASTS:
return await build_podcasts_listing(mass)
if media_content_id == LIBRARY_AUDIOBOOKS:
return await build_audiobooks_listing(mass)
if "artist" in media_content_id:
return await build_artist_items_listing(mass, media_content_id)
if "album" in media_content_id:
return await build_album_items_listing(mass, media_content_id)
if "playlist" in media_content_id:
return await build_playlist_items_listing(mass, media_content_id)
raise BrowseError(f"Media not found: {media_content_type} / {media_content_id}")
@ -148,16 +162,15 @@ async def build_playlists_listing(mass: MusicAssistantClient) -> BrowseMedia:
can_play=False,
can_expand=True,
children_media_class=media_class,
children=sorted(
[
children=[
build_item(mass, item, can_expand=True)
# we only grab the first page here because the
# HA media browser does not support paging
for item in await mass.music.get_library_playlists(limit=500)
for item in await mass.music.get_library_playlists(
limit=500, order_by=SORT_NAME_DESC
)
if item.available
],
key=lambda x: x.title,
),
)
@ -201,16 +214,15 @@ async def build_artists_listing(mass: MusicAssistantClient) -> BrowseMedia:
can_play=False,
can_expand=True,
children_media_class=media_class,
children=sorted(
[
children=[
build_item(mass, artist, can_expand=True)
# we only grab the first page here because the
# HA media browser does not support paging
for artist in await mass.music.get_library_artists(limit=500)
for artist in await mass.music.get_library_artists(
limit=500, order_by=SORT_NAME_DESC
)
if artist.available
],
key=lambda x: x.title,
),
)
@ -252,16 +264,15 @@ async def build_albums_listing(mass: MusicAssistantClient) -> BrowseMedia:
can_play=False,
can_expand=True,
children_media_class=media_class,
children=sorted(
[
children=[
build_item(mass, album, can_expand=True)
# we only grab the first page here because the
# HA media browser does not support paging
for album in await mass.music.get_library_albums(limit=500)
for album in await mass.music.get_library_albums(
limit=500, order_by=SORT_NAME_DESC
)
if album.available
],
key=lambda x: x.title,
),
)
@ -301,16 +312,61 @@ async def build_tracks_listing(mass: MusicAssistantClient) -> BrowseMedia:
can_play=False,
can_expand=True,
children_media_class=media_class,
children=sorted(
[
children=[
build_item(mass, track, can_expand=False)
# we only grab the first page here because the
# HA media browser does not support paging
for track in await mass.music.get_library_tracks(limit=500)
for track in await mass.music.get_library_tracks(
limit=500, order_by=SORT_NAME_DESC
)
if track.available
],
key=lambda x: x.title,
),
)
async def build_podcasts_listing(mass: MusicAssistantClient) -> BrowseMedia:
"""Build Podcasts browse listing."""
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_PODCASTS]
return BrowseMedia(
media_class=MediaClass.DIRECTORY,
media_content_id=LIBRARY_PODCASTS,
media_content_type=MediaType.PODCAST,
title=LIBRARY_TITLE_MAP[LIBRARY_PODCASTS],
can_play=False,
can_expand=True,
children_media_class=media_class,
children=[
build_item(mass, podcast, can_expand=False)
# we only grab the first page here because the
# HA media browser does not support paging
for podcast in await mass.music.get_library_podcasts(
limit=500, order_by=SORT_NAME_DESC
)
if podcast.available
],
)
async def build_audiobooks_listing(mass: MusicAssistantClient) -> BrowseMedia:
"""Build Audiobooks browse listing."""
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_AUDIOBOOKS]
return BrowseMedia(
media_class=MediaClass.DIRECTORY,
media_content_id=LIBRARY_AUDIOBOOKS,
media_content_type=DOMAIN,
title=LIBRARY_TITLE_MAP[LIBRARY_AUDIOBOOKS],
can_play=False,
can_expand=True,
children_media_class=media_class,
children=[
build_item(mass, audiobook, can_expand=False)
# we only grab the first page here because the
# HA media browser does not support paging
for audiobook in await mass.music.get_library_audiobooks(
limit=500, order_by=SORT_NAME_DESC
)
if audiobook.available
],
)
@ -329,7 +385,9 @@ async def build_radio_listing(mass: MusicAssistantClient) -> BrowseMedia:
build_item(mass, track, can_expand=False, media_class=media_class)
# we only grab the first page here because the
# HA media browser does not support paging
for track in await mass.music.get_library_radios(limit=500)
for track in await mass.music.get_library_radios(
limit=500, order_by=SORT_NAME_DESC
)
if track.available
],
)

View File

@ -9,7 +9,9 @@ from homeassistant.components.music_assistant.const import DOMAIN
from homeassistant.components.music_assistant.media_browser import (
LIBRARY_ALBUMS,
LIBRARY_ARTISTS,
LIBRARY_AUDIOBOOKS,
LIBRARY_PLAYLISTS,
LIBRARY_PODCASTS,
LIBRARY_RADIO,
LIBRARY_TRACKS,
async_browse_media,
@ -25,8 +27,10 @@ from .common import setup_integration_from_fixtures
(LIBRARY_PLAYLISTS, MediaType.PLAYLIST, "library://playlist/40"),
(LIBRARY_ARTISTS, MediaType.ARTIST, "library://artist/127"),
(LIBRARY_ALBUMS, MediaType.ALBUM, "library://album/396"),
(LIBRARY_TRACKS, MediaType.TRACK, "library://track/486"),
(LIBRARY_TRACKS, MediaType.TRACK, "library://track/456"),
(LIBRARY_RADIO, DOMAIN, "library://radio/1"),
(LIBRARY_PODCASTS, MediaType.PODCAST, "library://podcast/6"),
(LIBRARY_AUDIOBOOKS, DOMAIN, "library://audiobook/1"),
("artist", MediaType.ARTIST, "library://album/115"),
("album", MediaType.ALBUM, "library://track/247"),
("playlist", DOMAIN, "tidal--Ah76MuMg://track/77616130"),