slstatus: VOL y BT cada 10 s o al recibir SIGUSR1

Componente lento: run_command con caché. slstatus.c cuenta las SIGUSR1
para que se refresque en cuanto un script o un clic lo pide. Así ya no se
lanzan wpctl y bluetoothctl cada 2 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C5v1qWDwgkaVM5kjVHGGh8
This commit is contained in:
Alejandro Guerrero 2026-09-28 15:38:41 +02:00
parent 73d005dd30
commit 3864c31ba1
Signed by: alejandrogs73
GPG key ID: 1CFF10953BEE333C
4 changed files with 58 additions and 2 deletions

View file

@ -168,6 +168,11 @@ and which area is which is marked by the `\001`...`\004` bytes in
| BT | `OFF`, or the connected device and its battery if it reports it (`VJ 901 100%`) | `bluetooth` menu: connect, disconnect, scan and pair, power off | | Power on or off | | | BT | `OFF`, or the connected device and its battery if it reports it (`VJ 901 100%`) | `bluetooth` menu: connect, disconnect, scan and pair, power off | | Power on or off | |
| Date | Day and time | This month's calendar (`calendario`) | | | | | Date | Day and time | This month's calendar (`calendario`) | | | |
VOL and BT are not read every 2 s like the rest, but every 10 s or as soon as
`SIGUSR1` arrives (`lento` component in slstatus's `config.h`): `volumen`,
`bluetooth`, `wifi` and the clicks send it, so your own changes show up at
once and wpctl and bluetoothctl are not spawned every 2 s.
After changing dwm's `config.h`, reinstall and restart it for new clicks to After changing dwm's `config.h`, reinstall and restart it for new clicks to
work: `pkill -HUP dwm` restarts it without closing windows (restartsig and work: `pkill -HUP dwm` restarts it without closing windows (restartsig and
preserveonrestart patches). preserveonrestart patches).
@ -236,5 +241,7 @@ preserveonrestart patches).
- In st, Ctrl+Shift+right click on an image opens it in `nsxiv`. - In st, Ctrl+Shift+right click on an image opens it in `nsxiv`.
- st shows images with the kitty graphics protocol; yazi detects it on its - st shows images with the kitty graphics protocol; yazi detects it on its
own and shows previews without ueberzugpp. own and shows previews without ueberzugpp.
- slstatus.c has a hand-made change (not a patch): it counts `SIGUSR1`
signals so `lento` knows when to refresh.
- slock is modified by hand (not a patch): clock, date, battery and a bottom - slock is modified by hand (not a patch): clock, date, battery and a bottom
bar with the state colour. bar with the state colour.

View file

@ -165,6 +165,11 @@ y qué zona es cada una lo marcan los bytes `\001`...`\004` de
| BT | `OFF`, o el dispositivo conectado y su batería si la da (`VJ 901 100%`) | Menú `bluetooth`: conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | | | BT | `OFF`, o el dispositivo conectado y su batería si la da (`VJ 901 100%`) | Menú `bluetooth`: conectar, desconectar, buscar y emparejar, apagar | | Encender o apagar | |
| Fecha | Día y hora | Calendario del mes (`calendario`) | | | | | Fecha | Día y hora | Calendario del mes (`calendario`) | | | |
VOL y BT no se miran cada 2 s como el resto, sino cada 10 s o en cuanto
llega `SIGUSR1` (componente `lento` del `config.h` de slstatus): lo mandan
`volumen`, `bluetooth`, `wifi` y los clics, así que lo que cambias tú se ve al
momento y wpctl y bluetoothctl no se lanzan cada 2 s.
Si se cambia el `config.h` de dwm, hay que reinstalarlo y reiniciarlo para Si se cambia el `config.h` de dwm, hay que reinstalarlo y reiniciarlo para
que los clics nuevos funcionen: `pkill -HUP dwm` lo relanza sin cerrar las que los clics nuevos funcionen: `pkill -HUP dwm` lo relanza sin cerrar las
ventanas (parches restartsig y preserveonrestart). ventanas (parches restartsig y preserveonrestart).
@ -231,5 +236,7 @@ ventanas (parches restartsig y preserveonrestart).
- En st, Ctrl+Shift+clic derecho sobre una imagen la abre en `nsxiv`. - En st, Ctrl+Shift+clic derecho sobre una imagen la abre en `nsxiv`.
- st muestra imágenes con el protocolo de gráficos de kitty; yazi lo detecta - st muestra imágenes con el protocolo de gráficos de kitty; yazi lo detecta
solo y enseña las vistas previas sin ueberzugpp. solo y enseña las vistas previas sin ueberzugpp.
- slstatus.c tiene un cambio a mano (no es un parche): cuenta las señales
`SIGUSR1` para que `lento` sepa cuándo refrescar.
- slock está modificado a mano (no es un parche): reloj, fecha, batería y - slock está modificado a mano (no es un parche): reloj, fecha, batería y
una barra inferior con el color del estado. una barra inferior con el color del estado.

View file

@ -37,6 +37,45 @@ red(const char *unused)
return bprintf("WiFi: %s", s); return bprintf("WiFi: %s", s);
} }
/*
* run_command, pero solo cada LENTO segundos o en cuanto llega SIGUSR1 (lo
* mandan los scripts volumen, bluetooth y wifi y los clics en la barra). Así
* VOL y BT no lanzan wpctl y bluetoothctl cada 2 s; lo que cambie por otro
* lado tarda como mucho LENTO segundos en verse. La cuenta de SIGUSR1 (usr1)
* la lleva slstatus.c.
*/
#define LENTO 10
static const char *
lento(const char *cmd)
{
static struct {
const char *cmd;
char out[256];
int ok;
sig_atomic_t usr1;
time_t t;
} c[4];
struct timespec ahora;
const char *res;
size_t i;
clock_gettime(CLOCK_MONOTONIC, &ahora);
for (i = 0; i < LEN(c) && c[i].cmd && c[i].cmd != cmd; i++)
;
if (i == LEN(c))
return run_command(cmd);
if (c[i].cmd && c[i].usr1 == usr1 && ahora.tv_sec - c[i].t < LENTO)
return c[i].ok ? c[i].out : NULL;
c[i].cmd = cmd;
c[i].usr1 = usr1;
c[i].t = ahora.tv_sec;
if ((c[i].ok = (res = run_command(cmd)) != NULL))
snprintf(c[i].out, sizeof(c[i].out), "%s", res);
return c[i].ok ? c[i].out : NULL;
}
/* /*
* Los bytes \001 a \004 delimitan las zonas clicables de la barra * Los bytes \001 a \004 delimitan las zonas clicables de la barra
* (parche statuscmd de dwm): la red, el volumen, el bluetooth y la fecha. Lo que hace * (parche statuscmd de dwm): la red, el volumen, el bluetooth y la fecha. Lo que hace
@ -50,11 +89,11 @@ static const struct arg args[] = {
{ battery_perc, "[ BAT: %s%%", "BAT1" }, { battery_perc, "[ BAT: %s%%", "BAT1" },
{ battery_state, " %s ] ", "BAT1" }, { battery_state, " %s ] ", "BAT1" },
/* mismo volumen que maneja wpctl (PipeWire); MIC OFF si el micro está silenciado */ /* mismo volumen que maneja wpctl (PipeWire); MIC OFF si el micro está silenciado */
{ run_command, "\002[ VOL: %s ]\002 ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; " { lento, "\002[ VOL: %s ]\002 ", "wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{ printf \"%d%%\", $2 * 100 + 0.5 } /MUTED/ { printf \" MUT\" }'; "
"wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" }, "wpctl get-volume @DEFAULT_AUDIO_SOURCE@ | grep -q MUTED && printf ' MIC OFF'" },
/* OFF si el adaptador está apagado; si no, el primer dispositivo conectado /* OFF si el adaptador está apagado; si no, el primer dispositivo conectado
* y su batería, si la da ("Battery Percentage: 0x64 (100)" -> " 100%") */ * y su batería, si la da ("Battery Percentage: 0x64 (100)" -> " 100%") */
{ run_command, "\003[ BT: %s ]\003 ", "bluetoothctl show | grep -q 'Powered: yes' || { echo OFF; exit; }; " { lento, "\003[ BT: %s ]\003 ", "bluetoothctl show | grep -q 'Powered: yes' || { echo OFF; exit; }; "
"set -- $(bluetoothctl devices Connected | head -1); [ $# -gt 0 ] || exit; " "set -- $(bluetoothctl devices Connected | head -1); [ $# -gt 0 ] || exit; "
"m=$2; shift 2; printf %s \"$*\"; " "m=$2; shift 2; printf %s \"$*\"; "
"bluetoothctl info \"$m\" | awk -F'[()]' '/Battery Percentage/ { printf \" %s%%\", $2 }'" }, "bluetoothctl info \"$m\" | awk -F'[()]' '/Battery Percentage/ { printf \" %s%%\", $2 }'" },

View file

@ -19,6 +19,7 @@ struct arg {
char buf[1024]; char buf[1024];
static volatile sig_atomic_t done; static volatile sig_atomic_t done;
static volatile sig_atomic_t usr1; /* SIGUSR1 recibidas, para lento() en config.h */
static Display *dpy; static Display *dpy;
#include "config.h" #include "config.h"
@ -28,6 +29,8 @@ terminate(const int signo)
{ {
if (signo != SIGUSR1) if (signo != SIGUSR1)
done = 1; done = 1;
else
usr1++;
} }
static void static void