Dotfiles for my tiling window manager + terminal workflow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

345 lines
11 KiB

#!/bin/bash
# Displays the default device, volume, and mute status for i3blocks
# default vars {{{ #
set -a
SINK_SYMB=""
AUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-''}
AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50}
AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-''}
AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0}
AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-''}
AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-''}
. "/home/kevin/.cache/wal/colors.sh"
# DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"}
DEFAULT_COLOR="$color7"
MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"}
USE_ALSA_NAME=${USE_ALSA_NAME:-0}
USE_DESCRIPTION=${USE_DESCRIPTION:-0}
SUBSCRIBE=${SUBSCRIBE:-0}
MIXER=${MIXER:-""}
SCONTROL=${SCONTROL:-""}
# }}} default vars #
AUDIO_DELTA=${AUDIO_DELTA:-3}
# AUDIO_DELTA=${AUDIO_DELTA:-2}
# AUDIO_DELTA=${AUDIO_DELTA:-1}
# LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'}
LONG_FORMAT=${SHORT_FORMAT:-'${SINK_SYMB} ${VOL}%'}
# SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}%[${INDEX}]'}
SHORT_FORMAT=${SHORT_FORMAT:-'${SINK_SYMB} ${VOL}%'}
# flags {{{ #
while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; do
case "$opt" in
S) SUBSCRIBE=1 ;;
F) LONG_FORMAT="$OPTARG" ;;
f) SHORT_FORMAT="$OPTARG" ;;
a) USE_ALSA_NAME=1 ;;
d) USE_DESCRIPTION=1 ;;
H) AUDIO_HIGH_SYMBOL="$OPTARG" ;;
M) AUDIO_MED_SYMBOL="$OPTARG" ;;
L) AUDIO_LOW_SYMBOL="$OPTARG" ;;
X) AUDIO_MUTED_SYMBOL="$OPTARG" ;;
T) AUDIO_MED_THRESH="$OPTARG" ;;
t) AUDIO_LOW_THRESH="$OPTARG" ;;
C) DEFAULT_COLOR="$OPTARG" ;;
c) MUTED_COLOR="$OPTARG" ;;
i) AUDIO_INTERVAL="$OPTARG" ;;
m) MIXER="$OPTARG" ;;
s) SCONTROL="$OPTARG" ;;
h) printf \
"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb]
[-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter]
[-m mixer] [-s scontrol] [-h]
Options:
-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables:
\${SYMB}, \${VOL}, \${INDEX}, \${NAME}
-S\tSubscribe to volume events (requires persistent block, always uses long format)
-a\tUse ALSA name if possible
-d\tUse device description instead of name if possible
-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL'
-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL'
-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL'
-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL'
-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH
-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH
-C\tColor for non-muted audio. Default: $DEFAULT_COLOR
-c\tColor for muted audio. Default: $MUTED_COLOR
-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA
-m\tUse the given mixer.
-s\tUse the given scontrol.
-h\tShow this help text
" && exit 0;;
esac
done
# }}} flags #
# functions {{{ #
if [[ -z "$MIXER" ]] ; then
# Use the default ALSA mixer
MIXER="default"
fi
if [[ -z "$SCONTROL" ]] ; then
# Use the 'Master' control
SCONTROL="Master"
fi
CAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p")
function move_sinks_to_new_default {
DEFAULT_SINK=$1
pacmd list-sink-inputs | grep index: | grep -o '[0-9]\+' | while read SINK
do
pacmd move-sink-input $SINK $DEFAULT_SINK
done
}
function set_default_playback_device_next {
inc=${1:-1}
num_devices=$(pacmd list-sinks | grep -c index:)
sink_arr=($(pacmd list-sinks | grep index: | grep -o '[0-9]\+'))
default_sink_index=$(( $(pacmd list-sinks | grep index: | grep -no '*' | grep -o '^[0-9]\+') - 1 ))
default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices ))
default_sink=${sink_arr[$default_sink_index]}
pacmd set-default-sink $default_sink
move_sinks_to_new_default $default_sink
}
# }}} functions #
# triggers {{{ #
case "$BLOCK_BUTTON" in
1) set_default_playback_device_next ;;
# 2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;;
2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY 15% ;;
3) set_default_playback_device_next -1 ;;
4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;;
5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;;
esac
# }}} triggers #
# print_format {{{ #
function print_format {
case $NAME in
*"Fiio"*)
SINK_SYMB=""
;;
*"hdmi"*)
SINK_SYMB=""
;;
*"pci"*)
SINK_SYMB=" "
;;
esac
eval "echo \"$1\""
}
# }}} print_format #
# print_block {{{ #
function print_block {
# Use amixer to get volume and mute status
VOL_INFO=$(amixer -D $MIXER get $SCONTROL | grep -m1 -oE '[0-9]+%|\[on\]|\[off\]')
VOL=$(echo "$VOL_INFO" | grep -oE '[0-9]+%' | head -1)
VOL="${VOL%?}"
MUTED=$(echo "$VOL_INFO" | grep -oE '\[on\]|\[off\]')
# Default name for ALSA
NAME=$(amixer -D $MIXER scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)
if [[ $USE_ALSA_NAME == 1 ]] ; then
ALSA_NAME=$(amixer -D $MIXER scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)
NAME=${ALSA_NAME:-$NAME}
elif [[ $USE_DESCRIPTION == 1 ]] ; then
DESCRIPTION=$(amixer -D $MIXER scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1)
NAME=${DESCRIPTION:-$NAME}
fi
# Fix mute status check
if [[ $MUTED == "[on]" ]] ; then
SYMB=$AUDIO_HIGH_SYMBOL
[[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL
[[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOL
COLOR=$DEFAULT_COLOR
else
SYMB=$AUDIO_MUTED_SYMBOL
COLOR=$MUTED_COLOR
fi
if [[ $SUBSCRIBE == 1 ]] ; then
print_format "$LONG_FORMAT"
else
print_format "$LONG_FORMAT"
print_format "$SHORT_FORMAT"
echo "$COLOR"
fi
}
# }}} print_block #
print_block
if [[ $SUBSCRIBE == 1 ]] ; then
while read -r EVENT; do
print_block
done < <(pactl subscribe | stdbuf -oL grep change)
fi
# Hardware Configuration
#CARD=2
#SINK="alsa_output.pci-0000_30_00.6.analog-stereo"
#FRONT="Front Playback Switch"
#REAR="Surround Playback Switch"
#FRONT_VOL="Front Playback Volume"
#REAR_VOL="Surround Playback Volume"
## Debugging output
#LOG_FILE=~/.audio-toggle.log
#echo "=== $(date) ===" >> $LOG_FILE
## Get current active output (PulseAudio fallback)
#get_active_output() {
## Get full sink info for debugging
#SINK_INFO=$(pacmd list-sinks)
#echo "Full sink info:" >> $LOG_FILE
#echo "$SINK_INFO" >> $LOG_FILE
## Try alternative port detection method
#PORT=$(echo "$SINK_INFO" | awk -v sink="$SINK" '
#$1 == "name:" && $2 == "<"sink">" {active=1}
#active && /active port:/ {
## Extract port name between angle brackets
#match($0, /<[^>]+>/)
#port = substr($0, RSTART+1, RLENGTH-2)
#print port
#exit
#}
#')
#echo "Raw port detection: $PORT" >> $LOG_FILE
#if [[ "$PORT" == "analog-output-headphones" ]]; then
#echo "front"
#elif [[ "$PORT" == "analog-output-lineout" ]]; then
#echo "rear"
#else
#echo "unknown"
#fi
#}
## Switch outputs with hardware-level control
#switch_output() {
#echo "Starting switch to $1" >> $LOG_FILE
## First disable both outputs
#echo "Disabling both outputs" >> $LOG_FILE
## ALSA controls
#amixer -c $CARD set "$FRONT" mute >/dev/null
#amixer -c $CARD set "$FRONT_VOL" 0% >/dev/null
#amixer -c $CARD set "$REAR" mute >/dev/null
#amixer -c $CARD set "$REAR_VOL" 0% >/dev/null
## PulseAudio controls
#pactl set-sink-mute "$SINK" 1 >/dev/null
#sleep 0.2
#if [[ "$1" == "front" ]]; then
#echo "Enabling front output" >> $LOG_FILE
## Check if headphones port exists
#if echo "$SINK_INFO" | grep -q "analog-output-headphones"; then
#echo "Attempting to set port to analog-output-headphones" >> $LOG_FILE
#if ! pacmd set-sink-port "$SINK" "analog-output-headphones" 2>>$LOG_FILE; then
#echo "Port switch failed, trying alternative method" >> $LOG_FILE
#pactl set-sink-port "$SINK" "analog-output-headphones" 2>>$LOG_FILE || true
#fi
#else
#echo "Headphones port not available, using hardware controls only" >> $LOG_FILE
#fi
## Additional hardware control
#amixer -c $CARD set 'Headphone' unmute >/dev/null
#amixer -c $CARD set 'Speaker' mute >/dev/null
#pactl set-sink-mute "$SINK" 0 >/dev/null
## ALSA controls
#amixer -c $CARD set "$FRONT" unmute >/dev/null
#amixer -c $CARD set "$FRONT_VOL" 100% >/dev/null
#OUTPUT=" FRONT"
#else
#echo "Enabling rear output" >> $LOG_FILE
## PulseAudio controls
#echo "Attempting to set port to analog-output-lineout" >> $LOG_FILE
#if ! pacmd set-sink-port "$SINK" "analog-output-lineout" 2>>$LOG_FILE; then
#echo "Port switch failed, trying alternative method" >> $LOG_FILE
#pactl set-sink-port "$SINK" "analog-output-lineout" 2>>$LOG_FILE || true
#fi
## Additional hardware control
#amixer -c $CARD set 'Speaker' unmute >/dev/null
#amixer -c $CARD set 'Headphone' mute >/dev/null
#pactl set-sink-mute "$SINK" 0 >/dev/null
## ALSA controls
#amixer -c $CARD set "$REAR" unmute >/dev/null
#amixer -c $CARD set "$REAR_VOL" 100% >/dev/null
#OUTPUT=" REAR"
#fi
## Reset audio pipeline
#echo "Resetting audio pipeline" >> $LOG_FILE
#{ pactl suspend-sink "$SINK" 1 && sleep 0.2 && pactl suspend-sink "$SINK" 0; } >/dev/null 2>&1
## Verify switch
#echo "Verifying switch..." >> $LOG_FILE
#CURRENT=$(get_active_output)
#echo "Current output: $CURRENT" >> $LOG_FILE
#if [[ "$CURRENT" != "$1" ]]; then
#echo "Switch verification failed!" >> $LOG_FILE
## Force hardware-level switch
#echo "Forcing hardware-level switch..." >> $LOG_FILE
#if [[ "$1" == "front" ]]; then
#amixer -c $CARD set 'Headphone' unmute >/dev/null
#amixer -c $CARD set 'Speaker' mute >/dev/null
#else
#amixer -c $CARD set 'Speaker' unmute >/dev/null
#amixer -c $CARD set 'Headphone' mute >/dev/null
#fi
#fi
#echo "Switch complete" >> $LOG_FILE
#echo "$OUTPUT" # Output to i3blocks
#}
## Main execution
#case "${BLOCK_BUTTON:-}" in
#1)
#CURRENT=$(get_active_output)
#if [[ "$CURRENT" == "front" ]]; then
#switch_output "rear"
#else
#switch_output "front"
#fi
#;;
#*)
#CURRENT=$(get_active_output)
#[[ "$CURRENT" == "front" ]] && echo " FRONT" || echo " REAR"
#;;
#esac
#exit 0