22
33import logging
44from datetime import datetime
5- from typing import Any , List , Optional
5+ from typing import List , Optional
66
77from music_assistant .constants import (
88 CONF_ENABLED ,
1212 EVENT_PLAYER_CONTROL_REGISTERED ,
1313 EVENT_PLAYER_CONTROL_UPDATED ,
1414 EVENT_PLAYER_REMOVED ,
15+ EVENT_REGISTER_PLAYER_CONTROL ,
16+ EVENT_UNREGISTER_PLAYER_CONTROL ,
1517)
1618from music_assistant .models .config_entry import ConfigEntry , ConfigEntryType
1719from music_assistant .models .media_types import MediaItem , MediaType , Track
@@ -51,6 +53,14 @@ def __init__(self, mass):
5153 self ._poll_ticks = 0
5254 self ._controls = {}
5355 self ._player_controls_config_entries = []
56+ self .mass .add_event_listener (
57+ self .__handle_websocket_player_control_event ,
58+ [
59+ EVENT_REGISTER_PLAYER_CONTROL ,
60+ EVENT_UNREGISTER_PLAYER_CONTROL ,
61+ EVENT_PLAYER_CONTROL_UPDATED ,
62+ ],
63+ )
5464
5565 async def async_setup (self ):
5666 """Async initialize of module."""
@@ -162,26 +172,39 @@ async def async_update_player(self, player: Player):
162172
163173 async def async_register_player_control (self , control : PlayerControl ):
164174 """Register a playercontrol with the player manager."""
165- self ._controls [control .id ] = control
166- LOGGER .info ("New %s PlayerControl registered: %s" , control .type , control .name )
167- self .mass .signal_event (EVENT_PLAYER_CONTROL_REGISTERED , control .id )
175+ # control.mass = self.mass
176+ control .mass = self .mass
177+ control .type = PlayerControlType (control .type )
178+ self ._controls [control .control_id ] = control
179+ LOGGER .info (
180+ "New PlayerControl (%s) registered: %s\\ %s" ,
181+ control .type ,
182+ control .provider ,
183+ control .name ,
184+ )
168185 await self .__async_create_playercontrol_config_entries ()
169186 # update all players as they may want to use this control
170187 for player in self ._players .values ():
171188 self .mass .add_job (self .async_update_player (player ))
172189
173- async def async_update_player_control (self , control_id : str , new_state : Any ):
190+ async def async_update_player_control (self , control : PlayerControl ):
174191 """Update a playercontrol's state on the player manager."""
175- control = self ._controls .get (control_id )
176- if not control or control .state == new_state :
192+ if control .control_id not in self ._controls :
193+ return await self .async_register_player_control (control )
194+ new_state = control .state
195+ if self ._controls [control .control_id ].state == new_state :
177196 return
178- LOGGER .info ("PlayerControl %s updated - new state: %s" , control .name , new_state )
179- control .state = new_state
180- self .mass .signal_event (EVENT_PLAYER_CONTROL_UPDATED , control .id )
197+ self ._controls [control .control_id ].state = new_state
198+ LOGGER .debug (
199+ "PlayerControl %s\\ %s updated - new state: %s" ,
200+ control .provider ,
201+ control .name ,
202+ new_state ,
203+ )
181204 # update all players using this playercontrol
182205 for player_id , player in self ._players .items ():
183206 conf = self .mass .config .player_settings [player_id ]
184- if control .id in [
207+ if control .control_id in [
185208 conf .get (CONF_POWER_CONTROL ),
186209 conf .get (CONF_VOLUME_CONTROL ),
187210 ]:
@@ -361,7 +384,7 @@ async def async_cmd_power_on(self, player_id: str) -> None:
361384 if player_config .get (CONF_POWER_CONTROL ):
362385 control = self .get_player_control (player_config [CONF_POWER_CONTROL ])
363386 if control :
364- self . mass . add_job ( control . set_state , control .id , True )
387+ await control .async_set_state ( True )
365388
366389 async def async_cmd_power_off (self , player_id : str ) -> None :
367390 """
@@ -377,7 +400,7 @@ async def async_cmd_power_off(self, player_id: str) -> None:
377400 if player_config .get (CONF_POWER_CONTROL ):
378401 control = self .get_player_control (player_config [CONF_POWER_CONTROL ])
379402 if control :
380- self . mass . add_job ( control . set_state , control .id , False )
403+ await control .async_set_state ( False )
381404 # handle group power
382405 if player .is_group_player :
383406 # player is group, turn off all childs
@@ -433,7 +456,7 @@ async def async_cmd_volume_set(self, player_id: str, volume_level: int) -> None:
433456 if player_config .get (CONF_VOLUME_CONTROL ):
434457 control = self .get_player_control (player_config [CONF_VOLUME_CONTROL ])
435458 if control :
436- self . mass . add_job ( control . set_state , control .id , volume_level )
459+ await control .async_set_state ( volume_level )
437460 # just force full volume on actual player if volume is outsourced to volumecontrol
438461 await player_prov .async_cmd_volume_set (player_id , 100 )
439462 # handle group volume
@@ -645,7 +668,8 @@ async def __async_create_playercontrol_config_entries(self):
645668 power_controls = self .get_player_controls (PlayerControlType .POWER )
646669 if power_controls :
647670 controls = [
648- {"text" : item .name , "value" : item .id } for item in power_controls
671+ {"text" : f"{ item .provider } : { item .name } " , "value" : item .control_id }
672+ for item in power_controls
649673 ]
650674 entries .append (
651675 ConfigEntry (
@@ -659,7 +683,8 @@ async def __async_create_playercontrol_config_entries(self):
659683 volume_controls = self .get_player_controls (PlayerControlType .VOLUME )
660684 if volume_controls :
661685 controls = [
662- {"text" : item .name , "value" : item .id } for item in volume_controls
686+ {"text" : f"{ item .provider } : { item .name } " , "value" : item .control_id }
687+ for item in volume_controls
663688 ]
664689 entries .append (
665690 ConfigEntry (
@@ -695,3 +720,13 @@ def __player_updated(self, player_id: str, changed_value: str):
695720 self .mass .add_job (self .async_update_player (child_player ))
696721 if player_id in self ._player_queues and player .active_queue == player_id :
697722 self .mass .add_job (self ._player_queues [player_id ].async_update_state ())
723+
724+ async def __handle_websocket_player_control_event (self , msg , msg_details ):
725+ """Handle player controls over the websockets api."""
726+ if msg in [EVENT_REGISTER_PLAYER_CONTROL , EVENT_PLAYER_CONTROL_UPDATED ]:
727+ # create or update a playercontrol registered through the websockets api
728+ control = PlayerControl (** msg_details )
729+ await self .async_update_player_control (control )
730+ # send confirmation to the client that the register was successful
731+ if msg == EVENT_PLAYER_CONTROL_REGISTERED :
732+ self .mass .signal_event (EVENT_PLAYER_CONTROL_REGISTERED , control )
0 commit comments