#!/bin/zsh export LC_ALL=C.UTF-8 declare -a ItemName declare -a ItemType declare -a ItemCard declare -a ItemIndex declare -a ItemDisplayName get_default_sink() { pactl info | sed -En 's/Default Sink: (.*)/\1/p' } get_default_source() { pactl info | sed -En 's/Default Source: (.*)/\1/p' } new_sink() { ( get_default_sink comm -1 -3 <(echo ${1} | sort -u) <(pactl list sinks short | sort -u) | awk '{ print $2; exit }' ) | tail -n1 } new_source() { ( get_default_source comm -1 -3 <(echo ${1} | sort -u) <(pactl list sources short | sort -u) | awk '{ print $2; exit }' ) | tail -n1 } move_all_streams() { for stream in $(pactl list sink-inputs | awk '$1 == "index:" {print $2}') ; do pactl move-sink-input ${stream} ${1} >/dev/null 2>&1 done } move_all_recordings() { for stream in $(pactl list source-outputs | awk '$1 == "index:" {print $2}') ; do pactl move-source-output ${stream} ${1} >/dev/null 2>&1 done } SinkList=$(pactl list sinks short) SourceList=$(pactl list sources short) i=1 for Sink in $(echo ${SinkList} | awk '{ print $2 }'); do ItemIndex[${i}]=${i} ItemType[${i}]="sink" ItemName[${i}]=${Sink} if [[ ${Sink} == $(get_default_sink) ]]; then ItemDisplayName[${i}]="> sink: ${Sink}" else ItemDisplayName[${i}]=" sink: ${Sink}" fi i=$((i+1)) done for Source in $(echo ${SourceList} | awk '{ print $2 }'); do ItemIndex[${i}]=${i} ItemType[${i}]="source" ItemName[${i}]=${Source} if [[ ${Source} == $(get_default_source) ]]; then ItemDisplayName[${i}]="> source: ${Source}" else ItemDisplayName[${i}]=" source: ${Source}" fi i=$((i+1)) done Available=", available: yes)" for Card in ${(ps:\n\n:)"$(pactl list cards 2> /dev/null)"}; do ActiveProfile=${Card##*Active Profile: } ActiveProfile=${ActiveProfile%%$'\n\t'Ports*} RawProfiles=${Card##*Profiles:} RawProfiles=${RawProfiles%%Active Profile:*} for Profile in ${(f)RawProfiles}; do ProfileName=${Profile%%: *} ProfileName=${ProfileName//[[:blank:]]/} ProfileDescription=${Profile#*: } [[ ${ProfileDescription} == *${Available}* ]] || continue [[ ${ProfileName} == ${ActiveProfile} ]] && continue ItemIndex[${i}]=${i} ItemType[${i}]="profile" ItemName[${i}]=${ProfileName} ItemCard[${i}]=${Card%%$'\n\t'Driver: *} ItemCard[${i}]=${ItemCard[${i}]##Card \#*$'\n\t'Name: } DisplayCard=${ItemCard[${i}]%%_*}.${ItemCard[${i}]#*.} DisplayCard=${DisplayCard%%-*}.${ItemCard[${i}]##*.} ItemDisplayName[${i}]="${DisplayCard} ? ${ItemName[${i}]}" i=$((i+1)) done done Selection=$( for i in ${ItemIndex}; do echo -e "${ItemIndex[${i}]} \034 ${ItemDisplayName[${i}]}" done | fzf -d ' \034 ' --with-nth=2 --nth=2 ) test -z "${Selection}" && exit 0 Selection=${Selection%% $'\034' *} case "${ItemType[${Selection}]}" in "sink") pactl set-default-sink ${ItemName[${Selection}]} move_all_streams ${ItemName[${Selection}]} ;; "source") pactl set-default-source ${ItemName[${Selection}]} move_all_recordings ${ItemName[${Selection}]} ;; "profile") pactl set-card-profile ${ItemCard[${Selection}]} ${ItemName[${Selection}]} NewSink=$(new_sink ${SinkList}) NewSource=$(new_source ${SourceList}) pactl set-default-source ${NewSource} pactl set-default-sink ${NewSink} move_all_recordings ${NewSink} move_all_streams ${NewSink} ;; esac