Fix group volume and player state after Players controller refactor (#2364)
authorMaxim Raznatovski <nda.mr43@gmail.com>
Fri, 5 Sep 2025 10:27:38 +0000 (12:27 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Sep 2025 10:27:38 +0000 (12:27 +0200)
music_assistant/controllers/players.py
music_assistant/models/player.py

index ce4f518853716b44876cb31630af41e4a05210a1..522f029fd9408ecb98563aac17ecc03461b24f98 100644 (file)
@@ -1356,6 +1356,16 @@ class PlayerController(CoreController):
                     # - the leader has DSP enabled
                     self.mass.create_task(self.mass.players.on_player_dsp_change(player_id))
 
+        if ATTR_GROUP_MEMBERS in changed_values:
+            # Removed group members also need to be updated since they are no longer part
+            # of this group and are available for playback again
+            prev_group_members = changed_values[ATTR_GROUP_MEMBERS][0] or []
+            new_group_members = changed_values[ATTR_GROUP_MEMBERS][1] or []
+            removed_members = set(prev_group_members) - set(new_group_members)
+            for player_id in removed_members:
+                if removed_player := self.get(player_id):
+                    self.mass.loop.call_soon(removed_player.update_state, True)
+
         # signal player update on the eventbus
         self.mass.signal_event(EventType.PLAYER_UPDATED, object_id=player_id, data=player)
 
@@ -1368,6 +1378,9 @@ class PlayerController(CoreController):
         # update/signal group player(s) when child updates
         for group_player in self._get_player_groups(player, powered_only=False):
             self.mass.loop.call_soon(group_player.update_state, True)
+        # update/signal manually synced to player when child updates
+        if (synced_to := player.synced_to) and (synced_to_player := self.get(synced_to)):
+            self.mass.loop.call_soon(synced_to_player.update_state, True)
 
     async def register_player_control(self, player_control: PlayerControl) -> None:
         """Register a new PlayerControl on the controller."""
index c64806493bb6f0e054167228f09ebff873004448..354fb08f06a223b2072a456003cb08635a5f1547 100644 (file)
@@ -289,6 +289,13 @@ class Player(ABC):
 
         If there are currently no group members, this should return an empty list.
         """
+        if self.type == PlayerType.PLAYER and (
+            len(self._attr_group_members) >= 1 and self.player_id not in self._attr_group_members
+        ):
+            # always ensure the player_id is in the group_members list for players
+            return [self.player_id, *self._attr_group_members]
+        elif self._attr_group_members == [self.player_id]:
+            return []
         return self._attr_group_members
 
     @property