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

pavucontrol GUI

pavucontrol GUI

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

 

You may also like...

Leave a Reply

Your email address will not be published.