Fix mass user playlists (and queue items) limited to 50 items (#1293)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sat, 11 May 2024 17:44:41 +0000 (19:44 +0200)
committerGitHub <noreply@github.com>
Sat, 11 May 2024 17:44:41 +0000 (19:44 +0200)
music_assistant/common/models/media_items.py
music_assistant/server/controllers/media/playlists.py
music_assistant/server/controllers/player_queues.py
music_assistant/server/providers/builtin/__init__.py
music_assistant/server/providers/filesystem_local/base.py

index 83af5cfa6b54daee19ab8af353bcf807dd2afbb4..366eab78139b336371abd1732359ad12fba9c608 100644 (file)
@@ -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
index 0bbc6ad2dc2b459502ecddb77f79d3671f7d3b65..b4d3261d1a23a7d90bdd6b9839f3b94898faa20f 100644 (file)
@@ -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
index 605acc14a0fe2ec2388d41ac706f2cb132980dd8..c93323c8f9dabaa14129950c26955395b65245f6 100644 (file)
@@ -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]),
index 48a4bcf0da6fb3f27f68f7d6f6a0dc0c46f719f9..009e8905535425b6e038705e6c56c6dd6d7a297f 100644 (file)
@@ -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."""
index ab75b96c5ad5b48a0a7e8aa664ed878ca141d260..d1ae90e890577003c81712a497ac1c0042065082 100644 (file)
@@ -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(