How to change pulseaudio sink with "pacmd set-default-sink" during playback?
PulseAudio pacmd
is not capable of switching the default sinks while there is an actively playing stream to the sink input. However there is a way to still achieve this.
Changing default sink from command line
First we need to determine the index number of the sinks we want to switch. This can be done by calling:
pacmd list-sinks
Depending on our system this will give you a more or less lengthy list of sinks and properties that are at present accessible:
>>> 2 sink(s) available.
* index: 0
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1>
driver: <module-alsa-card.c>
:
:
index: 1
name: <alsa_output.pci-0000_00_14.2.analog-stereo>
driver: <module-alsa-card.c>
The index
or the name
given here is what we need for adressing the sink by command line. The present default sink is marked with an asterix (here 0
).
To be able to switch the default sinks from command line we may need to disable stream target device restore by editing the corresponing line in /etc/pulse/default.pa
to:
load-module module-stream-restore restore_device=false
To change the default output sink to sink 1
we then run
pacmd set-default-sink 1
Sucess can be visualized by opening the Sound Settings menu.
Moving a stream to another sink
Changing the default sink while we have an active input stream playing to a given sink has no effect. This should rather be done by moving this input to another sink.
pacmd list-sink-inputs
will tell us the index of the input stream
>>> 1 sink input(s) available.
index: 5
driver: <protocol-native.c>
We now know that we want to move the input stream 5
to sink 1
by calling
pacmd move-sink-input 5 1
or back to sink 0
if we like. This will be done immediately without the need of stopping playback.
Changing default sink while playing
Of course we can combine those two commands to immediately switch default sinks during playback e.g. with
pacmd set-default-sink 1 & pacmd move-sink-input 5 1
A drawback of this method is that the input stream index changes every time we stop and restart the music player. So we always have to find out the current stream index before we can switch using the commmand line.
I have written a simple script to move all the sink-inputs automatically.
Usage: ./movesinks.sh <sink number>
#!/bin/bash
echo "Setting default sink to: $1";
pacmd set-default-sink $1
pacmd list-sink-inputs | grep index | while read line
do
echo "Moving input: ";
echo $line | cut -f2 -d' ';
echo "to sink: $1";
pacmd move-sink-input `echo $line | cut -f2 -d' '` $1
done
Improved version of @Gaco script
#!/usr/bin/env bash
case "${1:-}" in
(""|list)
pacmd list-sinks |
grep -E 'index:|name:'
;;
([0-9]*)
echo switching default
pacmd set-default-sink $1 ||
echo failed
echo switching applications
pacmd list-sink-inputs |
awk '/index:/{print $2}' |
xargs -r -I{} pacmd move-sink-input {} $1 ||
echo failed
;;
(*)
echo "Usage: $0 [|list|<sink name to switch to>]"
;;
esac
my runtime copy is on github and it includes also automated switching of Master channel for kmix
Based on Gaco's answer, I rewrote it a bit for my personal use. Maybe someone finds it useful. It's for toggling my USB Speakers and USB Gaming headset.
#!/bin/bash
# get list of sinks/cards (for settings CARD1/CARD2)
# pacmd list-sinks | awk '/name:/ {print $0};' | awk '{ print $2}' | sed 's/<//g; s/>//g'
CARD1="alsa_output.usb-C-Media_INC._C-Media_USB_Audio-00"
CARD2="alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00"
CURRENT_SINK=$(pacmd stat | awk -F": " '/^Default sink name: /{print $2}' | awk 'BEGIN{FS=OFS="."} NF--' | sed 's/alsa_output/alsa_output/g')
function setCard() {
if [ "$CURRENT_SINK" == "$1" ]
then
echo "Already using this Sink"
exit 1
fi
NEW_SINK=$(pacmd list-sinks | awk '/index:/ {print $1 $2 $3} /name:/ {print $0};' | grep -m1 -B1 $1 | grep index | awk '{print $1}' | cut -d ":" -f2)
SINK=$(pacmd set-default-sink $NEW_SINK)
INPUT=$(pacmd list-sink-inputs | grep index | awk '{print $2}')
pacmd move-sink-input $INPUT $NEW_SINK
echo "Moving input: $INPUT to sink: $NEW_SINK";
echo "Setting default sink to: $NEW_SINK";
notify-send --urgency=low "Audio Switching" "SINK: $NEW_SINK"
}
function toggleSinks() {
if [ "$CURRENT_SINK" == "$CARD1" ]
then
setCard $CARD2
else
setCard $CARD1
fi
}
function showHelp() {
echo "------------------------------------"
echo "AUDIO SINK SWITCHER"
echo " "
echo "$0 [options]"
echo " "
echo "options:"
echo "-h --help What you are looking at.."
echo "-g, --gaming Sets Gaming headset as output device"
echo "-s, --speakers Sets Speakers as output device"
echo "-t, --toggle Toggles the different output devices"
echo " "
echo "------------------------------------"
}
# check args length
if [ $# -eq 0 ]
then
echo "Toggling output devices (Speakers/Headset)"
toggleSinks
fi
# arg options
while test $# -gt 0; do
case "$1" in
-h|--help)
showHelp
exit 1
;;
-g|--gaming)
setCard $CARD2
exit 1
;;
-s|--speakers)
setCard $CARD1
exit 1
;;
-t|--toggle)
toggleSinks
echo "Toggling output devices (Speakers/Headset)"
exit 1
;;
*)
showHelp
exit 1
;;
esac
done