Hello, Find attached a patch to support (not so new) sndiod OpenBSD. All credits goes to spoon [1] authors, thanks to them!
Maybe someone will want to add this by default. [1] : https://git.2f30.org/spoon/
>From f94be3fddf225d890b981841700c6aec885d5af6 Mon Sep 17 00:00:00 2001 From: prx <p...@ybad.name> Date: Wed, 30 Sep 2020 14:37:11 +0200 Subject: [PATCH] update volume.c to support new sioctl interface in OpenBSD. All credits to spoon project (https://git.2f30.org/spoon). --- Makefile | 5 ++ components/volume.c | 196 ++++++++++++++++++++++++++++++++------------ config.def.h | 1 + 3 files changed, 150 insertions(+), 52 deletions(-) diff --git a/Makefile b/Makefile index 945b5e3..988a8eb 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,11 @@ COM =\ components/volume\ components/wifi +# uncomment on OpenBSD +#LDFLAGS += -L/usr/local/lib +#CPPFLAGS += -I/usr/local/include +#LDLIBS += -lsndio # vol_perc on OpenBSD + all: slstatus $(COM:=.o): config.mk $(REQ:=.h) diff --git a/components/volume.c b/components/volume.c index 61cec90..9ee0cb8 100644 --- a/components/volume.c +++ b/components/volume.c @@ -8,69 +8,161 @@ #include "../util.h" #if defined(__OpenBSD__) - #include <sys/audioio.h> + /* + Copyright (c) 2016-2018 Lazaros Koromilas <lo...@2f30.org> + Copyright (c) 2016-2018 Dimitris Papastamos <s...@2f30.org> + Copyright (c) 2017-2018 Lucas Gabriel Vuotto <lu...@nanashi.co> + See: https://git.2f30.org/spoon/ + */ - const char * - vol_perc(const char *card) + #include <err.h> + #include <errno.h> + #include <poll.h> + #include <sndio.h> + #include <stdlib.h> + + #define MAX_CHANNELS 16 + + static struct sioctl_hdl *hdl = NULL; + static struct pollfd *pfds = NULL; + + static struct { + unsigned int addr; + int val; + } channel[MAX_CHANNELS]; + static size_t nchannels = 0; + + static int + get_output(void) { - static int cls = -1; - mixer_devinfo_t mdi; - mixer_ctrl_t mc; - int afd = -1, m = -1, v = -1; + size_t i; + int val; - if ((afd = open(card, O_RDONLY)) < 0) { - warn("open '%s':", card); - return NULL; + if (nchannels == 0) + return 0; + + val = 0; + for (i = 0; i < nchannels; i++) + val += channel[i].val; + return 100 * ((val / (double)nchannels) / 255.0); + } + + static void + ondesc(void *arg, struct sioctl_desc *desc, int val) + { + size_t i; + + if (desc == NULL) + return; + + if (desc->type != SIOCTL_NUM || + strcmp(desc->func, "level") != 0 || + strcmp(desc->node0.name, "output") != 0) + return; + + for (i = 0; i < nchannels; i++) + if (channel[i].addr == desc->addr) + break; + + if (i < nchannels) { + channel[i].val = val; + return; } - for (mdi.index = 0; cls == -1; mdi.index++) { - if (ioctl(afd, AUDIO_MIXER_DEVINFO, &mdi) < 0) { - warn("ioctl 'AUDIO_MIXER_DEVINFO':"); - close(afd); - return NULL; - } - if (mdi.type == AUDIO_MIXER_CLASS && - !strncmp(mdi.label.name, - AudioCoutputs, - MAX_AUDIO_DEV_LEN)) - cls = mdi.index; + if (nchannels >= MAX_CHANNELS) { + warnx("too many channels"); + return; + } + channel[i].addr = desc->addr; + channel[i].val = val; + nchannels++; + } + + static void + onval(void *arg, unsigned int addr, unsigned int val) + { + size_t i; + + for (i = 0; i < nchannels; i++) + if (channel[i].addr == addr) { + channel[i].val = val; + break; } - for (mdi.index = 0; v == -1 || m == -1; mdi.index++) { - if (ioctl(afd, AUDIO_MIXER_DEVINFO, &mdi) < 0) { - warn("ioctl 'AUDIO_MIXER_DEVINFO':"); - close(afd); - return NULL; + } + + static int + do_init(void) + { + hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); + if (hdl == NULL) { + warnx("sioctl_open %s", SIO_DEVANY); + return 0; + } + if (!sioctl_ondesc(hdl, ondesc, NULL)) { + warnx("sioctl_ondesc"); + sioctl_close(hdl); + return 0; + } + sioctl_onval(hdl, onval, NULL); + + return 1; + } + + static int + poll_peek(void) + { + int nfds, revents; + + if (pfds == NULL) { + pfds = malloc(sizeof(struct pollfd) * sioctl_nfds(hdl)); + if (pfds == NULL) { + warnx("out of memory"); + goto out; } - if (mdi.mixer_class == cls && - ((mdi.type == AUDIO_MIXER_VALUE && - !strncmp(mdi.label.name, - AudioNmaster, - MAX_AUDIO_DEV_LEN)) || - (mdi.type == AUDIO_MIXER_ENUM && - !strncmp(mdi.label.name, - AudioNmute, - MAX_AUDIO_DEV_LEN)))) { - mc.dev = mdi.index, mc.type = mdi.type; - if (ioctl(afd, AUDIO_MIXER_READ, &mc) < 0) { - warn("ioctl 'AUDIO_MIXER_READ':"); - close(afd); - return NULL; - } - if (mc.type == AUDIO_MIXER_VALUE) - v = mc.un.value.num_channels == 1 ? - mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] : - (mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] > - mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] ? - mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] : - mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT]); - else if (mc.type == AUDIO_MIXER_ENUM) - m = mc.un.ord; + } + + nfds = sioctl_pollfd(hdl, pfds, POLLIN); + if (nfds == 0) + return 1; + while (poll(pfds, nfds, 0) == -1) + if (errno != EINTR) { + warn("sioctl poll"); + goto out; } + revents = sioctl_revents(hdl, pfds); + if (revents & POLLHUP) { + warnx("sioctl disconnected"); + goto out; } - close(afd); + return 1; + + out: + free(pfds); + pfds = NULL; + sioctl_close(hdl); + + return 0; + } + + const char * + vol_perc(const char *card) + { + static int init_done = 0; + struct pollfd *pfds; + int nfds; + + if (!init_done) { + if (!do_init()) + return NULL; + init_done = 1; + } + + init_done = poll_peek(); + printf("%d\n",get_output()); + bprintf("%d%%", get_output()); - return bprintf("%d", m ? 0 : v * 100 / 255); + return buf; } #else #include <sys/soundcard.h> diff --git a/config.def.h b/config.def.h index e06be66..8b392cf 100644 --- a/config.def.h +++ b/config.def.h @@ -58,6 +58,7 @@ static const char unknown_str[] = "n/a"; * uptime system uptime NULL * username username of current user NULL * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) + * NULL on OpenBSD * wifi_perc WiFi signal in percent interface name (wlan0) * wifi_essid WiFi ESSID interface name (wlan0) */ -- 2.28.0