tApply upstream patch by Lucas for sndio support on OpenBSD - spoon - dwm status utility (2f30 fork)
(HTM) git clone git://src.adamsgaard.dk/spoon
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
(DIR) commit bd47937068b0c19f7eea595f41b4acba720bd8b8
(DIR) parent 3c6eedee86ba611a19953902f16f2c2cdddd400f
(HTM) Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Sat, 23 May 2020 07:31:54 +0200
Apply upstream patch by Lucas for sndio support on OpenBSD
Diffstat:
M Makefile | 18 +++++++++++++++---
M mix.c | 178 +++++++++++++++++++++++--------
2 files changed, 147 insertions(+), 49 deletions(-)
---
(DIR) diff --git a/Makefile b/Makefile
t@@ -8,16 +8,28 @@ OBJ = spoon.o batt.o wifi.o cpu.o count.o temp.o date.o load.o file.o key.o\
BIN = spoon
DISTFILES = $(SRC) arg.h types.h util.h config.def.h Makefile LICENSE configure
-#include config.mk
+include config.mk
-CPPFLAGS = -I/usr/X11R6/include -I/usr/local/include
-LDFLAGS = -L/usr/X11R6/lib -L/usr/local/lib
+CPPFLAGS_OpenBSD = -I/usr/X11R6/include -I/usr/local/include
+LDFLAGS_OpenBSD = -L/usr/X11R6/lib -L/usr/local/lib
+CPPFLAGS_Linux = -I/usr/local/include
+CPPFLAGS = $(CPPFLAGS_$(UNAME))
+LDFLAGS = $(LDFLAGS_$(UNAME))
LDLIBS = -lX11
+
# To remove extra compile time dependencies for unwanted plugins
# comment out the following sections. The stub implementations
# from stub.c will be used instead.
OBJ += mix.o
+LDLIBS_OpenBSD_mix = -lsndio
+# if ALSA
+LDLIBS_Linux_mix = -lasound
+CPPFLAGS += -DUSE_TINYALSA=0
+# else TinyALSA
+#LDLIBS_Linux_mix = -ltinyalsa
+#CPPFLAGS += -DUSE_TINYALSA=1
+LDLIBS += $(LDLIBS_$(UNAME)_mix)
OBJ += xkblayout.o
LDLIBS += -lxkbfile
(DIR) diff --git a/mix.c b/mix.c
t@@ -4,67 +4,153 @@
#include "util.h"
#ifdef __OpenBSD__
-#include <sys/ioctl.h>
-#include <sys/audioio.h>
-
-#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <sndio.h>
+#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-int
-mixread(void *arg, char *buf, size_t len)
+#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)
{
- mixer_devinfo_t dinfo;
- mixer_ctrl_t mctl;
- int fd, master, ret = 0, i = -1;
+ size_t i;
+ int val;
- fd = open("/dev/mixer", O_RDONLY);
- if (fd == -1) {
- warn("open %s", "/dev/mixer");
- return -1;
+ 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;
}
- dinfo.index = 0;
- /* outputs */
- for (; ; dinfo.index++) {
- ret = ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo);
- if (ret == -1) {
- warn("AUDIO_MIXER_DEVINFO %s", "/dev/mixer");
- goto out;
- }
- if (dinfo.type == AUDIO_MIXER_CLASS &&
- strcmp(dinfo.label.name, AudioCoutputs) == 0) {
- i = dinfo.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;
}
+}
+
+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 (i == -1) {
- warnx("no outputs mixer class: %s", "/dev/mixer");
- goto out;
+ if (!sioctl_ondesc(hdl, ondesc, NULL)) {
+ warnx("sioctl_ondesc");
+ sioctl_close(hdl);
+ return 0;
}
- /* outputs.master */
- for (; ; dinfo.index++) {
- ret = ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo);
- if (ret == -1) {
- warn("AUDIO_MIXER_DEVINFO %s", "/dev/mixer");
+ 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 (dinfo.type == AUDIO_MIXER_VALUE &&
- dinfo.prev == AUDIO_MIXER_LAST &&
- dinfo.mixer_class == i &&
- strcmp(dinfo.label.name, AudioNmaster) == 0)
- break;
}
- mctl.dev = dinfo.index;
- ret = ioctl(fd, AUDIO_MIXER_READ, &mctl);
- if (ret == -1) {
- warn("AUDIO_MIXER_READ %s", "/dev/mixer");
+
+ 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;
}
- master = mctl.un.value.level[0] * 100 / 255;
- snprintf(buf, len, "%d%%", master);
+
+ return 1;
+
out:
- close(fd);
- return ret;
+ free(pfds);
+ pfds = NULL;
+ sioctl_close(hdl);
+
+ return 0;
+}
+
+int
+mixread(void *arg, char *buf, size_t len)
+{
+ static int init_done = 0;
+ struct pollfd *pfds;
+ int nfds;
+
+ if (!init_done) {
+ if (!do_init())
+ return -1;
+ init_done = 1;
+ }
+
+ init_done = poll_peek();
+ snprintf(buf, len, "%d%%", get_output());
+
+ return 0;
}
#elif __linux__ && !USE_TINYALSA
#include <alsa/asoundlib.h>