mirror of
https://github.com/Stichting-MINIX-Research-Foundation/pkgsrc-ng.git
synced 2025-08-03 17:59:07 -04:00
429 lines
11 KiB
Plaintext
429 lines
11 KiB
Plaintext
$NetBSD: patch-aa,v 1.5 1998/11/05 02:46:09 mycroft Exp $
|
|
|
|
--- /dev/null Wed Nov 4 21:26:51 1998
|
|
+++ src/auddev_netbsd.c Wed Nov 4 21:27:03 1998
|
|
@@ -0,0 +1,423 @@
|
|
+/*
|
|
+ * FILE: netbsd.c
|
|
+ * PROGRAM: RAT
|
|
+ * AUTHOR: Isidor Kouvelas
|
|
+ * MODIFIED: Colin Perkins
|
|
+ *
|
|
+ * $Revision: 1.5 $
|
|
+ * $Date: 1998/11/05 02:46:09 $
|
|
+ *
|
|
+ * Copyright (c) 1995,1996 University College London
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, is permitted, for non-commercial use only, provided
|
|
+ * that the following conditions are met:
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ * 3. All advertising materials mentioning features or use of this software
|
|
+ * must display the following acknowledgement:
|
|
+ * This product includes software developed by the Computer Science
|
|
+ * Department at University College London
|
|
+ * 4. Neither the name of the University nor of the Department may be used
|
|
+ * to endorse or promote products derived from this software without
|
|
+ * specific prior written permission.
|
|
+ * Use of this software for commercial purposes is explicitly forbidden
|
|
+ * unless prior written permission is obtained from the authors.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
+ * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
+ * SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+
|
|
+
|
|
+#include "assert.h"
|
|
+#include "bat_include.h"
|
|
+#ifdef __NetBSD__
|
|
+
|
|
+static audio_info_t dev_info;
|
|
+static int mulaw_device = FALSE; /* TRUE if the hardware can only do 8bit mulaw sampling */
|
|
+
|
|
+#define bat_to_device(x) ((x) * AUDIO_MAX_GAIN / MAX_AMP)
|
|
+#define device_to_bat(x) ((x) * MAX_AMP / AUDIO_MAX_GAIN)
|
|
+
|
|
+/* Try to open the audio device. */
|
|
+/* Returns a valid file descriptor if ok, -1 otherwise. */
|
|
+int
|
|
+audio_open(audio_format format)
|
|
+{
|
|
+ audio_info_t tmp_info;
|
|
+
|
|
+ int audio_fd = open("/dev/audio", O_RDWR | O_NDELAY);
|
|
+
|
|
+ if (audio_fd > 0) {
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.monitor_gain = 0;
|
|
+ dev_info.play.sample_rate = format.sample_rate;
|
|
+ dev_info.record.sample_rate = format.sample_rate;
|
|
+ dev_info.play.channels = format.num_channels;
|
|
+ dev_info.record.channels = format.num_channels;
|
|
+ dev_info.play.precision = format.bits_per_sample;
|
|
+ dev_info.record.precision = format.bits_per_sample;
|
|
+ dev_info.play.gain = (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) * 0.75;
|
|
+ dev_info.record.gain = (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) * 0.75;
|
|
+ dev_info.play.port = AUDIO_HEADPHONE;
|
|
+ dev_info.record.port = AUDIO_MICROPHONE;
|
|
+ dev_info.play.balance = AUDIO_MID_BALANCE;
|
|
+ dev_info.record.balance = AUDIO_MID_BALANCE;
|
|
+#ifdef SunOS_5
|
|
+ dev_info.play.buffer_size = DEVICE_BUF_UNIT;
|
|
+ dev_info.record.buffer_size = DEVICE_BUF_UNIT;
|
|
+#endif
|
|
+ switch (format.encoding) {
|
|
+ case DEV_PCMU:
|
|
+ dev_info.record.encoding = AUDIO_ENCODING_ULAW;
|
|
+ dev_info.play.encoding = AUDIO_ENCODING_ULAW;
|
|
+ break;
|
|
+ case DEV_L8:
|
|
+ assert(format.bits_per_sample == 8);
|
|
+ dev_info.record.encoding = AUDIO_ENCODING_LINEAR;
|
|
+ dev_info.play.encoding = AUDIO_ENCODING_LINEAR;
|
|
+ break;
|
|
+ case DEV_L16:
|
|
+ assert(format.bits_per_sample == 16);
|
|
+ dev_info.record.encoding = AUDIO_ENCODING_LINEAR;
|
|
+ dev_info.play.encoding = AUDIO_ENCODING_LINEAR;
|
|
+ break;
|
|
+ default:
|
|
+ printf("ERROR: Unknown audio encoding in audio_open!\n");
|
|
+ abort();
|
|
+ }
|
|
+
|
|
+ memcpy(&tmp_info, &dev_info, sizeof(audio_info_t));
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&tmp_info) < 0) {
|
|
+ if (format.encoding == DEV_L16) {
|
|
+#ifdef DEBUG
|
|
+ printf("Old hardware detected: can't do 16 bit audio, trying 8 bit...\n");
|
|
+#endif
|
|
+ dev_info.play.precision = 8;
|
|
+ dev_info.record.precision = 8;
|
|
+ dev_info.record.encoding = AUDIO_ENCODING_ULAW;
|
|
+ dev_info.play.encoding = AUDIO_ENCODING_ULAW;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0) {
|
|
+ perror("Setting MULAW audio paramterts");
|
|
+ return -1;
|
|
+ }
|
|
+ mulaw_device = TRUE;
|
|
+ } else {
|
|
+ perror("Setting audio paramterts");
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ return audio_fd;
|
|
+ } else {
|
|
+ /* Because we opened the device with O_NDELAY
|
|
+ * the waiting flag was not updated so update
|
|
+ * it manually using the audioctl device...
|
|
+ */
|
|
+ audio_fd = open("/dev/audioctl", O_RDWR);
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.play.waiting = 1;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0) {
|
|
+#ifdef DEBUG
|
|
+ perror("Setting requests");
|
|
+#endif
|
|
+ }
|
|
+ close(audio_fd);
|
|
+ return -1;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Close the audio device */
|
|
+void
|
|
+audio_close(int audio_fd)
|
|
+{
|
|
+ close(audio_fd);
|
|
+ audio_fd = -1;
|
|
+}
|
|
+
|
|
+/* Flush input buffer */
|
|
+void
|
|
+audio_drain(int audio_fd)
|
|
+{
|
|
+ ioctl(audio_fd, AUDIO_FLUSH, 0);
|
|
+}
|
|
+
|
|
+/* Gain and volume values are in the range 0 - MAX_AMP */
|
|
+
|
|
+void
|
|
+audio_set_gain(int audio_fd, int gain)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.record.gain = bat_to_device(gain);
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting gain");
|
|
+}
|
|
+
|
|
+int
|
|
+audio_get_gain(int audio_fd)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return (0);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting gain");
|
|
+ return (device_to_bat(dev_info.record.gain));
|
|
+}
|
|
+
|
|
+void
|
|
+audio_set_volume(int audio_fd, int vol)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.play.gain = bat_to_device(vol);
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting volume");
|
|
+}
|
|
+
|
|
+int
|
|
+audio_get_volume(int audio_fd)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return (0);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting gain");
|
|
+ return (device_to_bat(dev_info.play.gain));
|
|
+}
|
|
+
|
|
+int
|
|
+audio_read(int audio_fd, sample *buf, int samples)
|
|
+{
|
|
+ int i, len;
|
|
+ static u_char mulaw_buf[DEVICE_REC_BUF];
|
|
+ u_char *p;
|
|
+
|
|
+ if (mulaw_device) {
|
|
+ if ((len = read(audio_fd, mulaw_buf, samples)) < 0) {
|
|
+ return 0;
|
|
+ } else {
|
|
+ p = mulaw_buf;
|
|
+ for (i = 0; i < len; i++) {
|
|
+ *buf++ = u2s((unsigned)*p);
|
|
+ p++;
|
|
+ }
|
|
+ return (len);
|
|
+ }
|
|
+ } else {
|
|
+ if ((len = read(audio_fd, (char *)buf, samples * BYTES_PER_SAMPLE)) < 0) {
|
|
+ return 0;
|
|
+ } else {
|
|
+ return (len / BYTES_PER_SAMPLE);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+int
|
|
+audio_write(int audio_fd, sample *buf, int samples)
|
|
+{
|
|
+ int i, done, len, bps;
|
|
+ unsigned char *p, *q;
|
|
+ static u_char mulaw_buf[DEVICE_REC_BUF];
|
|
+
|
|
+ if (mulaw_device) {
|
|
+ p = mulaw_buf;
|
|
+ for (i = 0; i < samples; i++)
|
|
+ *p++ = lintomulaw[(unsigned short)*buf++];
|
|
+ p = mulaw_buf;
|
|
+ len = samples;
|
|
+ bps = 1;
|
|
+ } else {
|
|
+ p = (char *)buf;
|
|
+ len = samples * BYTES_PER_SAMPLE;
|
|
+ bps = BYTES_PER_SAMPLE;
|
|
+ }
|
|
+
|
|
+ q = p;
|
|
+ while (1) {
|
|
+ if ((done = write(audio_fd, p, len)) == len)
|
|
+ break;
|
|
+ if (errno != EINTR)
|
|
+ return (samples - ((len - done) / bps));
|
|
+ len -= done;
|
|
+ p += done;
|
|
+ }
|
|
+
|
|
+ return (samples);
|
|
+}
|
|
+
|
|
+/* Set ops on audio device to be non-blocking */
|
|
+void
|
|
+audio_non_block(int audio_fd)
|
|
+{
|
|
+ int on = 1;
|
|
+
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ if (ioctl(audio_fd, FIONBIO, (char *)&on) < 0)
|
|
+ fprintf(stderr, "Failed to set non blocking mode on audio device!\n");
|
|
+}
|
|
+
|
|
+/* Set ops on audio device to block */
|
|
+void
|
|
+audio_block(int audio_fd)
|
|
+{
|
|
+ int on = 0;
|
|
+
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ if (ioctl(audio_fd, FIONBIO, (char *)&on) < 0)
|
|
+ fprintf(stderr, "Failed to set blocking mode on audio device!\n");
|
|
+}
|
|
+
|
|
+void
|
|
+audio_set_oport(int audio_fd, int port)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ /* AUDIO_SPEAKER or AUDIO_HEADPHONE */
|
|
+ dev_info.play.port = port;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting port");
|
|
+}
|
|
+
|
|
+int
|
|
+audio_get_oport(int audio_fd)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return (AUDIO_SPEAKER);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting port");
|
|
+ return (dev_info.play.port);
|
|
+}
|
|
+
|
|
+int
|
|
+audio_next_oport(int audio_fd)
|
|
+{
|
|
+ int port;
|
|
+
|
|
+ if (audio_fd <= 0)
|
|
+ return (AUDIO_SPEAKER);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting port");
|
|
+
|
|
+
|
|
+ port = dev_info.play.port;
|
|
+ port <<= 1;
|
|
+
|
|
+ /* It is either wrong on some machines or i got something wrong! */
|
|
+ if (dev_info.play.avail_ports < 3)
|
|
+ dev_info.play.avail_ports = 3;
|
|
+
|
|
+ if ((port & dev_info.play.avail_ports) == 0)
|
|
+ port = 1;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.play.port = port;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting port");
|
|
+
|
|
+ return (port);
|
|
+}
|
|
+
|
|
+void
|
|
+audio_set_iport(int audio_fd, int port)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.record.port = port;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting port");
|
|
+}
|
|
+
|
|
+int
|
|
+audio_get_iport(int audio_fd)
|
|
+{
|
|
+ if (audio_fd <= 0)
|
|
+ return (AUDIO_SPEAKER);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting port");
|
|
+ return (dev_info.record.port);
|
|
+}
|
|
+
|
|
+int
|
|
+audio_next_iport(int audio_fd)
|
|
+{
|
|
+ int port;
|
|
+
|
|
+ if (audio_fd <= 0)
|
|
+ return (AUDIO_SPEAKER);
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ if (ioctl(audio_fd, AUDIO_GETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Getting port");
|
|
+
|
|
+ port = dev_info.record.port;
|
|
+ port <<= 1;
|
|
+
|
|
+ if (dev_info.record.avail_ports > 3)
|
|
+ dev_info.record.avail_ports = 3;
|
|
+
|
|
+ /* Hack to fix Sparc 5 SOLARIS bug */
|
|
+ if ((port & dev_info.record.avail_ports) == 0)
|
|
+ port = 1;
|
|
+
|
|
+ AUDIO_INITINFO(&dev_info);
|
|
+ dev_info.record.port = port;
|
|
+ if (ioctl(audio_fd, AUDIO_SETINFO, (caddr_t)&dev_info) < 0)
|
|
+ perror("Setting port");
|
|
+
|
|
+ return (port);
|
|
+}
|
|
+
|
|
+void
|
|
+audio_switch_out(int audio_fd, cushion_struct *ap)
|
|
+{
|
|
+ /* Full duplex device: do nothing! */
|
|
+}
|
|
+
|
|
+void
|
|
+audio_switch_in(int audio_fd)
|
|
+{
|
|
+ /* Full duplex device: do nothing! */
|
|
+}
|
|
+
|
|
+int
|
|
+audio_duplex(int audio_fd)
|
|
+{
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+#endif /* __NetBSD__ */
|
|
+
|