16

I like to switch the sound output from Speaker to USB headphone with a Shortcut. Is there a way to accomplish this?

user.dz
  • 49,176
Evenbit GmbH
  • 4,726

9 Answers9

8

Automated solution https://ubuntuforums.org/showthread.php?t=1370383 It works on Ubuntu 18.04

  1. Open the terminal and type:

     sudoedit /usr/local/bin/audio-device-switch.sh
    
  2. Copy and paste the below code in nano editor

  3. Save it and close nano editor.

  4. sudo chmod 755 /usr/local/bin/audio-device-switch.sh

  5. System -> Preferences -> Keyboard Shortcuts

  6. Press Add and enter Switch between audio devices as name and audio-device-switch.sh as command and press Apply.

  7. Select the newly added shortcut row and click on the shortcut column. 8. Choose a shortcut combination – e.g. Win + F12.

  8. 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

Lauloque
  • 103
8
  1. 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:
            pcm
    
  2. Set sink port using pactl set-sink-port:

     pactl set-sink-port 1 analog-output-speaker
    

    or

     pactl set-sink-port 1 analog-output-headphones
    

    If you are using a removable device (Example: USB devices), it's better to use sink name instead of id. For example:

     pactl set-sink-port alsa_output.pci-0000_00_1b.0.analog-stereo analog-output-headphones
    

Reference: man pactl

user.dz
  • 49,176
3

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.

j2L4e
  • 210
1

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;

fairtrax
  • 111
1

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

1

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

0

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

RanzQ
  • 1
0
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

  1. Open an editor and paste . Save it asaudio-device-switch.sh

  2. copy it to /usr/local/bin/

  3. open a terminal and type sudo chmod 755 /usr/local/bin/audio-device-switch.sh

  4. Go to System -> Preferences -> Keyboard Shortcuts

  5. click Add and to command enter audio-device-switch.sh. give it a name like Switch Audio Click Apply.

  6. 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.

-1

Do this in 2 steps:

  1. Find a command line setting to change back/forth between these settings.

  2. Add these to some key combinations. Systems Settings >> Keyboard >> Shortcuts

david6
  • 14,528
  • 5
  • 38
  • 46