From: Marcel van der Veldt Date: Tue, 25 Feb 2025 10:32:13 +0000 (+0100) Subject: Fix: Don't use look_up key in player providers X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=37c84b11fcff37d8b423587cf22c02222b3ddb5f;p=music-assistant-server.git Fix: Don't use look_up key in player providers It casuses some side effects --- diff --git a/music_assistant/controllers/config.py b/music_assistant/controllers/config.py index 28881412..2e9ca087 100644 --- a/music_assistant/controllers/config.py +++ b/music_assistant/controllers/config.py @@ -570,7 +570,10 @@ class ConfigController: msg = f"Unknown provider domain: {provider_domain}" raise KeyError(msg) config_entries = await self.get_provider_config_entries(provider_domain) - instance_id = f"{manifest.domain}--{shortuuid.random(8)}" + if manifest.multi_instance: + instance_id = f"{manifest.domain}--{shortuuid.random(8)}" + else: + instance_id = manifest.domain default_config: ProviderConfig = ProviderConfig.parse( config_entries, { @@ -911,7 +914,10 @@ class ConfigController: if existing and not manifest.multi_instance: msg = f"Provider {manifest.name} does not support multiple instances" raise ValueError(msg) - instance_id = f"{manifest.domain}--{shortuuid.random(8)}" + if manifest.multi_instance: + instance_id = f"{manifest.domain}--{shortuuid.random(8)}" + else: + instance_id = manifest.domain # all checks passed, create config object config_entries = await self.get_provider_config_entries( provider_domain=provider_domain, instance_id=instance_id, values=values diff --git a/music_assistant/controllers/players.py b/music_assistant/controllers/players.py index 88d8af65..d03016ab 100644 --- a/music_assistant/controllers/players.py +++ b/music_assistant/controllers/players.py @@ -933,9 +933,9 @@ class PlayerController(CoreController): msg = f"Player {player_id} is already registered" raise AlreadyRegisteredError(msg) - # make sure that the player's provider is set to the lookup key (=instance id) + # make sure that the player's provider is set to the instance_id prov = self.mass.get_provider(player.provider) - if not prov or prov.lookup_key != player.provider: + if not prov or prov.instance_id != player.provider: raise RuntimeError(f"Invalid provider ID given: {player.provider}") # make sure a default config exists diff --git a/music_assistant/providers/airplay/provider.py b/music_assistant/providers/airplay/provider.py index 29e3ac98..0d405953 100644 --- a/music_assistant/providers/airplay/provider.py +++ b/music_assistant/providers/airplay/provider.py @@ -522,7 +522,7 @@ class AirplayProvider(PlayerProvider): volume = FALLBACK_VOLUME mass_player = Player( player_id=player_id, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=display_name, available=True, @@ -538,7 +538,7 @@ class AirplayProvider(PlayerProvider): PlayerFeature.VOLUME_SET, }, volume_level=volume, - can_group_with={self.lookup_key}, + can_group_with={self.instance_id}, enabled_by_default=not is_broken_raop_model(manufacturer, model), ) await self.mass.players.register_or_update(mass_player) diff --git a/music_assistant/providers/bluesound/__init__.py b/music_assistant/providers/bluesound/__init__.py index 534f728b..ebaa8d42 100644 --- a/music_assistant/providers/bluesound/__init__.py +++ b/music_assistant/providers/bluesound/__init__.py @@ -277,7 +277,7 @@ class BluesoundPlayerProvider(PlayerProvider): bluos_player.mass_player = mass_player = Player( player_id=self.player_id, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=name, available=True, @@ -294,7 +294,7 @@ class BluesoundPlayerProvider(PlayerProvider): }, needs_poll=True, poll_interval=30, - can_group_with={self.lookup_key}, + can_group_with={self.instance_id}, ) await self.mass.players.register(mass_player) diff --git a/music_assistant/providers/chromecast/__init__.py b/music_assistant/providers/chromecast/__init__.py index 32f12f79..c472e7a4 100644 --- a/music_assistant/providers/chromecast/__init__.py +++ b/music_assistant/providers/chromecast/__init__.py @@ -413,7 +413,7 @@ class ChromecastProvider(PlayerProvider): ), player=Player( player_id=player_id, - provider=self.lookup_key, + provider=self.instance_id, type=player_type, name=cast_info.friendly_name, available=False, diff --git a/music_assistant/providers/dlna/__init__.py b/music_assistant/providers/dlna/__init__.py index eb07e45f..c1d623b9 100644 --- a/music_assistant/providers/dlna/__init__.py +++ b/music_assistant/providers/dlna/__init__.py @@ -480,7 +480,7 @@ class DLNAPlayerProvider(PlayerProvider): udn=udn, player=Player( player_id=udn, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=udn, available=False, diff --git a/music_assistant/providers/hass_players/__init__.py b/music_assistant/providers/hass_players/__init__.py index e9ab4da3..20cdeaa5 100644 --- a/music_assistant/providers/hass_players/__init__.py +++ b/music_assistant/providers/hass_players/__init__.py @@ -476,7 +476,7 @@ class HomeAssistantPlayers(PlayerProvider): player = Player( player_id=state["entity_id"], - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=state["attributes"]["friendly_name"], available=state["state"] not in UNAVAILABLE_STATES, diff --git a/music_assistant/providers/player_group/__init__.py b/music_assistant/providers/player_group/__init__.py index bc2ecb52..52388977 100644 --- a/music_assistant/providers/player_group/__init__.py +++ b/music_assistant/providers/player_group/__init__.py @@ -291,7 +291,7 @@ class PlayerGroupProvider(PlayerProvider): return base_entries # guard if TYPE_CHECKING: player_provider = cast(PlayerProvider, player_provider) - assert player_provider.lookup_key != self.lookup_key + assert player_provider.instance_id != self.instance_id if not (child_player := next((x for x in player_provider.players), None)): return base_entries # guard @@ -584,7 +584,7 @@ class PlayerGroupProvider(PlayerProvider): if ProviderFeature.SYNC_PLAYERS not in player_prov.supported_features: msg = f"Provider {player_prov.name} does not support creating groups" raise UnsupportedFeaturedException(msg) - group_type = player_prov.lookup_key # just in case only domain was sent + group_type = player_prov.instance_id # just in case only domain was sent new_group_id = f"{prefix}{shortuuid.random(8).lower()}" # cleanup list, just in case the frontend sends some garbage @@ -730,7 +730,7 @@ class PlayerGroupProvider(PlayerProvider): async def _register_all_players(self) -> None: """Register all (virtual/fake) group players in the Player controller.""" player_configs = await self.mass.config.get_player_configs( - self.lookup_key, include_values=True + self.instance_id, include_values=True ) for player_config in player_configs: if self.mass.players.get(player_config.player_id): @@ -773,9 +773,9 @@ class PlayerGroupProvider(PlayerProvider): ) can_group_with = { # allow grouping with all providers, except the playergroup provider itself - x.lookup_key + x.instance_id for x in self.mass.players.providers - if x.lookup_key != self.lookup_key + if x.instance_id != self.instance_id } player_features.add(PlayerFeature.MULTI_DEVICE_DSP) elif player_provider := self.mass.get_provider(group_type): @@ -784,7 +784,7 @@ class PlayerGroupProvider(PlayerProvider): player_provider = cast(PlayerProvider, player_provider) model_name = "Sync Group" manufacturer = self.mass.get_provider(group_type).name - can_group_with = {player_provider.lookup_key} + can_group_with = {player_provider.instance_id} for feature in (PlayerFeature.PAUSE, PlayerFeature.VOLUME_MUTE, PlayerFeature.ENQUEUE): if all(feature in x.supported_features for x in player_provider.players): player_features.add(feature) @@ -800,7 +800,7 @@ class PlayerGroupProvider(PlayerProvider): player = Player( player_id=group_player_id, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.GROUP, name=name, available=True, @@ -904,12 +904,12 @@ class PlayerGroupProvider(PlayerProvider): if group_type == GROUP_TYPE_UNIVERSAL: can_group_with = { # allow grouping with all providers, except the playergroup provider itself - x.lookup_key + x.instance_id for x in self.mass.players.providers - if x.lookup_key != self.lookup_key + if x.instance_id != self.instance_id } elif sync_player_provider := self.mass.get_provider(group_type): - can_group_with = {sync_player_provider.lookup_key} + can_group_with = {sync_player_provider.instance_id} else: can_group_with = {} player.can_group_with = can_group_with @@ -1028,7 +1028,7 @@ class PlayerGroupProvider(PlayerProvider): x for x in members if (player := self.mass.players.get(x)) - and player.provider == player_provider.lookup_key + and player.provider == player_provider.instance_id ] # cleanup members - filter out impossible choices syncgroup_childs: list[str] = [] diff --git a/music_assistant/providers/slimproto/__init__.py b/music_assistant/providers/slimproto/__init__.py index b44a5bfe..c98f5e17 100644 --- a/music_assistant/providers/slimproto/__init__.py +++ b/music_assistant/providers/slimproto/__init__.py @@ -647,7 +647,7 @@ class SlimprotoProvider(PlayerProvider): # player does not yet exist, create it player = Player( player_id=player_id, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=slimplayer.name, available=True, @@ -666,7 +666,7 @@ class SlimprotoProvider(PlayerProvider): PlayerFeature.VOLUME_MUTE, PlayerFeature.ENQUEUE, }, - can_group_with={self.lookup_key}, + can_group_with={self.instance_id}, ) await self.mass.players.register_or_update(player) diff --git a/music_assistant/providers/snapcast/__init__.py b/music_assistant/providers/snapcast/__init__.py index e6e92ad2..ea24ddfe 100644 --- a/music_assistant/providers/snapcast/__init__.py +++ b/music_assistant/providers/snapcast/__init__.py @@ -370,7 +370,7 @@ class SnapCastProvider(PlayerProvider): ) player = Player( player_id=player_id, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=snap_client.friendly_name, available=snap_client.connected, @@ -385,7 +385,7 @@ class SnapCastProvider(PlayerProvider): PlayerFeature.VOLUME_MUTE, }, synced_to=self._synced_to(player_id), - can_group_with={self.lookup_key}, + can_group_with={self.instance_id}, ) asyncio.run_coroutine_threadsafe( self.mass.players.register_or_update(player), loop=self.mass.loop diff --git a/music_assistant/providers/sonos/player.py b/music_assistant/providers/sonos/player.py index 3aa32b02..97ae9005 100644 --- a/music_assistant/providers/sonos/player.py +++ b/music_assistant/providers/sonos/player.py @@ -127,7 +127,7 @@ class SonosPlayer: # instantiate the MA player self.mass_player = mass_player = Player( player_id=self.player_id, - provider=self.prov.lookup_key, + provider=self.prov.instance_id, type=PlayerType.PLAYER, name=self.discovery_info["device"]["name"] or self.discovery_info["device"]["modelDisplayName"], @@ -140,7 +140,7 @@ class SonosPlayer: supported_features=supported_features, # NOTE: strictly taken we can have multiple sonos households # but for now we assume we only have one - can_group_with={self.prov.lookup_key}, + can_group_with={self.prov.instance_id}, ) if SonosCapability.LINE_IN in self.discovery_info["device"]["capabilities"]: mass_player.source_list.append(PLAYER_SOURCE_MAP[SOURCE_LINE_IN]) @@ -308,7 +308,7 @@ class SonosPlayer: if x.player_id != airplay_player.player_id ) else: - self.mass_player.can_group_with = {self.prov.lookup_key} + self.mass_player.can_group_with = {self.prov.instance_id} self.mass_player.synced_to = None else: # player is group child (synced to another player) diff --git a/music_assistant/providers/sonos_s1/__init__.py b/music_assistant/providers/sonos_s1/__init__.py index c06056e3..ebb2e5aa 100644 --- a/music_assistant/providers/sonos_s1/__init__.py +++ b/music_assistant/providers/sonos_s1/__init__.py @@ -429,7 +429,7 @@ class SonosPlayerProvider(PlayerProvider): if not (mass_player := self.mass.players.get(soco.uid)): mass_player = Player( player_id=soco.uid, - provider=self.lookup_key, + provider=self.instance_id, type=PlayerType.PLAYER, name=soco.player_name, available=True, @@ -441,7 +441,7 @@ class SonosPlayerProvider(PlayerProvider): ), needs_poll=True, poll_interval=30, - can_group_with={self.lookup_key}, + can_group_with={self.instance_id}, ) self.sonosplayers[player_id] = sonos_player = SonosPlayer( self, diff --git a/music_assistant/providers/spotify_connect/__init__.py b/music_assistant/providers/spotify_connect/__init__.py index eadbfc38..3c4104aa 100644 --- a/music_assistant/providers/spotify_connect/__init__.py +++ b/music_assistant/providers/spotify_connect/__init__.py @@ -122,7 +122,7 @@ class SpotifyConnectProvider(PluginProvider): self._librespot_started = asyncio.Event() self.named_pipe = f"/tmp/{self.instance_id}" # noqa: S108 self._source_details = PluginSource( - id=self.lookup_key, + id=self.instance_id, name=self.manifest.name, # we set passive to true because we # dont allow this source to be selected directly @@ -276,7 +276,7 @@ class SpotifyConnectProvider(PluginProvider): # initiate playback by selecting this source on the default player self.logger.error("Initiating playback on %s", self.mass_player_id) self.mass.create_task( - self.mass.players.select_source(self.mass_player_id, self.lookup_key) + self.mass.players.select_source(self.mass_player_id, self.instance_id) ) self._source_details.in_use_by = self.mass_player_id