Fix: Ignore airplay for broken Sonos devices
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sat, 16 Nov 2024 14:50:10 +0000 (15:50 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Sat, 16 Nov 2024 14:50:10 +0000 (15:50 +0100)
music_assistant/providers/airplay/const.py
music_assistant/providers/airplay/provider.py

index ea106adc701494972e7451f3c9bc242878c3a169..ff636979b889c2b1c32f406486dc8f94ec8c7ea3 100644 (file)
@@ -29,3 +29,15 @@ AIRPLAY_FLOW_PCM_FORMAT = AudioFormat(
 AIRPLAY_PCM_FORMAT = AudioFormat(
     content_type=ContentType.from_bit_depth(16), sample_rate=44100, bit_depth=16
 )
+
+IGNORE_RAOP_SONOS_MODELS = (
+    # A recent fw update of newer gen Sonos speakers block RAOP (airplay 1) support,
+    # basically rendering our airplay implementation useless on these devices.
+    # This list contains the models that are known to have this issue.
+    # Hopefully the issue won't spread to other models.
+    "Era 100",
+    "Era 300",
+    "Move 2",
+    "Roam 2",
+    "Arc Ultra",
+)
index b4a5f5bb73b36ccaec1110a2607f38e71c31bc53..39f722a359fbd5a0d8df809b4529d4714b03958b 100644 (file)
@@ -52,6 +52,7 @@ from .const import (
     CONF_PASSWORD,
     CONF_READ_AHEAD_BUFFER,
     FALLBACK_VOLUME,
+    IGNORE_RAOP_SONOS_MODELS,
 )
 from .helpers import convert_airplay_volume, get_model_from_am, get_primary_ip_address
 from .player import AirPlayPlayer
@@ -450,17 +451,30 @@ class AirplayProvider(PlayerProvider):
             return
         self.logger.debug("Discovered Airplay device %s on %s", display_name, address)
         manufacturer, model = get_model_from_am(info.decoded_properties.get("am"))
+
+        default_enabled = not info.server.startswith("Sonos-")
+        if not self.mass.config.get_raw_player_config_value(player_id, "enabled", default_enabled):
+            self.logger.debug("Ignoring %s in discovery as it is disabled.", display_name)
+            return
+
         if "apple tv" in model.lower():
             # For now, we ignore the Apple TV until we implement the authentication.
             # maybe we can simply use pyatv only for this part?
             # the cliraop application has already been prepared to accept the secret.
-            self.logger.debug(
-                "Ignoring %s in discovery due to authentication requirement.", display_name
+            self.logger.info(
+                "Ignoring %s in discovery because it is not yet supported.", display_name
             )
             return
-        if not self.mass.config.get_raw_player_config_value(player_id, "enabled", True):
-            self.logger.debug("Ignoring %s in discovery as it is disabled.", display_name)
+        if model in IGNORE_RAOP_SONOS_MODELS:
+            # for now completely ignore the sonos models that have broken RAOP support
+            # its very much unlikely that this will ever be fixed by Sonos
+            # revisit this once/if we have support for airplay 2.
+            self.logger.info(
+                "Ignoring %s in discovery as it is a known Sonos model with broken RAOP support.",
+                display_name,
+            )
             return
+
         self._players[player_id] = AirPlayPlayer(self, player_id, info, address)
         if not (volume := await self.mass.cache.get(player_id, base_key=CACHE_KEY_PREV_VOLUME)):
             volume = FALLBACK_VOLUME