Skip to content

Instantly share code, notes, and snippets.

@miyl
Last active October 17, 2024 02:19
Show Gist options
  • Save miyl/40cdf1a66b360ad8ec0b19e2ffa56194 to your computer and use it in GitHub Desktop.
Save miyl/40cdf1a66b360ad8ec0b19e2ffa56194 to your computer and use it in GitHub Desktop.
Pipewire default sink (output) switching (Pulseaudio pactl)
#! /usr/bin/env sh
# This script switches between whatever sinks exist.
# Removing pulseaudio (but not libpulse) means removing pacmd, so this is an attempt at switching the default via pactl instead.
# Sinks can be specified by name or index. Index changes sometimes when you disconnect and reconnect, restart or whatever, so names are better as they are persistent.
# Annoyingly the command used to switch audio over to a new sink cannot take a name as its argument, otherwise I'd only need the name here.
# TODO: Trigger a zenity or dmenu dialog with entr that asks whether to switch monitor and/or sound to hdmi? Could do
# the same for mounting.
get_all_sinks() {
pactl list short sinks | cut -f 2
}
get_default_sink() {
#pw-play --list-targets | grep \* | tail -n 1 | cut -d' ' -f 2 | cut -d : -f 1
pactl info | grep 'Default Sink' | cut -d':' -f 2
}
DEF_SINK=$(get_default_sink)
for SINK in $(get_all_sinks) ; do
[ -z "$FIRST" ] && FIRST=$SINK # Save the first index in case the current default is the last in the list
# get_default_sink currently returns the index with a leading space
if [ " $SINK" = "$DEF_SINK" ]; then
NEXT=1;
# Subsequent pass, don't need continue above
elif [ -n "$NEXT" ]; then
NEW_DEFAULT_SINK=$SINK
break
fi
done
# Don't particularly like this method of making it circular, but...
[ -z "$NEW_DEFAULT_SINK" ] && NEW_DEFAULT_SINK=$FIRST
# Set default sink for new audio playback
pactl set-default-sink "$NEW_DEFAULT_SINK"
notify-send --expire-time 1350 "Switched default output sink to: $NEW_DEFAULT_SINK"
@miyl
Copy link
Author

miyl commented May 9, 2022

Glad to help!

That other script used to be needed in Pulseaudio to switch currently playing audio over, at least for me, but it seems that's no longer the case with Pipewire? At least I just tested it and it moved everything playing already over to the new output just fine without it.

@kevenwyld
Copy link

Hey thanks for posting this! Based on this I came up with a one-liner using rofi to select the output by name in i3wm in case anyone's interested:

bindsym $mod+m exec pactl set-default-sink $(pactl list short sinks |awk '{print $2}' |rofi $rofi_args -dmenu)

it looks like this when run:

Screenshot_2022-07-29_08-27-22

@Cruising0904
Copy link

Thank you so much for sharing this! I spent hours to figure out how to implement this feature though yours is much nicer!

@new-penguin
Copy link

Well, I was going to upload my own short script here but yours is better. I set it to a hotkey in KDE, so much faster than manually switching.

@johnczaia
Copy link

Thank you so much! I was looking for something like this for ages!

@sephid86
Copy link

안녕하세요, 게시해 주셔서 감사합니다! 이를 바탕으로 누구든지 관심이 있는 경우를 대비해 rofi를 사용하여 i3wm에서 이름으로 출력을 선택하는 한 줄짜리 코드를 생각해냈습니다.

bindsym $mod+m exec pactl set-default-sink $(pactl list short sinks |awk '{print $2}' |rofi $rofi_args -dmenu)

실행하면 다음과 같습니다.

스크린샷_2022-07-29_08-27-22

You are a genius.

thank your idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment