From 1aa9dbfd810676b36b5665387bd5151b48f6db5c Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Thu, 4 Mar 2021 21:12:23 +0100 Subject: [PATCH] better handling of chromecast group players --- music_assistant/constants.py | 2 +- music_assistant/managers/players.py | 12 +++++++++++ .../providers/chromecast/__init__.py | 10 ++++++--- .../providers/chromecast/models.py | 8 +++---- .../providers/chromecast/player.py | 21 +++++++++++++------ 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/music_assistant/constants.py b/music_assistant/constants.py index 389d110d..d599ff20 100755 --- a/music_assistant/constants.py +++ b/music_assistant/constants.py @@ -1,6 +1,6 @@ """All constants for Music Assistant.""" -__version__ = "0.1.4" +__version__ = "0.1.5" REQUIRED_PYTHON_VER = "3.8" # configuration keys/attributes diff --git a/music_assistant/managers/players.py b/music_assistant/managers/players.py index 2bd93d6a..bcb964c4 100755 --- a/music_assistant/managers/players.py +++ b/music_assistant/managers/players.py @@ -103,6 +103,18 @@ class PlayerManager: """Return Player by player_id or None if player does not exist.""" return self._players.get(player_id) + @callback + def get_player_by_name( + self, name: str, provider_id: Optional[str] = None + ) -> Optional[Player]: + """Return Player by name.""" + for player in self: + if provider_id is not None and player.provider_id != provider_id: + continue + if player.name == name or player.player_state.name == name: + return player + return None + @callback def get_player_provider(self, player_id: str) -> PlayerProvider: """Return provider by player_id or None if player does not exist.""" diff --git a/music_assistant/providers/chromecast/__init__.py b/music_assistant/providers/chromecast/__init__.py index f1f5939c..a0041392 100644 --- a/music_assistant/providers/chromecast/__init__.py +++ b/music_assistant/providers/chromecast/__init__.py @@ -73,9 +73,6 @@ class ChromecastProvider(PlayerProvider): def __chromecast_add_update_callback(self, cast_uuid, cast_service_name): """Handle zeroconf discovery of a new or updated chromecast.""" # pylint: disable=unused-argument - if cast_uuid is None: - return # Discovered chromecast without uuid? - service = self._listener.services[cast_uuid] cast_info = ChromecastInfo( services=service[0], @@ -86,11 +83,18 @@ class ChromecastProvider(PlayerProvider): port=service[5], ) cast_info.fill_out_missing_chromecast_info(self.mass.zeroconf) + if cast_info.uuid is None: + return # Discovered chromecast without uuid? player_id = cast_info.uuid LOGGER.debug( "Chromecast discovered: %s (%s)", cast_info.friendly_name, player_id ) player = self.mass.players.get_player(player_id) + if not player and cast_info.is_audio_group: + # audio groups may reappear with new uuid, try to handle that + player = self.mass.players.get_player_by_name( + cast_info.friendly_name, PROV_ID + ) if not player: player = ChromecastPlayer(self.mass, cast_info) # if player was already added, the player will take care of reconnects itself. diff --git a/music_assistant/providers/chromecast/models.py b/music_assistant/providers/chromecast/models.py index 2c08064f..a96ae10e 100644 --- a/music_assistant/providers/chromecast/models.py +++ b/music_assistant/providers/chromecast/models.py @@ -59,7 +59,7 @@ class ChromecastInfo: http_group_status = None if self.uuid: http_group_status = dial.get_multizone_status( - self.host, + None, services=self.services, zconf=zconf, ) @@ -71,10 +71,10 @@ class ChromecastInfo: else: # Fill out some missing information (friendly_name, uuid) via HTTP dial. http_device_status = dial.get_device_status( - self.host, services=self.services, zconf=zconf + None, services=self.services, zconf=zconf ) - if not self.uuid and http_device_status: - self.uuid = http_device_status.uuid + if http_device_status: + self.uuid = str(http_device_status.uuid) if not self.friendly_name and http_device_status: self.friendly_name = http_device_status.friendly_name if not self.model_name and http_device_status: diff --git a/music_assistant/providers/chromecast/player.py b/music_assistant/providers/chromecast/player.py index ee1ea31d..442ebf46 100644 --- a/music_assistant/providers/chromecast/player.py +++ b/music_assistant/providers/chromecast/player.py @@ -76,9 +76,15 @@ class ChromecastPlayer(Player): @property def powered(self) -> bool: """Return power state of this player.""" + if not self._chromecast or not self.cast_status: + return False if self.is_group_player: - return self._chromecast.is_idle - return not self.cast_status.volume_muted if self.cast_status else False + return ( + self.media_status.player_is_playing + or self.media_status.player_is_paused + or self.media_status.player_is_idle + ) + return not self.cast_status.volume_muted and not self.cast_status.is_stand_by @property def should_poll(self) -> bool: @@ -88,6 +94,8 @@ class ChromecastPlayer(Player): @property def state(self) -> PlaybackState: """Return the state of the player.""" + if self.cast_status and self.cast_status.is_stand_by: + return PlaybackState.Off if self.media_status is None: return PlaybackState.Stopped if self.media_status.player_is_playing: @@ -192,10 +200,11 @@ class ChromecastPlayer(Player): self._available = False self.cast_status = chromecast.status self.media_status = chromecast.media_controller.status - mz_controller = MultizoneController(chromecast.uuid) - chromecast.register_handler(mz_controller) - chromecast.mz_controller = mz_controller - chromecast.start() + if self._cast_info.is_audio_group: + mz_controller = MultizoneController(chromecast.uuid) + chromecast.register_handler(mz_controller) + chromecast.mz_controller = mz_controller + self._chromecast.start() def set_cast_info(self, cast_info: ChromecastInfo) -> None: """Set (or update) the cast discovery info.""" -- 2.34.1