Add switch-pa-sink
This script can be used to switch the pulseaudio sink of an application to the next sink in the list of sinks. The sink is found by querying the currently focused window from i3 and retrieving the PID via _NET_WM_PID attribute using xprop. If that PID doesn't directly have sink attached, the script searches for children of this PID having a sink and switches those. This is useful to switch e.g. an mpv running inside a terminal.
This commit is contained in:
parent
12c3ac9c05
commit
e558da4427
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
import setuptools
|
||||
|
||||
|
||||
setuptools.setup()
|
|
@ -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()
|
Loading…
Reference in New Issue