Handle player volume correctly
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 4 Dec 2025 00:06:18 +0000 (01:06 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 4 Dec 2025 00:06:18 +0000 (01:06 +0100)
music_assistant/controllers/players/player_controller.py

index 65d52d02816844643567c793cebc6d46b2337c4b..b2f762825c45e2805a75cd658653b4780db3f299 100644 (file)
@@ -690,13 +690,11 @@ class PlayerController(CoreController):
         ):
             await self.mass.player_queues.resume(player_id)
 
-    @api_command("players/cmd/volume_set")
-    @handle_player_command
-    async def cmd_volume_set(self, player_id: str, volume_level: int) -> None:
-        """Send VOLUME_SET command to given player.
+    async def _volume_set(self, player_id: str, volume_level: int) -> None:
+        """Set volume without permission checks (internal use only).
 
-        - player_id: player_id of the player to handle the command.
-        - volume_level: volume level (0..100) to set on the player.
+        :param player_id: player_id of the player to handle the command.
+        :param volume_level: volume level (0..100) to set on the player.
         """
         player = self.get(player_id, True)
         assert player is not None  # for type checker
@@ -740,6 +738,16 @@ class PlayerController(CoreController):
             assert player_control.volume_set is not None
             await player_control.volume_set(volume_level)
 
+    @api_command("players/cmd/volume_set")
+    @handle_player_command
+    async def cmd_volume_set(self, player_id: str, volume_level: int) -> None:
+        """Send VOLUME_SET command to given player.
+
+        :param player_id: player_id of the player to handle the command.
+        :param volume_level: volume level (0..100) to set on the player.
+        """
+        await self._volume_set(player_id, volume_level)
+
     @api_command("players/cmd/volume_up")
     @handle_player_command
     async def cmd_volume_up(self, player_id: str) -> None:
@@ -1712,7 +1720,8 @@ class PlayerController(CoreController):
             new_child_volume = int(cur_child_volume + volume_dif)
             new_child_volume = max(0, new_child_volume)
             new_child_volume = min(100, new_child_volume)
-            coros.append(self.cmd_volume_set(child_player.player_id, new_child_volume))
+            # Use private method to skip permission check - already validated on group
+            coros.append(self._volume_set(child_player.player_id, new_child_volume))
         await asyncio.gather(*coros)
 
     def get_announcement_volume(self, player_id: str, volume_override: int | None) -> int | None: