Fix play from here for playlists and albums (#786)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 20 Jul 2023 16:39:11 +0000 (18:39 +0200)
committerGitHub <noreply@github.com>
Thu, 20 Jul 2023 16:39:11 +0000 (18:39 +0200)
* Fix play from here for playlists and albums

* bump frontend

music_assistant/common/models/media_items.py
music_assistant/server/controllers/media/base.py
music_assistant/server/controllers/player_queues.py
pyproject.toml
requirements_all.txt

index b881896d1e2bde277347bc6fdcfbcc30eccd5e11..e29ea475dcca917b2e168abfb5ec1b597b993f1a 100755 (executable)
@@ -268,12 +268,6 @@ class MediaItem(DataClassDictMixin):
         """Return (calculated) availability."""
         return any(x.available for x in self.provider_mappings)
 
-    @available.setter
-    def available(self, available: bool):
-        """Set availability."""
-        for provider_mapping in self.provider_mappings:
-            provider_mapping.available = available
-
     @property
     def image(self) -> MediaItemImage | None:
         """Return (first/random) image/thumb from metadata (if any)."""
@@ -293,6 +287,14 @@ class MediaItem(DataClassDictMixin):
         }
         self.provider_mappings.add(prov_mapping)
 
+    def __hash__(self) -> int:
+        """Return custom hash."""
+        return hash(self.uri)
+
+    def __eq__(self, other: ItemMapping) -> bool:
+        """Check equality of two items."""
+        return self.uri == other.uri
+
 
 @dataclass
 class ItemMapping(DataClassDictMixin):
@@ -323,11 +325,11 @@ class ItemMapping(DataClassDictMixin):
 
     def __hash__(self) -> int:
         """Return custom hash."""
-        return hash((self.media_type.value, self.provider, self.item_id))
+        return hash(self.uri)
 
-    def __eq__(self, other: ProviderMapping) -> bool:
+    def __eq__(self, other: ItemMapping) -> bool:
         """Check equality of two items."""
-        return self.__hash__() == other.__hash__()
+        return self.uri == other.uri
 
 
 @dataclass
index cc200801d9dafc320c4b5956f240abf455ec5c56..6ae70f694301f7c2e6a107b3fdf7d274365d9c5f 100644 (file)
@@ -415,10 +415,9 @@ class MediaControllerBase(Generic[ItemCls], metaclass=ABCMeta):
             item_id, provider_instance_id_or_domain
         )
         if fallback and not (isinstance(fallback, ItemMapping) and self.item_cls in (Track, Album)):
-            # simply return the fallback item (marked as unavailable)
+            # simply return the fallback item
             # NOTE: we only accept ItemMapping as fallback for flat items
             # so not for tracks and albums (which rely on other objects)
-            fallback.available = False
             return fallback
         # all options exhausted, we really can not find this item
         raise MediaNotFoundError(
index 5e9e59fe67bbe7928580c3bed32bd53843b7a972..d39656e2fd94da542c809c011e102b4880f766a5 100755 (executable)
@@ -150,12 +150,14 @@ class PlayerQueuesController(CoreController):
         media: MediaItemType | list[MediaItemType] | str | list[str],
         option: QueueOption = QueueOption.PLAY,
         radio_mode: bool = False,
+        start_item: str | None = None,
     ) -> None:
         """Play media item(s) on the given queue.
 
         - media: Media that should be played (MediaItem(s) or uri's).
         - queue_opt: Which enqueue mode to use.
         - radio_mode: Enable radio mode for the given item(s).
+        - start_item: Optional item to start the playlist or album from.
         """
         # ruff: noqa: PLR0915,PLR0912
         queue = self._queues[queue_id]
@@ -209,6 +211,17 @@ class PlayerQueuesController(CoreController):
                 # single track or radio item
                 tracks += [media_item]
 
+            # handle optional start item (play playlist from here feature)
+            if start_item is not None:
+                prev_items = []
+                next_items = []
+                for track in tracks:
+                    if next_items or track.item_id == start_item:
+                        next_items.append(track)
+                    else:
+                        prev_items.append(track)
+                tracks = next_items + prev_items
+
         # Use collected media items to calculate the radio if radio mode is on
         if radio_mode:
             tracks = await self._get_radio_tracks(queue_id)
index 5a913561183f7226e60be8c67e135c389ad02fb7..2ef649395e30db30368896059dccb8a0c09998ae 100644 (file)
@@ -37,7 +37,7 @@ server = [
   "python-slugify==8.0.1",
   "mashumaro==3.8.1",
   "memory-tempfile==2.2.3",
-  "music-assistant-frontend==2.0.3",
+  "music-assistant-frontend==2.0.4",
   "pillow==9.5.0",
   "unidecode==1.3.6",
   "xmltodict==0.13.0",
index 298c9c1d42e97bdc82f4ab0fc1935f240937c455..bda5f1bad7a4ff6c7d0179c5a320956f527d8627 100644 (file)
@@ -18,7 +18,7 @@ git+https://github.com/gieljnssns/python-radios.git@main
 ifaddr==0.2.0
 mashumaro==3.8.1
 memory-tempfile==2.2.3
-music-assistant-frontend==2.0.3
+music-assistant-frontend==2.0.4
 orjson==3.9.2
 pillow==9.5.0
 plexapi==4.14.0