#!/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()