18

I recently switched to OpenSUSE (with KDE) from Windows, and I'm still going through the learning curve.

I switch fairly frequently between using my headphones with built-in microphone, and using my monitor's built-in speakers and my webcam's microphone. Using the Phonon menu through KMix (example below), I'm able to re-arrange the devices to put the one I want to use on top, but I'd prefer to be able to do it with a hotkey, similar to what the Audio Switcher application does on Windows. When I do it, I'd also like to set the Master channel to the new one as well so I can easily adjust the audio.

enter image description here

Is there a way through some script that would allow me to (a) select a new default audio playback and audio recording device on the fly, (b) while also setting the master channel to that same playback device (c) with a hotkey or other quick method on the desktop?

Ryan
  • 3,925

5 Answers5

11

Most GUI kits use same backend PulseAudio. Use pactl to write control script.

NAME
       pactl - Control a running PulseAudio sound server

DESCRIPTION
       pactl can be used to issue control commands to the PulseAudio sound server.

       pactl only exposes a subset of the available operations. For the full set use the pacmd(1).

Source: man pactl

  1. To check available output sinks

    $ pactl list short sinks
    0   alsa_output.pci-0000_01_00.1.hdmi-stereo    module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
    1   alsa_output.pci-0000_00_1b.0.analog-stereo  module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
    
  2. To check available input sources

    $ pactl list short sources
    0   alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor    module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
    1   alsa_output.pci-0000_00_1b.0.analog-stereo.monitor  module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
    2   alsa_input.pci-0000_00_1b.0.analog-stereo   module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
    
  3. To check default

    $ pactl info
    Server String: /run/user/1000/pulse/native
    Library Protocol Version: 30
    Server Protocol Version: 30
    Is Local: yes
    Client Index: 2
    Tile Size: 65472
    User Name: user
    Host Name: userpc
    Server Name: pulseaudio
    Server Version: 6.0
    Default Sample Specification: s16le 2ch 44100Hz
    Default Channel Map: front-left,front-right
    Default Sink: alsa_output.pci-0000_00_1b.0.analog-stereo
    Default Source: alsa_input.pci-0000_00_1b.0.analog-stereo
    
  4. To set default

    pactl set-default-source id-or-name
    pactl set-default-sink id-or-name
    

    Example:

    pactl set-default-source alsa_input.pci-0000_00_1b.0.analog-stereo
    pactl set-default-sink alsa_output.pci-0000_00_1b.0.analog-stereo
    

    or:

    pactl set-default-source 2
    pactl set-default-sink 1
    

Notes:

  • This will affect only new streams, you have to move the current running streams, so use:

    pacmd move-sink-input <stream-id> <sink-id/name>
    

    Nice example to copy from: Switching to HDMI Audio when HDMI is plugged into a laptop (14.04)

  • Some cards has multiple switchable ports, May be the one you want is not the default.

    Check for available ports:

    $pactl list sinks
    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
    ...
    

    To set it:

    pactl set-sink-port <sink-id/name> <port-name>
    

    Example:

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

To change the Master Channel

Following this tutorial, you can set the master channel using qdbus as follows:

  1. Find the Master Mixer for each of your devices with the following command. First manually set the Master Channel to the one you want to check, then run the command:

    qdbus org.kde.kmix /Mixers org.kde.KMix.MixSet.currentMasterControl
    
  2. Using the result of that command and the audio sink you wish you control, use the following syntax to change your master channel:

    qdbus org.kde.kmix /Mixers org.kde.KMix.MixSet.setCurrentMaster "[insert Mixer]" "[insert sink]" 2>&1 > /dev/null
    
  3. In the end, the script to switch all current audio to a new channel, set it as the default, and set it as the master channel looks like the following:

    #!/bin/bash
    pactl set-default-sink alsa_output.usb-Logitech_Logitech_G930_Headset-00-Headset.analog-stereo
    pactl set-default-source alsa_input.usb-Logitech_Logitech_G930_Headset-00-Headset.analog-mono
    INPUTS=($(pacmd list-sink-inputs | grep index | awk '{print $2}'))
    for i in ${INPUTS[*]}; do pacmd move-sink-input $i alsa_output.usb-Logitech_Logitech_G930_Headset-00-Headset.analog-stereo &> /dev/null; done
    qdbus org.kde.kmix /Mixers org.kde.KMix.MixSet.setCurrentMaster "PulseAudio::Playback_Devices=:1" "alsa_output.usb-Logitech_Logitech_G930_Headset-00-Headset.analog-stereo" 2>&1 > /dev/null
    
user.dz
  • 698
3

Thanks to this answer I finally found a solution, see the below instruction

Show always HDMI output in the mixed We will create a new profile that link both profiles "Analog audio" and "HDMI audio".

From my understanding this file /usr/share/pulseaudio/alsa-mixer/profile-sets/default.conf list all mapping profiles between Alsa and Pulseaudio.

1.
Find the mapping that are related to your Analog profile and HDMI profile definition. (description: should match the Device Profiles shown in Audio Volume Kde setting module )

For me are the following:

[Mapping analog-stereo]
device-strings = front:%f
channel-map = left,right
paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
priority = 10

[Mapping hdmi-stereo-extra1]
description = Digital Stereo (HDMI 2)
device-strings = hdmi:%f,1
paths-output = hdmi-output-1
channel-map = left,right
priority = 2
direction = output

2.
On the base of the above Mapping definition I have created the following new profile that group both the above ones:

[Profile output:analog-stereo+output:hdmi-stereo-extra1]
description = All
output-mappings = analog-stereo hdmi-stereo-extra1
input-mappings = analog-stereo

3.
Restart pulse audio with this command:

pulseaudio --kill; sleep 1; pulseaudio --start

4.
Go to KDE phonon settings > Audio Hardware setup and select the new profile. 2 profiles in the mixer

Now you should see both profile in the mixed and so you'll be able to switch easy:

HDMI is always shown in the mixer now
I would suggest to use this plasmoid mixer: https://store.kde.org/p/1100894/

(extra step) Force both output enabled

If you don't mind having both computer speaker and TV output audio in the same time ( so basically you don't have to switch the audio output ever ).

You can select the below setting and then you'll have a new entry in the mixer

enter image description here

Francesco
  • 279
1

Building upon previous comments, I wrote the following script and bind it to a hotkey for use in KDE Plasma to toggle between my two audio devices. I like having the control of my audio source as opposed to completely automating this process.

Change your audio devices as appropriate. Use pactl list short sinks to determine your devices.

#!/bin/bash

# Audio sinks
HEADSET='alsa_output.usb-Corsair_Corsair_VOID_PRO_Wireless_Gaming_Headset-00.analog-stereo'
SPEAKERS='alsa_output.pci-0000_1f_00.3.analog-stereo'

# Get current audio sink
CURRENTDEV=$(pactl list short sinks | grep RUNNING | awk {'print $2'})

# Determine our next audio sink
if [[ "$CURRENTDEV" == "$HEADSET" ]]; then
    NEXTDEV=$SPEAKERS
else
    NEXTDEV=$HEADSET
fi

# Set our default device
pactl set-default-sink $NEXTDEV

# Move current streams (dont check for null, if null you wont see heads up display of audio change)
INPUTS=($(pacmd list-sink-inputs | grep index | awk '{print $2}'))
for i in ${INPUTS[*]}; do pacmd move-sink-input $i $NEXTDEV &> /dev/null; done

linuxkd
  • 11
0

My situation is simple. I have two output some hdmi and some analog, so based on user.dz answer (thanks) I wrote this little script and call it with keyboard shortcuts.

#!/bin/bash
# parameter: "hdmi" or "analog"

output=`pactl list short sinks |grep $1 | cut -f1`

pactl set-default-sink $output

for i in `pacmd list-sink-inputs |grep index: | awk '{print $2}'`; do
  pacmd move-sink-input $i $output
done

If you have other interfaces you can look for unique pattern in "pactl list short sinks" output and call the script with whatever parameter you want.

gabor.zed
  • 101
  • 1
0

I searched everywhere ... I did not find ... I made a script in python, use it)

import os
speakers = []
st = 0
au = os.popen("pacmd list-sinks")
audiotm = au.read()
audio = list(audiotm.split())
indices = [i for i, x in enumerate(audio) if x == "name:"]
for num in range(len(indices)):
    speakers.append(audio[indices[num]+1])
for num in range(len(speakers)):
    speakers[num] = speakers[num][1:len(speakers[num])-1]
dir = os.path.abspath(__file__)
dir = dir[:-5]
try: f = open(dir + "lststate.txt","r");st = int(f.read()) ;f.close();
except:f = open(dir + "lststate.txt","w");f.write(str(st)); f.close();
if st == len(speakers): st = 0;
OUT = speakers[st]
st += 1
f = open(dir + "lststate.txt","w");f.write(str(st)); f.close();
z = os.popen("pactl list short sink-inputs")
OUTID = z.read().split()
x = os.popen("pacmd set-default-sink " + OUT)
for num in range(0,len(OUTID),7):
    y = os.popen("pactl move-sink-input " + OUTID[num] + " " + OUT)
exit()
Asion
  • 1