You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

47 lines
1.5 KiB

#!/usr/bin/env python3
import subprocess
import i3ipc
import psutil
import pulsectl
def main():
i3 = i3ipc.Connection()
window = i3.get_tree().find_focused()
cmd = ['xprop', '-id', str(window.window), '_NET_WM_PID']
o = subprocess.run(cmd, encoding='utf-8', capture_output=True)
# _NET_WM_PID(CARDINAL) = 418472
pid = int(o.stdout.strip().split(' = ')[1])
pulse = pulsectl.Pulse('Focused sink switcher')
sink_input_by_pid = {}
for i in pulse.sink_input_list():
sink_pid = int(i.proplist['application.process.id'])
sink_input_by_pid[sink_pid] = i
if pid in sink_input_by_pid:
sink_input = sink_input_by_pid[pid]
else:
# try the childprocesses of our process, because this might be a
# terminal having started an mpv or something
p = psutil.Process(pid)
for child in p.children(recursive=True):
if child.pid in sink_input_by_pid:
sink_input = sink_input_by_pid[child.pid]
break
else:
msg = 'Did not find a pulse client for pid {} or its children.'
raise RuntimeError(msg.format(pid))
sink_index_list = [s.index for s in pulse.sink_list()]
old_sink = sink_input.sink
old_sink_index = sink_index_list.index(old_sink)
new_sink_index = sink_index_list[(old_sink_index + 1) % len(sink_index_list)]
pulse.sink_input_move(sink_input.index, new_sink_index)
if __name__ == '__main__':
main()