Recently Written · git

sad

sad (2f30.org simple audio daemon) with a Cygwin/OSS port on branch cygwin

git clone https://github.com/equwal/sad

Log | Files | Refs


commit 046fa6955fedc8e5965d99e2088f6b02baf86ead
equwal <13551856+equwal@users.noreply.github.com>
2026-10-04 04:33:31 -0700

Add OSS output backend, link only the selected backend

Cygwin has no sndio or ALSA but emulates OSS /dev/dsp on top of
Windows audio. oss.c opens /dev/dsp as S16LE at the configured
rate and channels.

config.def.h now lists an output only when SOUNDSYS selects it,
and the Makefile takes the backend objects and libraries from
OUTOBJ and OUTLIBS, so a build no longer needs every backend's
library. Build on Cygwin with:

  make OUTOBJ=oss.o OUTLIBS=

 Makefile     | 10 +++++++---
 config.def.h | 33 +++++++++++++-----------------
 oss.c        | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sad.h        |  4 ++++
 4 files changed, 90 insertions(+), 22 deletions(-)
diff --git a/Makefile b/Makefile
index d9d7281..40a42ad 100644
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,15 @@ MANPREFIX = $(PREFIX)/man
 
 CFLAGS = -I/usr/local/include
 LDFLAGS = -L /usr/local/lib
-LDLIBS = -lsndfile -lmpg123 -lsndio -lasound -lvorbisfile -lsoxr
+# sound backends: must match SOUNDSYS in config.h
+# OSS (Cygwin, *BSD): OUTOBJ = oss.o, OUTLIBS =
+OUTOBJ = alsa.o sndio.o
+OUTLIBS = -lsndio -lasound
+
+LDLIBS = -lsndfile -lmpg123 -lvorbisfile -lsoxr $(OUTLIBS)
 
 OBJ =\
-	alsa.o\
+	$(OUTOBJ)\
 	cmd.o\
 	decoder.o\
 	fifo.o\
@@ -18,7 +23,6 @@ OBJ =\
 	pcm.o\
 	playlist.o\
 	sad.o\
-	sndio.o\
 	vorbis.o\
 	wav.o
 
diff --git a/config.def.h b/config.def.h
index 32f3ef8..6c70b67 100644
--- a/config.def.h
+++ b/config.def.h
@@ -6,35 +6,30 @@
 
 /*
    Only need to edit below this line if you have multiple sound backends.
+   Only the backend selected by SOUNDSYS is linked; see OUTOBJ in Makefile.
 */
 
-#if SOUNDSYS == SNDIO
-#define SNDIOON 1
-#else
-#define SNDIOON 0
-#endif
-#if SOUNDSYS == ALSA
-#define ALSAON 1
-#else
-#define ALSAON 0
-#endif
-#if SOUNDSYS == FIFO
-#define FIFOON 1
-#else
-#define FIFOON 0
-#endif
-
 Outputcfg outputcfgs[] = {
+#if SOUNDSYS == SNDIO
     {.name = "sndio",
      .fmt = {.bits = BITDEPTH, .rate = BITRATE, .channels = CHANNELS},
-     .enabled = SNDIOON,
+     .enabled = 1,
      .output = &sndiooutput},
+#endif
+#if SOUNDSYS == ALSA
     {.name = "alsa",
      .fmt = {.bits = BITDEPTH, .rate = BITRATE, .channels = CHANNELS},
-     .enabled = ALSAON,
+     .enabled = 1,
      .output = &alsaoutput},
+#endif
+#if SOUNDSYS == OSS
+    {.name = "oss",
+     .fmt = {.bits = BITDEPTH, .rate = BITRATE, .channels = CHANNELS},
+     .enabled = 1,
+     .output = &ossoutput},
+#endif
     {.name = "fifo",
      .fmt = {.bits = BITDEPTH, .rate = BITRATE, .channels = CHANNELS},
-     .enabled = FIFOON,
+     .enabled = SOUNDSYS == FIFO,
      .output = &fifooutput},
 };
diff --git a/oss.c b/oss.c
new file mode 100644
index 0000000..b4fefbe
--- /dev/null
+++ b/oss.c
@@ -0,0 +1,65 @@
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/soundcard.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "sad.h"
+
+static int ossfd = -1;
+int ossvolstatus = DEFAULTVOL;
+
+static int ossvol(int vol) {
+  ossvolstatus = vol;
+  return 0;
+}
+
+static int ossopen(Format *fmt) {
+  int afmt = AFMT_S16_LE, chans = fmt->channels, rate = fmt->rate;
+
+  ossfd = open("/dev/dsp", O_WRONLY);
+  if (ossfd < 0) {
+    warn("open /dev/dsp");
+    return -1;
+  }
+  if (ioctl(ossfd, SNDCTL_DSP_SETFMT, &afmt) < 0 ||
+      ioctl(ossfd, SNDCTL_DSP_CHANNELS, &chans) < 0 ||
+      ioctl(ossfd, SNDCTL_DSP_SPEED, &rate) < 0) {
+    warn("ioctl /dev/dsp");
+    goto err0;
+  }
+  if (afmt != AFMT_S16_LE || chans != (int)fmt->channels ||
+      rate != (int)fmt->rate) {
+    warnx("unsupported audio params");
+    goto err0;
+  }
+  return 0;
+
+err0:
+  close(ossfd);
+  ossfd = -1;
+  return -1;
+}
+
+static int ossplay(void *buf, size_t nbytes) {
+  return write(ossfd, buf, nbytes);
+}
+
+static int ossclose(void) {
+  if (ossfd != -1)
+    close(ossfd);
+  ossfd = -1;
+  return 0;
+}
+
+Output ossoutput = {
+    .volstatus = &ossvolstatus,
+    .vol = ossvol,
+    .open = ossopen,
+    .play = ossplay,
+    .close = ossclose,
+};
diff --git a/sad.h b/sad.h
index f1102c0..85aaed5 100644
--- a/sad.h
+++ b/sad.h
@@ -10,6 +10,7 @@
 #define SNDIO 0
 #define ALSA 1
 #define FIFO 2
+#define OSS 3
 typedef struct {
   char *name;
   void (*fn)(int, char *);
@@ -105,6 +106,9 @@ extern Output sndiooutput;
 /* alsa.c */
 extern Output alsaoutput;
 
+/* oss.c */
+extern Output ossoutput;
+
 /* fifo.c */
 extern Output fifooutput;