distribution/packages/sysutils/system-utils/sources/scripts/volume_sense

173 lines
4.8 KiB
Bash
Executable file

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2021-present Fewtarius
# 2021-present pkegg
. /etc/profile
set -e
set -o pipefail
LOG="/var/log/$(basename "$0").log"
### Summary
# This script listens to volume keys and adjusts volume
# Fn + Volume up/down will adjust brightness
###
# Event examples for reference
# type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
# type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
VOL_EVENT='*(KEY_VOLUME*, value *' # This matches all volume events
VOL_UP='*UP), value *' # Differentiate 'up' volume event
VOL_DOWN='*DOWN), value *' #Differentiate 'down' volume event
V_FUNC_KEY_EVENT='*('${DEVICE_VOL_MODIFIER}'), value *'
# Matches if a button was pressed (1), released (0) or held down (2)
PRESS='value [1-9]'
RELEASE='value 0'
# Volume repeat
VOLUME_REPEAT_MOD=4
# Brightness repeat
BRIGHTNESS_REPEAT_MOD=4
# Variable to keep track of Fn being currently pressed
FUNC_PRESSED=no
CONTROLLER_DISCONNECTED="*error reading: No such device"
DEVICE_DISCONNECTED="*error reading: No such device"
get_devices() {
KJDEVS=false
FOUNDKEYS=false
FOUNDJOY=false
RETRY=5
while [ ${KJDEVS} = false ]
do
# Detect input devices automatically
for DEV in /dev/input/ev*
do
unset SUPPORTS
SUPPORTS=$(udevadm info ${DEV} | awk '/ID_INPUT_KEY=|ID_INPUT_JOYSTICK=/ {print $2}')
if [ -n "${SUPPORTS}" ]
then
DEVICE=$(udevadm info ${DEV} | awk 'BEGIN {FS="="} /DEVNAME=/ {print $2}')
INPUT_DEVICES+=("${DEVICE}")
if [[ "${SUPPORTS}" =~ ID_INPUT_KEY ]]
then
echo "Found Keyboard: ${DEVICE}" 2>&1 >${LOG}
FOUNDKEYS=true
elif [[ "${SUPPORTS}" =~ ID_INPUT_JOYSTICK ]]
then
echo "Found Joystick: ${DEVICE}" 2>&1 >${LOG}
FOUNDJOY=true
fi
fi
done
if [ "${FOUNDKEYS}" = "true" ] &&
[ "${FOUNDJOY}" = "true" ]
then
echo "Found all of the needed devices." 2>&1 >${LOG}
KJDEVS=true
break
fi
if [ "${RETRY}" -ge 5 ]
then
echo "Did not find all of the needed devices, but that may be OK. Breaking." 2>&1 >${LOG}
break
else
RETRY=$(( ${RETRY} + 1 ))
fi
sleep 1
done
}
get_devices
# If the input devices change, it may be a new controller
# so handle it here.
mkcontroller 2>/dev/null ||:
# Logic:
# - Listen to any input device events to get volume keys (not part of the joystick api)
# - Switch statement keeps high level cases to only 'volume' and 'V function key'
# this is to avoid processing for other events or creating a lot of cases as this will be called
# for all button pushes
# - Using 'read' means the loop is idle when no button is pressed
(
for INPUT_DEVICE in ${INPUT_DEVICES[@]}
do
evtest "${INPUT_DEVICE}" 2>&1 &
done
wait
) | while read line; do
case $line in
(${CONTROLLER_DISCONNECTED})
echo "Reloading due to ${CONTROLLER_DEVICE} reattach..." >${LOG} 2>&1
get_devices
;;
(${DEVICE_DISCONNECTED})
echo "Reloading due to ${DEVICE} reattach..." >${LOG} 2>&1
get_devices
;;
(${VOL_EVENT})
# We don't care when you 'let go' ('release') the volume button
if [[ "$line" =~ ${RELEASE} ]]; then
REPEAT_NUM=0
continue
fi
# Setup for 'brightness' if Fn pressed
if [[ "${FUNC_PRESSED}" == "yes" ]]; then
COMMAND=/usr/bin/brightness
UP="up"
DOWN="down"
REPEAT_MOD=${BRIGHTNESS_REPEAT_MOD}
# Default to 'volume' if Fn is not pressed
else
COMMAND="/usr/bin/system_utils vol"
UP="+"
DOWN="-"
REPEAT_MOD=${VOLUME_REPEAT_MOD}
fi
REPEAT_NUM=$(( ${REPEAT_NUM} + 1 ))
# This isn't time to evaluate repeat so just skip
if [[ "$line" == ${REPEAT_PRESS} && $(( ${REPEAT_NUM} % ${REPEAT_MOD} )) != "0" ]]; then
continue
fi
INCREMENT_AMOUNT=5
if [[ "${REPEAT_NUM}" -gt "20" ]]; then
INCREMENT_AMOUNT=10
fi
# Run the commands to adjust volume/brightness
if [[ "${line}" == ${VOL_UP} ]]; then
${COMMAND} ${UP} ${INCREMENT_AMOUNT} > /dev/null
elif [[ "${line}" == ${VOL_DOWN} ]]; then
${COMMAND} ${DOWN} ${INCREMENT_AMOUNT} > /dev/null
fi
;;
(${V_FUNC_KEY_EVENT})
#Reset the number of repeats when Fn is pressed/release
# as repeat speed is different between volume/brightness
REPEAT_NUM=0
if [[ "${line}" =~ ${PRESS} ]]; then
FUNC_PRESSED=yes
elif [[ "${line}" =~ ${RELEASE} ]]; then
FUNC_PRESSED=no
fi
;;
esac
done