Edit
the code for this answer/explanation is outdated and has some bugs.
I'm keeping this Up-to-date here: https://github.com/madacol/sinkSwitcher
Yet Another Sink Switcher Script
tested on Ubuntu 16 and 18
But this one lets you switch only the audio of the application you want.
USAGE: Focus the application you want to change its sink and run this script. That's it!!!
This script detects the application that is on focus, finds all audios playing from it, and switch them to the next available sink.
https://gist.github.com/madacol/1a0d8569166886d2d98f073f7f5c5fe3
Explaining the script
We need to find the PID of the application on focus
But first we need the xid
xprop -root _NET_ACTIVE_WINDOW
Then insert it here $xid
to get the pid of the application
xprop -id $xid _NET_WM_PID
Now we need find the sink-inputs related to that PID
First let's linearize the output of the command pacmd list-sink-inputs
to list one sink-input per line, showing its index, sink and pid on the same line
pacmd list-sink-inputs | grep -E 'index:|sink:|process.id' | tr '\n' ' ' | tr -d '"' | sed -e 's/index:/\n/g' | tail -n +2
let's analyze it step by step:
grep -E 'index:|sink:|process.id
only keep lines that contain index:
, sink:
or process.id
tr '\n' ' '
joins all lines
tr -d '"'
removes all "
characters. Necessary to get the pid without quotes
sed -e 's/index:/\n/g'
replaces all index:
occurrences with a new line character \n
tail -n +2
removes the first line because it's empty
And the result is something like this:
180 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 3521
181 sink: 1 <alsa_output.pci-0000_00_01.0.analog-stereo> application.process.id = 2733
182 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 13752
Let's analyze one line to understand what it means:
# 182 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 13752
182
is the sink-input index, 0
is the sink index, and 13752
at the end, is the pid of the belonging application
Then we iterate through each line
... | while IFS= read -r line || [ -n "$line" ]; do
sink_input_pid=$(echo $line | awk '{print $NF}')
And finally filter only the sink-input's pid that matches the focused app's pid
if [ $sink_input_pid = $app_pid ]; then
Extracting data
With awk
we can get the elements we need
sink_input_index=$(echo $sink_input | awk '{print $1}')
current_sink_index=$(echo $sink_input | awk '{print $3}')
Get numbers of sinks, to know when the rotation of sinks should restart from 0.
sink_list_size=${#sink_list_array[@]}
Finding next sink, we have to iterate through the list of sinks, to know which one matches current_sink_index and to know the index of the next sink.
i=0
for sink in "${sink_list_array[@]}"; do
i=$((($i+1)%sink_list_size)) # i++ mod(#sinks)
if [ $sink = $current_sink_index ]; then
next_sink_index=${sink_list_array[i]}
break
fi
done
And finally, we move the sink-input to play in next_sink_index
pacmd move-sink-input $sink_input_index $next_sink_index
Note on Ubuntu 16.04:
When configuring the shortcut key, I couldn't make it work with ubuntu's shortcut manager.
So I had to install compizconfig-settings-manager
sudo apt-get install compizconfig-settings-manager