"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)
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
from .provider import SyncGroupProvider
-class SyncGroupPlayer(GroupPlayer):
+class SyncGroupPlayer(Player):
"""Sync Group Player implementation."""
_attr_type: PlayerType = PlayerType.GROUP
"""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
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
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
)
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
}
-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}"
"""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."""