A few small tweaks (#1012)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 21 Jan 2024 01:50:38 +0000 (02:50 +0100)
committerGitHub <noreply@github.com>
Sun, 21 Jan 2024 01:50:38 +0000 (02:50 +0100)
music_assistant/common/models/config_entries.py
music_assistant/common/models/player.py
music_assistant/constants.py
music_assistant/server/controllers/players.py
music_assistant/server/models/player_provider.py
music_assistant/server/providers/airplay/__init__.py

index bc02e6ba7bf5f082cba907db7d428b76e94b9e7f..1d822c3c774dcf6bc3d52a9ae9a4db53db6b01ee 100644 (file)
@@ -18,6 +18,7 @@ from music_assistant.constants import (
     CONF_EQ_MID,
     CONF_EQ_TREBLE,
     CONF_FLOW_MODE,
+    CONF_HIDE_PLAYER,
     CONF_LOG_LEVEL,
     CONF_OUTPUT_CHANNELS,
     CONF_VOLUME_NORMALIZATION,
@@ -404,3 +405,14 @@ CONF_ENTRY_CROSSFADE_DURATION = ConfigEntry(
     depends_on=CONF_CROSSFADE,
     advanced=True,
 )
+
+CONF_ENTRY_HIDE_PLAYER = ConfigEntry(
+    key=CONF_HIDE_PLAYER,
+    type=ConfigEntryType.BOOLEAN,
+    label="Hide this player in the user interface",
+    default_value=False,
+    description="Hide this player in the user interface. \n\n"
+    "Note that it can still be controlled and it will also show up in any "
+    "sync groups the player belongs to.",
+    advanced=True,
+)
index 8dbeb126924434d780bd943cacbc51e8238340a9..157a1674f444f06386ba6384a98defab78106c23 100644 (file)
@@ -84,10 +84,10 @@ class Player(DataClassDictMixin):
     # nor will it be added to the HA integration
     enabled: bool = True
 
-    # hidden_by: if the player is enabled
+    # hidden: if the player is hidden in the UI
     # will be set by the player manager based on config
-    # a disabled player is hidden in the UI only but can still be controlled
-    hidden_by: set = field(default_factory=set)
+    # a hidden player is hidden in the UI only but can still be controlled
+    hidden: bool = False
 
     # group_volume: if the player is a player group or syncgroup master,
     # this will return the average volume of all child players
index 145e655a952040b275ef32bf21993693e3a19647..65d2c40a92bcd817bf6f222818348dca3927a3f5 100755 (executable)
@@ -52,6 +52,7 @@ CONF_AUTO_PLAY: Final[str] = "auto_play"
 CONF_GROUP_PLAYERS: Final[str] = "group_players"
 CONF_CROSSFADE: Final[str] = "crossfade"
 CONF_GROUP_MEMBERS: Final[str] = "group_members"
+CONF_HIDE_PLAYER: Final[str] = "hide_player"
 
 # config default values
 DEFAULT_HOST: Final[str] = "0.0.0.0"
index c2e32bbe7242f65d173a4ecc41a7aac45a4ebaa8..cced5ca3da44c9664d642ccdc1c1cb3c9f19f4fd 100755 (executable)
@@ -30,6 +30,7 @@ from music_assistant.common.models.queue_item import QueueItem
 from music_assistant.constants import (
     CONF_AUTO_PLAY,
     CONF_GROUP_MEMBERS,
+    CONF_HIDE_PLAYER,
     CONF_PLAYERS,
     ROOT_LOGGER_NAME,
     SYNCGROUP_PREFIX,
@@ -234,7 +235,7 @@ class PlayerController(CoreController):
             player.volume_level = player.group_volume
         # prefer any overridden name from config
         player.display_name = (
-            self.mass.config.get(f"{CONF_PLAYERS}/{player_id}/name")
+            self.mass.config.get_raw_player_config_value(player.player_id, "name")
             or player.name
             or player.player_id
         )
@@ -247,7 +248,9 @@ class PlayerController(CoreController):
             # mark player as powered if its playing
             # could happen for players that do not officially support power commands
             player.powered = True
-
+        player.hidden = self.mass.config.get_raw_player_config_value(
+            player.player_id, CONF_HIDE_PLAYER, False
+        )
         # handle syncgroup - get attributes from first player that has this group as source
         if player.player_id.startswith(SYNCGROUP_PREFIX):
             if sync_leader := self.get_sync_leader(player):
index f6d62eaae8d41ff4123aaa79a7739f5b754b7580..85f03c5397b5718d7ad33d61dea1cc50eaa10b72 100644 (file)
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
 
 from music_assistant.common.models.config_entries import (
     CONF_ENTRY_AUTO_PLAY,
+    CONF_ENTRY_HIDE_PLAYER,
     CONF_ENTRY_VOLUME_NORMALIZATION,
     CONF_ENTRY_VOLUME_NORMALIZATION_TARGET,
     ConfigEntry,
@@ -38,6 +39,7 @@ class PlayerProvider(Provider):
             CONF_ENTRY_VOLUME_NORMALIZATION,
             CONF_ENTRY_AUTO_PLAY,
             CONF_ENTRY_VOLUME_NORMALIZATION_TARGET,
+            CONF_ENTRY_HIDE_PLAYER,
         )
         if player_id.startswith(SYNCGROUP_PREFIX):
             # add default entries for syncgroups
index c580858947e93a12b46d34408eeb091a929da256..6d75afc4577839aeb26bc79ec277a57c5fd9626c 100644 (file)
@@ -134,7 +134,10 @@ class AirplayProvider(PlayerProvider):
     @property
     def supported_features(self) -> tuple[ProviderFeature, ...]:
         """Return the features supported by this Provider."""
-        return (ProviderFeature.SYNC_PLAYERS,)
+        # for now do not allow creation of airplay groups
+        # in preparation of new airplay provider coming up soon
+        # return (ProviderFeature.SYNC_PLAYERS,)
+        return tuple()
 
     async def handle_setup(self) -> None:
         """Handle async initialization of the provider."""
@@ -287,6 +290,9 @@ class AirplayProvider(PlayerProvider):
             manufacturer="Generic",
         )
         player.supports_24bit = False
+        # disable sonos by default
+        if "sonos" in player.name.lower() or "rincon" in player.name.lower():
+            player.enabled_by_default = False
 
         # extend info from the discovery xml
         async with aiofiles.open(self._config_file, "r") as _file:
@@ -301,20 +307,10 @@ class AirplayProvider(PlayerProvider):
                     udn = device_elem.find("udn").text
                     udn_name = udn.split("@")[1].split("._")[0]
                     player.name = udn_name
-                    # disable sonos by default
-                    if "sonos" in (device_elem.find("friendly_name").text or "").lower():
-                        player.enabled_by_default = False
-                        # TODO: query more info directly from the device
-                        player.device_info = DeviceInfo(
-                            model="Airplay device",
-                            address=player.device_info.address,
-                            manufacturer="SONOS",
-                        )
                     break
 
     def _handle_player_update_callback(self, player: Player) -> None:
         """Handle player update callback from slimproto source player."""
-        # we could override anything on the player object here
 
     async def _get_bridge_binary(self):
         """Find the correct bridge binary belonging to the platform."""