tApply upstream patch by Lucas for sndio support on OpenBSD - spoon - dwm statu… | |
git clone git://src.adamsgaard.dk/spoon | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit bd47937068b0c19f7eea595f41b4acba720bd8b8 | |
parent 3c6eedee86ba611a19953902f16f2c2cdddd400f | |
Author: Anders Damsgaard <[email protected]> | |
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(-) | |
--- | |
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… | |
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 | |
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> |