From: Marcel van der Veldt Date: Sat, 21 Feb 2026 22:59:42 +0000 (+0100) Subject: Small simplification for GroupPlayer X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=11449c639099511cf7d7412ab9efe570571c335c;p=music-assistant-server.git Small simplification for GroupPlayer --- diff --git a/music_assistant/models/player.py b/music_assistant/models/player.py index 0ef7d258..9575dd2b 100644 --- a/music_assistant/models/player.py +++ b/music_assistant/models/player.py @@ -1988,26 +1988,3 @@ __all__ = [ "PlayerSource", "PlayerState", ] - - -class GroupPlayer(Player): - """Helper class for a (generic) group player.""" - - _attr_type: PlayerType = PlayerType.GROUP - - @cached_property - def synced_to(self) -> str | None: - """Return the id of the player this player is synced to (sync leader).""" - # default implementation: groups can't be synced - return None - - async def volume_set(self, volume_level: int) -> None: - """ - Handle VOLUME_SET command on the player. - - :param volume_level: volume level (0..100) to set on the player. - """ - # Default implementation: - # This will set the (relative) volume level on all child players. - # free to override if you want to handle this differently. - await self.mass.players.set_group_volume(self, volume_level) diff --git a/music_assistant/providers/sync_group/player.py b/music_assistant/providers/sync_group/player.py index 097045b9..9a2be8d1 100644 --- a/music_assistant/providers/sync_group/player.py +++ b/music_assistant/providers/sync_group/player.py @@ -15,7 +15,7 @@ from music_assistant.constants import ( CONF_DYNAMIC_GROUP_MEMBERS, CONF_GROUP_MEMBERS, ) -from music_assistant.models.player import DeviceInfo, GroupPlayer, Player, PlayerMedia +from music_assistant.models.player import DeviceInfo, Player, PlayerMedia from .constants import CONF_ENTRY_SGP_NOTE, EXTRA_FEATURES_FROM_MEMBERS @@ -23,7 +23,7 @@ if TYPE_CHECKING: from .provider import SyncGroupProvider -class SyncGroupPlayer(GroupPlayer): +class SyncGroupPlayer(Player): """Sync Group Player implementation.""" _attr_type: PlayerType = PlayerType.GROUP @@ -49,6 +49,12 @@ class SyncGroupPlayer(GroupPlayer): """Return if the player is a dynamic group player.""" return bool(self.config.get_value(CONF_DYNAMIC_GROUP_MEMBERS, False)) + @cached_property + def synced_to(self) -> str | None: + """Return the id of the player this player is synced to (sync leader).""" + # groups can't be synced + return None + async def on_config_updated(self) -> None: """Handle logic when the player is loaded or updated.""" # Config is only available after the player was registered @@ -128,6 +134,7 @@ class SyncGroupPlayer(GroupPlayer): if ( PlayerFeature.SET_MEMBERS in player.state.supported_features and player.state.can_group_with + and not player.state.active_group ): temp_can_group_with.add(player.player_id) return temp_can_group_with @@ -219,14 +226,21 @@ class SyncGroupPlayer(GroupPlayer): prev_leader = self.sync_leader was_playing = self.playback_state == PlaybackState.PLAYING needs_restart = False - if was_playing and prev_leader and prev_leader.player_id in (player_ids_to_remove or []): + if prev_leader and prev_leader.player_id in (player_ids_to_remove or []): # We're removing the current sync leader while the group is active # We need to select a new leader before we can handle the member changes - await self.mass.players._handle_cmd_stop(prev_leader.player_id) - await asyncio.sleep(1) + self.logger.debug( + "Removing current sync leader %s from group %s while it is active, " + "selecting a new leader and dissolving the current syncgroup", + prev_leader.display_name, + self.display_name, + ) + if was_playing: + await self.mass.players._handle_cmd_stop(prev_leader.player_id) + await asyncio.sleep(1) await self._dissolve_syncgroup() await asyncio.sleep(2) - needs_restart = True + needs_restart = was_playing cur_leader = self._select_sync_leader(new_members=player_ids_to_add) # handle additions diff --git a/music_assistant/providers/universal_group/player.py b/music_assistant/providers/universal_group/player.py index ba04fe62..88b5bafa 100644 --- a/music_assistant/providers/universal_group/player.py +++ b/music_assistant/providers/universal_group/player.py @@ -30,7 +30,7 @@ from music_assistant.constants import ( ) from music_assistant.helpers.audio import get_player_filter_params from music_assistant.helpers.util import TaskManager -from music_assistant.models.player import DeviceInfo, GroupPlayer, PlayerMedia +from music_assistant.models.player import DeviceInfo, Player, PlayerMedia from music_assistant.providers.universal_group.constants import UGP_FORMAT from .constants import CONF_ENTRY_SAMPLE_RATES_UGP, CONFIG_ENTRY_UGP_NOTE @@ -47,15 +47,17 @@ BASE_FEATURES = { } -class UniversalGroupPlayer(GroupPlayer): +class UniversalGroupPlayer(Player): """Universal Group Player implementation.""" + _attr_type: PlayerType = PlayerType.GROUP + def __init__( self, provider: UniversalGroupProvider, player_id: str, ) -> None: - """Initialize GroupPlayer instance.""" + """Initialize UniversalGroupPlayer instance.""" super().__init__(provider, player_id) self.stream: UGPStream | None = None self._attr_name = self.config.name or f"Universal Group {player_id}" @@ -88,6 +90,12 @@ class UniversalGroupPlayer(GroupPlayer): """Return if the player requires flow mode.""" return True + @cached_property + def synced_to(self) -> str | None: + """Return the id of the player this player is synced to (sync leader).""" + # groups can't be synced + return None + @property def can_group_with(self) -> set[str]: """Return the id's of players this player can group with."""