Toggle Audio Output Between Several Devices
With PulseAudio one can choose the output (in PA syntax, it’s called “sink-input”) device for each audio stream, for example, I can listen to my music on my headphone (USB sound card in my case) and play a movie for my kid on the external speakers. There is a GUI application called “pavucontrol” which allow you to this by point and click, but now days I found myself doing this switch too often, so I was looking for a quick shortcut, and so this is my quick and ugly hack, which I hope will benefit someone else as well.
Toggle Output – The GUI way
Toggle the output – Script
#!/bin/bash
set -e
set -u
function get_index() {
declare -a my_array
my_array=($2)
value=$1
for i in ${!my_array[@]}; do
if [[ "${my_array[$i]}" = "${value}" ]]; then
echo "${i}";
fi
done
}
# get card list
# declare -A CARDS
CARDS=( $(pactl list sinks short | awk '{print $1}') )
num_cards=$(( ${#CARDS[@]} -1)) # for using with index
# dump "${CARDS[*]}"
# get last active sink (application which use the sound card)
LAST_SINK_LINE=$(pactl list sink-inputs short | tail -n1)
# output example
# 329 1 16 protocol-native.c float32le 2ch 44100Hz
# 1st - 329 in this case is the sink stream
# 2nd - 1 is the sound card
# 3rd - 16 is the application
# we basically like to move the application output to a new card.
if [[ -z ${LAST_SINK_LINE} ]];
then
notify-send 'Error' 'was not able to get last sink line'
else
last_sink_app_index=$( echo "${LAST_SINK_LINE}" | awk '{print $3}' )
last_sink_card=$( echo "${LAST_SINK_LINE}" | awk '{print $2}' )
last_sink_out_index=$( echo "${LAST_SINK_LINE}" | awk '{print $1}' )
fi
if [[ ! -z ${last_sink_card} ]];
then
current_card_index=$(get_index "${last_sink_card}" "${CARDS[*]}")
if [[ ${current_card_index} == ${num_cards} ]]; then
switch_to_card_index=0
else
switch_to_card_index=$((current_card_index+1))
fi
pactl move-sink-input "${last_sink_out_index}" ${CARDS[${switch_to_card_index}]}
fi
Now one just need to assign a shortcut key for this script, and it’s done.
Notes
# list output DEVICES
pacmd list-sinks | grep -e index -e 'alsa.name'
# list playback streems (to which DEVICE each application will output)
pacmd list-sink-inputs | grep -e index: -e 'application.name '
# change sink input
pacmd move-sink-input 63 1
# [streem][card]
» pacmd list-cards | grep -e index: -e alsa.card_name | xargs -n5
index: 0 alsa.card_name = HDA Intel PCH
index: 4 alsa.card_name = USB PnP Sound Device
