12

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

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

3
  • Thank you. Finally after a long time a working answer :) Feb 15 '14 at 19:55
  • 1
    Come'n :) you were still waiting, I just fill it in case someone need it come by.
    – user.dz
    Feb 15 '14 at 20:00
  • Really. I haven't found a solution for that. But i stopped trying to find one a long time ago. Feb 15 '14 at 20:04
5

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
3
  • great work! don't try to run the script as root (e.g. with sudo), it will not work. just run as normal user
    – sotix
    Nov 30 '20 at 16:44
  • I had to fix the last if and do to match the bash syntax. The script works perfectly!. Dec 22 '20 at 14:39
  • I just realized, that the indices of sinks are not necessarily counted from 0 to COUNT-1, so you have to get list of indices and then move to the next one from the list
    – fairtrax
    Jan 2 '21 at 9:53
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;
1
  • This still didn't work for me. I got the following error when I tried to run the script. Sink 2945029504090482540 does not exist
    – Heisenberg
    Sep 20 '21 at 13:52
0

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

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

3
  • How can one find out, what command line setting is needed to switch the sound output? Is there a way to trace what happens, when I do it with the GUI? Jun 28 '12 at 5:43
  • No, you need to use amixer (command line) and/or alsamixer (char-mode) in a terminal. These are old-school, and require some effort to master. Start by adding output from amixer -c 0 to your question ..
    – david6
    Jun 28 '12 at 7:16
  • 1
    I find that command and successfully run a shortcut to switch between analog and HDMI output, see my answer here. Mar 30 '17 at 22:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.