aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar remph <lhr@disroot.org>2024-09-09 16:10:56 +0100
committerLibravatar remph <lhr@disroot.org>2024-09-09 16:10:56 +0100
commitad56debc8d30252f04ce339f402f753a1a1f54ee (patch)
treea9f705ad33d71b392f189f68d2c958cc7cc41f96
init commit
-rw-r--r--README.md47
-rw-r--r--swob-swayconfig5
-rwxr-xr-xswob.sh107
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 &copy; 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
diff --git a/swob.sh b/swob.sh
new file mode 100755
index 0000000..6a62adf
--- /dev/null
+++ b/swob.sh
@@ -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 $!