if player_id not in self._players:
return
player = self._players[player_id]
- # calculate active_source
+ # calculate active_source (if needed)
player.active_source = self._get_active_source(player)
# calculate group volume
player.group_volume = self._get_group_volume_level(player)
elif member.active_source == group_player.player_id:
# turn off child player when group turns off
tg.create_task(self.cmd_power(member.player_id, False))
+ member.active_source = None
# edge case: group turned on but no members are powered, power them all!
if not members_powered and power:
for member in self.iter_group_members(group_player, only_powered=False):
"""Return the active_source id for given player."""
# if player is synced, return group leader's active source
if player.synced_to and (parent_player := self.get(player.synced_to)):
- return parent_player.player_id
- if active_player_group := self._get_active_player_group(player):
- return active_player_group.player_id
+ return parent_player.active_source
+ # fallback to the first active group player
+ if player.powered:
+ for group_player in self._get_player_groups(
+ player, available_only=True, powered_only=True
+ ):
+ if group_player.state in (PlayerState.PLAYING, PlayerState.PAUSED):
+ return group_player.active_source
# defaults to the player's own player id if not active source set
return player.active_source or player.player_id
self.connected = False
self._connection_attempts = 0
self._connection_was_lost = False
- self._task = None
self._playing: interface.Playing | None = None
self.logger = self.mass.players.logger.getChild("airplay").getChild(self.player_id)
self.cliraop_proc: AsyncProcess | None = None
if self.atv:
self.atv.close()
self.atv = None
- if self._task:
- self._task.cancel()
- self._task = None
except Exception: # pylint: disable=broad-except
self.logger.exception("An error occurred while disconnecting")
mass_player.state = PlayerState.IDLE
self.mass.players.update(self.player_id)
- @property
- def is_connecting(self):
- """Return true if connection is in progress."""
- return self._task is not None
-
def address_updated(self, address):
"""Update cached address in config entry."""
self.logger.debug("Changing address to %s", address)
):
extra_args += ["-u"]
if self.mass.config.get_raw_player_config_value(
- atv_player.player_id, CONF_ALAC_ENCODE, False
+ atv_player.player_id, CONF_ALAC_ENCODE, True
):
extra_args += ["-a"]
if self.mass.config.get_raw_player_config_value(
# active source
if (
- status.content_id and castplayer.player_id in status.content_id
- ) or castplayer.cc.app_id == pychromecast.config.APP_MEDIA_RECEIVER:
+ status.content_id
+ and self.mass.streams.base_url in status.content_id
+ and castplayer.player_id in status.content_id
+ ):
castplayer.player.active_source = castplayer.player_id
else:
castplayer.player.active_source = castplayer.cc.app_display_name
if not self._valid:
return
if group_uuid == self.castplayer.player.active_source:
- self.castplayer.player.active_source = ""
+ self.castplayer.player.active_source = None
self.prov.logger.debug(
"%s is removed from multizone: %s", self.castplayer.player.display_name, group_uuid
)
return PlayerState.IDLE
@staticmethod
- def get_supported_features(device: DmrDevice) -> set(PlayerFeature):
+ def get_supported_features(device: DmrDevice) -> set[PlayerFeature]:
"""Get player features that are supported at this moment.
Supported features may change as the device enters different states.
# media info (track info)
self.mass_player.current_item_id = self.uri
- if self.uri and self.player_id in self.uri:
+ if self.uri and self.mass.streams.base_url in self.uri and self.player_id in self.uri:
self.mass_player.active_source = self.player_id
else:
self.mass_player.active_source = self.source_name
async def handle_async_init(self) -> None:
"""Handle async initialization of the provider."""
- self._throttler = Throttler(rate_limit=1, period=0.1)
+ self._throttler = Throttler(rate_limit=1, period=1)
self._cache_dir = CACHE_DIR
self._ap_workaround = False
# try to get a token, raise if that fails
async with self.mass.http_session.get(
url, headers=headers, params=kwargs, ssl=False, timeout=120
) as response:
- # get text before json so we can log the body in case of errorrs
+ # get text before json so we can log the body in case of errors
result = await response.text()
result = json_loads(result)
if "error" in result or ("status" in result and "error" in result["status"]):