From: Marcel van der Veldt Date: Thu, 26 Feb 2026 01:21:59 +0000 (+0100) Subject: Fix really strange bug with airplay X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=c76ff9b64eea8cd83b0118d7f692952e12f96671;p=music-assistant-server.git Fix really strange bug with airplay --- diff --git a/music_assistant/models/player.py b/music_assistant/models/player.py index 98e1c18e..801643a8 100644 --- a/music_assistant/models/player.py +++ b/music_assistant/models/player.py @@ -1123,7 +1123,11 @@ class Player(ABC): changed_values = self.__calculate_player_state() if prev_media_checksum != self._get_player_media_checksum(): # current media changed, call the media updated callback - self._on_player_media_updated() + # debounce the callback to avoid multiple calls when multiple + # state updates happen in a short time + self.mass.call_later( + 1, self._on_player_media_updated, task_id=f"player_media_updated_{self.player_id}" + ) # ignore some values that are not relevant for the state changed_values.pop("elapsed_time_last_updated", None) changed_values.pop("extra_attributes.seq_no", None) diff --git a/music_assistant/providers/airplay/protocols/_protocol.py b/music_assistant/providers/airplay/protocols/_protocol.py index fe7dced6..791528c3 100644 --- a/music_assistant/providers/airplay/protocols/_protocol.py +++ b/music_assistant/providers/airplay/protocols/_protocol.py @@ -58,6 +58,8 @@ class AirPlayProtocol(ABC): self._total_bytes_sent = 0 self._stream_bytes_sent = 0 self._connected = asyncio.Event() + self._metadata_checksum = "" + self._last_metadata_sent: float = 0.0 @property def running(self) -> bool: @@ -80,6 +82,9 @@ class AirPlayProtocol(ABC): # to ignore it the first time # https://github.com/music-assistant/support/issues/3330 self.mass.call_later(2, self.send_cli_command(f"VOLUME={self.player.volume_level}")) + # we also need to send the metadata after connection, because some players (e.g. Sonos) + # simply won't start playback until they receive the metadata ?! + self.mass.call_later(2, self.player._on_player_media_updated) async def stop(self, force: bool = False) -> None: """ @@ -121,8 +126,20 @@ class AirPlayProtocol(ABC): title = metadata.title or "" artist = metadata.artist or "" album = metadata.album or "" + + metadata_checksum = f"{title}|{artist}|{album}|{duration}|{metadata.image_url}" + if ( + metadata_checksum == self._metadata_checksum + and time.time() - self._last_metadata_sent <= 2 + ): + # metadata has not changed since last time, skip sending to CLI + return + self._metadata_checksum = metadata_checksum + self._last_metadata_sent = time.time() + cmd = f"TITLE={title}\nARTIST={artist}\nALBUM={album}\n" cmd += f"DURATION={duration}\nPROGRESS=0\nACTION=SENDMETA\n" + await self.send_cli_command(cmd) # get image if metadata.image_url: