I like to switch the sound output from Speaker to USB headphone with a Shortcut. Is there a way to accomplish this?
9 Answers
Automated solution https://ubuntuforums.org/showthread.php?t=1370383 It works on Ubuntu 18.04
Open the terminal and type:
sudoedit /usr/local/bin/audio-device-switch.shCopy and paste the below code in nano editor
Save it and close nano editor.
sudo chmod 755 /usr/local/bin/audio-device-switch.shSystem -> Preferences -> Keyboard Shortcuts
Press Add and enter Switch between audio devices as name and audio-device-switch.sh as command and press Apply.
Select the newly added shortcut row and click on the shortcut column. 8. Choose a shortcut combination – e.g. Win + F12.
That's all - now you can plug in your plug in your HDMI device and switch the audio output by pressing the chosen shortcut combination.
Code:
#!/bin/bash
declare -i sinks_count=pacmd list-sinks | grep -c index:[[:space:]][[:digit:]]
declare -i active_sink_index=pacmd list-sinks | sed -n -e 's/\*[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p'
declare -i major_sink_index=$sinks_count-1
declare -i next_sink_index=0
if [ $active_sink_index -ne $major_sink_index ] ; then
next_sink_index=active_sink_index+1
fi
#change the default sink
pacmd "set-default-sink ${next_sink_index}"
#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_index"
done
#display notification
declare -i ndx=0
pacmd list-sinks | sed -n -e 's/device.description[[:space:]]=[[:space:]]"(.*)"/\1/p' | while read line;
do
if [ $next_sink_index -eq $ndx ] ; then
notify-send -i notification-audio-volume-high "Sound output switched to" "$line"
exit
fi
done
- 103
- 181
Check for port names
pactl list sinks(I remove non needed sinks output):Sink #1 State: RUNNING Name: alsa_output.pci-0000_00_1b.0.analog-stereo Description: Built-in Audio Analog Stereo Driver: module-alsa-card.c ... Ports: analog-output-speaker: Speakers (priority: 10000, not available) analog-output-headphones: Headphones (priority: 9000, available) Active Port: analog-output-headphones Formats: pcmSet sink port using
pactl set-sink-port:pactl set-sink-port 1 analog-output-speakeror
pactl set-sink-port 1 analog-output-headphonesIf you are using a removable device (Example: USB devices), it's better to use sink
nameinstead ofid. For example:pactl set-sink-port alsa_output.pci-0000_00_1b.0.analog-stereo analog-output-headphones
Reference: man pactl
- 49,176
Since everyone's been adding their solutions, here's mine.
#!/bin/sh
currentline=$(pactl list short sinks | grep -n "$(pactl get-default-sink)" | cut -d: -f 1)
lastline=$(pactl list short sinks | wc -l)
nextline=$(($currentline % $lastline + 1))
nextsink=$(pactl list short sinks | head "-n$nextline" | tail -1 | cut -f 1)
pactl set-default-sink $nextsink
for sinkinput in $(pactl list short sink-inputs | cut -f 1); do
pactl move-sink-input $sinkinput "@DEFAULT_SINK@"
done
edit: My new motherboard comes with ALC4080. pactl now lists both the front and the rear output jack as available, although only one of them can actually be in use at the same time. Hence, cycling through the outputs with this script no longer works. The loop gets stuck at the last available output.
- 210
I have Ubuntu 20, and realized, that the indices of devices are not counted from 0 to COUNT-1. So I had to modify the script. This one works now:
#!/bin/bash
declare -i sinks_count=pacmd list-sinks | grep -c index:[[:space:]][[:digit:]]
if [ $sinks_count -eq 0 ] ; then
exit
fi
declare -i active_sink_index=pacmd list-sinks | sed -n -e 's/\*[[:space:]]index: [[:space:]]\([[:digit:]]\)/\1/p'
active_index_position_found=0
let next_sink_index=-1
while read index ;
do
declare -i ind=($(echo $index | tr -dc '[0-9]+'))
if [ $next_sink_index -lt 0 ] ; then
export next_sink_index=$ind
fi
if [ $active_index_position_found -eq 1 ] ; then
export next_sink_index=$ind
break;
fi
if [ $active_sink_index -eq $ind ] ; then
export active_index_position_found=1
fi
done < <(pacmd list-sinks | grep index:[[:space:]][[:digit:]])
#change the default sink
pacmd "set-default-sink ${next_sink_index}"
#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_index"
done
#display notification
declare -i ndx=0
pacmd list-sinks | sed -n -e 's/device.description[[:space:]]=[[:space:]]"(.*)" /\1/p' | while read line;
do
if [ $next_sink_index -eq $ndx ] ; then
notify-send -i notification-audio-volume-high "Sound output switched to" "$line"
exit
fi
ndx+=1
done;
- 111
It was not working with two digit indices. In my case Nvidia HDMI sink was with index 23. Here is a working solution :)
#!/bin/bash
declare -i sinks_count=pacmd list-sinks | grep -Pc 'index:\s+\d+'
if [ $sinks_count -eq 0 ] ; then
exit
fi
declare -i active_sink_index=pacmd list-sinks | grep -Po '\*\s+index:\s+\K\d+'
active_index_position_found=0
let next_sink_index=-1
while read index ;
do
declare -i ind=($(echo $index | tr -dc '[0-9]+'))
if [ $next_sink_index -lt 0 ] ; then
export next_sink_index=$ind
fi
if [ $active_index_position_found -eq 1 ] ; then
export next_sink_index=$ind
break;
fi
if [ $active_sink_index -eq $ind ] ; then
export active_index_position_found=1
fi
done < <(pacmd list-sinks | grep -Po 'index:\s+\K\d+')
#change the default sink
pacmd "set-default-sink ${next_sink_index}"
#move all inputs to the new sink
for app in $(pacmd list-sink-inputs | grep -Po 'index:\s+\K\d+');
do
pacmd "move-sink-input $app $next_sink_index"
done
The only script version that worked for me was thew one @rosetta-stoned shared above. Scripts from other comments did not. [OS: Ubuntu Mate 22.04 LTS (Jammy Jellyfish) 64-bit]
I further extended the script with a line to play a sound. This way you can hear sound in the devices as you keep switching output devices. Hearing sound in the desired device will mean you don't need to swap around anymore.
#!/bin/bash
declare -i sinks_count=pacmd list-sinks | grep -Pc 'index:\s+\d+'
if [ $sinks_count -eq 0 ] ; then
exit
fi
declare -i active_sink_index=pacmd list-sinks | grep -Po '\*\s+index:\s+\K\d+'
active_index_position_found=0
let next_sink_index=-1
while read index ;
do
declare -i ind=($(echo $index | tr -dc '[0-9]+'))
if [ $next_sink_index -lt 0 ] ; then
export next_sink_index=$ind
fi
if [ $active_index_position_found -eq 1 ] ; then
export next_sink_index=$ind
break;
fi
if [ $active_sink_index -eq $ind ] ; then
export active_index_position_found=1
fi
done < <(pacmd list-sinks | grep -Po 'index:\s+\K\d+')
#change the default sink
pacmd "set-default-sink ${next_sink_index}"
#move all inputs to the new sink
for app in $(pacmd list-sink-inputs | grep -Po 'index:\s+\K\d+');
do
pacmd "move-sink-input $app $next_sink_index"
done
paplay /usr/share/sounds/mate/default/alerts/sonar.ogg
- 11
I added support for "prev" and "next" arguments, since I have quite a few devices to choose from. Just bind 2 keys.
#!/bin/bash
declare direction="$1"
declare -i sinks_count=pacmd list-sinks | grep -Pc 'index:\s+\d+'
if [ $sinks_count -eq 0 ] ; then
exit
fi
declare -i active_sink_index=pacmd list-sinks | grep -Po '\*\s+index:\s+\K\d+'
readarray -t indexes < <(pacmd list-sinks | grep -Po 'index:\s+\K\d+')
declare indexes_count=${#indexes[@]}
declare active_index=-1
for i in "${!indexes[@]}"; do
if [[ "${indexes[$i]}" = "${active_sink_index}" ]]; then
active_index=$i;
fi
done
declare next_index=$((( $active_index + 1 ) % $indexes_count))
declare prev_index=$((( $active_index - 1 ) % $indexes_count))
declare next_sink_index=${indexes[$next_index]}
declare prev_sink_index=${indexes[$prev_index]}
declare sink_to_use="${next_sink_index}"
if [ "$direction" = "prev" ] ; then
sink_to_use="${prev_sink_index}"
fi
Change the default sink
pacmd "set-default-sink ${sink_to_use}"
Move all inputs to the new sink
for app in $(pacmd list-sink-inputs | grep -Po 'index:\s+\K\d+');
do
pacmd "move-sink-input $app $sink_to_use"
done
- 1
Error: No PulseAudio daemon running, or not running as session daemon.
If you see this you are using pacmd,which no longer works for me.You need to use pactl instead.
Here is how:
Copy this :
#!/bin/sh
currentline=$(pactl list short sinks | grep -n "$(pactl get-default-sink)" | cut -d: -f 1)
lastline=$(pactl list short sinks | wc -l)
nextline=$(($currentline % $lastline + 1))
nextsink=$(pactl list short sinks | head "-n$nextline" | tail -1 | cut -f 1)
pactl set-default-sink $nextsink
for sinkinput in $(pactl list short sink-inputs | cut -f 1); do
pactl move-sink-input $sinkinput "@DEFAULT_SINK@"
done
paplay /usr/share/sounds/mate/default/alerts/sonar.ogg
Open an editor and paste . Save it as
audio-device-switch.shcopy it to
/usr/local/bin/open a terminal and type
sudo chmod 755 /usr/local/bin/audio-device-switch.shGo to System -> Preferences -> Keyboard Shortcutsclick
Addand to command enteraudio-device-switch.sh. give it a name likeSwitch AudioClickApply.Select the newly added shortcut row and click on the shortcut column and choose a shortcut key combination.
My system: Ubuntu Mate 24.04.1 LTS (Noble Numbat) 64-bit. Updating from Ubuntu Mate 22.04 LTS (Jammy Jellyfish) broke the pacmd based script for me.
Honourable mentions: This solution is a merge of previous solutions in this thread. Code is based on what user j2l4e shared, I only added the last line so you can hear a sound as you keep switching output devices. Hearing the sound in the desired device will mean you don't need to swap around anymore. steps to add keyboard shortcuts are based on matreshkin's post above.
- 11
Do this in 2 steps:
Find a command line setting to change back/forth between these settings.
Add these to some key combinations. Systems Settings >> Keyboard >> Shortcuts
- 14,528
- 5
- 38
- 46