Skip to content

Instantly share code, notes, and snippets.

@Jguer
Created January 17, 2016 03:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jguer/3443e23145902ff30481 to your computer and use it in GitHub Desktop.
Save Jguer/3443e23145902ff30481 to your computer and use it in GitHub Desktop.
Cycles pulse audio output devices
#! /bin/bash
#################################################################################
# File Name : cycle_audio_output.sh
# Created By : jguer
# Creation Date : [2016-01-16 22:55]
# Last Modified : [2016-01-17 00:42]
# Description : Cycles audio output devices
#################################################################################
VERBOSITY=0
NOTIFICATIONS=0
function swap_sink {
#Treats pulseaudio sink list to avoid calling pacmd list-sinks twice
o_pulseaudio=$(pacmd list-sinks| grep -e 'index' -e 'device.description')
#Gets max sink index
nsinks=$(echo "$o_pulseaudio" | grep index | cut -d: -f2 | sed '$!d')
if [ $VERBOSITY == 1 ]; then
echo "Max sink index: $nsinks"
fi
#Gets present default sink index
ssink=$(echo "$o_pulseaudio" | grep "* index" | cut -d: -f2)
if [ $VERBOSITY == 1 ]; then
echo "Selected sink index: $ssink"
fi
#Sets new sink index
newsink=$((++ssink))
if [ "$newsink" -gt "$nsinks" ]; then
newsink=0
fi
if [ $VERBOSITY == 1 ]; then
echo "New sink index: $newsink"
fi
$(pacmd set-default-sink $newsink)
#Moves all audio threads to new sink
inputs=`pactl list sink-inputs short | cut -f 1`
for i in $inputs; do
$(pacmd move-sink-input $i $newsink)
if [ $VERBOSITY == 1 ]; then
echo "Moved input $i to card with index $newsink"
fi
done
}
function send_notification {
o_pulseaudio=$(pacmd list-sinks| grep -e 'index' -e 'device.description')
device_name=$(echo "$o_pulseaudio" | sed -n '/* index/{n;p;}' | grep -o '".*"' | sed 's/"//g')
notify-send "Output cycle" "Changed output to ${device_name}" --icon=audio-headphones-symbolic
}
#MAIN
while getopts "vn" opt; do
case "${opt}" in
v)
VERBOSITY=1
echo VERBOSE
;;
n)
NOTIFICATIONS=1
;;
*)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
shift $((OPTIND-1))
swap_sink
if [ $NOTIFICATIONS == 1 ]; then
send_notification
fi
@frebib
Copy link

frebib commented Mar 24, 2016

Hey man, your script is great and I use it a lot. I do seem to have a problem though when the sinks aren't sequential, it won't switch. This usually happens if I unplug a device then try to switch. I'd attempt to mod it myself but my shell script skills are basically non-existent.
Thanks in advance if you can help me out :)

@gnull
Copy link

gnull commented Jun 11, 2021

@frebib, I achieved cycling through the sinks with this one-liner (sorry for the length 🙃):

pacmd set-default-sink $((s=$(pacmd list-sinks | grep index); echo "$s"; echo "$s") | grep '\*' -m 1 -A 1 | tail -1 | sed -e 's/    index: //')

It works no matter what the indices are. For example, it worked for me when I had indices 1 and 3:

io@arch ~ $ pacmd list-sinks | grep index
  * index: 1
    index: 3
io@arch ~ $ pacmd set-default-sink $((s=$(pacmd list-sinks | grep index); echo "$s"; echo "$s") | grep '\*' -m 1 -A 1 | tail -1 | sed -e 's/    index: //')
io@arch ~ $ pacmd list-sinks | grep index
    index: 1
  * index: 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment