diff options
| author | 2024-09-09 16:10:56 +0100 | |
|---|---|---|
| committer | 2024-09-09 16:10:56 +0100 | |
| commit | ad56debc8d30252f04ce339f402f753a1a1f54ee (patch) | |
| tree | a9f705ad33d71b392f189f68d2c958cc7cc41f96 | |
init commit
| -rw-r--r-- | README.md | 47 | ||||
| -rw-r--r-- | swob-swayconfig | 5 | ||||
| -rwxr-xr-x | swob.sh | 107 |
3 files changed, 159 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c0617d --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +swob (sway+wob helper) +====================== + +This is a simple/stupid helper script and config files to provide volume and +brightness controls under Wayland using [wob]. Sway is *not* mandatory (the +helper script doesn't depend on sway or any wlroots features) but a sway +config snippet is provided for convenience. + +[wob]: https://github.com/francma/wob + +Calling wob from a script or config file is not too intuitive, because it +panics if the process it's reading from hangs up. The helper script ensures +that there is a process keeping wob open for a few seconds to allow it to +time out, and potentially respond without invoking a whole new wob instance +on successive taps of the volume/brightness controls, especially with pauses +between. It doesn't go the way of keeping an always-open wob instance, +instead trying to balance invoking as needed with not starting a whole new +binary unnecessarily with every tap. + +Dependencies +------------ + +- POSIX sh, sed and mkfifo(1); non-POSIX mktemp(1) (all pretty universally available) +- [wob] +- [amixer (from alsa-utils)](https://www.alsa-project.org) +- [brightnessctl](https://github.com/Hummer12007/brightnessctl) + +Installation +------------ + +Put swob.sh on your PATH, or edit the sway(5) config snippet to point to its +exact location. Copy the sway config snippet into your own sway config file, +or source it from that file, or copy it into /etc/sway/config.d -- obviously +if you aren't on sway, do the equivalent for your window manager. + +Copying +------- + +Copyright © 2024 The Remph <lhr@disroot.org> + +This file is free software; the Remph gives unlimited permission to copy +and/or distribute it, with or without modification, as long as this +notice is preserved. + +This software is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/swob-swayconfig b/swob-swayconfig new file mode 100644 index 0000000..969326b --- /dev/null +++ b/swob-swayconfig @@ -0,0 +1,5 @@ +bindsym XF86MonBrightnessDown exec swob.sh brightness 5%- +bindsym XF86MonBrightnessUp exec swob.sh brightness 5%+ +bindsym XF86AudioLowerVolume exec swob.sh volume 5%- +bindsym XF86AudioRaiseVolume exec swob.sh volume 5%+ +bindsym XF86AudioMute exec swob.sh volume toggle @@ -0,0 +1,107 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2023-2024 The Remph <lhr@disroot.org> +# SPDX-License-Identifier: FSFULLRWD + +wobfifo=${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}/wob +readonly wobfifo +set -o pipefail -e # `set -e' comes after readonly and pipefail, they + # aren't vital enough to kill the script for + +start_wob() { + if test -e "$wobfifo"; then + return # Already started + fi + + # temporary fifo (call mkfifo(1) asap to minimise possibility of races) + # TODO: should this be in C, so we can call mkfifo(2) and check for + # EEXIST, rather than using test(1)? Alternatively, there is flock(1), + # or any other IPC or SHM system + mkfifo -m600 "$wobfifo" + + default_wobini= + for dir in ${XDG_CONFIG_HOME:+"$XDG_CONFIG_HOME"} ~/.config /etc; do + if test -r "$dir"/wob/wob.ini; then + default_wobini="$dir"/wob/wob.ini + break + fi + done + + # temporary wob.ini(5) file, to set wob colours + wobini=`mktemp` + { + # This order means that a user can change the styles in + # their own config if they like + printf '[style.mute]\nbackground_color = af0000\n\n' + cat - ${default_wobini:+"$default_wobini"} <<EOF +[style.volume] +background_color = 000000 +[style.mute] +background_color = af0000 +[style.brightness] +background_color = a89800 + +EOF + } >$wobini + + # spawn wob process with temporary files + ( + trap 'rm "$wobini" "$wobfifo"' 0 + # Don't `exec' wob here, else the trap won't work + wob -c "$wobini" -v <$wobfifo + ) & +} + +do_cmd_get_percent() { + case $1 in + volume|vol) + amixer sset Master "$2" | sed -E ' +# Extract percentage, keep original line for later +h +s/.*\[([0-9]+)%\].*/\1/ +t match +d + +: match +# Get original line back +x +# Test if audio is muted +/\[off\]/ { + g + s/$/ mute/ + b +} +# else +g +s/$/ volume/ +' ;; + brightness|brt) + brightnessctl -m set "$2" | sed -En 's/(.*[^0-9])?([0-9]+)%.*/\2 brightness/p' + ;; + *) + echo >&2 "$0: error: unrecognised argument: $target" + exit -1 + ;; + esac +} + +## MAIN ## + +start_wob + +{ + do_cmd_get_percent "$@" + sleep 3 # Needs to be long enough that there aren't too many wob(1) + # processes spawned and respawned consecutively on repeated + # taps, but short enough that there aren't too many /bin/sh + # processes hanging around simultaneously running sleep(1) + # from this script! 3 seconds is an uneducated guess. +} >$wobfifo + +# Don't let wob die if it's still receiving input from another process; wait +# until it says it's finished +# To solve the above mentioned problem of too many /bin/sh processes hanging +# around, we could setsid(1) wob so the script can exit without waiting as +# soon as it's done sleeping (the existing situation is that as long as one +# script sleeps, the shell that spawned the wob process will wait until that +# sleep is done) +test -z $! || wait $! |
