From e77881a72b735ca12aa055054656afdfbd6a8fc8 Mon Sep 17 00:00:00 2001 From: Robert Günzler Date: Thu, 29 Jul 2021 23:45:43 +0200 Subject: bin: format scripts --- bin/soundswitch | 259 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 149 insertions(+), 110 deletions(-) (limited to 'bin/soundswitch') diff --git a/bin/soundswitch b/bin/soundswitch index acd287a..e39a292 100755 --- a/bin/soundswitch +++ b/bin/soundswitch @@ -1,14 +1,17 @@ #!/bin/sh # # DESCRIPTION: -# dmenu-based pulseaudio helper +# dmenu-based audio helper # +# TODO +# - auto-select the currently active profile + set -e [ -n "$DEBUG" ] && set -x # check requirements -for tool in jq swq pactl perl; do +for tool in jq swq pactl perl pw-dump; do if ! command -v "$tool" >/dev/null; then printf "%s: %s not installed but required\n" "$(basename "$0")" "$tool" >&2 exit 1 @@ -17,9 +20,9 @@ done DEFAULT_PROFILE="output:analog-stereo+input:analog-stereo" HDMI_PROFILE="output:hdmi-stereo" -export MENU_PROMPT="soundswitch" _menu() { + export MENU_PROMPT="soundswitch" menu -l 8 } @@ -49,24 +52,44 @@ usage() { exit 2 } _args="$*" -while getopts hIOgfpHRmMvV name; do +while getopts hIOgfpHRmMvVB name; do case ${name} in - g) mode=global ;; - f) mode=focused ;; - p) mode=profile ;; - H) mode=hdmi ;; - R) mode=reset ;; - O) output=1 ;; - I) input=1 ;; - # quick actions, to make move to pipewire easier - m) mode=none ; output=1 ; mute=1 ;; - M) mode=none ; input=1 ; mute=1 ;; - v) mode=none ; output=1 ; volume_down=1 ;; - V) mode=none ; output=1 ; volume_up=1 ;; - h|?) echo "$*" ; usage ;; + g) mode=global ;; + f) mode=focused ;; + p) mode=profile output=1 input=1 ;; + H) mode=hdmi output=1 input=1 ;; + R) mode=reset ;; + B) mode=mute output=1 input=1 ;; + O) output=1 ;; + I) input=1 ;; + # quick actions, to make move to pipewire easier + m) + mode=none + output=1 + mute=1 + ;; + M) + mode=none + input=1 + mute=1 + ;; + v) + mode=none + output=1 + volume_down=1 + ;; + V) + mode=none + output=1 + volume_up=1 + ;; + h | ?) + echo "$*" + usage + ;; esac done -shift $((OPTIND-1)) +shift $((OPTIND - 1)) # ask mode _mode_global="󰣨 global" @@ -74,17 +97,20 @@ _mode_focused="󰻿 focused" _mode_profile_card="󱂇 card profile" _mode_profile_hdmi="󰡁 hdmi profile" _mode_profile_reset="󰕍 reset profile" +_mode_mute="󰂛 mute" if [ -z "$mode" ]; then - printf "$_mode_global\n$_mode_focused\n$_mode_profile_card\n$_mode_profile_hdmi\n$_mode_profile_reset\n" | _menu | { + printf "$_mode_global\n$_mode_focused\n$_mode_profile_card\n$_mode_profile_hdmi\n$_mode_profile_reset\n$_mode_mute\n" | _menu | { read -r line case ${line} in - $_mode_global) exec "$0" -g "$*" ;; - $_mode_focused) exec "$0" -f "$*" ;; - $_mode_profile_card) exec "$0" -p "$*" ;; - $_mode_profile_hdmi) exec "$0" -H "$*" ;; - $_mode_profile_reset) exec "$0" -R "$*" ;; - *) - usage ;; + $_mode_global) exec "$0" -g "$*" ;; + $_mode_focused) exec "$0" -f "$*" ;; + $_mode_profile_card) exec "$0" -p "$*" ;; + $_mode_profile_hdmi) exec "$0" -H "$*" ;; + $_mode_profile_reset) exec "$0" -R "$*" ;; + $_mode_mute) exec "$0" -B "$*" ;; + *) + usage + ;; esac } exit $? @@ -98,9 +124,9 @@ if [ -n "$mode" ]; then printf "$_mode_output\n$_mode_input\n" | _menu | { read -r line case ${line} in - $_mode_output) exec "$0" -O $_args ;; - $_mode_input) exec "$0" -I $_args ;; - *) usage ;; + $_mode_output) exec "$0" -O $_args ;; + $_mode_input) exec "$0" -I $_args ;; + *) usage ;; esac } fi @@ -112,110 +138,123 @@ fi [ -n "$volume_down" ] && exec pactl set-sink-volume '@DEFAULT_SINK@' '-5%' [ -n "$volume_up" ] && exec pactl set-sink-volume '@DEFAULT_SINK@' '+5%' -[ -n "$output" ] && keyword="sink" && what="sink-input" -[ -n "$input" ] && keyword="source" && what="source-output" +[ -n "$output" ] && keyword="sink" && what="sink-input" +[ -n "$input" ] && keyword="source" && what="source-output" # returns the sink_id -selects() -{ - pactl list short "${1}s" | cut -f2 | menu +selects() { + pactl list short "${1}s" | cut -f2 | _menu } -notif() -{ +notif() { topic=$1 mesg=$2 urgency=normal [ -n "$3" ] && urgency=critical - notify-send -u ${urgency} -a soundswitch "soundswitch: ${topic}" "${mesg}" + notify-send -i /usr/share/icons/mdi/scalable/cast-audio.svg -u ${urgency} -a soundswitch "soundswitch: ${topic}" "${mesg}" } case ${mode} in -global) - target=$(selects "${keyword}") - if [ -z "${target}" ]; then - notif "focused" "no target ${what}" err - exit 1 - fi + global) + target=$(selects "${keyword}") + if [ -z "${target}" ]; then + notif "focused" "no target ${what}" err + exit 1 + fi - notif "global" "switch to ${target}" - # set new default - pactl "set-default-${keyword}" "${target}" - # move all attached to the new target - pactl list "${what}s" short | cut -f1 \ - | xargs -i pactl "move-${what}" "{}" "${target}" - ;; - -focused) - # parse pid of currently focused container - # then get the sink-inputs for it and parse the sink-input-id - focused_binary=$(swq current con | jq -r '.pid' | xargs ps -o comm=) - what_id=$(printf "%s\n" "${focused_binary}" \ - | xargs pactl list "${what}s" \ + notif "global" "switch to ${target}" + # set new default + pactl "set-default-${keyword}" "${target}" + # move all attached to the new target + pactl list "${what}s" short | cut -f1 \ + | xargs -i pactl "move-${what}" "{}" "${target}" + ;; + + focused) + # parse pid of currently focused container + # then get the sink-inputs for it and parse the sink-input-id + focused_binary=$(swq current con | jq -r '.pid' | xargs ps -o comm=) + what_id=$(printf "%s\n" "${focused_binary}" \ + | xargs pactl list "${what}s" \ | tr '\n' '\r' \ | perl -pe 's/[^\r]*index: ([0-9]+).+?application\.process\.binary = "([^\r]+)"\r.+?(?=index:|$)/\2=\1\r/g' \ | tr '\r' '\n' \ | grep "^{}" \ - | cut -d'=' -f2) - if [ -z "${what_id}" ]; then - notif "focused" "no ${what}" err - exit 1 - fi + | cut -d'=' -f2) + if [ -z "${what_id}" ]; then + notif "focused" "no ${what}" err + exit 1 + fi - # select where to switch to - target=$(selects "${keyword}") - if [ -z "${target}" ]; then - exit 1 - fi + # select where to switch to + target=$(selects "${keyword}") + if [ -z "${target}" ]; then + exit 1 + fi - notif "${focused_binary}" "switch to ${target}" - pactl move-sink-input "${what_id}" "${target}" - ;; + notif "${focused_binary}" "switch to ${target}" + pactl move-sink-input "${what_id}" "${target}" + ;; -profile) - target_card=$(selects "card") - if [ -z "${target_card}" ]; then - exit 1 - fi + profile) + target_card=$(selects "card") + if [ -z "${target_card}" ]; then + exit 1 + fi - # [^\r]#([0-9]+).*?Name: ([^\r]+).*?Profiles:\r(.*?)Active.*?(?=Card #|$) - target_profile=$(pactl list cards \ - | tr '\n' '\r' \ - | perl -pe 's/[^\r]#([0-9]+).*?Name: ([^\r]+).*?Profiles:\r(.*?)Active.*?(?=Card #|$)/\2~\3`/g' \ - | tr -d '\t' \ - | tr '`' '\n' \ - | grep "${target_card}" \ - | cut -d'~' -f2- \ - | tr '\r' '\n' \ - | xargs -L1 \ - | _menu \ - | perl -pe 's/^\s*([^\s]+):\s.*$/\1/') - if [ -z "${target_profile}" ]; then - exit 1 - fi + # [^\r]#([0-9]+).*?Name: ([^\r]+).*?Profiles:\r(.*?)Active.*?(?=Card #|$) + target_profile=$(pactl list cards \ + | tr '\n' '\r' \ + | perl -pe 's/[^\r]#([0-9]+).*?Name: ([^\r]+).*?Profiles:\r(.*?)Active.*?(?=Card #|$)/\2~\3`/g' \ + | tr -d '\t' \ + | tr '`' '\n' \ + | grep "${target_card}" \ + | cut -d'~' -f2- \ + | tr '\r' '\n' \ + | xargs -L1 \ + | _menu \ + | perl -pe 's/^\s*([^\s]+):\s.*$/\1/') + if [ -z "${target_profile}" ]; then + exit 1 + fi - notif "profile" "switch ${target_card} to ${target_profile} profile" - pactl set-card-profile "${target_card}" "${target_profile}" - ;; + notif "profile" "switch ${target_card} to ${target_profile} profile" + pactl set-card-profile "${target_card}" "${target_profile}" + ;; -hdmi) - target_card=$(selects "card") - if [ -z "${target_card}" ]; then - exit 1 - fi + hdmi) + target_card=$(selects "card") + if [ -z "${target_card}" ]; then + exit 1 + fi - notif "hdmi" "switch ${target_card} to HDMI profile" - pactl set-card-profile "${target_card}" ${HDMI_PROFILE} - exit $? - ;; + notif "hdmi" "switch ${target_card} to HDMI profile" + pactl set-card-profile "${target_card}" ${HDMI_PROFILE} + exit $? + ;; -reset) - target_card=$(selects "card") - if [ -z "${target_card}" ]; then - exit 1 - fi + reset) + target_card=$(selects "card") + if [ -z "${target_card}" ]; then + exit 1 + fi + + notif "reset" "switch ${target_card} to default profile" + pactl set-card-profile "${target_card}" ${DEFAULT_PROFILE} + ;; + + mute) + _data=$(pw-dump -N | jq -r '.. | select(.type?=="PipeWire:Interface:Node" and .info.props."media.class"?=="Stream/Output/Audio" and .info.props."stream.is-live"?==true) | @text') + _id=$(printf "${_data}" | jq -r '. | [ .info.props."application.name", .info.props."application.process.id", .id ] | @tsv' \ + | awk '{ system("swaymsg -t get_tree | jq -r \".. | select(.pid?==" $2 ") | .name\" | grep -v Picture-in-Picture | tr -d \"\\n\""); printf " [%s]", $3 }' \ + | _menu \ + | perl -pe 's/^.*\[([0-9]+)\]$/\1/') + if [ -z "${_id}" ]; then + exit 1 + fi - notif "reset" "switch ${target_card} to default profile" - pactl set-card-profile "${target_card}" ${DEFAULT_PROFILE} - ;; + _oid=$(printf "${_data}" | jq -r --argjson id "${_id}" '.. | select(.id?==$id) | .info.props."object.id"') + _target_state=$(printf "${_data}" | jq -r --argjson id "${_id}" '.. | select(.id?==$id) | .info.params.Props[0] | .mute = (.mute | not) | @text') + pw-cli set-param "${_oid}" Props "${_target_state}" + ;; esac -- cgit 1.4.1