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

Reply via email to