-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathswap-audio-output-device-gui.py
More file actions
executable file
·84 lines (73 loc) · 2.42 KB
/
swap-audio-output-device-gui.py
File metadata and controls
executable file
·84 lines (73 loc) · 2.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3
from collections import OrderedDict
import subprocess
import json
from typing import Iterator
def main():
sinks = [
s
for s in pactl("list", "sinks")
if any((p.get("availability") != "not available" for p in s.get("ports", [])))
]
current_sink_name = pactl("info")["default_sink_name"]
print(f"Current sink name: {current_sink_name}")
current_sink = next(x for x in sinks if x.get("name") == current_sink_name)
print(f"Current sink: {current_sink}")
if not current_sink:
raise ValueError("Could not find defaut sink in sinks")
default_sink_index = sinks.index(current_sink)
# move default sink to the end of the list
sinks.append(sinks.pop(default_sink_index))
sink_desc_to_sink = OrderedDict(
(desc(sink, sink == current_sink), sink) for sink in sinks
)
next_sink_desc = select_one(map(str, sink_desc_to_sink.keys()))
if not next_sink_desc:
print("Cancelled selection")
return
next_sink = sink_desc_to_sink[next_sink_desc]
if next_sink == current_sink:
print("Already selected")
return
sink_inputs = pactl("list", "sink-inputs")
for sink_input in sink_inputs:
print(f"Moving {sink_input['index']} to {next_sink['name']}")
pactl("move-sink-input", sink_input["index"], next_sink["index"])
pactl("set-default-sink", next_sink["index"])
def pactl(*args: str):
"""
Run pactl with the given arguments.
Sets the format to json so output is some parsed json.
"""
cmd = ["pactl", "-f", "json"] + list(args)
cmd = list(map(str, cmd))
res = subprocess.run(cmd, check=True, text=True, capture_output=True)
if res.stdout:
return json.loads(res.stdout)
else:
return None
def desc(sink: dict, current=False):
return f"{sink['description']} ({sink['index']}){' [current]' if current else ''}"
def select_one(items: Iterator[str]):
cmd = [
"vicinae",
"dmenu",
"--no-section",
"--no-footer",
"--no-quick-look",
"--no-metadata",
"--placeholder",
"Select audio output",
]
p = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout = p.communicate(input="\n".join(items))[0]
p.terminate()
return stdout.strip()
if __name__ == "__main__":
main()