diff --git a/switch-pa-sink/setup.cfg b/switch-pa-sink/setup.cfg new file mode 100644 index 0000000..ab81b66 --- /dev/null +++ b/switch-pa-sink/setup.cfg @@ -0,0 +1,17 @@ +[metadata] +name = switch-pa-sink +version = 0.1 +description = Find the pulseaudio sink of currently active window in i3 and switch it to the next pulseaudio sink + +[options] +scripts = switch-pa-sink +install_requires = + i3ipc + psutil + pulsectl + + +[flake8] +max-line-length = 120 +exclude = .git,__pycache__,*.egg-info,*lib/python* +ignore = E241,E741,W503,W504 diff --git a/switch-pa-sink/setup.py b/switch-pa-sink/setup.py new file mode 100644 index 0000000..056ba45 --- /dev/null +++ b/switch-pa-sink/setup.py @@ -0,0 +1,4 @@ +import setuptools + + +setuptools.setup() diff --git a/switch-pa-sink/switch-pa-sink b/switch-pa-sink/switch-pa-sink new file mode 100755 index 0000000..bc187d6 --- /dev/null +++ b/switch-pa-sink/switch-pa-sink @@ -0,0 +1,46 @@ +#!/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()