some small fixes/tweaks
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 25 Aug 2024 11:05:39 +0000 (13:05 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 25 Aug 2024 11:05:39 +0000 (13:05 +0200)
music_assistant/common/models/player_queue.py
music_assistant/server/controllers/player_queues.py
music_assistant/server/controllers/streams.py
music_assistant/server/providers/airplay/__init__.py

index 97a2cd6ec6e11c393e52624e2f293bb22b7f2300..4684aeff22fd930a47d69a7c4e9af2a69305648b 100644 (file)
@@ -42,7 +42,7 @@ class PlayerQueue(DataClassDictMixin):
     flow_mode_start_index: int = 0
     stream_finished: bool | None = None
     end_of_track_reached: bool | None = None
-    queue_items_last_updated: float = time.time()
+    queue_version: str = ""
 
     @property
     def corrected_elapsed_time(self) -> float:
index 63c4e155af2ac145a840c7d871b475526a1777be..8c3a256d3e31f38772bd40a44f80600b11fb0f31 100644 (file)
@@ -8,6 +8,8 @@ import time
 from contextlib import suppress
 from typing import TYPE_CHECKING, Any, TypedDict
 
+import shortuuid
+
 from music_assistant.common.helpers.util import get_changed_keys
 from music_assistant.common.models.config_entries import (
     ConfigEntry,
@@ -221,10 +223,7 @@ class PlayerQueuesController(CoreController):
             if player.active_group and player.active_group != player.player_id:
                 return self.get_active_queue(player.active_group)
             # active_source may be filled with other queue id
-            if player.active_source != player_id and (
-                queue := self.get_active_queue(player.active_source)
-            ):
-                return queue
+            return self.get(player.active_source) or self.get(player_id)
         return self.get(player_id)
 
     # Queue commands
@@ -887,6 +886,7 @@ class PlayerQueuesController(CoreController):
         queue.state = player.state
         queue.current_item = self.get_item(queue_id, queue.current_index)
         queue.next_item = self._get_next_item(queue_id)
+
         # correct elapsed time when seeking
         if (
             queue.current_item
@@ -934,6 +934,8 @@ class PlayerQueuesController(CoreController):
         # handle enqueuing of next item to play
         if not queue.flow_mode or queue.stream_finished:
             self._check_enqueue_next(player, queue, prev_state, new_state)
+
+        queue.resume_pos = queue.corrected_elapsed_time
         # do not send full updates if only time was updated
         if changed_keys == {"elapsed_time"}:
             self.mass.signal_event(
@@ -1090,8 +1092,8 @@ class PlayerQueuesController(CoreController):
     def signal_update(self, queue_id: str, items_changed: bool = False) -> None:
         """Signal state changed of given queue."""
         queue = self._queues[queue_id]
+        queue.queue_version = shortuuid.random(8)
         if items_changed:
-            queue.queue_items_last_updated = time.time()
             self.mass.signal_event(EventType.QUEUE_ITEMS_UPDATED, object_id=queue_id, data=queue)
             # save items in cache
             self.mass.create_task(
index 4728526919d7127cb46c2002832369af23bcaee4..70416197e2f64def6e0a90f3c40070eca895d258 100644 (file)
@@ -574,8 +574,8 @@ class StreamsController(CoreController):
 
             # set some basic vars
             pcm_sample_size = int(pcm_format.sample_rate * (pcm_format.bit_depth / 8) * 2)
-            crossfade_duration = await self.mass.config.get_player_config_value(
-                queue.queue_id, CONF_CROSSFADE_DURATION
+            crossfade_duration = self.mass.config.get_raw_player_config_value(
+                queue.queue_id, CONF_CROSSFADE_DURATION, 10
             )
             crossfade_size = int(pcm_sample_size * crossfade_duration)
             bytes_written = 0
index 6205f2e4a7f56202427d459ea509d31602d617bc..aee97eec08b651f4cdce6a98ad2b0062a0ccf39a 100644 (file)
@@ -646,6 +646,9 @@ class AirplayProvider(PlayerProvider):
         """Handle PLAY MEDIA on given player."""
         async with self._play_media_lock:
             player = self.mass.players.get(player_id)
+            # set the active source for the player to the media queue
+            # this accounts for syncgroups and linked players (e.g. sonos)
+            player.active_source = media.queue_id
             if player.synced_to:
                 # should not happen, but just in case
                 raise RuntimeError("Player is synced")
@@ -804,7 +807,9 @@ class AirplayProvider(PlayerProvider):
         group_leader.group_childs.remove(player_id)
         player.synced_to = None
         await self.cmd_stop(player_id)
-        self.mass.players.update(player_id)
+        # make sure that the player manager gets an update
+        self.mass.players.update(player.player_id, skip_forward=True)
+        self.mass.players.update(group_leader.player_id, skip_forward=True)
 
     async def _getcliraop_binary(self):
         """Find the correct raop/airplay binary belonging to the platform."""