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 + +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 #else + #include #include #endif /* HAVE_NETINET_IN6_H */ ],[