Amixer
Getting Volume Keys to work
If you can't get the XF86 Key Events for your volume keys to work, the following script provides a good workaround. (Tested with amixer version 1.0.28)
#!/bin/bash
# $HOME/bin/volctrl
COMMAND=$1
case $COMMAND in
'tmute')
amixer set Master toggle
;;
'up')
amixer -M set Master 10%+
;;
'down')
amixer -M set Master 10%-
;;
*)
echo "Invalid argument $COMMAND"
exit -1
;;
esac
You can increase the volume with
volctrl up
decrease it with
volctrl down
and toggle mute with
volctrl tmute
All you need to do now is mapping these commands to the keyboard shortcuts you want.
Older Amixer versions
The -M flag for non-linear scaling isn't available in older Amixer version. The below version of the script addresses this to a certain extent.
#!/bin/bash
# $HOME/bin/volctrl
CONTROL_NAME="Master"
VOLUME_RANGE_STR=$(amixer get $CONTROL_NAME | grep 'Limits: Playback' | sed -e 's/.*Playback//g' | sed -e 's/ \- /:/g')
MIN_VOLUME=$(echo $VOLUME_RANGE_STR | cut -d':' -f 1)
MAX_VOLUME=$(echo $VOLUME_RANGE_STR | cut -d':' -f 2)
VOL_RANGE=$[ $MAX_VOLUME - $MIN_VOLUME ]
function get_mute_state(){
amixer get $CONTROL_NAME | tail -n 1 | egrep -o "\[o[fn]f?\]" | tr -d [\[\]]
}
function get_volume(){
amixer get $CONTROL_NAME | tail -n 1 | egrep -o \(\-\|\)[0-9]* | head -n 1
}
function volum_abs_to_rel(){
local abs_val=$1
local norm_val=$(echo "100 * ((( $abs_val - $MIN_VOLUME ) / $VOL_RANGE ) ^4)" | bc -l)
stripped_val=$(echo ${norm_val} | sed -e 's/\..*//g')
echo ${stripped_val:-0}
}
function get_volume_percent(){
echo $(volum_abs_to_rel $(get_volume))
}
function set_volume_percent(){
local target=$1
[ $target -gt 100 ] && target=100
[ $target -lt 0 ] && target=0
local target_abs=$(echo "$MIN_VOLUME + $VOL_RANGE * sqrt(sqrt( $target / 100))" | bc -l)
amixer -- set $CONTROL_NAME ${target_abs%.*}
}
function volume_change_percent(){
local delta=$1
local current=$(get_volume_percent)
local new=$[ $current + $delta ]
set_volume_percent $new
}
COMMAND=$1
case $COMMAND in
'tmute')
amixer set $CONTROL_NAME toggle
;;
'up')
volume_change_percent 10
;;
'down')
volume_change_percent -10
;;
'get')
if [ "off" == "$(get_mute_state)" ];then
echo "M";
else
echo $(get_volume_percent)"%"
fi
;;
*)
echo "Invalid argument $COMMAND"
exit -1
;;
esac