from __future__ import annotations class MediaControlsPlugin: name = "Media Controls" desc = "Send system media keys through the backend plugin action path." version = "0.1.0" actions = [ { "id": "media_key", "name": "Media Key", "desc": "Play/pause, skip, stop, mute, or adjust volume.", "fields": [ { "id": "command", "label": "Command", "type": "select", "default": "play_pause", "options": [ {"label": "Play / Pause", "value": "play_pause"}, {"label": "Next Track", "value": "next"}, {"label": "Previous Track", "value": "previous"}, {"label": "Stop", "value": "stop"}, {"label": "Volume Up", "value": "volume_up"}, {"label": "Volume Down", "value": "volume_down"}, {"label": "Mute", "value": "mute"}, ], } ], }, { "id": "volume_repeat", "name": "Volume Repeat", "desc": "Send volume up or down multiple times.", "fields": [ { "id": "direction", "label": "Direction", "type": "select", "default": "volume_up", "options": [ {"label": "Volume Up", "value": "volume_up"}, {"label": "Volume Down", "value": "volume_down"}, ], }, {"id": "steps", "label": "Steps", "type": "number", "default": 3}, ], }, ] def on_load(self, ctx): ctx.db.add_event("plugin.loaded", {"plugin": self.name}) def execute_action(self, ctx, action_id, config, event): if action_id == "media_key": self._press(config.get("command", "play_pause")) return if action_id == "volume_repeat": steps = max(1, min(20, int(config.get("steps", 3) or 3))) command = config.get("direction", "volume_up") for _ in range(steps): self._press(command) return raise ValueError(f"Unknown media action '{action_id}'.") def _press(self, command): from pynput.keyboard import Controller, Key keys = { "play_pause": "media_play_pause", "next": "media_next", "previous": "media_previous", "stop": "media_stop", "volume_up": "media_volume_up", "volume_down": "media_volume_down", "mute": "media_volume_mute", } key_name = keys.get(command) if not key_name: raise ValueError(f"Unknown media command '{command}'.") key = getattr(Key, key_name, None) if key is None: raise RuntimeError(f"pynput does not expose Key.{key_name} on this platform.") keyboard = Controller() keyboard.press(key) keyboard.release(key) PLUGIN = MediaControlsPlugin()