Last active
December 24, 2022 08:57
-
-
Save Programie/b50106cd2e66b3e474884f057507759a to your computer and use it in GitHub Desktop.
Toggle PulseAudio output sink for the active application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
# This script toggles the PulseAudio output sink of the currently active application (guessed by the currently active X window) between the given output sink and the default output sink. | |
# The output sink is passed as first argument to the script. | |
# | |
# Requirements: | |
# | |
# xdotool (on Ubuntu install via "sudo apt install xdotool") | |
# pulsectl ("sudo pip3 install pulsectl") | |
import pulsectl | |
import subprocess | |
import sys | |
def notify_send(message): | |
subprocess.call(["notify-send", "PulseAudio App Sink Switcher", message]) | |
def fail(message): | |
print(message, file=sys.stderr) | |
notify_send(message) | |
exit(1) | |
if len(sys.argv) < 2: | |
print("Usage: {} <toggle sink name>", file=sys.stderr) | |
exit(1) | |
toggle_output_sink_name = sys.argv[1] | |
try: | |
active_window_id = int(subprocess.getoutput("xdotool getactivewindow")) | |
foreground_pid = int(subprocess.getoutput("xdotool getwindowpid {}".format(active_window_id))) | |
except Exception: | |
fail("Can't get PID of active window") | |
try: | |
application_name = subprocess.getoutput("xdotool getwindowname {}".format(active_window_id)) | |
except Exception: | |
application_name = None | |
pulse = pulsectl.Pulse("app-sink-switcher") | |
default_output_sink_name = pulse.server_info().default_sink_name | |
default_output_sink = pulse.get_sink_by_name(default_output_sink_name).index | |
try: | |
toggle_output_sink = pulse.get_sink_by_name(toggle_output_sink_name).index | |
except pulsectl.PulseIndexError: | |
fail("Sink '{}' not found!".format(toggle_output_sink_name)) | |
input_sink = None | |
current_output_sink = None | |
for sink in pulse.sink_input_list(): | |
if "application.process.id" in sink.proplist and int(sink.proplist["application.process.id"]) == foreground_pid: | |
input_sink = sink.index | |
current_output_sink = sink.sink | |
break | |
if input_sink is None: | |
fail("Foreground application {} (PID {}) is not connected to PulseAudio!".format(application_name, foreground_pid)) | |
# Toggle between default and specified sink | |
if current_output_sink == default_output_sink: | |
new_output_sink_name = toggle_output_sink_name | |
new_output_sink = toggle_output_sink | |
else: | |
new_output_sink_name = default_output_sink_name | |
new_output_sink = default_output_sink | |
print("Connecting application {} (PID {}) to sink {} (input sink {} -> output sink {})".format(application_name, foreground_pid, new_output_sink_name, input_sink, new_output_sink)) | |
pulse.sink_input_move(input_sink, new_output_sink) | |
notify_send("Application audio output of {} switched to {}".format(application_name, new_output_sink_name)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment