mirror of
https://git.FreeBSD.org/ports.git
synced 2024-11-04 22:33:27 +00:00
eb92024368
PR: 21445 Submitted by: maintainer
942 lines
27 KiB
Plaintext
942 lines
27 KiB
Plaintext
diff -uPr rat/MODS /home/oh/src/rat-newpcm/rat/MODS
|
|
--- rat/MODS Fri Sep 8 21:02:40 2000
|
|
+++ /home/oh/src/rat-newpcm/rat/MODS Sat Sep 16 20:33:47 2000
|
|
@@ -1,7 +1,7 @@
|
|
MODIFICATIONS FILE
|
|
------------------
|
|
|
|
-$Id: MODS,v 1.225 2000/09/08 19:58:13 ucaccsp Exp $
|
|
+$Id: MODS,v 1.226 2000/09/16 17:43:21 ucacoxh Exp $
|
|
|
|
Copyright (C) 1995-2000 University College London
|
|
All rights reserved.
|
|
@@ -1429,18 +1429,23 @@
|
|
- Fix labelling of transcoder input/output ports
|
|
* Released 8 September 2000
|
|
|
|
-
|
|
-
|
|
-
|
|
+v4.2.9p1 - Added auddev_newpcm.[ch] with newpcm style mixer control. Includes
|
|
+ support for loopback and preservation of mixer settings so mixer is
|
|
+ returned to original state upon exit. [oh]
|
|
+
|
|
+ Note: both driver interfaces (luigi, newpcm) are pulled in
|
|
+ by configure and this is possible whilst luigi pcm and
|
|
+ newpcm maintain the same function call interface. This may
|
|
+ break in future. Both are necessary because mixer operation
|
|
+ is not consistent between the two interfaces.
|
|
|
|
TODO -- They're features not bugs dammit!
|
|
----
|
|
|
|
- Assorted audio driver problems:
|
|
- - FreeBSD driver bug on SoundBlaster 16 has small write buffers
|
|
+ - Luigi pcm driver bug on SoundBlaster 16 has small write buffers
|
|
and stops working full duplex mode after a time. Hard to fix because
|
|
of cushion.
|
|
- - Loopback support is broken on FreeBSD newpcm driver.
|
|
- Broken auddev_pca with adding of audio interface conversion code.
|
|
FreeBSD 3.1 pca audio does not seem to work anymore.
|
|
- SunVideoPlus interface code does not work properly. The driver Sun
|
|
diff -uPr rat/acconfig.h /home/oh/src/rat-newpcm/rat/acconfig.h
|
|
--- rat/acconfig.h Fri Sep 8 21:02:44 2000
|
|
+++ /home/oh/src/rat-newpcm/rat/acconfig.h Sat Sep 16 20:33:49 2000
|
|
@@ -1,7 +1,7 @@
|
|
/*
|
|
* Define this if your C library doesn't have usleep.
|
|
*
|
|
- * $Id: acconfig.h,v 1.10 2000/02/06 22:04:23 ucacoxh Exp $
|
|
+ * $Id: acconfig.h,v 1.11 2000/09/16 17:43:22 ucacoxh Exp $
|
|
*/
|
|
#undef NEED_USLEEP
|
|
#undef NEED_SNPRINTF
|
|
@@ -42,12 +42,15 @@
|
|
#undef HAVE_SGI_AUDIO
|
|
#undef HAVE_PCA_AUDIO
|
|
#undef HAVE_LUIGI_AUDIO
|
|
+#undef HAVE_NEWPCM_AUDIO
|
|
#undef HAVE_OSS_AUDIO
|
|
#undef HAVE_HP_AUDIO
|
|
#undef HAVE_NETBSD_AUDIO
|
|
#undef HAVE_OSPREY_AUDIO
|
|
#undef HAVE_MACHINE_PCAUDIOIO_H
|
|
#undef HAVE_ALSA_AUDIO
|
|
+
|
|
+#undef HAVE_IPv6
|
|
|
|
/* GSM related */
|
|
#undef SASR
|
|
diff -uPr rat/auddev.c /home/oh/src/rat-newpcm/rat/auddev.c
|
|
--- rat/auddev.c Fri Sep 8 21:02:44 2000
|
|
+++ /home/oh/src/rat-newpcm/rat/auddev.c Sat Sep 16 20:33:52 2000
|
|
@@ -9,7 +9,7 @@
|
|
|
|
#ifndef HIDE_SOURCE_STRINGS
|
|
static const char cvsid[] =
|
|
- "$Id: auddev.c,v 1.58 2000/05/08 10:11:40 ucaccsp Exp $";
|
|
+ "$Id: auddev.c,v 1.59 2000/09/16 17:43:22 ucacoxh Exp $";
|
|
#endif /* HIDE_SOURCE_STRINGS */
|
|
|
|
#include "config_unix.h"
|
|
@@ -22,6 +22,7 @@
|
|
#include "auddev.h"
|
|
#include "auddev_null.h"
|
|
#include "auddev_luigi.h"
|
|
+#include "auddev_newpcm.h"
|
|
#include "auddev_osprey.h"
|
|
#include "auddev_oss.h"
|
|
#include "auddev_alsa.h"
|
|
@@ -298,6 +299,38 @@
|
|
luigi_audio_supports
|
|
},
|
|
#endif /* HAVE_LUIGI_AUDIO */
|
|
+#ifdef HAVE_NEWPCM_AUDIO
|
|
+ {
|
|
+ newpcm_audio_query_devices,
|
|
+ NULL,
|
|
+ newpcm_get_device_count,
|
|
+ newpcm_get_device_name,
|
|
+ newpcm_audio_open,
|
|
+ newpcm_audio_close,
|
|
+ newpcm_audio_drain,
|
|
+ newpcm_audio_duplex,
|
|
+ newpcm_audio_read,
|
|
+ newpcm_audio_write,
|
|
+ newpcm_audio_non_block,
|
|
+ newpcm_audio_block,
|
|
+ newpcm_audio_set_igain,
|
|
+ newpcm_audio_get_igain,
|
|
+ newpcm_audio_set_ogain,
|
|
+ newpcm_audio_get_ogain,
|
|
+ newpcm_audio_loopback,
|
|
+ newpcm_audio_oport_set,
|
|
+ newpcm_audio_oport_get,
|
|
+ newpcm_audio_oport_details,
|
|
+ newpcm_audio_oport_count,
|
|
+ newpcm_audio_iport_set,
|
|
+ newpcm_audio_iport_get,
|
|
+ newpcm_audio_iport_details,
|
|
+ newpcm_audio_iport_count,
|
|
+ newpcm_audio_is_ready,
|
|
+ newpcm_audio_wait_for,
|
|
+ newpcm_audio_supports
|
|
+ },
|
|
+#endif /* HAVE_NEWPCM_AUDIO */
|
|
#ifdef HAVE_PCA_AUDIO
|
|
{
|
|
pca_audio_init,
|
|
diff -uPr rat/auddev_luigi.c /home/oh/src/rat-newpcm/rat/auddev_luigi.c
|
|
--- rat/auddev_luigi.c Fri Sep 8 21:02:46 2000
|
|
+++ /home/oh/src/rat-newpcm/rat/auddev_luigi.c Sat Sep 16 20:33:54 2000
|
|
@@ -1,15 +1,13 @@
|
|
/*
|
|
* FILE: auddev_luigi.c - Sound interface for Luigi Rizzo's FreeBSD driver
|
|
*
|
|
- * Modified to support newpcm (July 2000).
|
|
- *
|
|
* Copyright (c) 1996-2000 University College London
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#ifndef HIDE_SOURCE_STRINGS
|
|
static const char cvsid[] =
|
|
- "$Id: auddev_luigi.c,v 1.51 2000/07/23 10:33:29 ucacoxh Exp $";
|
|
+ "$Id: auddev_luigi.c,v 1.52 2000/09/16 17:43:23 ucacoxh Exp $";
|
|
#endif /* HIDE_SOURCE_STRINGS */
|
|
|
|
#include "config_unix.h"
|
|
@@ -51,24 +49,6 @@
|
|
static audio_format *input_format, *output_format, *tmp_format;
|
|
static snd_capabilities soundcaps[LUIGI_MAX_AUDIO_DEVICES];
|
|
|
|
-/* There are some differences between the FreeBSD 4x newpcm driver
|
|
- * and Luigi's pcm driver:
|
|
- *
|
|
- * 1) Mixer loopback writes are handled differently (not supported
|
|
- * on newpcm yet - new mixer infrastructure looks to be WIP)
|
|
- *
|
|
- * 2) newpcm does not set AFMT_FULLDUPLEX when device caps are queried.
|
|
- * Luigi's driver does. Luigi's driver also opens half-duplex devices
|
|
- * when open() use O_RDWR. So with Luigi's driver we have to check
|
|
- * AFMT_FULLDUPLEX, with newpcm we assume if device opens O_RDWR it
|
|
- * is full duplex.
|
|
- *
|
|
- * The variable is_newpcm indicates applications understanding of which
|
|
- * driver it is talking to.
|
|
- */
|
|
-
|
|
-static int is_newpcm;
|
|
-
|
|
int
|
|
luigi_audio_open(audio_desc_t ad, audio_format *ifmt, audio_format *ofmt)
|
|
{
|
|
@@ -100,16 +80,12 @@
|
|
LUIGI_AUDIO_IOCTL(audio_fd,SNDCTL_DSP_RESET,0);
|
|
|
|
/* Check card is full duplex - need for Luigi driver only */
|
|
- if (is_newpcm == FALSE &&
|
|
- (soundcaps[ad].formats & AFMT_FULLDUPLEX) == 0) {
|
|
+ if ((soundcaps[ad].formats & AFMT_FULLDUPLEX) == 0) {
|
|
fprintf(stderr, "Sorry driver does support full duplex for this soundcard\n");
|
|
luigi_audio_close(ad);
|
|
return FALSE;
|
|
}
|
|
|
|
- /* From newpcm source code it looks like AFMT_WEIRD is handled
|
|
- * by driver interface, but Luigi's driver needs this.
|
|
- */
|
|
if (soundcaps[ad].formats & AFMT_WEIRD) {
|
|
/* this is a sb16/32/64...
|
|
* you can change either ifmt or ofmt to U8
|
|
@@ -556,16 +532,14 @@
|
|
ndev++;
|
|
} else if (strstr(buf, "newpcm")) {
|
|
/* This is a clunky check for the
|
|
- * newpcm driver.
|
|
+ * newpcm driver. Don't use luigi in this case
|
|
*/
|
|
- is_newpcm = TRUE;
|
|
+ ndev = 0;
|
|
+ break;
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
-
|
|
- debug_msg("Audio driver is %s\n",
|
|
- (is_newpcm) ? "newpcm" : "luigi");
|
|
|
|
return (ndev);
|
|
}
|
|
diff -uPr rat/auddev_newpcm.c /home/oh/src/rat-newpcm/rat/auddev_newpcm.c
|
|
--- rat/auddev_newpcm.c Thu Jan 1 01:00:00 1970
|
|
+++ /home/oh/src/rat-newpcm/rat/auddev_newpcm.c Sat Sep 16 20:33:54 2000
|
|
@@ -0,0 +1,622 @@
|
|
+/*
|
|
+ * FILE: auddev_newpcm.c - Sound interface for newpcm FreeBSD driver.
|
|
+ *
|
|
+ * Modified to support newpcm (July 2000).
|
|
+ *
|
|
+ * Copyright (c) 1996-2000 University College London
|
|
+ * All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef HIDE_SOURCE_STRINGS
|
|
+static const char cvsid[] =
|
|
+ "$Id: auddev_newpcm.c,v 1.1 2000/09/16 17:43:23 ucacoxh Exp $";
|
|
+#endif /* HIDE_SOURCE_STRINGS */
|
|
+
|
|
+#include "config_unix.h"
|
|
+#include "config_win32.h"
|
|
+#include "audio_types.h"
|
|
+#include "audio_fmt.h"
|
|
+#include "auddev_newpcm.h"
|
|
+#include "memory.h"
|
|
+#include "debug.h"
|
|
+
|
|
+#include <machine/soundcard.h>
|
|
+
|
|
+static char *port_names[] = SOUND_DEVICE_LABELS;
|
|
+static int iport, oport, loop;
|
|
+static snd_chan_param pa;
|
|
+static struct snd_size sz;
|
|
+static int audio_fd = -1;
|
|
+
|
|
+#define RAT_TO_DEVICE(x) ((x) * 100 / MAX_AMP)
|
|
+#define DEVICE_TO_RAT(x) ((x) * MAX_AMP / 100)
|
|
+
|
|
+#define NEWPCM_AUDIO_IOCTL(fd, cmd, val) if (ioctl((fd), (cmd), (val)) < 0) { \
|
|
+ debug_msg("Failed %s - line %d\n",#cmd, __LINE__); \
|
|
+ newpcm_error = __LINE__; \
|
|
+ }
|
|
+
|
|
+#define NEWPCM_MAX_AUDIO_NAME_LEN 32
|
|
+#define NEWPCM_MAX_AUDIO_DEVICES 3
|
|
+
|
|
+static int dev_ids[NEWPCM_MAX_AUDIO_DEVICES];
|
|
+static char names[NEWPCM_MAX_AUDIO_DEVICES][NEWPCM_MAX_AUDIO_NAME_LEN];
|
|
+static int ndev = 0;
|
|
+static int newpcm_error;
|
|
+static audio_format *input_format, *output_format, *tmp_format;
|
|
+static snd_capabilities soundcaps[NEWPCM_MAX_AUDIO_DEVICES];
|
|
+
|
|
+static void newpcm_mixer_save(int fd);
|
|
+static void newpcm_mixer_restore(int fd);
|
|
+static void newpcm_mixer_init(int fd);
|
|
+static void newpcm_audio_loopback_config(int gain);
|
|
+
|
|
+int
|
|
+newpcm_audio_open(audio_desc_t ad, audio_format *ifmt, audio_format *ofmt)
|
|
+{
|
|
+ int32_t fragment;
|
|
+ char thedev[64];
|
|
+
|
|
+ assert(ad >= 0 && ad < ndev);
|
|
+ sprintf(thedev, "/dev/audio%d", dev_ids[ad]);
|
|
+
|
|
+ debug_msg("Opening %s\n", thedev);
|
|
+
|
|
+ audio_fd = open(thedev, O_RDWR);
|
|
+ if (audio_fd >= 0) {
|
|
+ /* Ignore any earlier errors */
|
|
+ newpcm_error = 0;
|
|
+
|
|
+ newpcm_mixer_save(audio_fd);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, AIOGCAP, &soundcaps[ad]);
|
|
+ debug_msg("soundcaps[%d].rate_min = %d\n", ad, soundcaps[ad].rate_min);
|
|
+ debug_msg("soundcaps[%d].rate_max = %d\n", ad, soundcaps[ad].rate_max);
|
|
+ debug_msg("soundcaps[%d].formats = 0x%08lx\n", ad, soundcaps[ad].formats);
|
|
+ debug_msg("soundcaps[%d].bufsize = %d\n", ad, soundcaps[ad].bufsize);
|
|
+ debug_msg("soundcaps[%d].mixers = 0x%08lx\n", ad, soundcaps[ad].mixers);
|
|
+ debug_msg("soundcaps[%d].inputs = 0x%08lx\n", ad, soundcaps[ad].inputs);
|
|
+ debug_msg("soundcaps[%d].left = 0x%04lx\n", ad, soundcaps[ad].left);
|
|
+ debug_msg("soundcaps[%d].right = 0x%04lx\n", ad, soundcaps[ad].right);
|
|
+
|
|
+ /* Setup input and output format settings */
|
|
+ assert(ofmt->channels == ifmt->channels);
|
|
+ memset(&pa, 0, sizeof(pa));
|
|
+ if (ifmt->channels == 2) {
|
|
+ if (!soundcaps[ad].formats & AFMT_STEREO) {
|
|
+ fprintf(stderr,"Driver does not support stereo for this soundcard\n");
|
|
+ newpcm_audio_close(ad);
|
|
+ return FALSE;
|
|
+ }
|
|
+ pa.rec_format = AFMT_STEREO;
|
|
+ pa.play_format = AFMT_STEREO;
|
|
+ }
|
|
+
|
|
+ switch(ifmt->encoding) {
|
|
+ case DEV_PCMU: pa.rec_format |= AFMT_MU_LAW; break;
|
|
+ case DEV_PCMA: pa.rec_format |= AFMT_A_LAW; break;
|
|
+ case DEV_S8: pa.rec_format |= AFMT_S8; break;
|
|
+ case DEV_S16: pa.rec_format |= AFMT_S16_LE; break;
|
|
+ case DEV_U8: pa.rec_format |= AFMT_U8; break;
|
|
+ }
|
|
+
|
|
+ switch(ofmt->encoding) {
|
|
+ case DEV_PCMU: pa.play_format |= AFMT_MU_LAW; break;
|
|
+ case DEV_PCMA: pa.play_format |= AFMT_A_LAW; break;
|
|
+ case DEV_S8: pa.play_format |= AFMT_S8; break;
|
|
+ case DEV_S16: pa.play_format |= AFMT_S16_LE; break;
|
|
+ case DEV_U8: pa.play_format |= AFMT_U8; break;
|
|
+ }
|
|
+ pa.play_rate = ofmt->sample_rate;
|
|
+ pa.rec_rate = ifmt->sample_rate;
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, AIOSFMT, &pa);
|
|
+
|
|
+ sz.play_size = ofmt->bytes_per_block;
|
|
+ sz.rec_size = ifmt->bytes_per_block;
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, AIOSSIZE, &sz);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, AIOGSIZE, &sz);
|
|
+ debug_msg("rec size %d, play size %d bytes\n",
|
|
+ sz.rec_size, sz.play_size);
|
|
+
|
|
+ /* Fragment : 8msb = #frags, 16lsbs = log2 fragsize */
|
|
+ fragment = 0x08000007;
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragment);
|
|
+
|
|
+ if (newpcm_error != 0) {
|
|
+ /* Failed somewhere in initialization - reset error and exit*/
|
|
+ newpcm_audio_close(ad);
|
|
+ newpcm_error = 0;
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ /* Store format in case we have to re-open device because
|
|
+ * of driver bug. Careful with freeing format as input format
|
|
+ * could be static input_format if device reset during write.
|
|
+ */
|
|
+ tmp_format = audio_format_dup(ifmt);
|
|
+ if (input_format != NULL) {
|
|
+ audio_format_free(&input_format);
|
|
+ }
|
|
+ input_format = tmp_format;
|
|
+
|
|
+ tmp_format = audio_format_dup(ofmt);
|
|
+ if (output_format != NULL) {
|
|
+ audio_format_free(&output_format);
|
|
+ }
|
|
+ output_format = tmp_format;
|
|
+
|
|
+ newpcm_mixer_init(audio_fd);
|
|
+ /* Turn off loopback from input to output... not fatal so
|
|
+ * after error check.
|
|
+ */
|
|
+ newpcm_audio_loopback(ad, 0);
|
|
+
|
|
+ read(audio_fd, thedev, 64);
|
|
+ return TRUE;
|
|
+ } else {
|
|
+ fprintf(stderr,
|
|
+ "Could not open device: %s (half-duplex?)\n",
|
|
+ names[ad]);
|
|
+ perror("newpcm_audio_open");
|
|
+ newpcm_audio_close(ad);
|
|
+ return FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Close the audio device */
|
|
+void
|
|
+newpcm_audio_close(audio_desc_t ad)
|
|
+{
|
|
+ UNUSED(ad);
|
|
+
|
|
+ if (audio_fd < 0) {
|
|
+ debug_msg("Device already closed!\n");
|
|
+ return;
|
|
+ }
|
|
+ if (input_format != NULL) {
|
|
+ audio_format_free(&input_format);
|
|
+ }
|
|
+ if (output_format != NULL) {
|
|
+ audio_format_free(&output_format);
|
|
+ }
|
|
+ newpcm_mixer_restore(audio_fd);
|
|
+ newpcm_audio_drain(audio_fd);
|
|
+ close(audio_fd);
|
|
+ audio_fd = -1;
|
|
+}
|
|
+
|
|
+/* Flush input buffer */
|
|
+void
|
|
+newpcm_audio_drain(audio_desc_t ad)
|
|
+{
|
|
+ u_char buf[4];
|
|
+ int pre, post;
|
|
+
|
|
+ assert(audio_fd > 0);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, FIONREAD, &pre);
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SNDCTL_DSP_RESET, 0);
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SNDCTL_DSP_SYNC, 0);
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, FIONREAD, &post);
|
|
+ debug_msg("audio drain: %d -> %d\n", pre, post);
|
|
+ read(audio_fd, buf, sizeof(buf));
|
|
+
|
|
+ UNUSED(ad);
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_duplex(audio_desc_t ad)
|
|
+{
|
|
+ /* We only ever open device full duplex! */
|
|
+ UNUSED(ad);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_read(audio_desc_t ad, u_char *buf, int read_bytes)
|
|
+{
|
|
+ int done, this_read;
|
|
+ int len;
|
|
+ /* Figure out how many bytes we can read before blocking... */
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, FIONREAD, &len);
|
|
+
|
|
+ len = min(len, read_bytes);
|
|
+
|
|
+ /* Read the data... */
|
|
+ done = 0;
|
|
+ while(done < len) {
|
|
+ this_read = read(audio_fd, (void*)buf, len - done);
|
|
+ done += this_read;
|
|
+ buf += this_read;
|
|
+ }
|
|
+ return done;
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_write(audio_desc_t ad, u_char *buf, int write_bytes)
|
|
+{
|
|
+ int done;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+
|
|
+ done = write(audio_fd, (void*)buf, write_bytes);
|
|
+ if (done != write_bytes && errno != EINTR) {
|
|
+ /* Only ever seen this with soundblaster cards.
|
|
+ * Driver occasionally packs in reading. Seems to be
|
|
+ * no way to reset cleanly whilst running, even
|
|
+ * closing device, waiting a few 100ms and re-opening
|
|
+ * seems to fail.
|
|
+ */
|
|
+ perror("Error writing device.");
|
|
+ fprintf(stderr, "Please email this message to rat-trap@cs.ucl.ac.uk with output of:\n\t uname -a\n\t cat /dev/sndstat\n");
|
|
+ return (write_bytes - done);
|
|
+ }
|
|
+
|
|
+ return write_bytes;
|
|
+}
|
|
+
|
|
+/* Set ops on audio device to be non-blocking */
|
|
+void
|
|
+newpcm_audio_non_block(audio_desc_t ad)
|
|
+{
|
|
+ int frag = 1;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd != -1);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SNDCTL_DSP_NONBLOCK, &frag);
|
|
+}
|
|
+
|
|
+/* Set ops on audio device to be blocking */
|
|
+void
|
|
+newpcm_audio_block(audio_desc_t ad)
|
|
+{
|
|
+ int frag = 0;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SNDCTL_DSP_NONBLOCK, &frag);
|
|
+}
|
|
+
|
|
+
|
|
+static int recmask, playmask;
|
|
+
|
|
+static void
|
|
+newpcm_mixer_init(int fd)
|
|
+{
|
|
+ int devmask;
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_READ_RECMASK, &recmask);
|
|
+
|
|
+ if (recmask & SOUND_MASK_MIC) {
|
|
+ iport = SOUND_MASK_MIC;
|
|
+ } else {
|
|
+ iport = 1;
|
|
+ while ((iport & recmask) == 0) {
|
|
+ iport <<= 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_READ_DEVMASK, &devmask);
|
|
+ playmask = devmask & ~recmask & ~SOUND_MASK_RECLEV;
|
|
+ debug_msg("devmask 0x%08x recmask 0x%08x playmask 0x%08x\n",
|
|
+ devmask,
|
|
+ recmask,
|
|
+ playmask);
|
|
+}
|
|
+
|
|
+static int
|
|
+newpcm_count_ports(int mask)
|
|
+{
|
|
+ int n = 0, m = mask;
|
|
+
|
|
+ while (m > 0) {
|
|
+ n += (m & 0x01);
|
|
+ m >>= 1;
|
|
+ }
|
|
+
|
|
+ return n;
|
|
+}
|
|
+
|
|
+static int
|
|
+newpcm_get_nth_port_mask(int mask, int n)
|
|
+{
|
|
+ static int lgmask;
|
|
+
|
|
+ lgmask = -1;
|
|
+ do {
|
|
+ lgmask ++;
|
|
+ if ((1 << lgmask) & mask) {
|
|
+ n--;
|
|
+ }
|
|
+ } while (n >= 0);
|
|
+
|
|
+ assert((1 << lgmask) & mask);
|
|
+ return lgmask;
|
|
+}
|
|
+
|
|
+/* Gain and volume values are in the range 0 - MAX_AMP */
|
|
+void
|
|
+newpcm_audio_set_ogain(audio_desc_t ad, int vol)
|
|
+{
|
|
+ int volume, lgport, op;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+
|
|
+ volume = vol << 8 | vol;
|
|
+
|
|
+ lgport = -1;
|
|
+ op = oport;
|
|
+ while (op > 0) {
|
|
+ op >>= 1;
|
|
+ lgport ++;
|
|
+ }
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, MIXER_WRITE(lgport), &volume);
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_get_ogain(audio_desc_t ad)
|
|
+{
|
|
+ int volume, lgport, op;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+
|
|
+ lgport = -1;
|
|
+ op = oport;
|
|
+ while (op > 0) {
|
|
+ op >>= 1;
|
|
+ lgport ++;
|
|
+ }
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, MIXER_READ(lgport), &volume);
|
|
+
|
|
+ return DEVICE_TO_RAT(volume & 0xff); /* Extract left channel volume */
|
|
+}
|
|
+
|
|
+void
|
|
+newpcm_audio_oport_set(audio_desc_t ad, audio_port_t port)
|
|
+{
|
|
+ UNUSED(ad);
|
|
+ oport = port;
|
|
+ return;
|
|
+}
|
|
+
|
|
+audio_port_t
|
|
+newpcm_audio_oport_get(audio_desc_t ad)
|
|
+{
|
|
+ UNUSED(ad);
|
|
+ return oport;
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_oport_count(audio_desc_t ad)
|
|
+{
|
|
+ UNUSED(ad);
|
|
+ return newpcm_count_ports(playmask);
|
|
+}
|
|
+
|
|
+const audio_port_details_t*
|
|
+newpcm_audio_oport_details(audio_desc_t ad, int idx)
|
|
+{
|
|
+ static audio_port_details_t ap;
|
|
+ int lgmask;
|
|
+
|
|
+ UNUSED(ad);
|
|
+
|
|
+ lgmask = newpcm_get_nth_port_mask(playmask, idx);
|
|
+ ap.port = 1 << lgmask;
|
|
+ sprintf(ap.name, "%s", port_names[lgmask]);
|
|
+
|
|
+ return ≈
|
|
+}
|
|
+
|
|
+void
|
|
+newpcm_audio_set_igain(audio_desc_t ad, int gain)
|
|
+{
|
|
+ int volume = RAT_TO_DEVICE(gain) << 8 | RAT_TO_DEVICE(gain);
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+ newpcm_audio_loopback_config(gain);
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SOUND_MIXER_WRITE_RECLEV, &volume);
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_get_igain(audio_desc_t ad)
|
|
+{
|
|
+ int volume;
|
|
+
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, SOUND_MIXER_READ_RECLEV, &volume);
|
|
+ return (DEVICE_TO_RAT(volume & 0xff));
|
|
+}
|
|
+
|
|
+void
|
|
+newpcm_audio_iport_set(audio_desc_t ad, audio_port_t port)
|
|
+{
|
|
+ /* Check port is in record mask */
|
|
+ int gain;
|
|
+
|
|
+ debug_msg("port 0x%08x recmask 0x%08x\n", port, recmask);
|
|
+
|
|
+ assert((port & recmask) != 0);
|
|
+
|
|
+ if (ioctl(audio_fd, SOUND_MIXER_WRITE_RECSRC, &port) < 0) {
|
|
+ perror("Unable to write record mask\n");
|
|
+ return;
|
|
+ }
|
|
+ iport = port;
|
|
+ gain = newpcm_audio_get_igain(ad);
|
|
+ newpcm_audio_loopback_config(gain);
|
|
+ UNUSED(ad);
|
|
+}
|
|
+
|
|
+audio_port_t
|
|
+newpcm_audio_iport_get(audio_desc_t ad)
|
|
+{
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+ return iport;
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_iport_count(audio_desc_t ad)
|
|
+{
|
|
+ UNUSED(ad);
|
|
+ return newpcm_count_ports(recmask);
|
|
+}
|
|
+
|
|
+const audio_port_details_t *
|
|
+newpcm_audio_iport_details(audio_desc_t ad, int idx)
|
|
+{
|
|
+ static audio_port_details_t ap;
|
|
+ int lgmask;
|
|
+
|
|
+ UNUSED(ad);
|
|
+
|
|
+ lgmask = newpcm_get_nth_port_mask(recmask, idx);
|
|
+ ap.port = 1 << lgmask;
|
|
+ sprintf(ap.name, "%s", port_names[lgmask]);
|
|
+
|
|
+ return ≈
|
|
+}
|
|
+
|
|
+void
|
|
+newpcm_audio_loopback(audio_desc_t ad, int gain)
|
|
+{
|
|
+ UNUSED(ad); assert(audio_fd > 0);
|
|
+ loop = gain;
|
|
+}
|
|
+
|
|
+static void
|
|
+newpcm_audio_loopback_config(int gain)
|
|
+{
|
|
+ int lgport, vol;
|
|
+
|
|
+ /* Find current input port id */
|
|
+ lgport = newpcm_get_nth_port_mask(iport, 0);
|
|
+
|
|
+ if (loop) {
|
|
+ vol = RAT_TO_DEVICE(gain) << 8 | RAT_TO_DEVICE(gain);
|
|
+ } else {
|
|
+ vol = 0;
|
|
+ }
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, MIXER_WRITE(lgport), &vol);
|
|
+}
|
|
+
|
|
+void
|
|
+newpcm_audio_wait_for(audio_desc_t ad, int delay_ms)
|
|
+{
|
|
+ if (!newpcm_audio_is_ready(ad)) {
|
|
+ usleep((unsigned int)delay_ms * 1000);
|
|
+ }
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_is_ready(audio_desc_t ad)
|
|
+{
|
|
+ int avail;
|
|
+
|
|
+ UNUSED(ad);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, FIONREAD, &avail);
|
|
+
|
|
+ return (avail >= sz.rec_size);
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_supports(audio_desc_t ad, audio_format *fmt)
|
|
+{
|
|
+ snd_capabilities s;
|
|
+
|
|
+ UNUSED(ad);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(audio_fd, AIOGCAP, &s);
|
|
+ if (!newpcm_error) {
|
|
+ if ((unsigned)fmt->sample_rate < s.rate_min || (unsigned)fmt->sample_rate > s.rate_max) return FALSE;
|
|
+ if (fmt->channels == 1) return TRUE; /* Always supports mono */
|
|
+ assert(fmt->channels == 2);
|
|
+ if (s.formats & AFMT_STEREO) return TRUE;
|
|
+ }
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_audio_query_devices()
|
|
+{
|
|
+ FILE *f;
|
|
+ char buf[128], *p;
|
|
+ int n, newpcm = FALSE;
|
|
+
|
|
+ f = fopen("/dev/sndstat", "r");
|
|
+ if (f) {
|
|
+ while (!feof(f) && ndev < NEWPCM_MAX_AUDIO_DEVICES) {
|
|
+ p = fgets(buf, 128, f);
|
|
+ n = sscanf(buf, "pcm%d: <%[A-z0-9 ]>", dev_ids + ndev, names[ndev]);
|
|
+ if (p && n == 2) {
|
|
+ debug_msg("dev (%d) name (%s)\n", dev_ids[ndev], names[ndev]);
|
|
+ ndev++;
|
|
+ } else if (strstr(buf, "newpcm")) {
|
|
+ newpcm = TRUE;
|
|
+ }
|
|
+ }
|
|
+ fclose(f);
|
|
+ }
|
|
+
|
|
+ if (newpcm == FALSE) {
|
|
+ ndev = 0; /* Should be using Luigi's interface */
|
|
+ }
|
|
+
|
|
+ return (ndev);
|
|
+}
|
|
+
|
|
+int
|
|
+newpcm_get_device_count()
|
|
+{
|
|
+ return ndev;
|
|
+}
|
|
+
|
|
+char *
|
|
+newpcm_get_device_name(audio_desc_t idx)
|
|
+{
|
|
+ if (idx >=0 && idx < ndev) {
|
|
+ return names[idx];
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/* Functions to save and restore recording source and mixer levels */
|
|
+
|
|
+static int saved_rec_mask, saved_gain_values[SOUND_MIXER_NRDEVICES];
|
|
+
|
|
+static void
|
|
+newpcm_mixer_save(int fd)
|
|
+{
|
|
+ int devmask, i;
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_READ_RECSRC, &saved_rec_mask);
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_READ_DEVMASK, &devmask);
|
|
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
|
|
+ if ((1 << i) & devmask) {
|
|
+ NEWPCM_AUDIO_IOCTL(fd, MIXER_READ(i), &saved_gain_values[i]);
|
|
+ } else {
|
|
+ saved_gain_values[i] = 0;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+newpcm_mixer_restore(int fd)
|
|
+{
|
|
+ int devmask, i;
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_WRITE_RECSRC, &saved_rec_mask);
|
|
+
|
|
+ NEWPCM_AUDIO_IOCTL(fd, SOUND_MIXER_READ_DEVMASK, &devmask);
|
|
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
|
|
+ if ((1 << i) & devmask) {
|
|
+ NEWPCM_AUDIO_IOCTL(fd, MIXER_WRITE(i), &saved_gain_values[i]);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff -uPr rat/auddev_newpcm.h /home/oh/src/rat-newpcm/rat/auddev_newpcm.h
|
|
--- rat/auddev_newpcm.h Thu Jan 1 01:00:00 1970
|
|
+++ /home/oh/src/rat-newpcm/rat/auddev_newpcm.h Sat Sep 16 20:33:54 2000
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ * FILE: auddev_newpcm.h
|
|
+ * PROGRAM: RAT
|
|
+ * AUTHOR: Orion Hodson
|
|
+ *
|
|
+ * Copyright (c) 1998-2000 University College London
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * $Id: auddev_newpcm.h,v 1.1 2000/09/16 17:43:24 ucacoxh Exp $
|
|
+ */
|
|
+
|
|
+#ifndef _AUDDEV_NEWPCM_H_
|
|
+#define _AUDDEV_NEWPCM_H_
|
|
+
|
|
+int newpcm_audio_open (audio_desc_t ad, audio_format* ifmt, audio_format *ofmt);
|
|
+void newpcm_audio_close (audio_desc_t ad);
|
|
+void newpcm_audio_drain (audio_desc_t ad);
|
|
+int newpcm_audio_duplex (audio_desc_t ad);
|
|
+
|
|
+void newpcm_audio_set_igain (audio_desc_t ad, int gain);
|
|
+int newpcm_audio_get_igain (audio_desc_t ad);
|
|
+void newpcm_audio_set_ogain (audio_desc_t ad, int vol);
|
|
+int newpcm_audio_get_ogain (audio_desc_t ad);
|
|
+void newpcm_audio_loopback (audio_desc_t ad, int gain);
|
|
+
|
|
+int newpcm_audio_read (audio_desc_t ad, u_char *buf, int buf_len);
|
|
+int newpcm_audio_write (audio_desc_t ad, u_char *buf, int buf_len);
|
|
+void newpcm_audio_non_block (audio_desc_t ad);
|
|
+void newpcm_audio_block (audio_desc_t ad);
|
|
+
|
|
+void newpcm_audio_oport_set (audio_desc_t ad, audio_port_t port);
|
|
+audio_port_t newpcm_audio_oport_get (audio_desc_t ad);
|
|
+int newpcm_audio_oport_count (audio_desc_t ad);
|
|
+const audio_port_details_t*
|
|
+ newpcm_audio_oport_details (audio_desc_t ad, int idx);
|
|
+
|
|
+void newpcm_audio_iport_set (audio_desc_t ad, audio_port_t port);
|
|
+audio_port_t newpcm_audio_iport_get (audio_desc_t ad);
|
|
+int newpcm_audio_iport_count (audio_desc_t ad);
|
|
+const audio_port_details_t*
|
|
+ newpcm_audio_iport_details (audio_desc_t ad, int idx);
|
|
+
|
|
+int newpcm_audio_is_ready (audio_desc_t ad);
|
|
+void newpcm_audio_wait_for (audio_desc_t ad, int delay_ms);
|
|
+int newpcm_audio_supports (audio_desc_t ad, audio_format *f);
|
|
+
|
|
+/* Functions to get names of devices */
|
|
+int newpcm_audio_query_devices (void);
|
|
+int newpcm_get_device_count (void);
|
|
+char *newpcm_get_device_name (audio_desc_t ad);
|
|
+
|
|
+#endif /* _AUDDEV_NEWPCM_H_ */
|
|
diff -uPr rat/config.h.in /home/oh/src/rat-newpcm/rat/config.h.in
|
|
--- rat/config.h.in Fri Sep 8 21:03:01 2000
|
|
+++ /home/oh/src/rat-newpcm/rat/config.h.in Sat Sep 16 20:34:04 2000
|
|
@@ -27,7 +27,7 @@
|
|
/*
|
|
* Define this if your C library doesn't have usleep.
|
|
*
|
|
- * $Id: config.h.in,v 1.18 2000/03/03 15:05:32 ucaccsp Exp $
|
|
+ * $Id: config.h.in,v 1.19 2000/09/16 17:43:24 ucacoxh Exp $
|
|
*/
|
|
#undef NEED_USLEEP
|
|
#undef NEED_SNPRINTF
|
|
@@ -68,12 +68,15 @@
|
|
#undef HAVE_SGI_AUDIO
|
|
#undef HAVE_PCA_AUDIO
|
|
#undef HAVE_LUIGI_AUDIO
|
|
+#undef HAVE_NEWPCM_AUDIO
|
|
#undef HAVE_OSS_AUDIO
|
|
#undef HAVE_HP_AUDIO
|
|
#undef HAVE_NETBSD_AUDIO
|
|
#undef HAVE_OSPREY_AUDIO
|
|
#undef HAVE_MACHINE_PCAUDIOIO_H
|
|
#undef HAVE_ALSA_AUDIO
|
|
+
|
|
+#undef HAVE_IPv6
|
|
|
|
/* GSM related */
|
|
#undef SASR
|
|
diff -uPr common/configure.in /home/oh/src/rat-newpcm/common/configure.in
|
|
--- common/configure.in Sat Sep 9 05:02:27 2000
|
|
+++ /home/oh/src/rat-newpcm/common/configure.in Thu Sep 21 10:15:12 2000
|
|
@@ -179,7 +179,7 @@
|
|
AC_DEFINE(HAVE_IPv6)
|
|
case "$host_os" in
|
|
# FreeBSD Kame uses seperate libinet6
|
|
- freebsd*)
|
|
+ freebsd[23]*)
|
|
LIBS="$LIBS -L/usr/local/v6/lib -linet6"
|
|
;;
|
|
*) ;;
|
|
@@ -216,6 +216,7 @@
|
|
#ifdef HAVE_NETINET6_IN6_H
|
|
#include <netinet6/in6.h>
|
|
#else
|
|
+ #include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#endif /* HAVE_NETINET_IN6_H */
|
|
],[
|