$OpenBSD: patch-utils_lqtplay_c,v 1.6 2010/05/26 22:31:23 jakemsr Exp $
--- utils/lqtplay.c.orig	Thu Jan 14 10:41:17 2010
+++ utils/lqtplay.c	Wed May 26 15:23:48 2010
@@ -41,6 +41,8 @@
 
 #include "common.h"
 
+#define HAVE_SNDIO
+
 #include <X11/Xlib.h>
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
@@ -70,6 +72,10 @@
 #ifdef HAVE_ALSA
 #include <alsa/asoundlib.h>
 #endif
+#ifdef HAVE_SNDIO
+#include <poll.h>
+#include <sndio.h>
+#endif
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -789,6 +795,88 @@ return 0;
 
 
 /* ------------------------------------------------------------------------ */
+/* sndio code                                                                 */
+
+#ifdef HAVE_SNDIO
+
+static struct sio_hdl *hdl;
+static struct sio_par par;
+
+static int use_sndio = 1;
+
+static int oss_sr,oss_hr;
+
+#else
+
+/* Disable sndio */
+static int use_sndio = 0;
+
+#endif /* HAVE_SNDIO */
+
+static int
+sndio_setformat(int chan, int rate)
+{
+#ifdef	HAVE_SNDIO
+    sio_initpar(&par);
+    par.bits = 16;
+    par.sig = 1;
+    par.rate = rate;
+    par.pchan = chan;
+    /* yes, lqtplay wants really small blocks */
+    par.round = rate / 100;
+    par.appbufsz = par.round * 25;
+
+    if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+	fprintf(stderr,_("ERROR: can't set sound format\n"));
+	exit(1);
+    }
+
+    if (par.pchan != chan || par.bits != 16 || par.sig != 1 ||
+      par.le != SIO_LE_NATIVE) {
+	fprintf(stderr,_("ERROR: can't set requested sound format\n"));
+	exit(1);
+    }
+
+    if (par.rate != rate) {
+        oss_sr = rate;
+	oss_hr = par.rate;
+	fprintf(stderr,_("WARNING: sample rate mismatch (need %d, got %d)\n"),
+		rate, par.rate);
+    }
+
+    return 0;
+#else
+    return 1;
+#endif
+}
+
+static int sndio_init(char *dev, int channels, int rate)
+{
+#ifdef	HAVE_SNDIO
+
+    /* this code is absolutely horrible.  lqtplay expects to be able
+       to write at least every 2 ms.  do not follow this example. */
+
+    hdl = sio_open(NULL, SIO_PLAY, 1);
+    if (NULL == hdl) {
+	fprintf(stderr,_("ERROR: can't open sndio\n"));
+	return -1;
+    }
+    sndio_setformat(channels,rate);
+
+    if (!sio_start(hdl)) {
+        fprintf(stderr,_("ERROR: can't start sndio\n"));
+        return -1;
+    }
+    return 0;
+#else
+    return 1;
+#endif
+}
+
+
+
+/* ------------------------------------------------------------------------ */
 /* oss code                                                                 */
 
 #ifndef AFMT_S16_NE
@@ -972,7 +1060,11 @@ static void qt_init(FILE *fp, char *filename)
 	qt_hasaudio = 1;
 	qt_channels = quicktime_track_channels(qt,0);
         qt_sample_rate = quicktime_sample_rate(qt,0);
-  if (use_alsa == 1) {
+  if (use_sndio == 1) {
+    if (-1 == sndio_init(adev_name, qt_channels, 
+         qt_sample_rate)) {
+           qt_hasaudio = 0;}
+  } else if (use_alsa == 1) {
     if (-1 == alsa_init(adev_name, qt_channels, 
          qt_sample_rate)) {
            qt_hasaudio = 0;}
@@ -1422,6 +1514,48 @@ static int qt_alsa_audio_write()
   return 0;
 }
 
+static int qt_sndio_audio_write(void)
+{
+#ifdef HAVE_SNDIO
+    struct pollfd pfd;
+    int rc, n, revents;
+
+    if(!qt_audio_samples_in_buffer)
+      decode_audio(AUDIO_BLOCK_SIZE);
+
+    /* this code is absolutely horrible.  do not follow this example. */
+
+    n = sio_pollfd(hdl, &pfd, POLLOUT);
+    rc = poll(&pfd, n, 10000);
+    if (rc <= 0)
+        goto fail;
+    revents = sio_revents(hdl, &pfd);
+    if (!(revents & POLLOUT))
+        goto fail;
+    rc = sio_write(hdl,qt_audio_ptr,qt_audio_samples_in_buffer * qt_channels * sizeof(*qt_audio));
+    switch (rc) {
+    case 0:
+        goto fail;
+	break;
+    default:
+        qt_audio_samples_in_buffer -= rc / (qt_channels * sizeof(*qt_audio));
+        qt_audio_ptr += rc / sizeof(*qt_audio);
+        break;
+    }
+
+    if (qt_audio_eof && 0 == qt_audio_samples_in_buffer) {
+       return -1;
+    }
+#endif
+    return 0;
+fail:
+    fprintf(stderr,_("write sndio: Huh? no data to write/no data written?\n"));
+    sio_close(hdl);
+    hdl = NULL;
+    qt_hasaudio = 0;
+    return 0;
+}
+
 static int qt_oss_audio_write(void)
 {
     int rc;
@@ -1803,7 +1937,7 @@ int main(int argc, char *argv[])
 		FD_SET(ConnectionNumber(dpy),&rd);
 		max = ConnectionNumber(dpy);
 		if (qt_hasaudio) {
-		    if (use_alsa == 0) {
+		    if (use_alsa == 0 && use_sndio == 0) {
 			FD_SET(oss_fd,&wr);
 			if (oss_fd > max)
 			    max = oss_fd;
@@ -1841,7 +1975,10 @@ int main(int argc, char *argv[])
 		}
 		rc = select(max+1,&rd,&wr,NULL,&wait);
 		if (qt_hasaudio) {
-		    if (use_alsa == 1) {
+		    if (use_sndio == 1) {
+			if (0 != qt_sndio_audio_write()) qt_hasaudio = 0;
+		    }
+		    else if (use_alsa == 1) {
 			if (0 != qt_alsa_audio_write()) qt_hasaudio = 0;
 		    }
 		    else if (FD_ISSET(oss_fd,&wr)) { 
