Last active
September 27, 2022 09:49
-
-
Save 00sapo/9f88f6994029b7eeac3a6b9063d87352 to your computer and use it in GitHub Desktop.
PulseAudio Solo Mode
This file contains hidden or 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
#!/bin/sh | |
SLEEP_TIME=0.1 | |
print_help() { | |
cat << EOF | |
This script can be used to run any shell command so that it's the only | |
process that can play sounds using PulseAudio. It continuously mutes all the | |
new streams that are not connected to the command passed as argument. Once | |
muted, it won't be managed by this script anymore (so that it will stay | |
unmuted if you want) | |
A typical use-case scenario is video-calling, when you want to avoid that | |
other apps unexpectedly play sounds (e.g. various websites do this) | |
Syntax: | |
$0 [-r regex] [-h] <yourcommand -with --yours --options> | |
Options: | |
-r : allows the usage of an awk regex; instead of non-muting children | |
processes, patterns that match the regex will be not muted; this | |
is useful for processes that internally use nohup or similar methods, | |
spawining processes that are not children. E.g. | |
$0 -r skype skypeforlinux | |
-h : show this help | |
Usage: | |
Just run the command. To exit, use ctrl+c. | |
EOF | |
} | |
get_stream_pid_list() { | |
pactl list sink-inputs | awk ' | |
/application.process.id/ { | |
gsub("\"", "", $3) | |
print $3 | |
}' | |
} | |
get_stream_index_from_pid() { | |
pid=$1 | |
pactl list sink-inputs | awk ' | |
/^Sink Input #[0-9]+$/ { | |
sub("#", "", $3) | |
x=$3 | |
} | |
/application.process.id = "'"$pid"'"/ { | |
print x | |
}' | |
} | |
daemon_mute_except() { | |
except_pid=$1 | |
regex=$2 | |
echo "Muting all streams except $except_pid and its children!" | |
already_toggled="" | |
old_stream_list="" | |
while true; do | |
stream_list=$(get_stream_pid_list) | |
if test "$stream_list" == "$old_stream_list": | |
then | |
continue | |
sleep $SLEEP_TIME | |
fi | |
if test -z "$regex" | |
then | |
# get the target pid's children | |
children=$(pstree "$except_pid" -p) | |
else | |
# if there is a regex, get the processes matching the regex | |
children=$(pstree -ap | awk "/.*${regex}.*/{print}") | |
fi | |
children=$(echo "$children" | awk -v FPAT='([0-9]+)' '{$1=$1;print}') | |
for pid in $stream_list; do | |
case "$children" in | |
*${pid}*) | |
# this is the target pid or a child | |
continue | |
sleep $SLEEP_TIME | |
;; | |
esac | |
case "$already_toggled" in | |
*${pid}*) | |
# this pid was already toggled | |
continue | |
sleep $SLEEP_TIME | |
;; | |
esac | |
# mute the stream | |
index=$(get_stream_index_from_pid "$pid") | |
echo "Muting stream index $index" | |
pactl set-sink-input-mute "$index" 1 | |
already_toggled="$already_toggled:$pid" | |
done | |
old_stream_list=$stream_list | |
sleep $SLEEP_TIME | |
done | |
} | |
# run our command and take its PID | |
option=$1 | |
case "$option" in | |
"-r") | |
regex=$2 | |
shift 2 | |
;; | |
"-h") | |
print_help | |
exit | |
;; | |
"") | |
print_help | |
exit | |
;; | |
*) | |
regex="" | |
;; | |
esac | |
echo "Running command" "$@" | |
"$@" & | |
except_pid=$! | |
# start the daemon: continuously mute streams | |
daemon_mute_except $except_pid "$regex" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment