20

To switch to HDMI audio output (of monitor) and back to normal audio output from system audio jack (for headphones, as my monitor doesn't have audio out), I find myself opening up sound preferences and selecting the right channel everytime. Is there any way I can create a toggle button in the panel or assign some shortcut key to toggle since I do the switching so often.

:aplay -l 
**** List of PLAYBACK Hardware Devices ****
card 0: Intel [HDA Intel], device 0: STAC92xx Analog [STAC92xx Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 3: HDMI 0 [HDMI 0]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 7: STAC92xx Digital [STAC92xx Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

enter image description here

2
  • 1
    +1 It would be awesome if I could switch to the correct HDMI display output mode and sound mode in one keypress.
    – Kit Menke
    Nov 30, 2011 at 2:10
  • What would be better yet is if when it detects this HDMI/Display Port audio channel it would switch it automatically. This is what docking is for. I seem to remember some docking code a while ago that will change configuration based on certain hardware IDs (MAC). Anyone know what that is called again? Jan 15, 2014 at 14:33

10 Answers 10

11

With pulseaudio we are able to select the output sink from the command line:

pacmd set-default-sink "SINKNAME"

This command can be used in a launcher, script or even assigned to a keyboard shortcut for fast switching between different sinks. Please replace "SINKNAME" by the name or number of your desired sink. A list of known sinks with their associated numbers and names is given by the command:

pacmd list-sinks

Note: Changing the output sink through the command line interface can only take effect if stream target device reading is disabled. This can be done by editing the corresponing line in /etc/pulse/default.pa to:

load-module module-stream-restore restore_device=false

Alternatively we could run pulseaudio to simultaneously output sound to the internal audio device, and to the hdmi-device by running paprefs with the option to add a virtual output device:

paprefs

6
  • 2
    pacmd set-default-sink "alsa_output.pci-0000_00_1b.0.analog-stereo" and pacmd set-default-sink "alsa_output.pci-0000_00_1b.0.hdmi-stereo" works only after selecting the corresponding profile in Sound Preferences. If I am having HDMI set and I run the pacmd command for analog stereo, I'm getting the eror Sink alsa_output.pci-0000_00_1b.0.analog-stereo does not exist. But if I manually select the profile from Sound Preferences GUI and run the same command, I am not getting the error. So it is not helping to switch. May 10, 2011 at 21:39
  • @iJeeves: see edit for update.
    – Takkat
    May 21, 2011 at 21:49
  • Similar issue. If I run the command it visually will change it in the GUI but the sound does not redirect. I have to manually toggle it in the GUI for it to work. Any ideas? Jan 15, 2014 at 14:57
  • 1
    @ElijahLynn: You may also have to move the stream: askubuntu.com/questions/71863/…
    – Takkat
    Jan 15, 2014 at 15:53
  • @Takkat: I didn't try it yet but that looks to be the exact issue I was having. Thanks so much! Jan 15, 2014 at 20:34
9

I found this very annoying myself and wrote a script to toggle the output:

#!/bin/bash

CURRENT_PROFILE=$(pacmd list-cards | grep "active profile" | cut -d ' ' -f 3-)

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo+input:analog-stereo>" ] ; then
  pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo"
else 
  pacmd set-card-profile 0 "output:hdmi-stereo+input:analog-stereo"        
fi

And then bound an unused key on my keyboard to execute it (see this).

2
  • Although you haven't signed on in 18 months just wanted to let you know this is the best answer IMO +1 Feb 8, 2017 at 0:45
  • How can I do this if I need to switch between two cards, not just two profiles of one card?
    – Oebele
    Jul 11, 2017 at 15:43
2

An alternative to Sound Switcher Indicator (which requires adding a PPA) is to create a command (or a script) and call it with a shortcut:

In my case was hdmi-stereo-extra1+input profile, so in one line would be:

[[ $(pacmd list-cards | grep "active profile" | cut -d " " -f 3-) = "<output:hdmi-stereo-extra1+input:analog-stereo>" ]] && \
     pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo" || \
     pacmd set-card-profile 0 "output:hdmi-stereo-extra1+input:analog-stereo"

You can use a custom shortcut (gnome-control-center keyboard) to execute it with bash -c (will warn you if there is any conflict with other shortcut):

screenshot

screenshot

I use:

  • Super + Alt + o: Toggle the output between headphones and HDMI.
  • Super + Alt + Up: Vol Up
  • Super + Alt + Down: Vol Down

Also, you can add an alias to your .bashrc.

Tested on Ubuntu 16.04 and 18.04


If you want above behavior on a script, I made some changes based on @user829996 answer:

#!/bin/bash
set -euo pipefail # strict mode

activeProfile() { pacmd list-cards | grep "active profile" | cut -d " " -f 3-; }
CURRENT_PROFILE="$(eval activeProfile)"

# If it doesn't work run  pacmd list-cards  and try the other outputs from profile section
ANALOG_PROFILE="output:analog-stereo+input:analog-stereo"
HDMI_PROFILE="output:hdmi-stereo-extra1+input:analog-stereo"

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo-extra1+input:analog-stereo>" ] ; then
  pacmd set-card-profile 0 "$ANALOG_PROFILE"
else
  pacmd set-card-profile 0 "$HDMI_PROFILE"
fi

activeProfile
2

Edit

the code for this answer/explanation is outdated and has some bugs. I'm keeping this Up-to-date here: https://github.com/madacol/sinkSwitcher


Yet Another Sink Switcher Script

tested on Ubuntu 16 and 18


But this one lets you switch only the audio of the application you want.

USAGE: Focus the application you want to change its sink and run this script. That's it!!!

This script detects the application that is on focus, finds all audios playing from it, and switch them to the next available sink.

https://gist.github.com/madacol/1a0d8569166886d2d98f073f7f5c5fe3

Explaining the script

We need to find the PID of the application on focus

But first we need the xid

xprop -root _NET_ACTIVE_WINDOW 

Then insert it here $xid to get the pid of the application

xprop -id $xid _NET_WM_PID

Now we need find the sink-inputs related to that PID

First let's linearize the output of the command pacmd list-sink-inputs to list one sink-input per line, showing its index, sink and pid on the same line

pacmd list-sink-inputs | grep -E 'index:|sink:|process.id' | tr '\n' ' ' | tr -d '"' | sed -e 's/index:/\n/g' | tail -n +2

let's analyze it step by step:

grep -E 'index:|sink:|process.id only keep lines that contain index:, sink: or process.id

tr '\n' ' ' joins all lines

tr -d '"' removes all " characters. Necessary to get the pid without quotes

sed -e 's/index:/\n/g' replaces all index: occurrences with a new line character \n

tail -n +2 removes the first line because it's empty

And the result is something like this:

  180 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 3521
  181 sink: 1 <alsa_output.pci-0000_00_01.0.analog-stereo> application.process.id = 2733
  182 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 13752

Let's analyze one line to understand what it means:

  # 182 sink: 0 <alsa_output.pci-0000_00_00.1.hdmi-stereo-extra1> application.process.id = 13752

182 is the sink-input index, 0 is the sink index, and 13752 at the end, is the pid of the belonging application

Then we iterate through each line

... | while IFS= read -r line || [ -n "$line" ]; do
  sink_input_pid=$(echo $line | awk '{print $NF}')

And finally filter only the sink-input's pid that matches the focused app's pid

  if [ $sink_input_pid = $app_pid ]; then

Extracting data

With awk we can get the elements we need

sink_input_index=$(echo $sink_input | awk '{print $1}')
current_sink_index=$(echo $sink_input | awk '{print $3}')

Get numbers of sinks, to know when the rotation of sinks should restart from 0.

sink_list_size=${#sink_list_array[@]}

Finding next sink, we have to iterate through the list of sinks, to know which one matches current_sink_index and to know the index of the next sink.

i=0
for sink in "${sink_list_array[@]}"; do
  i=$((($i+1)%sink_list_size))  # i++ mod(#sinks)
  if [ $sink = $current_sink_index ]; then
    next_sink_index=${sink_list_array[i]}
    break
  fi
done

And finally, we move the sink-input to play in next_sink_index

pacmd move-sink-input $sink_input_index $next_sink_index

Note on Ubuntu 16.04:

When configuring the shortcut key, I couldn't make it work with ubuntu's shortcut manager. So I had to install compizconfig-settings-manager

sudo apt-get install compizconfig-settings-manager
2
  • +1 for great first answer as new user. Since the original question was for Ubuntu 11.04 you should point out what version was tested with. Feb 7, 2017 at 22:51
  • @WinEunuuchs2Unix Wow! thank you :). I added Ubuntu's version below the title.
    – Madacol
    Feb 8, 2017 at 0:27
1

If you are using Gnome Shell instead of Unity you can install the extension below. You'll then be able to switch from the volume short-cut in the top panel. https://extensions.gnome.org/extension/142/output-device-chooser-on-volume-menu/

1

Since there is only one soundcard visible in the screenshot, I think the output of this soundcard should be switched.

For example: I have a Notebook with one integrated soundcard, but it has a digital output (SPDIF) when docked.

So what I wanted to do is switch the active output or "Profile" in pulseaudio.

I found the commands that do exactly that:

pacmd set-card-profile 0 output:analog-stereo
pacmd set-card-profile 0 output:iec958-stereo+input:analog-stereo

What I did to get the correct names for my desired output-setting--here, digital output, but analog (micro) input--was:

pacmd list | grep output
1

I've been trying to find a solution to this problem as well. As of Ubuntu 11.04 this does not seem to be possible directly, I only found this guide to add both HDMI and Analog as separate outputs, so pacmd shows 3 sinks now. Then it is possible to switch between sinks using the above commands. (see also)

But apparently Ubuntu 11.11 will get a PulseAudio with jack detection system. According to the website below, David Henningsson has coded a detection via udev so pulse audio automatically gets switched to the last added output, including switching between different profiles of the same soundcard (as is the case with your and my setup). (see here)

So I'm hoping this will work, when I try the final version next Friday.

1

Based on many of the previous answers, I wrote a script that sets the playback sink alternating between the available ones.

The best way to use it is by creating a keyboard shortcut to run it, so every time you press that key combination the audio is redirected to the next available sink.

The code is available here: https://gist.github.com/germank/7fa2fb07d45a838bf890addadd8bea8c

0

In my case the analog options where not in the list. Install pavucontrol: sudo apt install pavucontrol

Could fix the issue, by starting the application:

  1. Start the app via terminal, by entering: pavucontrol (enter)
  2. Go to the 'Configuration' tab.
  3. Select Analoge stereo output profile at Intern Sound

enter image description here

Now I could here sound and select different profiles (under Linux Mint):

enter image description here

0

Is there any way I can create a toggle button in the panel

I wrote an indicator applet that lets you switch the sound output.

1
  • Welcome to Ask Ubuntu! Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. Dec 21, 2013 at 13:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .