diff --git a/custom_components/mass_queue/actions.py b/custom_components/mass_queue/actions.py index 8469164..ab1d536 100644 --- a/custom_components/mass_queue/actions.py +++ b/custom_components/mass_queue/actions.py @@ -16,6 +16,8 @@ from homeassistant.helpers import entity_registry as er from .const import ( + ATTR_COMMAND, + ATTR_DATA, ATTR_LIMIT, ATTR_LIMIT_AFTER, ATTR_LIMIT_BEFORE, @@ -36,6 +38,7 @@ SERVICE_MOVE_QUEUE_ITEM_UP, SERVICE_PLAY_QUEUE_ITEM, SERVICE_REMOVE_QUEUE_ITEM, + SERVICE_SEND_COMMAND, ) from .controller import MassQueueController from .schemas import ( @@ -46,6 +49,7 @@ QUEUE_ITEM_SCHEMA, QUEUE_ITEMS_SERVICE_SCHEMA, REMOVE_QUEUE_ITEM_SERVICE_SCHEMA, + SEND_COMMAND_SERVICE_SCHEMA, ) if TYPE_CHECKING: @@ -115,6 +119,13 @@ def register_actions(self) -> None: schema=MOVE_QUEUE_ITEM_NEXT_SERVICE_SCHEMA, supports_response=SupportsResponse.NONE, ) + self._hass.services.async_register( + DOMAIN, + SERVICE_SEND_COMMAND, + self.send_command, + schema=SEND_COMMAND_SERVICE_SCHEMA, + supports_response=SupportsResponse.OPTIONAL, + ) def get_queue_id(self, entity_id: str): """Get the queue ID for a player.""" @@ -160,6 +171,13 @@ def _format_queue_item(self, queue_item: dict) -> dict: ) return response + async def send_command(self, call: ServiceCall) -> ServiceResponse: + """Sends command to Music Assistant and returns response.""" + command = call.data[ATTR_COMMAND] + data = call.data.get(ATTR_DATA) + response = await self._controller.send_command(command, data) + return {"response": response} + async def get_queue_items(self, call: ServiceCall) -> ServiceResponse: """Get all items in queue.""" entity_id = call.data[ATTR_PLAYER_ENTITY] diff --git a/custom_components/mass_queue/const.py b/custom_components/mass_queue/const.py index 619a8b9..159b601 100644 --- a/custom_components/mass_queue/const.py +++ b/custom_components/mass_queue/const.py @@ -10,21 +10,23 @@ SERVICE_MOVE_QUEUE_ITEM_UP = "move_queue_item_up" SERVICE_MOVE_QUEUE_ITEM_DOWN = "move_queue_item_down" SERVICE_MOVE_QUEUE_ITEM_NEXT = "move_queue_item_next" +SERVICE_SEND_COMMAND = "send_command" ATTR_CONFIG_ENTRY_ID = "config_entry_id" - -ATTR_PLAYER_ENTITY = "entity" -ATTR_OFFSET = "offset" ATTR_LIMIT = "limit" -ATTR_LIMIT_BEFORE = "limit_before" ATTR_LIMIT_AFTER = "limit_after" +ATTR_LIMIT_BEFORE = "limit_before" ATTR_QUEUE_ITEM_ID = "queue_item_id" ATTR_MEDIA_TITLE = "media_title" ATTR_MEDIA_ALBUM_NAME = "media_album_name" ATTR_MEDIA_ARTIST = "media_artist" ATTR_MEDIA_CONTENT_ID = "media_content_id" ATTR_MEDIA_IMAGE = "media_image" +ATTR_OFFSET = "offset" +ATTR_PLAYER_ENTITY = "entity" ATTR_QUEUE_ITEMS = "queue_items" +ATTR_COMMAND = "command" +ATTR_DATA = "data" LOGGER = logging.getLogger(__package__) DEFAULT_QUEUE_ITEMS_LIMIT = 500 diff --git a/custom_components/mass_queue/controller.py b/custom_components/mass_queue/controller.py index 07a2c4b..bbd7e3a 100644 --- a/custom_components/mass_queue/controller.py +++ b/custom_components/mass_queue/controller.py @@ -119,6 +119,11 @@ def update_player_queue(self, player_id: str): queue_id = get_queue_id_from_player_data(player) self.players.update(player_id, queue_id) + async def send_command(self, command: str, data: dict | None = None): + """Sends command to Music Assistant and returns response.""" + data = data if data else {} + return await self._client.send_command(command, require_schema=None, **data) + async def get_player_queue(self, player_id: str): """Gets queue items for single Music Assistant queue.""" player = self._client.players.get(player_id) diff --git a/custom_components/mass_queue/schemas.py b/custom_components/mass_queue/schemas.py index 1fa5f9b..3d1d109 100644 --- a/custom_components/mass_queue/schemas.py +++ b/custom_components/mass_queue/schemas.py @@ -6,6 +6,8 @@ from homeassistant.helpers import config_validation as cv from .const import ( + ATTR_COMMAND, + ATTR_DATA, ATTR_LIMIT, ATTR_LIMIT_AFTER, ATTR_LIMIT_BEFORE, @@ -79,3 +81,10 @@ vol.Required(ATTR_QUEUE_ITEM_ID): str, }, ) + +SEND_COMMAND_SERVICE_SCHEMA = vol.Schema( + { + vol.Required(ATTR_COMMAND): str, + vol.Optional(ATTR_DATA, default={}): dict, + }, +) diff --git a/custom_components/mass_queue/services.yaml b/custom_components/mass_queue/services.yaml index 0812d4b..b828c56 100644 --- a/custom_components/mass_queue/services.yaml +++ b/custom_components/mass_queue/services.yaml @@ -1,6 +1,8 @@ get_queue_items: fields: limit: + name: Limit + description: Limit on the number of items in queue to return required: false example: 500 selector: @@ -9,6 +11,8 @@ get_queue_items: max: 1000 step: 1 offset: + name: Offset + description: Location in queue to start where zero equals the first item in queue, not the current item. required: false advanced: true example: 50 @@ -18,6 +22,8 @@ get_queue_items: max: 1000 step: 1 limit_before: + name: Limit Before + description: Number of items to pull before current active item in queue. required: false example: 5 default: 5 @@ -27,6 +33,8 @@ get_queue_items: max: 1000 step: 1 limit_after: + name: Limit After + description: Number of items to pull after current active item in queue. required: false example: 50 default: 100 @@ -36,6 +44,8 @@ get_queue_items: max: 1000 step: 1 entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: @@ -44,10 +54,13 @@ get_queue_items: remove_queue_item: fields: queue_item_id: + name: Queue Item ID required: true selector: text: entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: @@ -56,10 +69,13 @@ remove_queue_item: move_queue_item_up: fields: queue_item_id: + name: Queue Item ID required: true selector: text: entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: @@ -68,10 +84,13 @@ move_queue_item_up: move_queue_item_down: fields: queue_item_id: + name: Queue Item ID required: true selector: text: entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: @@ -80,10 +99,13 @@ move_queue_item_down: move_queue_item_next: fields: queue_item_id: + name: Queue Item ID required: true selector: text: entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: @@ -92,12 +114,30 @@ move_queue_item_next: play_queue_item: fields: queue_item_id: + name: Queue Item ID required: true selector: text: entity: + name: Entity + description: Music Assistant Media Player Entity required: true selector: entity: domain: media_player integration: music_assistant +send_command: + fields: + command: + name: Command + description: Command to send to Music Assistant + required: true + selector: + text: + data: + name: Data + description: Command data to send + required: false + default: {} + selector: + object: