hypr-dotfiles/tofi/select_audio.py
2025-08-28 11:23:01 +09:00

64 lines
1.8 KiB
Python
Executable file

#!/usr/bin/env python3
import subprocess
import re
def parse_wpctl_status():
devices = []
current_section = None
output = subprocess.run(["wpctl", "status"], capture_output=True, text=True).stdout.splitlines()
for line in output:
line = line.rstrip()
if "Sinks:" in line:
current_section = "sink"
continue
elif "Sources:" in line:
current_section = "source"
continue
elif re.match(r"^[^\s]", line):
current_section = None
if current_section:
m = re.search(r"\*\s*|\s*(\d+)\.\s+(.*?)\s+\[vol:", line)
if m:
id_match = re.search(r"(\d+)\.", line)
dev_id = id_match.group(1) if id_match else None
name_match = re.search(r"\d+\.\s+(.*?)\s+\[vol:", line)
name = name_match.group(1) if name_match else None
if dev_id and name:
devices.append((current_section, dev_id, name))
return devices
def main():
devices = parse_wpctl_status()
if not devices:
print("No devices found.")
return
# Prepare choices and a mapping from display line to device ID
choices = []
id_map = {}
for dev_type, dev_id, name in devices:
label = "O" if dev_type == "sink" else "I"
line = f"{label} {name}"
choices.append(line)
id_map[line] = dev_id
result = subprocess.run(["tofi"], input="\n".join(choices), capture_output=True, text=True)
choice = result.stdout.strip()
if not choice:
return
selected_id = id_map.get(choice)
if selected_id:
subprocess.run(["wpctl", "set-default", selected_id])
subprocess.run(["notify-send", f"Set default device to {choice}"])
if __name__ == "__main__":
main()