workplace/workplace

364 lines
6.7 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
## INIT ##
# get script base directory
SCRIPT_PATH=$(readlink -f "${BASH_SOURCE[0]}")
SCRIPT_DIR=$(dirname -- "$SCRIPT_PATH")
# store arguments globally
ARG_LIST=("$@")
# get version number
VERSION=$(cat ${SCRIPT_DIR}/VERSION | xargs)
# location of workplace config file
CONFIG_PATH="${HOME}/.config/workplace.ini"
# load libraries
source "${SCRIPT_DIR}/lib/color"
source "${SCRIPT_DIR}/lib/log"
source "${SCRIPT_DIR}/lib/toolcheck"
source "${SCRIPT_DIR}/lib/ini"
source "${SCRIPT_DIR}/lib/snore"
#
# Explain usage of script.
#
workplace_help(){
echo "WorkPlace v${VERSION}"
echo
echo "Usage: $0 <command>"
echo
echo "Commands:"
echo " set <name> - Set workplace"
echo " update - Automatically determine current workplace setup"
echo " updatedaemon - Run as daemon and call update when setup changes are detected"
echo
echo " help - Display this help message and exit"
echo " version - Display version information and exit"
}
#
# Display version information.
#
workplace_version(){
echo "WorkPlace v${VERSION}"
echo "(c) 2024 DrMaxNix"
}
#
# Run commands `laptop` and `dock`.
#
workplace_set(){
## FIND CONFIG SECTION ##
# make sure param is present
if [[ ! ${1:-""} ]]; then
log_error "Missing workplace name; See '$0 help' for usage information"
fi
# try to find section
workplace_section=""
for n in $(workplace_available_name_list); do
if [[ "$n" == "$1" ]]; then
workplace_name="$n"
fi
done
if [[ ! ${workplace_name:-""} ]]; then
log_error "Invalid workplace name '$1'; Check config file"
fi
## RUN SET COMMANDS ##
local -n workplace_section_name="ini_$workplace_name"
for k in "${!workplace_section_name[@]}"; do
# make sure this is a `set` command
if [[ ! "$k" =~ ^set\. ]]; then
continue
fi
# extract command and parameter
command=$(echo "$k" | grep -oPe '(?<=^set.).*')
param="${workplace_section_name[$k]}"
# run command
workplace_setcommand_run "$command" "$param"
done
}
#
# Run command `update`.
#
workplace_update(){
## DETECT SETUP ##
# connected usb devices
usb_id_list=$(workplace_usb_id_list)
## FILTER ##
workplace_list_prio_0=""
workplace_list_prio_1=""
for n in $(workplace_available_name_list); do
local -n workplace_section_name="ini_$n"
# default
trigger_default="${workplace_section_name[trigger.default]:-""}"
if [[ "$trigger_default" == "true" ]]; then
workplace_list_prio_0="${workplace_list_prio_0} $n"
fi
# usb-id
trigger_usbid="${workplace_section_name[trigger.usb-id]:-""}"
if [[ "$trigger_usbid" ]]; then
for i in $usb_id_list; do
if [[ "$i" == "$trigger_usbid" ]]; then
workplace_list_prio_1="${workplace_list_prio_1} $n"
break
fi
done
fi
done
workplace_list_prio_0="$(echo $workplace_list_prio_0 | xargs)"
workplace_list_prio_1="$(echo $workplace_list_prio_1 | xargs)"
## SELECT BEST ONE ##
workplace=""
# by prio
if [[ "$workplace_list_prio_1" ]]; then
workplace="$workplace_list_prio_1"
elif [[ "$workplace_list_prio_0" ]]; then
workplace="$workplace_list_prio_0"
fi
# make sure we have found one
if [[ ! "$workplace" ]]; then
log_warn "No matching workplace trigger found"
return
fi
## SET NEW WORKPLACE ##
log_info "Switching to workplace '$workplace'"
workplace_set "$workplace"
}
#
# Run command `updatedaemon`.
#
workplace_updatedaemon(){
## INIT ##
# prepare forking
trap "kill -s SIGTERM -- -$$" EXIT
# update once
kill -s SIGUSR1 $$
## LISTEN FOR SCREEN RESOLUTION CHANGE ##
xeventbind resolution /usr/bin/echo |
while read -r; do
kill -s SIGUSR1 $$
done &
## LISTEN FOR LOGIN ##
gdbus monitor -y -d org.freedesktop.login1 |
grep --line-buffered "LockedHint" |
while read -r; do
kill -s SIGUSR1 $$
done &
## KEEP RUNNING ##
while true; do
workplace_handle_change
snore 0.5
done
}
#
# HELPER: (Re-)load config.
#
workplace_config_load(){
# clear used variables
for v in $(compgen -A variable | grep -Pe '^ini_'); do
unset $v
done
# parse ini file
ini_parse "$CONFIG_PATH"
}
#
# HELPER: Get defined workplace names.
#
workplace_available_name_list(){
for v in $(compgen -A variable | grep -oPe '(?<=^ini_).*'); do
echo $v
done
}
#
# HELPER: Run a `set` command.
#
workplace_setcommand_run(){
case ${1:-""} in
## CORE ##
# volume
"volume")
if [[ "$2" -le 0 ]]; then
amixer set 'Master',0 "$2%" off > /dev/null || true
else
amixer set 'Master',0 "$2%" on > /dev/null || true
fi
;;
# powerprofile
"powerprofile")
powerprofilesctl set "$2" || true
;;
# text scaling factor
"text-scaling-factor")
dconf write /org/gnome/desktop/interface/text-scaling-factor "$2" || true
;;
## DASH-TO-DOCK EXTENSION ##
# dock position (includes fix for buggy window size)
"dash-to-dock.position")
if [[ "$2" == "LEFT" ]]; then
dconf write /org/gnome/shell/extensions/dash-to-dock/dock-position "'BOTTOM'" || true
else
dconf write /org/gnome/shell/extensions/dash-to-dock/dock-position "'LEFT'" || true
fi
snore 0.3
dconf write /org/gnome/shell/extensions/dash-to-dock/dock-position "'$2'" || true
;;
## PAM EXTENSION ##
# fprintd module
"pam.fprintd")
if [[ "$2" == "true" || "$2" == "1" ]]; then
sudo --non-interactive pam-auth-update --enable fprintd
else
sudo --non-interactive pam-auth-update --disable fprintd
fi
;;
## ERROR HANDLING ##
*)
log_error "Invalid setcommand '$1'"
exit 1
;;
esac
}
#
# HELPER: Get list of connected usb device ids.
#
workplace_usb_id_list(){
lsusb_id_regex='^Bus [0-9]+ Device [0-9]+: ID ([0-9a-f]{4}:[0-9a-f]{4}) .*$'
lsusb_out=$"$(lsusb)"
while IFS= read -r line; do
if [[ "$line" =~ $lsusb_id_regex ]]; then
echo $line | sed -E "s/$lsusb_id_regex/\1/g"
fi
done <<< "$lsusb_out"
}
#
# HELPER: Handle detected setup change.
#
trap "workplace_change_flag=1" SIGUSR1
workplace_handle_change(){
## CHECK FLAG ##
# ignore if not set
if [[ ! ${workplace_change_flag:-""} -gt 0 ]]; then
return
fi
# unset flag
workplace_change_flag=0
## DO UPDATE ##
# reload config
workplace_config_load
# run update function
workplace_update
# sleep to prevent spamming
snore 1
}
## MAIN ##
case ${1:-""} in
set)
workplace_toolcheck
workplace_config_load
workplace_set "$2"
exit 0
;;
update)
workplace_toolcheck
workplace_config_load
workplace_update
exit 0
;;
updatedaemon)
workplace_toolcheck
workplace_updatedaemon
exit 0
;;
help)
workplace_help
exit 0
;;
version)
workplace_version
exit 0
;;
"")
log_error "No command given; See '$0 help' for usage information"
exit 1
;;
*)
log_error "Invalid command '$1'; See '$0 help' for usage information"
exit 1
;;
esac