Index: /rat/trunk/auddev_oss.c
===================================================================
--- /rat/trunk/auddev_oss.c (revision 2103)
+++ /rat/trunk/auddev_oss.c (revision 2107)
@@ -52,11 +52,8 @@
 #include "memory.h"
 #include "audio_types.h"
+#include "audio_fmt.h"
 #include "auddev_oss.h"
 
-int	can_read  = FALSE;
-int	can_write = FALSE;
 int	iport     = AUDIO_MICROPHONE;
-int	is_duplex = FALSE;
-int	done_test = FALSE;
 int	bytes_per_block;
 
@@ -69,5 +66,5 @@
 
 static char the_dev[] = "/dev/audioX";
-static int audio_fd = -1;
+static int audio_fd[OSS_MAX_DEVICES];
 
 audio_format format;
@@ -76,10 +73,22 @@
 #define device_to_bat(x)  ((x) * MAX_AMP / 100)
 
-static int 
-oss_audio_open_rw(audio_desc_t ad, char rw)
-{
-	int  mode     = AFMT_S16_LE;			/* 16bit linear, little-endian */
-	int  stereo   = format.channels - 1;	/* 0=mono, 1=stereo            */
-	int  speed    = format.sample_rate;
+static int
+deve2oss(deve_e encoding)
+{
+        switch(encoding) {
+        case DEV_PCMU: return AFMT_MU_LAW;
+        case DEV_S8:   return AFMT_S8;
+        case DEV_S16:  return AFMT_S16_LE;
+        }
+        abort();
+}
+
+
+/* Try to open the audio device.              */
+/* Return TRUE if successful FALSE otherwise. */
+int
+oss_audio_open(audio_desc_t ad, audio_format *ifmt, audio_format *ofmt)
+{
+	int  mode, stereo, speed;
 	int  volume   = (100<<8)|100;
 	int  frag     = 0x7fff0000; 			/* unlimited number of fragments */
@@ -87,86 +96,4 @@
 	char buffer[128];				/* sigh. */
 
-	/* Calculate the size of the fragments we want... 20ms worth of audio data... */
-	bytes_per_block = DEVICE_BUF_UNIT * (format.sample_rate / 8000) * (format.bits_per_sample / 8);
-	/* Round to the nearest legal frag size (next power of two lower...) */
-	frag |= (int) (log(bytes_per_block)/log(2));
-	debug_msg("frag=%x bytes_per_block=%d\n", frag, bytes_per_block);
-
-	switch (rw) {
-	case O_RDONLY: 
-		can_read  = TRUE;
-		can_write = FALSE;
-		break;
-	case O_WRONLY: 
-		can_read  = FALSE;
-		can_write = TRUE;
-		break;
-	case O_RDWR  : 
-		can_read  = TRUE;
-		can_write = TRUE;
-		break;
-	default : 
-		printf("Unknown r/w mode!\n");
-		abort();
-	}
-
-	audio_fd = open(the_dev, rw);
-	if (audio_fd > 0) {
-		/* Note: The order in which the device is set up is important! Don't */
-		/*       reorder this code unless you really know what you're doing! */
-		if ((rw == O_RDWR) && ioctl(audio_fd, SNDCTL_DSP_SETDUPLEX, 0) == -1) {
-			printf("ERROR: Cannot enable full-duplex mode!\n");
-			abort();
-		}
-		if ((ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)) {
-			printf("ERROR: Cannot set the fragement size\n");
-			abort();
-		}
-		if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &mode) == -1) || (mode != AFMT_S16_LE)) { 
-			printf("ERROR: Audio device doesn't support 16bit linear format!\n");
-			abort();
-		}
-		if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == -1) || (stereo != (format.channels - 1))) {
-			printf("ERROR: Audio device doesn't support %d channels!\n", format.channels);
-			abort();
-		}
-		if ((ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed) == -1) || (speed != format.sample_rate)) {
-			printf("ERROR: Audio device doesn't support %d sampling rate!\n", format.sample_rate);
-			abort();
-		}
-		/* Set global gain/volume to maximum values. This may fail on */
-		/* some cards, but shouldn't cause any harm when it does..... */ 
-		ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &volume);
-		ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_RECLEV), &volume);
-		/* Select microphone input. We can't select output source...  */
-		oss_audio_set_iport(audio_fd, iport);
-		/* Turn off loopback from input to output... This only works  */
-		/* on a few cards, but shouldn't cause problems on the others */
-		ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_IMIX), &reclb);
-		/* Device driver bug: we must read some data before the ioctl */
-		/* to tell us how much data is waiting works....              */
-		read(audio_fd, buffer, 128);	
-		/* Okay, now we're done...                                    */
-                UNUSED(ad);
-		return audio_fd;
-	} else {
-		close(audio_fd);
-		can_read  = FALSE;
-		can_write = FALSE;
-		return -1;
-	}
-}
-
-/* Try to open the audio device.              */
-/* Return TRUE if successful FALSE otherwise. */
-int
-oss_audio_open(audio_desc_t ad, audio_format *fmt)
-{
-        int mode;
-
-        UNUSED(ad); 
-
-        memcpy(&format, fmt, sizeof(audio_format));
-
         if (ad <0 || ad>OSS_MAX_DEVICES) {
                 debug_msg("Invalid audio descriptor (%d)", ad);
@@ -176,13 +103,69 @@
         sprintf(the_dev, "/dev/audio%d", ad);
 
-	if (oss_audio_duplex(-1)) {
-                mode = O_RDWR;
-        } else {
-                perror("Half duplex cards not supported\n");
-                exit(-1);
-                mode = O_WRONLY;
-	}
-        audio_fd = oss_audio_open_rw(ad, mode);
-        return (audio_fd > 0) ? TRUE : FALSE;
+	audio_fd[ad] = open(the_dev, O_RDWR | O_NDELAY);
+	if (audio_fd[ad] > 0) {
+		/* Note: The order in which the device is set up is important! Don't */
+		/*       reorder this code unless you really know what you're doing! */
+		if (ioctl(audio_fd[ad], SNDCTL_DSP_SETDUPLEX, 0) == -1) {
+			fprintf(stderr, "ERROR: Cannot enable full-duplex mode!\n");
+                        return FALSE;
+		}
+
+                mode = deve2oss(ifmt->encoding);
+                
+		if ((ioctl(audio_fd[ad], SNDCTL_DSP_SETFMT, &mode) == -1)) {
+                        if (ifmt->encoding == DEV_S16) {
+                                audio_format_change_encoding(ifmt, DEV_PCMU);
+                                audio_format_change_encoding(ofmt, DEV_PCMU);
+                                if ((ioctl(audio_fd[ad], SNDCTL_DSP_SETFMT, &mode) == -1)) {
+                                        oss_audio_close(ad);
+                                        return FALSE;
+                                }
+                                debug_msg("Using mu-law\n");
+                        }
+		}
+                /* 20 ms blocksize - only modulates read sizes */
+                bytes_per_block = 20 * (ifmt->sample_rate / 8000) * (ifmt->bits_per_sample / 8);
+                /* Round to the nearest legal frag size (next power of two lower...) */
+                frag |= (int) (log(bytes_per_block)/log(2));
+                debug_msg("frag=%x bytes_per_block=%d\n", frag, bytes_per_block);
+		if ((ioctl(audio_fd[ad], SNDCTL_DSP_SETFRAGMENT, &frag) == -1)) {
+			fprintf(stderr, "ERROR: Cannot set the fragement size\n");
+		}
+
+                stereo = ifmt->channels - 1; 
+                assert(stereo == 0 || stereo == 1);
+		if ((ioctl(audio_fd[ad], SNDCTL_DSP_STEREO, &stereo) == -1) || (stereo != (ifmt->channels - 1))) {
+			printf("ERROR: Audio device doesn't support %d channels!\n", ifmt->channels);
+                        oss_audio_close(ad);
+                        return FALSE;
+		}
+
+                speed = ifmt->sample_rate;
+		if ((ioctl(audio_fd[ad], SNDCTL_DSP_SPEED, &speed) == -1) || (speed != ifmt->sample_rate)) {
+			printf("ERROR: Audio device doesn't support %d sampling rate!\n", ifmt->sample_rate);
+                        oss_audio_close(ad);
+                        return FALSE;
+		}
+
+		/* Set global gain/volume to maximum values. This may fail on */
+		/* some cards, but shouldn't cause any harm when it does..... */ 
+		ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_VOLUME), &volume);
+		ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_RECLEV), &volume);
+		/* Select microphone input. We can't select output source...  */
+		oss_audio_set_iport(audio_fd[ad], iport);
+		/* Turn off loopback from input to output... This only works  */
+		/* on a few cards, but shouldn't cause problems on the others */
+		ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_IMIX), &reclb);
+		/* Device driver bug: we must read some data before the ioctl */
+		/* to tell us how much data is waiting works....              */
+		read(audio_fd[ad], buffer, 128);	
+		/* Okay, now we're done...                                    */
+                UNUSED(ad);
+		return audio_fd[ad];
+	} else {
+		oss_audio_close(ad);
+		return -1;
+	}
 }
 
@@ -191,8 +174,8 @@
 oss_audio_close(audio_desc_t ad)
 {
-        UNUSED(ad); assert(audio_fd > 0);
-	oss_audirain(audio_fd);
-	close(audio_fd);
-        audio_fd = -1;
+        assert(audio_fd[ad] > 0);
+	oss_audio_drain(ad);
+	close(audio_fd[ad]);
+        audio_fd[ad] = -1;
 }
 
@@ -201,9 +184,9 @@
 oss_audio_drain(audio_desc_t ad)
 {
-        sample buf[160];
-
-        UNUSED(ad); assert(audio_fd > 0);
-
-        while(oss_audio_read(audio_fd, buf, 160) == 160);
+        u_char buf[160];
+
+        assert(audio_fd[ad] > 0);
+
+        while(oss_audio_read(audio_fd[ad], buf, 160) == 160);
 }
 
@@ -211,41 +194,7 @@
 oss_audio_duplex(audio_desc_t ad)
 {
-	/* Find out if the device supports full-duplex operation. The device must
-	 * be open to do this, so if we're passed -1 as a file-descriptor we open
-	 * the device, do the ioctl, and then close it again...
-	 */
-	int info;
-	int did_open = FALSE;
-
-        UNUSED(ad); 
-
-	if (done_test) return is_duplex;
-
-	if (ad == -1) {
-		audio_fd = open(the_dev, O_RDWR | O_NDELAY);
-		did_open = TRUE;
-	}
-
-	if (ioctl(audio_fd, SNDCTL_DSP_SETDUPLEX, 0) == -1) {
-		if (did_open) close(audio_fd);
-		is_duplex = FALSE;
-		done_test = TRUE;
-		return FALSE;
-	}
-	if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &info) == -1) {
-		if (did_open) close(audio_fd);
-		is_duplex = FALSE;
-		done_test = TRUE;
-		return FALSE;
-	}
-
-	if (did_open) {
-		close(audio_fd);
-	}
-
-	is_duplex = info & DSP_CAP_DUPLEX;
-	done_test = TRUE;
-	debug_msg("%s duplex audio\n", is_duplex?"Full":"Half");
-	return is_duplex;
+        /* We don't open device if not full duplex. */
+        UNUSED(ad);
+        return TRUE;
 }
 
@@ -256,19 +205,19 @@
 	int volume = bat_to_device(gain) << 8 | bat_to_device(gain);
 
-        UNUSED(ad); assert(audio_fd > 0);
+        assert(audio_fd[ad] > 0);
 
 	switch (iport) {
 	case AUDIO_MICROPHONE : 
-		if (ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_MIC), &volume) == -1) {
+		if (ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_MIC), &volume) == -1) {
 			perror("Setting gain");
 		}
 		return;
 	case AUDIO_LINE_IN : 
-		if (ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_LINE), &volume) == -1) {
+		if (ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_LINE), &volume) == -1) {
 			perror("Setting gain");
 		}
 		return;
 	case AUDIO_CD:
-		if (ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_CD), &volume) < 0) {
+		if (ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_CD), &volume) < 0) {
 			perror("Setting gain");
 		}
@@ -284,19 +233,19 @@
 	int volume;
 
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 
 	switch (iport) {
 	case AUDIO_MICROPHONE : 
-		if (ioctl(audio_fd, MIXER_READ(SOUND_MIXER_MIC), &volume) == -1) {
+		if (ioctl(audio_fd[ad], MIXER_READ(SOUND_MIXER_MIC), &volume) == -1) {
 			perror("Getting gain");
 		}
 		break;
 	case AUDIO_LINE_IN : 
-		if (ioctl(audio_fd, MIXER_READ(SOUND_MIXER_LINE), &volume) == -1) {
+		if (ioctl(audio_fd[ad], MIXER_READ(SOUND_MIXER_LINE), &volume) == -1) {
 			perror("Getting gain");
 		}
 		break;
 	case AUDIO_CD:
-		if (ioctl(audio_fd, MIXER_READ(SOUND_MIXER_CD), &volume) < 0) {
+		if (ioctl(audio_fd[ad], MIXER_READ(SOUND_MIXER_CD), &volume) < 0) {
 			perror("Getting gain");
 		}
@@ -314,8 +263,8 @@
 	int volume;
 
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 
 	volume = vol << 8 | vol;
-	if (ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) {
+	if (ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1) {
 		perror("Setting volume");
 	}
@@ -325,8 +274,8 @@
 oss_audio_loopback(audio_desc_t ad, int gain)
 {
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 
         gain = gain << 8 | gain;
-        if (ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_IMIX), &gain) == -1) {
+        if (ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_IMIX), &gain) == -1) {
                 perror("loopback");
         }
@@ -338,7 +287,7 @@
 	int volume;
 
-        UNUSED(ad); assert(audio_fd > 0);
-
-	if (ioctl(audio_fd, MIXER_READ(SOUND_MIXER_PCM), &volume) == -1) {
+        UNUSED(ad); assert(audio_fd[ad] > 0);
+
+	if (ioctl(audio_fd[ad], MIXER_READ(SOUND_MIXER_PCM), &volume) == -1) {
 		perror("Getting volume");
 	}
@@ -347,77 +296,44 @@
 
 int
-oss_audio_read(audio_desc_t ad, sample *buf, int samples)
-{
-        UNUSED(ad); assert(audio_fd > 0);
-
-	if (can_read) {
-		int            len, read_len;
-		audio_buf_info info;
-
-		/* Figure out how many bytes we can read before blocking... */
-		ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info);
-		if (info.bytes > (int) (samples * BYTES_PER_SAMPLE)) {
-			read_len = (samples * BYTES_PER_SAMPLE);
-		} else {
-			read_len = info.bytes;
-		}
-		if ((len = read(audio_fd, (char *)buf, read_len)) < 0) {
-			perror("audio_read");
+oss_audio_read(audio_desc_t ad, u_char *buf, int read_bytes)
+{
+        int read_len;
+        audio_buf_info info;
+
+        assert(audio_fd[ad] > 0);        
+
+        /* Figure out how many bytes we can read before blocking... */
+        ioctl(audio_fd[ad], SNDCTL_DSP_GETISPACE, &info);
+
+        read_len = min(info.bytes, read_bytes);
+        if ((read_len = read(audio_fd[ad], (char *)buf, read_len)) < 0) {
+                perror("audio_read");
 			return 0;
-		}
-		return len / BYTES_PER_SAMPLE;
-	} else {
-		/* The value returned should indicate the time (in audio samples) */
-		/* since the last time read was called.                           */
-		int                   i;
-		int                   diff;
-		static struct timeval last_time;
-		static struct timeval curr_time;
-		static int            first_time = 0;
-
-		if (first_time == 0) {
-			gettimeofday(&last_time, NULL);
-			first_time = 1;
-		}
-		gettimeofday(&curr_time, NULL);
-		diff = (((curr_time.tv_sec - last_time.tv_sec) * 1e6) + (curr_time.tv_usec - last_time.tv_usec)) / 125;
-		if (diff > samples) diff = samples;
-		if (diff <      80) diff = 80;
-		xmemchk();
-		for (i=0; i<diff; i++) {
-			buf[i] = L16_AUDIO_ZERO;
-		}
-		xmemchk();
-		last_time = curr_time;
-		return diff;
-	}
-}
-
-int
-oss_audio_write(audio_desc_t ad, sample *buf, int samples)
-{
-        UNUSED(ad); assert(audio_fd > 0);
-	
-        if (can_write) {
-		int    		 done, len;
-		char  		*p;
-
-		p   = (char *) buf;
-		len = samples * BYTES_PER_SAMPLE;
-		while (1) {
-			if ((done = write(audio_fd, p, len)) = len) {
-				break;
-			}
-			if (errno != EINTR) {
+        }
+        return read_len;
+}
+
+int
+oss_audio_write(audio_desc_t ad, u_char *buf, int write_bytes)
+{
+        int    		 done, len;
+        char  		*p;
+
+        assert(audio_fd[ad] > 0);
+        
+        p   = (char *) buf;
+        len = write_bytes;
+        while (1) {
+                if ((done = write(audio_fd[ad], p, len)) == len) {
+                        break;
+                }
+                if (errno != EINTR) {
 				perror("Error writing device");
-				return samples - ((len - done) / BYTES_PER_SAMPLE);
-			}
-			len -= done;
-			p   += done;
-		}
-		return samples;
-	} else {
-		return samples;
-	}
+				return write_bytes - (len - done);
+                }
+                len -= done;
+                p   += done;
+        }
+        return write_bytes;
 }
 
@@ -428,7 +344,7 @@
 	int  on = 1;
 
-        UNUSED(ad); assert(audio_fd > 0);
-
-	if (ioctl(audio_fd, FIONBIO, (char *)&on) < 0) {
+        UNUSED(ad); assert(audio_fd[ad] > 0);
+
+	if (ioctl(audio_fd[ad], FIONBIO, (char *)&on) < 0) {
 		debug_msg("Failed to set non-blocking mode on audio device!\n");
 	}
@@ -441,7 +357,7 @@
 	int  on = 0;
 
-        UNUSED(ad); assert(audio_fd > 0);
-
-	if (ioctl(audio_fd, FIONBIO, (char *)&on) < 0) {
+        UNUSED(ad); assert(audio_fd[ad] > 0);
+
+	if (ioctl(audio_fd[ad], FIONBIO, (char *)&on) < 0) {
 		debug_msg("Failed to set blocking mode on audio device!\n");
 	}
@@ -452,5 +368,5 @@
 {
 	/* There appears to be no-way to select this with OSS... */
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 	UNUSED(port);
 	return;
@@ -461,5 +377,5 @@
 {
 	/* There appears to be no-way to select this with OSS... */
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 	return AUDIO_HEADPHONE;
 }
@@ -469,5 +385,5 @@
 {
 	/* There appears to be no-way to select this with OSS... */
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 	return AUDIO_HEADPHONE;
 }
@@ -480,7 +396,7 @@
 	int gain;
 
-        UNUSED(ad); assert(audio_fd > 0);
-
-	if (ioctl(audio_fd, MIXER_READ(SOUND_MIXER_RECMASK), &recmask) == -1) {
+        UNUSED(ad); assert(audio_fd[ad] > 0);
+
+	if (ioctl(audio_fd[ad], MIXER_READ(SOUND_MIXER_RECMASK), &recmask) == -1) {
 		debug_msg("WARNING: Unable to read recording mask!\n");
 		return;
@@ -490,11 +406,11 @@
 		if (recmask & SOUND_MASK_MIC) {
 			recsrc = SOUND_MASK_MIC;
-			if ((ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_MIC)) {
+			if ((ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_MIC)) {
 				debug_msg("WARNING: Unable to select recording source!\n");
 				return;
 			}
-			gain = oss_audio_get_gain(audio_fd);
+			gain = oss_audio_get_gain(audio_fd[ad]);
 			iport = port;
-			oss_audio_set_gain(audio_fd, gain);
+			oss_audio_set_gain(audio_fd[ad], gain);
 		} else {
 			debug_msg("Audio device doesn't support recording from microphone\n");
@@ -504,11 +420,11 @@
 		if (recmask & SOUND_MASK_LINE) {
 			recsrc = SOUND_MASK_LINE;
-			if ((ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_LINE)){
+			if ((ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_LINE)){
 				debug_msg("WARNING: Unable to select recording source!\n");
 				return;
 			}
-			gain = oss_audio_get_gain(audio_fd);
+			gain = oss_audio_get_gain(audio_fd[ad]);
 			iport = port;
-			oss_audio_set_gain(audio_fd, gain);
+			oss_audio_set_gain(audio_fd[ad], gain);
 		} else {
 			debug_msg("Audio device doesn't support recording from line-input\n");
@@ -518,11 +434,11 @@
 		if (recmask & SOUND_MASK_CD) {
 			recsrc = SOUND_MASK_CD;
-			if ((ioctl(audio_fd, MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_LINE)){
+			if ((ioctl(audio_fd[ad], MIXER_WRITE(SOUND_MIXER_RECSRC), &recsrc) == -1) && !(recsrc & SOUND_MASK_LINE)){
 				debug_msg("WARNING: Unable to select recording source!\n");
 				return;
 			}
-			gain = oss_audio_get_gain(audio_fd);
+			gain = oss_audio_get_gain(audio_fd[ad]);
 			iport = port;
-			oss_audio_set_gain(audio_fd, gain);
+			oss_audio_set_gain(audio_fd[ad], gain);
 		} else {
 			debug_msg("Audio device doesn't support recording from CD\n");
@@ -539,5 +455,5 @@
 oss_audio_get_iport(audio_desc_t ad)
 {
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 	return iport;
 }
@@ -546,15 +462,15 @@
 oss_audio_next_iport(audio_desc_t ad)
 {
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
 
         switch (iport) {
 	case AUDIO_MICROPHONE : 
-		oss_audio_set_iport(audio_fd, AUDIO_LINE_IN);
+		oss_audio_set_iport(audio_fd[ad], AUDIO_LINE_IN);
 		break;
 	case AUDIO_LINE_IN : 
-		oss_audio_set_iport(audio_fd, AUDIO_CD);
+		oss_audio_set_iport(audio_fd[ad], AUDIO_CD);
 		break;
 	case AUDIO_CD : 
-		oss_audio_set_iport(audio_fd, AUDIO_MICROPHONE);
+		oss_audio_set_iport(audio_fd[ad], AUDIO_MICROPHONE);
 		break;
 	default : 
@@ -565,25 +481,4 @@
 }
 
-int
-oss_audio_get_bytes_per_block(audio_desc_t ad)
-{
-        UNUSED(ad); assert(audio_fd > 0);
-	return bytes_per_block;
-}
-
-int
-oss_audio_get_channels(audio_desc_t ad)
-{
-        UNUSED(ad); assert(audio_fd > 0);
-	return format.channels;
-}
-
-int
-oss_audio_get_freq(audio_desc_t ad)
-{
-        UNUSED(ad); assert(audio_fd > 0);
-	return format.sample_rate;
-}
-
 static int
 oss_audio_select(audio_desc_t ad, int delay_us)
@@ -592,5 +487,5 @@
         struct timeval tv;
 
-        UNUSED(ad); assert(audio_fd > 0);
+        UNUSED(ad); assert(audio_fd[ad] > 0);
         
         tv.tv_sec = 0;
@@ -598,9 +493,9 @@
 
         FD_ZERO(&rfds);
-        FD_SET(audio_fd, &rfds);
-
-        select(audio_fd+1, &rfds, NULL, NULL, &tv);
-
-        return FD_ISSET(audio_fd, &rfds);
+        FD_SET(audio_fd[ad], &rfds);
+
+        select(audio_fd[ad]+1, &rfds, NULL, NULL, &tv);
+
+        return FD_ISSET(audio_fd[ad], &rfds);
 }
 
Index: /rat/trunk/auddev_oss.h
===================================================================
--- /rat/trunk/auddev_oss.h (revision 2105)
+++ /rat/trunk/auddev_oss.h (revision 2107)
@@ -44,5 +44,5 @@
 #define _AUDDEV_OSS_H_
 
-int  oss_audio_open       (audio_desc_t ad, audio_format* format);
+int  oss_audio_open       (audio_desc_t ad, audio_format* ifmt, audio_format *ofmt);
 void oss_audio_close      (audio_desc_t ad);
 void oss_audio_drain      (audio_desc_t ad);
@@ -53,6 +53,6 @@
 int  oss_audio_get_volume (audio_desc_t ad);
 void oss_audio_loopback   (audio_desc_t ad, int gain);
-int  oss_audio_read       (audio_desc_t ad, sample *buf, int samples);
-int  oss_audio_write      (audio_desc_t ad, sample *buf, int samples);
+int  oss_audio_read       (audio_desc_t ad, u_char *buf, int buf_bytes);
+int  oss_audio_write      (audio_desc_t ad, u_char *buf, int buf_bytes);
 void oss_audio_non_block  (audio_desc_t ad);
 void oss_audio_block      (audio_desc_t ad);
