output_format=AIRPLAY_PCM_FORMAT,
)
- # if an existing stream session is running, replace it with the new stream
+ # if an existing stream session is running, we could replace it with the new stream
if airplay_player.raop_stream and airplay_player.raop_stream.running:
- await airplay_player.raop_stream.session.replace_stream(audio_source)
- return
+ # check if we need to replace the stream
+ if airplay_player.raop_stream.prevent_playback:
+ # player is in prevent playback mode, we need to stop the stream
+ await airplay_player.cmd_stop(False)
+ else:
+ await airplay_player.raop_stream.session.replace_stream(audio_source)
+ return
# setup RaopStreamSession for player (and its sync childs if any)
sync_clients = self._get_sync_clients(player_id)
from music_assistant_models.config_entries import ConfigEntry, PlayerConfig
from music_assistant_models.enums import ConfigEntryType, MediaType, PlayerState, ProviderFeature
from music_assistant_models.errors import PlayerCommandFailed
-from music_assistant_models.player import DeviceInfo, PlayerMedia
+from music_assistant_models.player import DeviceInfo, Player, PlayerMedia
from zeroconf import ServiceStateChange
from music_assistant.constants import (
raise PlayerCommandFailed(msg)
# for now always reset the active session
sonos_player.client.player.group.active_session_id = None
- if airplay := sonos_player.get_linked_airplay_player(True):
+ if airplay_player := sonos_player.get_linked_airplay_player(True):
# airplay mode is enabled, redirect the command
self.logger.debug("Redirecting PLAY_MEDIA command to linked airplay player.")
- mass_player.active_source = airplay.active_source
- # Sonos has an annoying bug (for years already, and they dont seem to care),
- # where it looses its sync childs when airplay playback is (re)started.
- # Try to handle it here with this workaround.
- group_childs = [
- x for x in sonos_player.client.player.group.player_ids if x != player_id
- ]
- if group_childs:
- await self.mass.players.cmd_ungroup_many(group_childs)
- await self.mass.players.play_media(airplay.player_id, media)
- if group_childs:
- # ensure master player is first in the list
- group_childs = [sonos_player.player_id, *group_childs]
- await asyncio.sleep(5)
- await sonos_player.client.player.group.set_group_members(group_childs)
+ await self._play_media_airplay(sonos_player, airplay_player, media)
return
if media.media_type in (
MediaType.FLOW_STREAM,
) or media.queue_id.startswith("ugp_"):
# flow stream or plugin source playback
- # use the legacy playback method for this as it also
+ # always use the legacy (UPNP) playback method for this
await self._play_media_legacy(sonos_player, media)
return
# crossfading is handled by our streams controller
if sonos_player.client.player.group.play_modes.crossfade:
await sonos_player.client.player.group.set_play_modes(crossfade=False)
+
+ async def _play_media_airplay(
+ self,
+ sonos_player: SonosPlayer,
+ airplay_player: Player,
+ media: PlayerMedia,
+ ) -> None:
+ """Handle PLAY MEDIA using the legacy upnp api."""
+ player_id = sonos_player.player_id
+ mass_player = self.mass.players.get(player_id)
+ mass_player.active_source = airplay_player.active_source
+ if (
+ airplay_player.state == PlayerState.PLAYING
+ and airplay_player.active_source == media.queue_id
+ ):
+ # if the airplay player is already playing,
+ # the stream will be reused so no need to do the whole grouping thing below
+ await self.mass.players.play_media(airplay_player.player_id, media)
+ return
+
+ # Sonos has an annoying bug (for years already, and they dont seem to care),
+ # where it looses its sync childs when airplay playback is (re)started.
+ # Try to handle it here with this workaround.
+ group_childs = [x for x in sonos_player.client.player.group.player_ids if x != player_id]
+ if group_childs:
+ await self.mass.players.cmd_ungroup_many(group_childs)
+ await self.mass.players.play_media(airplay_player.player_id, media)
+ if group_childs:
+ # ensure master player is first in the list
+ group_childs = [sonos_player.player_id, *group_childs]
+ await asyncio.sleep(5)
+ await sonos_player.client.player.group.set_group_members(group_childs)