$NetBSD: patch-ag,v 1.1 2004/08/29 22:43:50 wiz Exp $

--- libavformat/audio.c.orig	2003-09-28 17:26:40.000000000 +0200
+++ libavformat/audio.c
@@ -18,10 +18,19 @@
  */
 #include "avformat.h"
 
+#ifdef __NetBSD__
+#define USE_SUNAUDIO
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#ifndef USE_SUNAUDIO
 #include <sys/soundcard.h>
+#else
+#include <sys/types.h>
+#include <sys/audioio.h>
+#endif
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -47,9 +56,18 @@ static int audio_open(AudioData *s, int 
     int tmp, err;
     char *flip = getenv("AUDIO_FLIP_LEFT");
 
+#ifdef USE_SUNAUDIO
+    audio_info_t info;
+    struct audio_prinfo *settings;
+    int mixer_fd;
+
+    if (!audio_device)
+	audio_device = "/dev/audio";
+#else
     /* open linux audio device */
     if (!audio_device)
         audio_device = "/dev/dsp";
+#endif
 
     if (is_output)
         audio_fd = open(audio_device, O_WRONLY);
@@ -77,6 +95,7 @@ static int audio_open(AudioData *s, int 
     }
 #endif
 
+#ifndef USE_SUNAUDIO
     /* select format : favour native format */
     err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
     
@@ -124,14 +143,114 @@ static int audio_open(AudioData *s, int 
     }
     if (tmp)
         s->channels = 2;
+#else /* USE_SUNAUDIO */
+    AUDIO_INITINFO(&info);
+    if (!is_output) {
+	info.mode = AUMODE_RECORD;
+	settings = &info.record;
+    } else {
+	info.mode = AUMODE_PLAY;
+	settings = &info.play;
+    }
+
+    /* select format */
+    /* Try native 16 bit format first */
+#ifdef WORDS_BIGENDIAN
+    settings->encoding = AUDIO_ENCODING_SLINEAR_BE;
+    s->codec_id = CODEC_ID_PCM_S16BE;
+#else
+    settings->encoding = AUDIO_ENCODING_SLINEAR_LE;
+    s->codec_id = CODEC_ID_PCM_S16LE;
+#endif
+    settings->precision = 16;
+    err = ioctl(audio_fd, AUDIO_SETINFO, &info);
+    if (err < 0) {
+        fprintf(stderr, "Soundcard does not support signed 16 bit sample format\n");
+        close(audio_fd);
+        return -EIO;
+    }
     
+    /* set channels */
+    AUDIO_INITINFO(&info);
+    settings->channels = s->channels;
+    err = ioctl(audio_fd, AUDIO_SETINFO, &info);
+    if (err < 0) {
+	fprintf(stderr, "stereo not supported, using mono");
+    }
+
+    /* set gain */
+    AUDIO_INITINFO(&info);
+    settings->gain = AUDIO_MAX_GAIN;
+    err = ioctl(audio_fd, AUDIO_SETINFO, &info);
+    if (err < 0) {
+	fprintf(stderr, "setting gain to %d failed", AUDIO_MAX_GAIN);
+    }
+
+#ifndef MIXER_DEVICE
+#define MIXER_DEVICE "/dev/mixer"
+#endif
+    if ((mixer_fd=open(MIXER_DEVICE, O_RDONLY)) == -1)
+	fprintf(stderr, "can't open %s\n", MIXER_DEVICE);
+    else {
+	int n;
+	mixer_devinfo_t mdt;
+	/* get debuggin information about all mixer devices */
+	mdt.index = n = 0;
+	while (ioctl(mixer_fd, AUDIO_MIXER_DEVINFO, &mdt) != -1) {
+	    if (strcasecmp(mdt.label.name, "inputs") == 0) {
+		while (mdt.next != -1) {
+		    printf("Mixer device %d: `%s' has type %d, class %d\n",
+			   mdt.index, mdt.label.name, mdt.type,
+			   mdt.mixer_class);
+		    mdt.index = mdt.next;
+		    if (ioctl(mixer_fd, AUDIO_MIXER_DEVINFO, &mdt) == -1) {
+			fprintf(stderr, "getting next mixer device "
+				"failed (%d)", mdt.index);
+			break;
+		    }
+		    printf("next device: ");
+		}
+		printf("Mixer device %d: `%s' has type %d, class %d\n",
+		       mdt.index, mdt.label.name, mdt.type,
+		       mdt.mixer_class);
+	    }
+	    n++;
+	    mdt.index = n;
+	}
+	/* set input to line-in */
+	AUDIO_INITINFO(&info);
+	settings->port = AUDIO_LINE_IN;
+	err = ioctl(audio_fd, AUDIO_SETINFO, &info);
+	if (err < 0) {
+	    fprintf(stderr, "setting input to line-in failed");
+	}
+    }
+    close(mixer_fd);
+#endif
+
+#ifndef USE_SUNAUDIO
     tmp = s->sample_rate;
     err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
     if (err < 0) {
         perror("SNDCTL_DSP_SPEED");
         goto fail;
     }
+    
     s->sample_rate = tmp; /* store real sample rate */
+#else
+    AUDIO_INITINFO(&info);
+    settings->sample_rate = s->sample_rate;
+    err = ioctl(audio_fd, AUDIO_SETINFO, &info);
+    if (err < 0) {
+	fprintf(stderr, "setting sample rate to %d failed", s->sample_rate);
+	err = ioctl(audio_fd, AUDIO_GETINFO, &info);
+	if (err < 0) {
+	    perror("AUDIO_GETINFO");
+	    goto fail;
+	}
+	s->sample_rate = settings->sample_rate;
+    }
+#endif
     s->fd = audio_fd;
 
     return 0;
@@ -239,7 +358,11 @@ static int audio_read_packet(AVFormatCon
     AudioData *s = s1->priv_data;
     int ret, bdelay;
     int64_t cur_time;
+#ifndef USE_SUNAUDIO
     struct audio_buf_info abufi;
+#else
+    audio_info_t info;
+#endif
     
     if (av_new_packet(pkt, s->frame_size) < 0)
         return -EIO;
@@ -274,9 +397,15 @@ static int audio_read_packet(AVFormatCon
     /* compute pts of the start of the packet */
     cur_time = av_gettime();
     bdelay = ret;
+#ifndef USE_SUNAUDIO
     if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
         bdelay += abufi.bytes;
     }
+#else
+    if (ioctl(s->fd, AUDIO_GETINFO, &info) == 0) {
+	bdelay += info.record.seek * (info.record.precision/8);
+    }
+#endif
     /* substract time represented by the number of bytes in the audio fifo */
     cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
 
