statusdir=$XDG_RUNTIME_DIR/statusbar
mkdir -pm0700 "$statusdir"
inotifywait -rqme close_write --format %f "$statusdir" | while read -r file; do
if read -r -- "$file" < "$statusdir/$file"; then
# ...
fi
done
With inotifywait
we can watch a directory of files. When one of those
files triggers the close_write
event we synthesise a new variable based
on the file name using read
if the file name is also a valid identifier.
The new variable will contain the first line of data from the file itself.
These new variables can, for example, be used with printf
to create a
formatted string designed for use in a typical statusbar.
Note
|
This event loop can be arbitrarily fast. Any pre-formatting should
be done before the values are written to files watched by
inotifywait so only a minimum amount of work is needed to process
them.
|
Some status updates which cannot be done using notification and have usually long intervals can be easily provided with per-user crond or systemd.timer services.
For example given a battery-status
script, we could run it every five
minutes using the following crontab:
*/5 * * * * battery-status > "$XDG_RUNTIME_DIR"/statusbar/battery
Although all these examples are simple sh
scripts it does not mean only
shell can be used. Any language capable of writing files (even to stdout)
is suitable for this.
#!/bin/sh --
statusdir=$XDG_RUNTIME_DIR/statusbar
mkdir -pm0700 "$statusdir"
fmt='[[%artist% - ]%title%]|[%file%]'
mpc current -f "$fmt" > "%statusdir"/mpd
mpc idleloop | while read -r event; do
case $event in
player) mpc current -f "$fmt" > "%statusdir"/mpd
esac
done
Use pactl subscribe
to provide real-time volume notification for default
sinks.
Note
|
One potential improvement would be to pair this with another
pacmd running as a "daemon" using exec_with_pipe
to accept commands over a control fifo thereby avoiding execution
of multiple pulseaudio clients.
|
#!/bin/sh --
statusdir=$XDG_RUNTIME_DIR/statusbar
mkdir -pm0700 "$statusdir"
pastat() {
local command=$1
local fmt=$2
pacmd list-"$command" | awk -v fmt="$fmt" '
# Default indices are marked with an * so we use that as a sentinel.
/\* index/ {m = 1; next}
m == 1 && /muted/ {muted = $2}
m == 1 && /^\s+volume:/ {volume = $5}
END{
if(muted == "no")
printf fmt, volume
else
print ""
}'
}
# If pulseaudio isn't running, print something out and exit.
if ! pulseaudio --check; then
printf 'VOL:N/A\n' > "$statusdir"/volume
exit 1
fi
# Initialise something before we begin monitoring events.
pastat sinks 'VOL:%s\n' > "$statusdir"/volume
pactl subscribe | while read -r _ event _ type _; do
if [ "$event" = \'change\' ]; then
case $type in
sink) pastat sinks 'VOL:%s\n' > "$statusdir"/volume
esac
fi
done