import asyncio import json from greendeck.config import PulseAudioActionConfig async def get_sink_info( action_config: PulseAudioActionConfig, ) -> tuple[int | None, int | None]: proc = await asyncio.create_subprocess_exec( "pactl", *["--format=json", "list", "sink-inputs"], stdin=asyncio.subprocess.DEVNULL, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, ) stdout, stderr = await proc.communicate() if proc.returncode != 0: print(f"error {proc.returncode}") print(stderr) return None, None data = json.loads(stdout) index = None for entry in data: if entry["properties"]["application.name"] == action_config.application_name: index = entry["index"] volume = int( round( sum([v["value"] for v in entry["volume"].values()]) / len(entry["volume"]), 0, ) ) print(index, volume, entry["volume"]) return index, volume print(f"unable to locate sink {action_config.application_name}") return None, None volume_step = int(round(0x10000 * 0.05, 0)) async def handle_pulseaudio_action( action_config: PulseAudioActionConfig, ) -> None: index, volume = await get_sink_info(action_config) if index is None: return match action_config.action: case "volume-up": new_volume = min(volume + volume_step, 0x10000) command = [ "set-sink-input-volume", f"{index}", f"{new_volume}", ] case "volume-down": new_volume = max(volume - volume_step, 0x00000) command = [ "set-sink-input-volume", f"{index}", f"{new_volume}", ] case "toggle-mute": command = ["set-sink-input-mute", f"{index}", "toggle"] case _: print(f"unknown action {action_config.action}") return proc = await asyncio.create_subprocess_exec( "pactl", *command, stdin=asyncio.subprocess.DEVNULL, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) stdout, stderr = await proc.communicate() if proc.returncode != 0: print(f"retcode: {proc.returncode}") print(stdout) print(stderr) index, volume = await get_sink_info(action_config)