#!/bin/bash # Define some icons SPEAKER_ICONS=("" "" "") SPEAKER_MUTED_ICON="" MIC_ICON="" MIC_MUTED_ICON="" # Define some helper functions for getting/setting audio data using wireplumber (wpctl) # $1 can either be "SINK" (speaker) or "SOURCE" (microphone) get_vol() { wpctl get-volume "@DEFAULT_AUDIO_${1}@" | awk '{print int($2*100)}' } # $1 can either be "SINK" (speaker) or "SOURCE" (microphone) # #2 is the voulme (as percentage) to set the volume to # $3 is optional, if set, it can be '+' or '-', which then adds/decreases volume, instead of setting set_vol() { wpctl set-volume "@DEFAULT_AUDIO_${1}@" "$(awk -v n="$2" 'BEGIN{print (n / 100)}')$3" } # $1 can either be "SINK" (speaker) or "SOURCE" (microphone) check_mute() { wpctl get-volume "@DEFAULT_AUDIO_${1}@" | grep -i muted >/dev/null echo $? } # $1 can either be "SINK" (speaker) or "SOURCE" (microphone) toggle_mute() { wpctl set-mute "@DEFAULT_AUDIO_${1}@" toggle } get_report() { spkr_vol="$(get_vol "SINK")" mic_vol="$(get_vol "SOURCE")" if [ "$(check_mute "SINK")" == "0" ]; then spkr_mute="true" spkr_icon="$SPEAKER_MUTED_ICON" else spkr_mute="false" index="$(awk -v n="$spkr_vol" -v m="${#SPEAKER_ICONS[@]}" 'BEGIN{print int(n/(100/m))}')" # We might end up with an higher than the length of icons, if the volume is over 100% # in this case, set the index to last icon if [ "$index" -ge "${#SPEAKER_ICONS[@]}" ]; then spkr_icon="${SPEAKER_ICONS[-1]}" else spkr_icon="${SPEAKER_ICONS[$index]}" fi fi if [ "$(check_mute "SOURCE")" = "0" ]; then mic_mute="true" mic_icon="$MIC_MUTED_ICON" else mic_mute="false" mic_icon="$MIC_ICON" fi echo "{ \"speaker_vol\": \"$spkr_vol\", \"speaker_mute\": $spkr_mute, \"speaker_icon\": \"$spkr_icon\", \"microphone_mute\": $mic_mute, \"microphone_vol\": \"$mic_vol\", \"microphone_icon\": \"$mic_icon\" }" } # Continually run and report every volume change (into stdout) loop() { pactl subscribe | grep --line-buffered "change" | while read -r _; do get_report done } case "$1" in "loop") get_report loop ;; "once") get_report ;; "togglemute") if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'" exit 1 fi toggle_mute "$2" ;; "setvol") if [ "$2" != "SOURCE" ] && [ "$2" != "SINK" ]; then >&2 echo "Invalid usage, expected second argument to be 'SINK' or 'SOURCE', got '$2'" exit 1 fi if [[ "$3" =~ ^[+-]?[0-9]*\.?[0-9]+$ ]]; then case "$4" in "") set_vol "$2" "$3" ;; up|+) set_vol "$2" "$3" "+" ;; down|-) set_vol "$2" "$3" "-" ;; *) >&2 echo "Invalid usage, expected fourth argument to be up/down or +/-, got '$4'" exit 1 ;; esac else >&2 echo "Invalid usage, exepcted third argument to be a number, got '$3'" exit 1 fi ;; *) >&2 echo "Invalid usage, argument '$1' not recognized." exit 1 ;; esac