greendeck/greendeck/lib/actions/pulseaudio.py
2022-12-13 14:25:50 -06:00

91 lines
2.5 KiB
Python

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)