status

statusbar program for dwm
git clone anongit@rnpnr.xyz:status.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 267f86ff9db191c807a558752815a37c905543bf
Parent: b9be071dd763a8c3a073ad2ba1ac6564a2962f46
Author: Randy Palamar
Date:   Tue, 16 Mar 2021 18:05:19 -0600

implement structure style configuration ala dsblocks/slstatus

currently interval and signal are unused fields but they will be
implemented similar to dsblocks

mpd and battery need still need to be modified but the changes are small.

Diffstat:
MLICENSE | 4+++-
MMakefile | 10+++++++---
Ablocks/battery.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ablocks/battery.h | 3+++
Ablocks/gettime.c | 12++++++++++++
Ablocks/gettime.h | 2++
Ablocks/mpd.c | 42++++++++++++++++++++++++++++++++++++++++++
Ablocks/volume.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ablocks/volume.h | 4++++
Mconfig.def.h | 16++++++++++++----
Mconfig.mk | 4----
Dlinux.c | 80-------------------------------------------------------------------------------
Dopenbsd.c | 40----------------------------------------
Mstatus.c | 66+++++-------------------------------------------------------------
Mstatus.h | 15++++++++++-----
Mutil.c | 9+++++----
Mutil.h | 2+-
17 files changed, 246 insertions(+), 203 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -1,4 +1,6 @@ -Copyright (c) 2019 Randy Palamar +ISC License (ISC) + +© 2019-2021 Randy Palamar <palamar@ualberta.ca> Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/Makefile b/Makefile @@ -1,6 +1,10 @@ +# See LICENSE for license details. include config.mk -SRC += status.c util.c +SRC =\ + blocks/gettime.c\ + blocks/volume.c\ + status.c util.c OBJ = $(SRC:.c=.o) all: status @@ -9,7 +13,7 @@ config.h: cp config.def.h config.h .c.o: - $(CC) $(CFLAGS) -c $< + $(CC) $(CFLAGS) -o $@ -c $< $(OBJ): config.h @@ -17,7 +21,7 @@ status: $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) clean: - rm -f *.o status + rm -f blocks/*.o *.o status install: all mkdir -p $(DESTDIR)$(PREFIX)/bin diff --git a/blocks/battery.c b/blocks/battery.c @@ -0,0 +1,84 @@ +/* See LICENSE for license details. */ +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#include "../status.h" +#include "../util.h" +#include "battery.h" + +#if 0 +#if defined(__linux__) +size_t +batinfo(struct Block *b) +{ + int perc; + unsigned long power_now, energy_now, h, m; + double timeleft; + char path[PATH_MAX], state[12]; + + snprintf(path, sizeof(path), "/sys/class/power_supply/%s/capacity", bat); + if (pscanf(path, "%d", &perc) != 1) + perc = 0; + + snprintf(path, sizeof(path), "/sys/class/power_supply/%s/status", bat); + if (pscanf(path, "%12s", &state) != 1) + snprintf(state, sizeof(state), "Unknown"); + + if (!strcmp(state, "Discharging")) { + snprintf(path, sizeof(path), + "/sys/class/power_supply/%s/power_now", bat); + if (pscanf(path, "%lu", &power_now) != 1) + power_now = 1; + + snprintf(path, sizeof(path), + "/sys/class/power_supply/%s/energy_now", bat); + if (pscanf(path, "%lu", &energy_now) != 1) + energy_now = 0; + + timeleft = (double)energy_now / (double)power_now; + h = timeleft; + m = (timeleft - (double)h) * 60; + + return bprintf("%d%% (%d:%02d)", perc, h, m); + } + + return bprintf("%d%% (%s)", perc, state); +} + +#elif defined(__OpenBSD__) +#include <fcntl.h> +#include <machine/apmvar.h> +#include <sys/ioctl.h> +#include <unistd.h> + +const char * +batinfo(const char *bat) +{ + struct apm_power_info pi; + int fd; + + if ((fd = open("/dev/apm", O_RDONLY)) < 0) + die("open\n"); + + if ((ioctl(fd, APM_IOC_GETPOWER, &pi)) < 0) { + close(fd); + die("ioctl\n"); + } + close(fd); + + switch (pi.ac_state) { + case APM_AC_OFF: + return smprintf("%d%% (%d:%02d)", pi.battery_life, + pi.minutes_left / 60, pi.minutes_left % 60); + case APM_AC_ON: + case APM_BATT_CHARGING: + return bprintf("%d%% (ac)", pi.battery_life); + default: + return bprintf("%d%% (unknown)", pi.battery_life); + } +} + +#else +#endif +#endif diff --git a/blocks/battery.h b/blocks/battery.h @@ -0,0 +1,2 @@ +extern const char *bat; +size_t batinfo(struct Block *b); +\ No newline at end of file diff --git a/blocks/gettime.c b/blocks/gettime.c @@ -0,0 +1,12 @@ +/* See LICENSE for license details. */ +#include <time.h> + +#include "../status.h" +#include "gettime.h" + +size_t +gettime(struct Block *b) +{ + time_t t = time(NULL); + return strftime(b->curstr, BLOCKLEN, b->fmt, localtime(&t)) + 1; +} diff --git a/blocks/gettime.h b/blocks/gettime.h @@ -0,0 +1 @@ +size_t gettime(struct Block *b); +\ No newline at end of file diff --git a/blocks/mpd.c b/blocks/mpd.c @@ -0,0 +1,42 @@ +/* See LICENSE for license details. */ +#include <mpd/client.h> + +#include "../status.h" +#include "../util.h" +#include "mpd.h" + +static const char * +mpd(enum mpd_tag_type type) +{ + struct mpd_connection *conn = NULL; + struct mpd_song *song = NULL; + struct mpd_status *status = NULL; + + conn = mpd_connection_new(mpdhost, 0, 600); + if (!conn || mpd_connection_get_error(conn)) + return NULL; + + mpd_command_list_begin(conn, true); + mpd_send_status(conn); + mpd_send_current_song(conn); + mpd_command_list_end(conn); + + status = mpd_recv_status(conn); + + /* >= covers both PLAY and PAUSE */ + if (status && (mpd_status_get_state(status) >= MPD_STATE_PLAY)) { + mpd_response_next(conn); + song = mpd_recv_song(conn); + snprintf(buf, sizeof(buf), "%s", + mpd_song_get_tag(song, type, 0)); + mpd_song_free(song); + } else + snprintf(buf, sizeof(buf), "%s", ""); + + if (status) + mpd_status_free(status); + mpd_response_finish(conn); + mpd_connection_free(conn); + + return buf; +} diff --git a/blocks/volume.c b/blocks/volume.c @@ -0,0 +1,56 @@ +/* See LICENSE for license details. */ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +#include "../status.h" +#include "../util.h" +#include "volume.h" + +#if defined(__linux__) +#include <alsa/asoundlib.h> +#include <alsa/mixer.h> + +size_t +getvol(struct Block *b) +{ + static char buf[6]; + + snd_mixer_t *handle; + snd_mixer_selem_id_t *sid; + snd_mixer_elem_t *elem; + + int notmuted; + long vol, min, max; + + snd_mixer_open(&handle, 0); + snd_mixer_attach(handle, alsacard); + snd_mixer_selem_register(handle, NULL, NULL); + snd_mixer_load(handle); + + snd_mixer_selem_id_malloc(&sid); + snd_mixer_selem_id_set_index(sid, 0); + snd_mixer_selem_id_set_name(sid, alsaoutput); + elem = snd_mixer_find_selem(handle, sid); + + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &vol); + snd_mixer_selem_get_playback_volume_range(elem, &min, &max); + snd_mixer_selem_get_playback_switch(elem, 0, &notmuted); + + /* covert from raw value to percent */ + vol = (double)(vol - min) / (double)(max - min) * 100; + + snd_mixer_elem_free(elem); + + if (notmuted) { + if (abs(vol) < 100) + bprintf(buf, sizeof(buf), "%d%%", (int)vol); + else + /* HACK: digital out is always 100% so just say on */ + bprintf(buf, sizeof(buf), "%s", "on"); + } else + bprintf(buf, sizeof(buf), "%s", "muted"); + + return bprintf(b->curstr, BLOCKLEN, b->fmt, buf); +} +#endif diff --git a/blocks/volume.h b/blocks/volume.h @@ -0,0 +1,4 @@ +extern const char *alsacard; +extern const char *alsaoutput; + +size_t getvol(struct Block *b); diff --git a/config.def.h b/config.def.h @@ -1,11 +1,11 @@ -#define STATUSLEN 2048 +#include "blocks/gettime.h" +#include "blocks/volume.h" + +#define STATUSLEN 1024 /* host for connecting to MPD, set to NULL for the MPD_HOST env variable */ static const char *mpdhost = "localhost"; -/* datetime format */ -static const char *timefmt = "%R"; - /* alsa card and output */ /* card is whatever alsamixer lists as card, default is probably correct output is the output from that specific card you want the vol from */ @@ -15,3 +15,11 @@ static const char *alsaoutput = "Speaker"; /* main battery in system */ /* found in /sys/class/power_supply/ */ static const char *bat = "BAT0"; + +/* status block definitions */ +struct Block blks[] = { +/* fn fmt interval signal */ + { getvol, "[ %s ]", 0, 0 }, + { gettime, "[ %R ]", 20, 0 }, + { NULL }, +}; diff --git a/config.mk b/config.mk @@ -1,7 +1,3 @@ -# Uncomment based on your OS -SRC = linux.c -#SRC = openbsd.c - PREFIX = / X11INC = /usr/X11R6/include diff --git a/linux.c b/linux.c @@ -1,80 +0,0 @@ -#include <limits.h> -#include <stdio.h> - -#include <alsa/asoundlib.h> -#include <alsa/mixer.h> - -#include "status.h" -#include "util.h" - -const char * -getvol(const char *card, const char *output) -{ - snd_mixer_t *handle; - snd_mixer_selem_id_t *sid; - snd_mixer_elem_t *elem; - - int notmuted; - long vol, min, max; - - snd_mixer_open(&handle, 0); - snd_mixer_attach(handle, card); - snd_mixer_selem_register(handle, NULL, NULL); - snd_mixer_load(handle); - - snd_mixer_selem_id_malloc(&sid); - snd_mixer_selem_id_set_index(sid, 0); - snd_mixer_selem_id_set_name(sid, output); - elem = snd_mixer_find_selem(handle, sid); - - snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &vol); - snd_mixer_selem_get_playback_volume_range(elem, &min, &max); - snd_mixer_selem_get_playback_switch(elem, 0, &notmuted); - - /* covert from raw value to percent */ - vol = (double)(vol - min) / (double)(max - min) * 100; - - snd_mixer_close(handle); - snd_mixer_selem_id_free(sid); - - if (notmuted) - return bprintf("%d%%", (int)vol); - return bprintf("(muted)"); -} - -const char * -batinfo(const char *bat) -{ - int perc; - unsigned long power_now, energy_now, h, m; - double timeleft; - char path[PATH_MAX], state[12]; - - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/capacity", bat); - if (pscanf(path, "%d", &perc) != 1) - perc = 0; - - snprintf(path, sizeof(path), "/sys/class/power_supply/%s/status", bat); - if (pscanf(path, "%12s", &state) != 1) - snprintf(state, sizeof(state), "Unknown"); - - if (!strcmp(state, "Discharging")) { - snprintf(path, sizeof(path), - "/sys/class/power_supply/%s/power_now", bat); - if (pscanf(path, "%lu", &power_now) != 1) - power_now = 1; - - snprintf(path, sizeof(path), - "/sys/class/power_supply/%s/energy_now", bat); - if (pscanf(path, "%lu", &energy_now) != 1) - energy_now = 0; - - timeleft = (double)energy_now / (double)power_now; - h = timeleft; - m = (timeleft - (double)h) * 60; - - return bprintf("%d%% (%d:%02d)", perc, h, m); - } - - return bprintf("%d%% (%s)", perc, state); -} diff --git a/openbsd.c b/openbsd.c @@ -1,40 +0,0 @@ -#include <fcntl.h> -#include <machine/apmvar.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include "status.h" -#include "util.h" - -const char * -getvol(const char *card, const char *output) -{ - return NULL; -} - -const char * -batinfo(const char *bat) -{ - struct apm_power_info pi; - int fd; - - if ((fd = open("/dev/apm", O_RDONLY)) < 0) - die("open\n"); - - if ((ioctl(fd, APM_IOC_GETPOWER, &pi)) < 0) { - close(fd); - die("ioctl\n"); - } - close(fd); - - switch (pi.ac_state) { - case APM_AC_OFF: - return smprintf("%d%% (%d:%02d)", pi.battery_life, - pi.minutes_left / 60, pi.minutes_left % 60); - case APM_AC_ON: - case APM_BATT_CHARGING: - return bprintf("%d%% (ac)", pi.battery_life); - default: - return bprintf("%d%% (unknown)", pi.battery_life); - } -} diff --git a/status.c b/status.c @@ -4,7 +4,6 @@ #include <string.h> #include <time.h> #include <unistd.h> -#include <mpd/client.h> #include <X11/Xlib.h> #include "status.h" @@ -13,7 +12,6 @@ static int done = 0; static int dflag = 0; -char buf[BUFLEN]; static Display *dpy; @@ -35,59 +33,13 @@ setstatus(char *str) XSync(dpy, False); } -static const char * -gettime(const char *fmt) -{ - time_t t = time(NULL); - if (!(strftime(buf, sizeof(buf), fmt, localtime(&t)))) - return NULL; - - return buf; -} - -static const char * -mpd(enum mpd_tag_type type) -{ - struct mpd_connection *conn = NULL; - struct mpd_song *song = NULL; - struct mpd_status *status = NULL; - - conn = mpd_connection_new(mpdhost, 0, 600); - if (!conn || mpd_connection_get_error(conn)) - return NULL; - - mpd_command_list_begin(conn, true); - mpd_send_status(conn); - mpd_send_current_song(conn); - mpd_command_list_end(conn); - - status = mpd_recv_status(conn); - - /* >= covers both PLAY and PAUSE */ - if (status && (mpd_status_get_state(status) >= MPD_STATE_PLAY)) { - mpd_response_next(conn); - song = mpd_recv_song(conn); - snprintf(buf, sizeof(buf), "%s", - mpd_song_get_tag(song, type, 0)); - mpd_song_free(song); - } else - snprintf(buf, sizeof(buf), "%s", ""); - - if (status) - mpd_status_free(status); - mpd_response_finish(conn); - mpd_connection_free(conn); - - return buf; -} - int main(int argc, char *argv[]) { struct sigaction sa; - const char *s; char status[STATUSLEN]; size_t len; + struct Block *b; memset(&sa, 0, sizeof(sa)); sa.sa_handler = terminate; @@ -108,18 +60,10 @@ main(int argc, char *argv[]) die("XOpenDisplay: can't open display\n"); for (len = 0; !done; sleep(1), len = 0) { - s = mpd(MPD_TAG_ARTIST); - len += snprintf(status + len, sizeof(status) - len, "[ %s -", s); - - s = mpd(MPD_TAG_TITLE); - len += snprintf(status + len, sizeof(status) - len, " %s ]", s); - - s = getvol(alsacard, alsaoutput); - len += snprintf(status + len, sizeof(status) - len, "[ %s ]", s); - - s = gettime(timefmt); - len += snprintf(status + len, sizeof(status) - len, "[ %s ]", s); - + for (b = blks; b->fn; b++) { + b->len = b->fn(b); + len += snprintf(status + len, sizeof(status) - len, "%s", b->curstr); + } setstatus(status); } diff --git a/status.h b/status.h @@ -1,5 +1,10 @@ -#define BUFLEN 1024 -extern char buf[BUFLEN]; - -const char *getvol(const char *card, const char *output); -const char *batinfo(const char *bat); +#define BLOCKLEN 32 +struct Block { + size_t (*const fn)(struct Block *b); + const char *fmt; + const int interval; + const int signal; + char curstr[BLOCKLEN]; + char prevstr[BLOCKLEN]; + size_t len; +}; diff --git a/util.c b/util.c @@ -1,3 +1,4 @@ +/* See LICENSE for license details. */ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -15,17 +16,17 @@ die(const char *errstr, ...) exit(1); } -const char * -bprintf(const char *fmt, ...) +size_t +bprintf(char *buf, size_t buflen, const char *fmt, ...) { size_t ret; va_list ap; va_start(ap, fmt); - ret = vsnprintf(buf, sizeof(buf), fmt, ap); + ret = vsnprintf(buf, buflen, fmt, ap); va_end(ap); - return (ret < 0)? NULL : buf; + return (ret < buflen)? ret : buflen; } int diff --git a/util.h b/util.h @@ -1,3 +1,3 @@ void die(const char *errstr, ...); -char *bprintf(const char *fmt, ...); +size_t bprintf(char *buf, size_t buflen, const char *fmt, ...); int pscanf(const char *path, const char *fmt, ...);