From 97f92a96ee2751a02df182a483eac58609793ca4 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sun, 11 Aug 2024 19:04:49 +0200 Subject: [PATCH] Fixes for global search (#1554) Prefer library items in global search --- music_assistant/client/music.py | 2 + .../server/controllers/media/base.py | 2 +- music_assistant/server/controllers/music.py | 39 +++++++++++++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/music_assistant/client/music.py b/music_assistant/client/music.py index 9cdadb3a..5a57d247 100644 --- a/music_assistant/client/music.py +++ b/music_assistant/client/music.py @@ -416,6 +416,7 @@ class Music: search_query: str, media_types: list[MediaType] = MediaType.ALL, limit: int = 50, + library_only: bool = False, ) -> SearchResults: """Perform global search for media items on all providers. @@ -429,6 +430,7 @@ class Music: search_query=search_query, media_types=media_types, limit=limit, + library_only=library_only, ), ) diff --git a/music_assistant/server/controllers/media/base.py b/music_assistant/server/controllers/media/base.py index 9e3444ea..4f077975 100644 --- a/music_assistant/server/controllers/media/base.py +++ b/music_assistant/server/controllers/media/base.py @@ -274,7 +274,7 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta): # create safe search string search_query = search_query.replace("/", " ").replace("'", "") if provider_instance_id_or_domain == "library": - return [item async for item in await self.iter_library_items(search=search_query)] + return await self.library_items(search=search_query, limit=limit) prov = self.mass.get_provider(provider_instance_id_or_domain) if prov is None: return [] diff --git a/music_assistant/server/controllers/music.py b/music_assistant/server/controllers/music.py index 0dc7864c..4db16ee7 100644 --- a/music_assistant/server/controllers/music.py +++ b/music_assistant/server/controllers/music.py @@ -177,6 +177,7 @@ class MusicController(CoreController): search_query: str, media_types: list[MediaType] = MediaType.ALL, limit: int = 25, + library_only: bool = False, ) -> SearchResults: """Perform global search for media items on all providers. @@ -219,8 +220,10 @@ class MusicController(CoreController): else: return SearchResults() - # include results from all (unique) music providers + # include results from library + all (unique) music providers + search_providers = [] if library_only else self.get_unique_providers() results_per_provider: list[SearchResults] = await asyncio.gather( + self.search_library(search_query, media_types, limit=limit), *[ self.search_provider( search_query, @@ -228,8 +231,8 @@ class MusicController(CoreController): media_types, limit=limit, ) - for provider_instance in self.get_unique_providers() - ] + for provider_instance in search_providers + ], ) # return result from all providers while keeping index # so the result is sorted as each provider delivered @@ -278,7 +281,6 @@ class MusicController(CoreController): :param search_query: Search query :param provider_instance_id_or_domain: instance_id or domain of the provider to perform the search on. - :param provider_instance: instance id of the provider to perform the search on. :param media_types: A list of media_types to include. :param limit: number of items to return in the search (per type). """ @@ -311,6 +313,35 @@ class MusicController(CoreController): ) return result + async def search_library( + self, + search_query: str, + media_types: list[MediaType], + limit: int = 10, + ) -> SearchResults: + """Perform search on the library. + + :param search_query: Search query + :param media_types: A list of media_types to include. + :param limit: number of items to return in the search (per type). + """ + result = SearchResults() + for media_type in media_types: + ctrl = self.get_controller(media_type) + search_results = await ctrl.search(search_query, "library", limit=limit) + if search_results: + if media_type == MediaType.ARTIST: + result.artists = search_results + elif media_type == MediaType.ALBUM: + result.albums = search_results + elif media_type == MediaType.TRACK: + result.tracks = search_results + elif media_type == MediaType.PLAYLIST: + result.playlists = search_results + elif media_type == MediaType.RADIO: + result.radio = search_results + return result + @api_command("music/browse") async def browse(self, path: str | None = None) -> list[MediaItemType]: """Browse Music providers.""" -- 2.34.1