From: Marcel van der Veldt Date: Thu, 16 Oct 2025 23:09:44 +0000 (+0200) Subject: Fix for Bluesound multizone devices (#2511) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=b0c9d576fcc6353f8fd6ad671757ae33e80273b1;p=music-assistant-server.git Fix for Bluesound multizone devices (#2511) --- diff --git a/music_assistant/helpers/util.py b/music_assistant/helpers/util.py index 6eb9111a..2a373e35 100644 --- a/music_assistant/helpers/util.py +++ b/music_assistant/helpers/util.py @@ -670,6 +670,13 @@ def validate_announcement_chime_url(url: str) -> bool: return False +async def get_mac_address(ip_address: str) -> str | None: + """Get MAC address for given IP address.""" + from getmac import get_mac_address # noqa: PLC0415 + + return await asyncio.to_thread(get_mac_address, ip=ip_address) + + class TaskManager: """ Helper class to run many tasks at once. diff --git a/music_assistant/providers/bluesound/provider.py b/music_assistant/providers/bluesound/provider.py index 00abdf09..22fdb574 100644 --- a/music_assistant/providers/bluesound/provider.py +++ b/music_assistant/providers/bluesound/provider.py @@ -2,15 +2,17 @@ from __future__ import annotations -from typing import TYPE_CHECKING, TypedDict +from typing import TYPE_CHECKING, TypedDict, cast from zeroconf import ServiceStateChange from music_assistant.helpers.util import ( + get_mac_address, get_port_from_zeroconf, get_primary_ip_address_from_zeroconf, ) from music_assistant.models.player_provider import PlayerProvider +from music_assistant.providers.bluesound.const import MUSP_MDNS_TYPE from .player import BluesoundPlayer @@ -46,17 +48,33 @@ class BluesoundPlayerProvider(PlayerProvider): return name = name.split(".", 1)[0] assert info is not None - player_id = info.decoded_properties["mac"] - assert player_id is not None ip_address = get_primary_ip_address_from_zeroconf(info) port = get_port_from_zeroconf(info) - assert ip_address is not None - assert port is not None + if not ip_address or not port: + self.logger.debug("Ignoring incomplete mdns discovery for Bluesound player: %s", name) + return + + if info.type == MUSP_MDNS_TYPE: + # this is a multi-zone device, we need to fetch the mac address of the main device + mac_address = await get_mac_address(ip_address) + player_id = f"{mac_address}:{port}" + else: + mac_address = info.decoded_properties.get("mac") + player_id = mac_address + + if not mac_address: + self.logger.debug( + "Ignoring mdns discovery for Bluesound player without MAC address: %s", + name, + ) + return # Handle update of existing player + assert player_id is not None # for type checker if bluos_player := self.mass.players.get(player_id): + bluos_player = cast("BluesoundPlayer", bluos_player) # Check if the IP address has changed if ip_address and ip_address != bluos_player.ip_address: self.logger.debug( @@ -76,7 +94,7 @@ class BluesoundPlayerProvider(PlayerProvider): _objectType=info.decoded_properties.get("_objectType", ""), ip_address=ip_address, port=str(port), - mac=info.decoded_properties["mac"], + mac=mac_address, model=info.decoded_properties.get("model", ""), zs=info.decoded_properties.get("zs", False), ) diff --git a/music_assistant/providers/filesystem_smb/__init__.py b/music_assistant/providers/filesystem_smb/__init__.py index 240a9a85..6c73b370 100644 --- a/music_assistant/providers/filesystem_smb/__init__.py +++ b/music_assistant/providers/filesystem_smb/__init__.py @@ -121,7 +121,7 @@ async def get_config_entries( label="Mount options", required=False, category="advanced", - default_value="noserverino,file_mode=0775,dir_mode=0775,uid=0,gid=0", + default_value="noserverino,file_mode=0775,dir_mode=0775,uid=0,gid=0,iocharset=utf8", description="[optional] Any additional mount options you " "want to pass to the mount command if needed for your particular setup.", ), diff --git a/pyproject.toml b/pyproject.toml index 2c823f60..b673d1d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dependencies = [ "cryptography==46.0.2", "chardet>=5.2.0", "ifaddr==0.2.0", + "get-mac==0.9.2", "mashumaro==3.16", "music-assistant-frontend==2.16.6", "music-assistant-models==1.1.62", diff --git a/requirements_all.txt b/requirements_all.txt index d1acb956..39c11e99 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -25,6 +25,7 @@ cryptography==46.0.2 deezer-python-async==0.3.0 defusedxml==0.7.1 duration-parser==1.0.1 +get-mac==0.9.2 gql[all]==4.0.0 hass-client==1.2.0 ibroadcastaio==0.4.0