chore: MusicCast player config improvements + friendly names (#2178)
authorFabian Munkes <105975993+fmunkes@users.noreply.github.com>
Wed, 7 May 2025 17:17:33 +0000 (19:17 +0200)
committerGitHub <noreply@github.com>
Wed, 7 May 2025 17:17:33 +0000 (19:17 +0200)
music_assistant/providers/musiccast/__init__.py
music_assistant/providers/musiccast/constants.py

index 746bb77f1fcd8270002cde3212d16a6df12551fa..1f227b0b4efaf110b33f7441c66a5c4fddcb96cd 100644 (file)
@@ -16,7 +16,7 @@ from aiohttp.client_exceptions import (
 from aiomusiccast.exceptions import MusicCastGroupException
 from aiomusiccast.musiccast_device import MusicCastDevice
 from aiomusiccast.pyamaha import MusicCastConnectionException
-from music_assistant_models.config_entries import ConfigEntry
+from music_assistant_models.config_entries import ConfigEntry, ConfigValueOption
 from music_assistant_models.enums import (
     ConfigEntryType,
     PlayerFeature,
@@ -54,7 +54,6 @@ from .constants import (
     MC_SOURCE_MAIN_SYNC,
     MC_SOURCE_MC_LINK,
     PLAYER_CONFIG_ENTRIES,
-    PLAYER_MAP_ZONE_SWITCH,
     PLAYER_ZONE_SPLITTER,
 )
 from .musiccast import (
@@ -198,23 +197,43 @@ class MusicCast(PlayerProvider):
         zone_entries: tuple[ConfigEntry, ...] = ()
         if zone_player := self._get_zone_player(player_id):
             if len(zone_player.physical_device.zone_devices) > 1:
-                zone_entries = (
-                    ConfigEntry(
-                        key=CONF_PLAYER_SWITCH_SOURCE_NON_NET,
-                        type=ConfigEntryType.STRING,
-                        label="Switch to this non-net source when leaving a group.",
-                        default_value=PLAYER_MAP_ZONE_SWITCH[zone_player.zone_name],
-                        description="The zone will switch to this source when leaving a "
-                        " group. It must be an input which doesn't require network connectivity.",
-                    ),
-                    ConfigEntry(
-                        key=CONF_PLAYER_TURN_OFF_ON_LEAVE,
-                        type=ConfigEntryType.BOOLEAN,
-                        label="Turn off the zone when it leaves a group.",
-                        default_value=False,
-                        description="Turn off the zone when it leaves a group.",
-                    ),
-                )
+                mass_player = self.mass.players.get(player_id)
+                assert mass_player is not None  # for type checking
+                source_options: list[ConfigValueOption] = []
+                allowed_sources = self._get_allowed_sources_zone_switch(zone_player)
+                for (
+                    source_id,
+                    source_name,
+                ) in zone_player.source_mapping.items():
+                    if source_id in allowed_sources:
+                        source_options.append(ConfigValueOption(title=source_name, value=source_id))
+                if len(source_options) == 0:
+                    # this should never happen
+                    self.logger.error(
+                        "The player %s has multiple zones, but lacks a non-net source to switch to."
+                        " Please report this on github or discord.",
+                        mass_player.display_name or mass_player.name,
+                    )
+                    zone_entries = ()
+                else:
+                    zone_entries = (
+                        ConfigEntry(
+                            key=CONF_PLAYER_SWITCH_SOURCE_NON_NET,
+                            label="Switch to this non-net source when leaving a group.",
+                            type=ConfigEntryType.STRING,
+                            options=source_options,
+                            default_value=source_options[0].value,
+                            description="The zone will switch to this source when leaving a  group."
+                            " It must be an input which doesn't require network connectivity.",
+                        ),
+                        ConfigEntry(
+                            key=CONF_PLAYER_TURN_OFF_ON_LEAVE,
+                            type=ConfigEntryType.BOOLEAN,
+                            label="Turn off the zone when it leaves a group.",
+                            default_value=False,
+                            description="Turn off the zone when it leaves a group.",
+                        ),
+                    )
 
         return base_entries + zone_entries + PLAYER_CONFIG_ENTRIES
 
@@ -342,6 +361,7 @@ class MusicCast(PlayerProvider):
         _input_sources: set[str] = set(zone_player.zone_data.input_list)
         _net_sources = set(MC_NETUSB_SOURCE_IDS)
         _net_sources.add(MC_SOURCE_MC_LINK)  # mc grouping source
+        _net_sources.add(MC_SOURCE_MAIN_SYNC)  # main zone sync
         return _input_sources.difference(_net_sources)
 
     async def _handle_zone_grouping(self, zone_player: MusicCastZoneDevice) -> None:
@@ -364,7 +384,9 @@ class MusicCast(PlayerProvider):
             mass_player = self.mass.players.get(player_id)
             assert mass_player is not None
             msg = (
-                f"The switch source you specified for {mass_player.name} is not allowed. "
+                "The switch source you specified for "
+                f"{mass_player.display_name or mass_player.name}"
+                " is not allowed. "
                 f"The source must be any of: {', '.join(sorted(_allowed_sources))} "
                 "Will use the first available source."
             )
@@ -645,13 +667,9 @@ class MusicCast(PlayerProvider):
             musiccast_player._log_allowed_sources = False
             player_main = musiccast_player.player_main
             assert player_main is not None
-            main_zone_device = musiccast_player.physical_device.zone_devices.get("main")
-            assert main_zone_device is not None
-            _allowed_sources = self._get_allowed_sources_zone_switch(main_zone_device)
             self.logger.info(
-                f"The player {player_main.name} has multiple zones. "
-                "Please use the player config to configure a non-net source  for grouping. "
-                f"Allowed values are: {', '.join(_allowed_sources)}. See docs."
+                f"The player {player_main.display_name or player_main.name} has multiple zones. "
+                "Please use the player config to configure a non-net source for grouping. "
             )
 
         self.musiccast_players[device_id] = musiccast_player
index 911ae5cca9ab662fec712d88b798a0038c503136..01d99985c4915bb450660269922a007596e33805 100644 (file)
@@ -28,12 +28,6 @@ MAIN_SWITCH_SOURCE_NON_NET = "audio1"
 PLAYER_ZONE2_SWITCH_SOURCE_NON_NET = "audio2"
 PLAYER_ZONE3_SWITCH_SOURCE_NON_NET = "audio3"
 PLAYER_ZONE4_SWITCH_SOURCE_NON_NET = "audio4"
-PLAYER_MAP_ZONE_SWITCH = {
-    "main": MAIN_SWITCH_SOURCE_NON_NET,
-    "zone2": PLAYER_ZONE2_SWITCH_SOURCE_NON_NET,
-    "zone3": PLAYER_ZONE3_SWITCH_SOURCE_NON_NET,
-    "zone4": PLAYER_ZONE4_SWITCH_SOURCE_NON_NET,
-}
 
 
 # MusicCast constants