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