From: Simon Vos Date: Fri, 2 Jan 2026 12:09:21 +0000 (+0100) Subject: Add configuration for Zeroconf discovery interfaces (#2880) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=d4320088c4524edc6ed032d714be5bdf0401432d;p=music-assistant-server.git Add configuration for Zeroconf discovery interfaces (#2880) feat(core): Add configuration for Zeroconf discovery interfaces - Add `zeroconf_interfaces` setting to allow choosing between 'default' and 'all' network interfaces for mDNS discovery. - Move ConfigController setup before AsyncZeroconf initialization in `MusicAssistant` to ensure config is available. - Initialize `AsyncZeroconf` based on the configured interface choice (`InterfaceChoice.All` vs `InterfaceChoice.Default`). --- diff --git a/music_assistant/constants.py b/music_assistant/constants.py index 906d4154..d9a5515a 100644 --- a/music_assistant/constants.py +++ b/music_assistant/constants.py @@ -101,6 +101,7 @@ CONF_USE_SSL: Final[str] = "use_ssl" CONF_VERIFY_SSL: Final[str] = "verify_ssl" CONF_SSL_FINGERPRINT: Final[str] = "ssl_fingerprint" CONF_AUTH_ALLOW_SELF_REGISTRATION: Final[str] = "auth_allow_self_registration" +CONF_ZEROCONF_INTERFACES: Final[str] = "zeroconf_interfaces" CONF_ENABLED: Final[str] = "enabled" # config default values @@ -688,6 +689,25 @@ CONF_ENTRY_LIBRARY_SYNC_ARTISTS = ConfigEntry( default_value=True, category="sync_options", ) + + +CONF_ENTRY_ZEROCONF_INTERFACES = ConfigEntry( + key=CONF_ZEROCONF_INTERFACES, + type=ConfigEntryType.STRING, + label="Mdns/Zeroconf discovery interface(s)", + description="In normal circumstances, Music Assistant will automatically " + "discover all players on the network using multicast discovery on the " + "(L2) local network, such as mDNS or UPNP.\n\n" + "By default, Music Assistant will only listen on the default interface. " + "If you have multiple network interfaces and you want to discover players " + "on all interfaces, you can change this setting to 'All interfaces'.", + options=[ + ConfigValueOption("Default interface", "default"), + ConfigValueOption("All interfaces", "all"), + ], + default_value="default", + category="advanced", +) CONF_ENTRY_LIBRARY_SYNC_ALBUMS = ConfigEntry( key="library_sync_albums", type=ConfigEntryType.BOOLEAN, diff --git a/music_assistant/controllers/streams/streams_controller.py b/music_assistant/controllers/streams/streams_controller.py index b1ca238d..89896412 100644 --- a/music_assistant/controllers/streams/streams_controller.py +++ b/music_assistant/controllers/streams/streams_controller.py @@ -45,6 +45,7 @@ from music_assistant.constants import ( CONF_ENTRY_ENABLE_ICY_METADATA, CONF_ENTRY_LOG_LEVEL, CONF_ENTRY_SUPPORT_GAPLESS_DIFFERENT_SAMPLE_RATES, + CONF_ENTRY_ZEROCONF_INTERFACES, CONF_HTTP_PROFILE, CONF_OUTPUT_CHANNELS, CONF_OUTPUT_CODEC, @@ -294,6 +295,7 @@ class StreamsController(CoreController): default_value="GLOBAL", category="advanced", ), + CONF_ENTRY_ZEROCONF_INTERFACES, ) async def setup(self, config: CoreConfig) -> None: diff --git a/music_assistant/mass.py b/music_assistant/mass.py index 645e3c9e..11743541 100644 --- a/music_assistant/mass.py +++ b/music_assistant/mass.py @@ -33,6 +33,7 @@ from music_assistant.constants import ( API_SCHEMA_VERSION, CONF_PROVIDERS, CONF_SERVER_ID, + CONF_ZEROCONF_INTERFACES, CONFIGURABLE_CORE_CONTROLLERS, MASS_LOGGER_NAME, MIN_SCHEMA_VERSION, @@ -143,14 +144,22 @@ class MusicAssistant: self.loop_thread_id = getattr(self.loop, "_thread_id") # noqa: B009 self.running_as_hass_addon = await is_hass_supervisor() self.version = await get_package_version("music_assistant") or "0.0.0" + # setup config controller first and fetch important config values + self.config = ConfigController(self) + await self.config.setup() # create shared zeroconf instance # TODO: enumerate interfaces and enable IPv6 support - self.aiozc = AsyncZeroconf(ip_version=IPVersion.V4Only, interfaces=InterfaceChoice.Default) + zeroconf_interfaces = self.config.get_raw_core_config_value( + "streams", CONF_ZEROCONF_INTERFACES, "default" + ) + self.aiozc = AsyncZeroconf( + ip_version=IPVersion.V4Only, + interfaces=InterfaceChoice.All + if zeroconf_interfaces == "all" + else InterfaceChoice.Default, + ) # load all available providers from manifest files await self.__load_provider_manifests() - # setup config controller first and fetch important config values - self.config = ConfigController(self) - await self.config.setup() # setup/migrate storage await self._setup_storage() LOGGER.info(