# - 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)
# 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."""
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