Skip to content

Instantly share code, notes, and snippets.

@luckyshot
Forked from pgillet/README.md
Last active October 3, 2024 07:02
Show Gist options
  • Save luckyshot/4d517105a3e00b6253b0acf29294eb91 to your computer and use it in GitHub Desktop.
Save luckyshot/4d517105a3e00b6253b0acf29294eb91 to your computer and use it in GitHub Desktop.
Switch audio output devices on Linux

Audio Output Switcher

This script will cycle to the next available audio output device. It can be tied to a hotkey to easily be triggered. This is handy, for example, for swapping between HDMI audio and headphones.

Install

  1. Download the audio-device-switch.sh script and place it in /usr/local/bin.
  2. Make the script executable: sudo chmod 755 /usr/local/bin/audio-device-switch.sh.
  3. Open the Keyboard Shortcuts settings page, add a new shortcut, tell it to execute audio-device-switch.sh, and set up your shortcut!
  4. Install the notify-send library if you want to see a popup notification when the audio device switches: sudo apt install libnotify-bin.

Customizations

Feel free to modify this script and make it your own. Some ideas for customization:

Different icon in the notification

Line 45 of the script calls notify-send with the -i flag which defines which icon is displayed. Stock icons are found in:

  • /usr/share/icons/gnome/32x32
  • /usr/share/notify-osd/icons/

Or, a custom icon file can be provided.

More details about the audio device

Line 41 fetches the output device names using the pacmd list-sinks command and filters out the alsa.name property. You could pull another property, such as the device.description.

Acknowledgements

This is a more modern, robust rewrite of tsvetan's solution on the Ubuntu forums.

#!/bin/bash
# Grab a count of how many audio sinks we have
sink_count=$(pacmd list-sinks | grep -c "index:[[:space:]][[:digit:]]")
# Create an array of the actual sink IDs
sinks=()
mapfile -t sinks < <(pacmd list-sinks | grep 'index:[[:space:]][[:digit:]]' | sed -n -e 's/.*index:[[:space:]]\([[:digit:]]\)/\1/p')
# Get the ID of the active sink
active_sink=$(pacmd list-sinks | sed -n -e 's/[[:space:]]*\*[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p')
# Get the ID of the last sink in the array
final_sink=${sinks[$((sink_count - 1 ))]}
# Find the index of the active sink
for index in "${!sinks[@]}"; do
if [[ "${sinks[$index]}" == "$active_sink" ]]; then
active_sink_index=$index
fi
done
# Default to the first sink in the list
next_sink=${sinks[0]}
next_sink_index=0
# If we're not at the end of the list, move up the list
if [[ $active_sink -ne $final_sink ]] ; then
next_sink_index=$(( active_sink_index + 1))
next_sink=${sinks[$next_sink_index]}
fi
#change the default sink
pacmd "set-default-sink ${next_sink}"
#move all inputs to the new sink
for app in $(pacmd list-sink-inputs | sed -n -e 's/index:[[:space:]]\([[:digit:]]\)/\1/p');
do
pacmd "move-sink-input $app $next_sink"
done
# Create a list of the sink descriptions
sink_descriptions=()
mapfile -t sink_descriptions < <(pacmd list-sinks | sed -n -e 's/.*alsa.name[[:space:]]=[[:space:]]"\(.*\)"/\1/p')
# Find the index that matches our new active sink
for sink_index in "${!sink_descriptions[@]}"; do
if [[ "$sink_index" == "$next_sink_index" ]] ; then
# Uncomment this line below to show a system notification when switching
#notify-send -i audio-volume-high "Sound output switched to ${sink_descriptions[$sink_index]}"
exit
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment