From 733ba48c6ddaeb574a0f11de44d527ce4f362d33 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 11 May 2024 19:44:41 +0200 Subject: [PATCH] Fix mass user playlists (and queue items) limited to 50 items (#1293) --- music_assistant/common/models/media_items.py | 2 +- .../server/controllers/media/playlists.py | 8 +++++- .../server/controllers/player_queues.py | 2 +- .../server/providers/builtin/__init__.py | 27 ++++++++++++------- .../server/providers/filesystem_local/base.py | 2 +- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/music_assistant/common/models/media_items.py b/music_assistant/common/models/media_items.py index 83af5cfa..366eab78 100644 --- a/music_assistant/common/models/media_items.py +++ b/music_assistant/common/models/media_items.py @@ -577,7 +577,7 @@ class PagedItems(Generic[_T]): self.limit = limit self.offset = offset self.total = total - if total is None and offset == 0 and count != limit: + if total is None and offset == 0 and count > limit: self.total = count if total is None and offset and count < limit: self.total = offset + count diff --git a/music_assistant/server/controllers/media/playlists.py b/music_assistant/server/controllers/media/playlists.py index 0bbc6ad2..b4d3261d 100644 --- a/music_assistant/server/controllers/media/playlists.py +++ b/music_assistant/server/controllers/media/playlists.py @@ -69,12 +69,18 @@ class PlaylistController(MediaControllerBase[Playlist]): if prefer_library_items: final_tracks = [] for track in tracks: - if db_item := await self.mass.music.tracks.get_library_item_by_prov_id( + # prefer library_item + # TODO: we could speedup this call by requesting all tracks at once + # but so far this doesn't seem to be that slow due to the paging + if track.provider == "library": + final_tracks.append(track) + elif db_item := await self.mass.music.tracks.get_library_item_by_prov_id( track.item_id, track.provider ): db_item.position = track.position final_tracks.append(db_item) else: + # fall back to the original playlist item if we do not know it in the db final_tracks.append(track) else: final_tracks = tracks diff --git a/music_assistant/server/controllers/player_queues.py b/music_assistant/server/controllers/player_queues.py index 605acc14..c93323c8 100644 --- a/music_assistant/server/controllers/player_queues.py +++ b/music_assistant/server/controllers/player_queues.py @@ -212,7 +212,7 @@ class PlayerQueuesController(CoreController): return PagedItems(items=[], limit=limit, offset=offset) return PagedItems( - items=self._queue_items[queue_id][offset:limit], + items=self._queue_items[queue_id][offset : offset + limit], limit=limit, offset=offset, total=len(self._queue_items[queue_id]), diff --git a/music_assistant/server/providers/builtin/__init__.py b/music_assistant/server/providers/builtin/__init__.py index 48a4bcf0..009e8905 100644 --- a/music_assistant/server/providers/builtin/__init__.py +++ b/music_assistant/server/providers/builtin/__init__.py @@ -38,7 +38,7 @@ from music_assistant.common.models.media_items import ( Track, ) from music_assistant.common.models.streamdetails import StreamDetails -from music_assistant.constants import MASS_LOGO, VARIOUS_ARTISTS_FANART +from music_assistant.constants import DB_SCHEMA_VERSION, MASS_LOGO, VARIOUS_ARTISTS_FANART from music_assistant.server.helpers.tags import AudioTags, parse_tags from music_assistant.server.models.music_provider import MusicProvider @@ -234,7 +234,7 @@ class BuiltinProvider(MusicProvider): images=[DEFAULT_THUMB] if prov_playlist_id in COLLAGE_IMAGE_PLAYLISTS else [DEFAULT_THUMB, DEFAULT_FANART], - cache_checksum=str(time.time()), + cache_checksum=str(int(time.time())), ), ) # user created universal playlist @@ -256,7 +256,7 @@ class BuiltinProvider(MusicProvider): owner="Music Assistant", is_editable=True, ) - playlist.metadata.cache_checksum = str(stored_item.get("last_updated", 0)) + playlist.metadata.cache_checksum = f"{DB_SCHEMA_VERSION}.{stored_item.get('last_updated')}" if image_url := stored_item.get("image_url"): playlist.metadata.images = [ MediaItemImage( @@ -355,16 +355,21 @@ class BuiltinProvider(MusicProvider): return await self._get_builtin_playlist_tracks(prov_playlist_id) # user created universal playlist result: list[Track] = [] - playlist_items = await self._read_playlist_file_items(prov_playlist_id) - for index, uri in enumerate(playlist_items[offset:limit]): + playlist_items = await self._read_playlist_file_items(prov_playlist_id, offset, limit) + for index, uri in enumerate(playlist_items): try: - # get the provider item and not the full track from a regular 'get' call - # as we only need basic track info here media_type, provider_instance_id_or_domain, item_id = await parse_uri(uri) media_controller = self.mass.music.get_controller(media_type) - track = await media_controller.get_provider_item( + # prefer item already in the db + track = await media_controller.get_library_item_by_prov_id( item_id, provider_instance_id_or_domain ) + if track is None: + # get the provider item and not the full track from a regular 'get' call + # as we only need basic track info here + track = await media_controller.get_provider_item( + item_id, provider_instance_id_or_domain + ) track.position = offset + index result.append(track) except (MediaNotFoundError, InvalidDataError, ProviderUnavailableError) as err: @@ -552,7 +557,9 @@ class BuiltinProvider(MusicProvider): return result return result - async def _read_playlist_file_items(self, playlist_id: str) -> list[str]: + async def _read_playlist_file_items( + self, playlist_id: str, offset: int = 0, limit: int = 100000 + ) -> list[str]: """Return lines of a playlist file.""" playlist_file = os.path.join(self._playlists_dir, playlist_id) if not await asyncio.to_thread(os.path.isfile, playlist_file): @@ -562,7 +569,7 @@ class BuiltinProvider(MusicProvider): aiofiles.open(playlist_file, "r", encoding="utf-8") as _file, ): lines = await _file.readlines() - return [x.strip() for x in lines] + return [x.strip() for x in lines[offset : offset + limit]] async def _write_playlist_file_items(self, playlist_id: str, lines: list[str]) -> None: """Return lines of a playlist file.""" diff --git a/music_assistant/server/providers/filesystem_local/base.py b/music_assistant/server/providers/filesystem_local/base.py index ab75b96c..d1ae90e8 100644 --- a/music_assistant/server/providers/filesystem_local/base.py +++ b/music_assistant/server/providers/filesystem_local/base.py @@ -540,7 +540,7 @@ class FileSystemProviderBase(MusicProvider): else: playlist_lines = parse_pls(playlist_data) - playlist_lines = playlist_lines[offset:limit] + playlist_lines = playlist_lines[offset : offset + limit] for line_no, playlist_line in enumerate(playlist_lines): if track := await self._parse_playlist_line( -- 2.34.1