PulseAudio Shell – Change PulseAudio Input/Output from Shell

alsaaudiopulseaudio

I have a set of nice wireless headphones which I use from time to time, in addition to my speakers and normal microphone.

I'd like to write a script to switch between one input and output source and another, essentially a switch between my headphones and my speakers+microphone.

I'd like to change between this:


…and this:


Is there a way for me script a transfer between the two inputs and outputs? Essentially I'm looking for something like this:

CURRENT_INPUT="$(get-current-input-name)"
CURRENT_OUTPUT="$(get-current-output-name)"

if [ "$CURRENT_INPUT" == "Vengeance 2000" ]; then
    set-current-input "HD Pro Webcam C920"
else 
    set-current-input "Vengeance 2000"
fi

if ["$CURRENT_OUTPUT" == "Vengeance 2000" ]; then
    set-current-output "Built-in Audio"
else
    set-current-output "Vengeance 2000"
fi

Is there a way to script this?

Best Answer

As @Teresa-e-Junior pointed out pactl is the tool to use:

First of all we might want to get the IDs of our PA sinks. On my system this is what I get:

$ pactl list short sinks
0       alsa_output.pci-0000_01_00.1.hdmi-surround      module-alsa-card.c      s16le 6ch 44100Hz  SUSPENDED
1       alsa_output.pci-0000_00_1b.0.analog-stereo      module-alsa-card.c      s16le 2ch 44100Hz  RUNNING

Sink 1 is currently my default sink.
But now I want all my current and future streams to be played via HDMI (i.e. sink 0).

There is a command to set the default sink for PulseAudio, but it doesn't seem to have any effect on my PC:

$ pacmd set-default-sink 0 #doesn't work on my PC :(

Instead, new streams seem to be connected to the sink that had a stream moved to it most recently.

So let's tell pactl to move all currently playing streams to sink 0. We'll first need to list them:

$ pactl list short sink-inputs
290     1       176     protocol-native.c       float32le 2ch 44100Hz
295     1       195     protocol-native.c       float32le 2ch 44100Hz

Ok, we've got two streams (IDs 290 and 295) that are both attached to sink 1.
Let's move them to sink 0:

$ pactl move-sink-input 290 0
$ pactl move-sink-input 295 0

So, that should be it. Now we just have to make a script that does the work for us:

#!/bin/bash

if [ -z "$1" ]; then
    echo "Usage: $0 <sinkId/sinkName>" >&2
    echo "Valid sinks:" >&2
    pactl list short sinks >&2
    exit 1
fi

newSink="$1"

pactl list short sink-inputs|while read stream; do
    streamId=$(echo $stream|cut '-d ' -f1)
    echo "moving stream $streamId"
    pactl move-sink-input "$streamId" "$newSink"
done

You can call it with either a sink ID or a sink name as parameter (i.e. either 0 or something like alsa_output.pci-0000_01_00.1.hdmi-surround).

Now you could attach this script to a udev event or key shortcut.

Related Question