Update of /cvsroot/alsa/alsa-oss/alsa
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12689/alsa

Modified Files:
        Makefile.am alsa-oss.c aoss.in 
Log Message:
- separated libaoss to libaoss (LD_PRELOAD wrapper) and libalsatoss
  (user space emulation)
- some fixes in oss-redir library
- note that code is not tested at all, so I'm 100% that it will fail :-(


Index: Makefile.am
===================================================================
RCS file: /cvsroot/alsa/alsa-oss/alsa/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile.am 9 Feb 2004 12:36:39 -0000       1.1
+++ Makefile.am 10 Feb 2004 13:39:55 -0000      1.2
@@ -1,10 +1,13 @@
-lib_LTLIBRARIES = libaoss.la
+lib_LTLIBRARIES = libalsatoss.la libaoss.la
 bin_SCRIPTS = aoss
 man_MANS = aoss.1
 EXTRA_DIST = aoss.1
 
 libaoss_la_SOURCES = alsa-oss.c
-libaoss_la_LIBADD = -ldl -lasound
+libaoss_la_LIBADD = -ldl -lalsatoss
+
+libalsatoss_la_SOURCES = pcm.c mixer.c
+libalsatoss_la_LIBADD = -lasound
 
 clean:
        rm -f aoss

Index: alsa-oss.c
===================================================================
RCS file: /cvsroot/alsa/alsa-oss/alsa/alsa-oss.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- alsa-oss.c  9 Feb 2004 12:36:39 -0000       1.1
+++ alsa-oss.c  10 Feb 2004 13:39:55 -0000      1.2
@@ -1,6 +1,7 @@
 /*
  *  OSS -> ALSA compatibility layer
- *  Copyright (c) by Abramo Bagnara <[EMAIL PROTECTED]>
+ *  Copyright (c) by Abramo Bagnara <[EMAIL PROTECTED]>,
+ *                  Jaroslav Kysela <[EMAIL PROTECTED]>
  *
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -38,31 +39,7 @@
 #include <linux/soundcard.h>
 #include <alsa/asoundlib.h>
 
-snd_pcm_uframes_t _snd_pcm_boundary(snd_pcm_t *pcm);
-snd_pcm_uframes_t _snd_pcm_mmap_hw_ptr(snd_pcm_t *pcm);
-
-static int debug = 0;
-static snd_output_t *debug_out = NULL;
-
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
-#define NEW_MACRO_VARARGS
-#endif
-
-#if 1
-#define DEBUG_POLL
-#define DEBUG_SELECT
-#ifdef NEW_MACRO_VARARGS
-#define DEBUG(...) do { if (debug) fprintf(stderr, __VA_ARGS__); } while (0)
-#else /* !NEW_MACRO_VARARGS */
-#define DEBUG(args...) do { if (debug) fprintf(stderr, ##args); } while (0)
-#endif
-#else
-#ifdef NEW_MACRO_VARARGS
-#define DEBUG(...)
-#else /* !NEW_MACRO_VARARGS */
-#define DEBUG(args...)
-#endif
-#endif
+#include "alsa-oss-emul.h"
 
 int (*_select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct 
timeval *timeout);
 int (*_poll)(struct pollfd *ufds, unsigned int nfds, int timeout);
@@ -76,64 +53,20 @@
 int (*_munmap)(void* addr, size_t len);
 
 typedef struct ops {
-       int (*open)(const char *file, int oflag, ...);
        int (*close)(int fd);
        ssize_t (*write)(int fd, const void *buf, size_t n);
        ssize_t (*read)(int fd, void *buf, size_t n);
        int (*ioctl)(int fd, unsigned long request, ...);
        int (*fcntl)(int fd, int cmd, ...);
        void *(*mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t 
offset);
-       int (*munmap)(int fd, void* addr, size_t len);
+       int (*munmap)(void* addr, size_t len);
 } ops_t;
 
-
-typedef struct {
-       snd_pcm_t *pcm;
-       size_t frame_bytes;
-       struct {
-               snd_pcm_uframes_t period_size;
-               snd_pcm_uframes_t buffer_size;
-               snd_pcm_uframes_t boundary;
-               snd_pcm_uframes_t old_hw_ptr;
-               size_t mmap_buffer_bytes;
-               size_t mmap_period_bytes;
-       } alsa;
-       struct {
-               snd_pcm_uframes_t period_size;
-               unsigned int periods;
-               snd_pcm_uframes_t buffer_size;
-               size_t bytes;
-       } oss;
-       unsigned int stopped:1;
-       void *mmap_buffer;
-       size_t mmap_bytes;
-       snd_pcm_channel_area_t *mmap_areas;
-       snd_pcm_uframes_t mmap_advance;
-} oss_dsp_stream_t;
-
-typedef struct {
-       unsigned int channels;
-       unsigned int rate;
-       unsigned int oss_format;
-       snd_pcm_format_t format;
-       unsigned int fragshift;
-       unsigned int maxfrags;
-       unsigned int subdivision;
-       oss_dsp_stream_t streams[2];
-} oss_dsp_t;
-
-
-typedef struct {
-       snd_mixer_t *mix;
-       unsigned int modify_counter;
-       snd_mixer_elem_t *elems[SOUND_MIXER_NRDEVICES];
-} oss_mixer_t;
-
 typedef enum {
        FD_OSS_DSP,
        FD_OSS_MIXER,
        FD_CLASSES,
-} fd_class_t;
+} fd_class_t;                                                            
 
 static ops_t ops[FD_CLASSES];
 
@@ -145,1223 +78,39 @@
 } fd_t;
 
 static int open_max;
+static int poll_fds_add = 0;
 static fd_t **fds;
 
-#define RETRY open_max
-#define OSS_MAJOR 14
-#define OSS_DEVICE_MIXER 0
-#define OSS_DEVICE_SEQUENCER 1
-#define OSS_DEVICE_MIDI 2
-#define OSS_DEVICE_DSP 3
-#define OSS_DEVICE_AUDIO 4
-#define OSS_DEVICE_DSPW 5
-#define OSS_DEVICE_SNDSTAT 6
-#define OSS_DEVICE_MUSIC 8
-#define OSS_DEVICE_DMMIDI 9
-#define OSS_DEVICE_DMFM 10
-#define OSS_DEVICE_AMIXER 11
-#define OSS_DEVICE_ADSP 12
-#define OSS_DEVICE_AMIDI 13
-#define OSS_DEVICE_ADMMIDI 14
-
-static unsigned int ld2(u_int32_t v)
-{
-       unsigned r = 0;
-
-       if (v >= 0x10000) {
-               v >>= 16;
-               r += 16;
-       }
-       if (v >= 0x100) {
-               v >>= 8;
-               r += 8;
-       }
-       if (v >= 0x10) {
-               v >>= 4;
-               r += 4;
-       }
-       if (v >= 4) {
-               v >>= 2;
-               r += 2;
-       }
-       if (v >= 2)
-               r++;
-       return r;
-}
-
-static snd_pcm_format_t oss_format_to_alsa(int format)
-{
-       switch (format) {
-       case AFMT_MU_LAW:       return SND_PCM_FORMAT_MU_LAW;
-       case AFMT_A_LAW:        return SND_PCM_FORMAT_A_LAW;
-       case AFMT_IMA_ADPCM:    return SND_PCM_FORMAT_IMA_ADPCM;
-       case AFMT_U8:           return SND_PCM_FORMAT_U8;
-       case AFMT_S16_LE:       return SND_PCM_FORMAT_S16_LE;
-       case AFMT_S16_BE:       return SND_PCM_FORMAT_S16_BE;
-       case AFMT_S8:           return SND_PCM_FORMAT_S8;
-       case AFMT_U16_LE:       return SND_PCM_FORMAT_U16_LE;
-       case AFMT_U16_BE:       return SND_PCM_FORMAT_U16_BE;
-       case AFMT_MPEG:         return SND_PCM_FORMAT_MPEG;
-       default:                return SND_PCM_FORMAT_U8;
-       }
-}
-
-static int alsa_format_to_oss(snd_pcm_format_t format)
-{
-       switch (format) {
-       case SND_PCM_FORMAT_MU_LAW:     return AFMT_MU_LAW;
-       case SND_PCM_FORMAT_A_LAW:      return AFMT_A_LAW;
-       case SND_PCM_FORMAT_IMA_ADPCM:  return AFMT_IMA_ADPCM;
-       case SND_PCM_FORMAT_U8:         return AFMT_U8;
-       case SND_PCM_FORMAT_S16_LE:     return AFMT_S16_LE;
-       case SND_PCM_FORMAT_S16_BE:     return AFMT_S16_BE;
-       case SND_PCM_FORMAT_S8:         return AFMT_S8;
-       case SND_PCM_FORMAT_U16_LE:     return AFMT_U16_LE;
-       case SND_PCM_FORMAT_U16_BE:     return AFMT_U16_BE;
-       case SND_PCM_FORMAT_MPEG:       return AFMT_MPEG;
-       default:                        return -EINVAL;
-       }
-}
-
-static int oss_dsp_hw_params(oss_dsp_t *dsp)
-{
-       int k;
-       for (k = 1; k >= 0; --k) {
-               oss_dsp_stream_t *str = &dsp->streams[k];
-               snd_pcm_t *pcm = str->pcm;
-               snd_pcm_hw_params_t *hw;
-               int err;
-               unsigned int rate, periods_min;
-               if (!pcm)
-                       continue;
-               str->frame_bytes = snd_pcm_format_physical_width(dsp->format) * 
dsp->channels / 8;
-               snd_pcm_hw_params_alloca(&hw);
-               snd_pcm_hw_params_any(pcm, hw);
-               dsp->format = oss_format_to_alsa(dsp->oss_format);
-
-               err = snd_pcm_hw_params_set_format(pcm, hw, dsp->format);
-               if (err < 0)
-                       return err;
-               err = snd_pcm_hw_params_set_channels(pcm, hw, dsp->channels);
-               if (err < 0)
-                       return err;
-               rate = dsp->rate;
-               err = snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, 0);
-               if (err < 0)
-                       return err;
-#if 0
-               err = snd_pcm_hw_params_set_periods_integer(pcm, hw);
-               if (err < 0)
-                       return err;
-#endif
-
-               if (str->mmap_buffer) {
-                       snd_pcm_access_mask_t *mask;
-                       snd_pcm_access_mask_alloca(&mask);
-                       snd_pcm_access_mask_any(mask);
-                       snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
-                       snd_pcm_access_mask_set(mask, 
SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
-                       snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
-                       err = snd_pcm_hw_params_set_access_mask(pcm, hw, mask);
-                       if (err < 0)
-                               return err;
-                       err = snd_pcm_hw_params_set_period_size(pcm, hw, 
str->alsa.mmap_period_bytes / str->frame_bytes, 0);
-                       if (err < 0)
-                               return err;
-                       err = snd_pcm_hw_params_set_buffer_size(pcm, hw, 
str->alsa.mmap_buffer_bytes / str->frame_bytes);
-                       if (err < 0)
-                               return err;
-                       err = snd_pcm_hw_params_set_access(pcm, hw, 
SND_PCM_ACCESS_MMAP_INTERLEAVED);
-                       if (err < 0)
-                               return err;
-               } else {
-                       err = snd_pcm_hw_params_set_access(pcm, hw, 
SND_PCM_ACCESS_RW_INTERLEAVED);
-                       if (err < 0)
-                               return err;
-                       periods_min = 2;
-                       err = snd_pcm_hw_params_set_periods_min(pcm, hw, &periods_min, 
0);
-                       if (err < 0)
-                               return err;
-                       if (dsp->maxfrags > 0) {
-                               unsigned int periods_max = dsp->maxfrags;
-                               err = snd_pcm_hw_params_set_periods_max(pcm, hw,
-                                                                       &periods_max, 
0);
-                               if (err < 0)
-                                       return err;
-                       }
-                       if (dsp->fragshift > 0) {
-                               snd_pcm_uframes_t s = (1 << dsp->fragshift) / 
str->frame_bytes;
-                               s *= 16;
-                               while (s >= 1024 && (err = 
snd_pcm_hw_params_set_buffer_size(pcm, hw, s)) < 0)
-                                       s /= 2;
-                               s = (1 << dsp->fragshift) / str->frame_bytes;
-                               while (s >= 256 && (err = 
snd_pcm_hw_params_set_period_size(pcm, hw, s, 0)) < 0)
-                                       s /= 2;
-                               if (err < 0) {
-                                       s = (1 << dsp->fragshift) / str->frame_bytes;
-                                       err = 
snd_pcm_hw_params_set_period_size_near(pcm, hw, &s, 0);
-                               }
-                       } else {
-                               snd_pcm_uframes_t s = 16, old_s;
-                               while (s * 2 < dsp->rate / 2) 
-                                       s *= 2;
-                               old_s = s = s / 2;
-                               while (s >= 1024 && (err = 
snd_pcm_hw_params_set_buffer_size(pcm, hw, s)) < 0)
-                                       s /= 2;
-                               s = old_s;
-                               while (s >= 256 && (err = 
snd_pcm_hw_params_set_period_size(pcm, hw, s, 0)) < 0)
-                                       s /= 2;
-                               if (err < 0) {
-                                       s = old_s;
-                                       err = 
snd_pcm_hw_params_set_period_size_near(pcm, hw, &s, 0);
-                               }
-                       }
-                       if (err < 0)
-                               return err;
-               }
-               err = snd_pcm_hw_params(pcm, hw);
-               if (err < 0)
-                       return err;
-#if 0
-               if (debug)
-                       snd_pcm_dump_setup(pcm, stderr);
-#endif
-               if (err < 0)
-                       return err;
-               dsp->oss_format = alsa_format_to_oss(dsp->format);
-               err = snd_pcm_hw_params_get_period_size(hw, &str->alsa.period_size, 0);
-               if (err < 0)
-                       return err;
-               err = snd_pcm_hw_params_get_buffer_size(hw, &str->alsa.buffer_size);
-               if (err < 0)
-                       return err;
-               str->oss.buffer_size = 1 << ld2(str->alsa.buffer_size);
-               if (str->oss.buffer_size < str->alsa.buffer_size)
-                       str->oss.buffer_size *= 2;
-               str->oss.period_size = 1 << ld2(str->alsa.period_size);
-               if (str->oss.period_size < str->alsa.period_size)
-                       str->oss.period_size *= 2;
-               str->oss.periods = str->oss.buffer_size / str->oss.period_size;
-               if (str->mmap_areas)
-                       free(str->mmap_areas);
-               str->mmap_areas = NULL;
-               if (str->mmap_buffer) {
-                       unsigned int c;
-                       snd_pcm_channel_area_t *a;
-                       unsigned int bits_per_sample, bits_per_frame;
-                       str->mmap_areas = calloc(dsp->channels, 
sizeof(*str->mmap_areas));
-                       if (!str->mmap_areas)
-                               return -ENOMEM;
-                       bits_per_sample = snd_pcm_format_physical_width(dsp->format);
-                       bits_per_frame = bits_per_sample * dsp->channels;
-                       a = str->mmap_areas;
-                       for (c = 0; c < dsp->channels; c++, a++) {
-                               a->addr = str->mmap_buffer;
-                               a->first = bits_per_sample * c;
-                               a->step = bits_per_frame;
-                       }
-               }
-       }
-       return 0;
-}
-
-static int oss_dsp_sw_params(oss_dsp_t *dsp)
-{
-       int k;
-       for (k = 1; k >= 0; --k) {
-               oss_dsp_stream_t *str = &dsp->streams[k];
-               snd_pcm_t *pcm = str->pcm;
-               snd_pcm_sw_params_t *sw;
-               int err;
-               if (!pcm)
-                       continue;
-               snd_pcm_sw_params_alloca(&sw);
-               snd_pcm_sw_params_current(pcm, sw);
-               snd_pcm_sw_params_set_xfer_align(pcm, sw, 1);
-               snd_pcm_sw_params_set_start_threshold(pcm, sw, 
-                                                     str->stopped ? 
str->alsa.buffer_size + 1 :
-                                                     str->alsa.period_size);
-#if 1
-               snd_pcm_sw_params_set_stop_threshold(pcm, sw,
-                                                    str->mmap_buffer ? LONG_MAX :
-                                                    str->alsa.buffer_size);
-#else
-               snd_pcm_sw_params_set_stop_threshold(pcm, sw,
-                                                    LONG_MAX);
-               snd_pcm_sw_params_set_silence_threshold(pcm, sw,
-                                                      str->alsa.period_size);
-               snd_pcm_sw_params_set_silence_size(pcm, sw,
-                                                  str->alsa.period_size);
-#endif
-               err = snd_pcm_sw_params(pcm, sw);
-               if (err < 0)
-                       return err;
-               str->alsa.boundary = _snd_pcm_boundary(pcm);
-       }
-       return 0;
-}
-
-static int oss_dsp_params(oss_dsp_t *dsp)
-{
-       int err;
-       err = oss_dsp_hw_params(dsp);
-       if (err < 0) 
-               return err;
-       err = oss_dsp_sw_params(dsp);
-       if (err < 0) 
-               return err;
-#if 0
-       if (debug && debug_out) {
-               int k;
-               for (k = 1; k >= 0; --k) {
-                       oss_dsp_stream_t *str = &dsp->streams[k];
-                       if (str->pcm)
-                               snd_pcm_dump(str->pcm, debug_out);
-               }
-       }
-#endif
-       return 0;
-}
-
-static int oss_dsp_close(int fd)
-{
-       int result = 0;
-       int k;
-       oss_dsp_t *dsp = fds[fd]->private;
-       for (k = 0; k < 2; ++k) {
-               int err;
-               oss_dsp_stream_t *str = &dsp->streams[k];
-               if (!str->pcm)
-                       continue;
-               if (k == SND_PCM_STREAM_PLAYBACK) {
-                       if (snd_pcm_state(str->pcm) != SND_PCM_STATE_OPEN)
-                               snd_pcm_drain(str->pcm);
-               }
-               err = snd_pcm_close(str->pcm);
-               if (err < 0)
-                       result = err;
-       }
-       free(dsp);
-       if (result < 0) {
-               errno = -result;
-               result = -1;
-       }
-       DEBUG("close(%d) -> %d", fd, result);
-       if (result < 0)
-               DEBUG("(errno=%d)\n", errno);
-       else
-               DEBUG("\n");
-       return 0;
-}
-
-static int oss_dsp_open(int card, int device, int oflag, mode_t mode)
-{
-       oss_dsp_t *dsp;
-       unsigned int pcm_mode = 0;
-       unsigned int streams, k;
-       int format = AFMT_MU_LAW;
-       int fd = -1;
-       int result;
-       char name[64];
-
-       if (debug_out == NULL) {
-               if (snd_output_stdio_attach(&debug_out, stderr, 0) < 0)
-                       debug_out = NULL;
-       }
-       switch (device) {
-       case OSS_DEVICE_DSP:
-               format = AFMT_U8;
-               sprintf(name, "dsp%d", card);
-               break;
-       case OSS_DEVICE_DSPW:
-               format = AFMT_S16_LE;
-               sprintf(name, "dspW%d", card);
-               break;
-       case OSS_DEVICE_AUDIO:
-               sprintf(name, "audio%d", card);
-               break;
-       case OSS_DEVICE_ADSP:
-               sprintf(name, "adsp%d", card);
-               break;
-       default:
-               return RETRY;
-       }
-       if (mode & O_NONBLOCK)
-               pcm_mode = SND_PCM_NONBLOCK;
-       switch (oflag & O_ACCMODE) {
-       case O_RDONLY:
-               streams = 1 << SND_PCM_STREAM_CAPTURE;
-               break;
-       case O_WRONLY:
-               streams = 1 << SND_PCM_STREAM_PLAYBACK;
-               break;
-       case O_RDWR:
-               streams = ((1 << SND_PCM_STREAM_PLAYBACK) | 
-                          (1 << SND_PCM_STREAM_CAPTURE));
-               break;
-       default:
-               errno = EINVAL;
-               return -1;
-       }
-       fd = _open("/dev/null", oflag & O_ACCMODE);
-       assert(fd >= 0);
-       fds[fd] = calloc(1, sizeof(fd_t));
-       fds[fd]->class = FD_OSS_DSP;
-       dsp = calloc(1, sizeof(oss_dsp_t));
-       if (!dsp) {
-               free(fds[fd]);
-               fds[fd] = NULL;
-               errno = ENOMEM;
-               return -1;
-       }
-       fds[fd]->private = dsp;
-       dsp->channels = 1;
-       dsp->rate = 8000;
-       dsp->oss_format = format;
-       result = -EINVAL;
-       for (k = 0; k < 2; ++k) {
-               if (!(streams & (1 << k)))
-                       continue;
-               result = snd_pcm_open(&dsp->streams[k].pcm, name, k, pcm_mode);
-               if (result < 0)
-                       break;
-       }
-       if (result < 0) {
-               result = 0;
-               for (k = 0; k < 2; ++k) {
-                       if (dsp->streams[k].pcm) {
-                               snd_pcm_close(dsp->streams[k].pcm);
-                               dsp->streams[k].pcm = NULL;
-                       }
-               }
-               /* try to open the default pcm as fallback */
-               if (card == 0 && (device == OSS_DEVICE_DSP || device == 
OSS_DEVICE_AUDIO))
-                       strcpy(name, "default");
-               else
-                       sprintf(name, "plughw:%d", card);
-               for (k = 0; k < 2; ++k) {
-                       if (!(streams & (1 << k)))
-                               continue;
-                       result = snd_pcm_open(&dsp->streams[k].pcm, name, k, pcm_mode);
-                       if (result < 0)
-                               goto _error;
-               }
-       }
-       result = oss_dsp_params(dsp);
-       if (result < 0)
-               goto _error;
-       return fd;
-
- _error:
-       close(fd);
-       errno = -result;
-       return -1;
-}
-
-int oss_mixer_dev(const char *name, unsigned int index)
-{
-       static struct {
-               char *name;
-               unsigned int index;
-       } id[SOUND_MIXER_NRDEVICES] = {
-               [SOUND_MIXER_VOLUME] = { "Master", 0 },
-               [SOUND_MIXER_BASS] = { "Tone Control - Bass", 0 },
-               [SOUND_MIXER_TREBLE] = { "Tone Control - Treble", 0 },
-               [SOUND_MIXER_SYNTH] = { "Synth", 0 },
-               [SOUND_MIXER_PCM] = { "PCM", 0 },
-               [SOUND_MIXER_SPEAKER] = { "PC Speaker", 0 },
-               [SOUND_MIXER_LINE] = { "Line", 0 },
-               [SOUND_MIXER_MIC] = { "Mic", 0 },
-               [SOUND_MIXER_CD] = { "CD", 0 },
-               [SOUND_MIXER_IMIX] = { "Monitor Mix", 0 },
-               [SOUND_MIXER_ALTPCM] = { "PCM", 1 },
-               [SOUND_MIXER_RECLEV] = { "-- nothing --", 0 },
-               [SOUND_MIXER_IGAIN] = { "Capture", 0 },
-               [SOUND_MIXER_OGAIN] = { "Playback", 0 },
-               [SOUND_MIXER_LINE1] = { "Aux", 0 },
-               [SOUND_MIXER_LINE2] = { "Aux", 1 },
-               [SOUND_MIXER_LINE3] = { "Aux", 2 },
-               [SOUND_MIXER_DIGITAL1] = { "Digital", 0 },
-               [SOUND_MIXER_DIGITAL2] = { "Digital", 1 },
-               [SOUND_MIXER_DIGITAL3] = { "Digital", 2 },
-               [SOUND_MIXER_PHONEIN] = { "Phone", 0 },
-               [SOUND_MIXER_PHONEOUT] = { "Phone", 1 },
-               [SOUND_MIXER_VIDEO] = { "Video", 0 },
-               [SOUND_MIXER_RADIO] = { "Radio", 0 },
-               [SOUND_MIXER_MONITOR] = { "Monitor", 0 },
-       };
-       unsigned int k;
-       for (k = 0; k < SOUND_MIXER_NRDEVICES; ++k) {
-               if (index == id[k].index &&
-                   strcmp(name, id[k].name) == 0)
-                       return k;
-       }
-       return -1;
-}
-
-static int oss_mixer_close(int fd)
-{
-       int err, result = 0;
-       oss_mixer_t *mixer = fds[fd]->private;
-       err = snd_mixer_close(mixer->mix);
-       if (err < 0)
-               result = err;
-       free(mixer);
-       if (result < 0) {
-               errno = -result;
-               result = -1;
-       }
-       DEBUG("close(%d) -> %d", fd, result);
-       if (result < 0)
-               DEBUG("(errno=%d)\n", errno);
-       else
-               DEBUG("\n");
-       return 0;
-}
-
-static int oss_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned int mask)
-{
-       oss_mixer_t *mixer = snd_mixer_elem_get_callback_private(elem);
-       if (mask == SND_CTL_EVENT_MASK_REMOVE) {
-               int idx = oss_mixer_dev(snd_mixer_selem_get_name(elem),
-                                       snd_mixer_selem_get_index(elem));
-               if (idx >= 0)
-                       mixer->elems[idx] = 0;
-               return 0;
-       }
-       if (mask & SND_CTL_EVENT_MASK_VALUE) {
-               mixer->modify_counter++;
-       }
-       return 0;
-}
-
-static int oss_mixer_callback(snd_mixer_t *mixer, unsigned int mask, 
-                             snd_mixer_elem_t *elem)
+static int oss_pcm_fcntl(int fd, int cmd, ...)
 {
-       if (mask & SND_CTL_EVENT_MASK_ADD) {
-               oss_mixer_t *mix = snd_mixer_get_callback_private(mixer);
-               int idx = oss_mixer_dev(snd_mixer_selem_get_name(elem),
-                                       snd_mixer_selem_get_index(elem));
-               if (idx >= 0) {
-                       mix->elems[idx] = elem;
-                       snd_mixer_selem_set_playback_volume_range(elem, 0, 100);
-                       snd_mixer_selem_set_capture_volume_range(elem, 0, 100);
-                       snd_mixer_elem_set_callback(elem, oss_mixer_elem_callback);
-                       snd_mixer_elem_set_callback_private(elem, mix);
-               }
-       }
-       return 0;
-}
-
-static int oss_mixer_open(int card, int device, int oflag, mode_t mode 
ATTRIBUTE_UNUSED)
-{
-       oss_mixer_t *mixer;
-       int fd = -1;
        int result;
-       char name[64];
-
-       switch (device) {
-       case OSS_DEVICE_MIXER:
-               sprintf(name, "mixer%d", card);
-               break;
-       case OSS_DEVICE_AMIXER:
-               sprintf(name, "amixer%d", card);
-               break;
-       default:
-               return RETRY;
-       }
-       switch (oflag & O_ACCMODE) {
-       case O_RDONLY:
-       case O_WRONLY:
-       case O_RDWR:
-               break;
-       default:
-               errno = EINVAL;
-               return -1;
-       }
-       fd = _open("/dev/null", oflag & O_ACCMODE);
-       assert(fd >= 0);
-       fds[fd] = calloc(1, sizeof(fd_t));
-       fds[fd]->class = FD_OSS_MIXER;
-       mixer = calloc(1, sizeof(oss_mixer_t));
-       if (!mixer) {
-               errno = -ENOMEM;
-               return -1;
-       }
-       fds[fd]->private = mixer;
-       result = snd_mixer_open(&mixer->mix, 0);
-       if (result < 0)
-               goto _error;
-       result = snd_mixer_attach(mixer->mix, name);
-       if (result < 0) {
-               /* try to open the default mixer as fallback */
-               if (card == 0)
-                       strcpy(name, "default");
-               else
-                       sprintf(name, "hw:%d", card);
-               result = snd_mixer_attach(mixer->mix, name);
-               if (result < 0)
-                       goto _error1;
-       }
-       result = snd_mixer_selem_register(mixer->mix, NULL, NULL);
-       if (result < 0)
-               goto _error1;
-       snd_mixer_set_callback(mixer->mix, oss_mixer_callback);
-       snd_mixer_set_callback_private(mixer->mix, mixer);
-       result = snd_mixer_load(mixer->mix);
-       if (result < 0)
-               goto _error1;
-       return fd;
- _error1:
-       snd_mixer_close(mixer->mix);
- _error:
-       close(fd);
-       errno = -result;
-       return -1;
-}
-
-static void error_handler(const char *file ATTRIBUTE_UNUSED,
-                         int line ATTRIBUTE_UNUSED,
-                         const char *func ATTRIBUTE_UNUSED,
-                         int err ATTRIBUTE_UNUSED,
-                         const char *fmt ATTRIBUTE_UNUSED,
-                         ...)
-{
-       /* suppress the error message from alsa-lib */
-}
-
-static int oss_open(const char *file, int oflag, ...)
-{
-       int result;
-       int minor, card, device;
-       struct stat s;
-       mode_t mode;
        va_list args;
-       va_start(args, oflag);
-       mode = va_arg(args, mode_t);
-       va_end(args);
-       result = stat(file, &s);
-       if (result < 0)
-               return RETRY;
-       if (!S_ISCHR(s.st_mode) || ((s.st_rdev >> 8) & 0xff) != OSS_MAJOR)
-               return RETRY;
-       if (! debug)
-               snd_lib_error_set_handler(error_handler);
-       minor = s.st_rdev & 0xff;
-       card = minor >> 4;
-       device = minor & 0x0f;
-       switch (device) {
-       case OSS_DEVICE_DSP:
-       case OSS_DEVICE_DSPW:
-       case OSS_DEVICE_AUDIO:
-       case OSS_DEVICE_ADSP:
-               result = oss_dsp_open(card, device, oflag, mode);
-               DEBUG("open(\"%s\", %d, %d) -> %d\n", file, oflag, mode, result);
-               return result;
-       case OSS_DEVICE_MIXER:
-       case OSS_DEVICE_AMIXER:
-               result = oss_mixer_open(card, device, oflag, mode);
-               DEBUG("open(\"%s\", %d, %d) -> %d\n", file, oflag, mode, result);
-               return result;
-       default:
-               return RETRY;
-       }
-}
-
-static ssize_t oss_dsp_write(int fd, const void *buf, size_t n)
-{
-       ssize_t result;
-       oss_dsp_t *dsp = fds[fd]->private;
-       oss_dsp_stream_t *str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-       snd_pcm_t *pcm = str->pcm;
-       snd_pcm_uframes_t frames;
-       if (!pcm) {
-               errno = EBADFD;
-               result = -1;
-               goto _end;
-       }
-       frames = n / str->frame_bytes;
- _again:
-       result = snd_pcm_writei(pcm, buf, frames);
-       if (result == -EPIPE && 
-           snd_pcm_state(pcm) == SND_PCM_STATE_XRUN &&
-           (result = snd_pcm_prepare(pcm)) == 0)
-               goto _again;
-       if (result == -EPIPE && 
-           snd_pcm_state(pcm) == SND_PCM_STATE_SUSPENDED) {
-               while ((result = snd_pcm_resume(pcm)) == -EAGAIN)
-                       sleep(1);
-               if (result < 0 && (result = snd_pcm_prepare(pcm)) == 0)
-                       goto _again;
-       }
-       if (result < 0) {
-               errno = -result;
-               result = -1;
-               goto _end;
-       }
-       result *= str->frame_bytes;
-       str->oss.bytes += result;
- _end:
-       DEBUG("write(%d, %p, %ld) -> %ld", fd, buf, (long)n, (long)result);
-       if (result < 0)
-               DEBUG("(errno=%d)\n", errno);
-       else
-               DEBUG("\n");
-       return result;
-}
-
-static ssize_t oss_dsp_read(int fd, void *buf, size_t n)
-{
-       ssize_t result;
-       oss_dsp_t *dsp = fds[fd]->private;
-       oss_dsp_stream_t *str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-       snd_pcm_t *pcm = str->pcm;
-       snd_pcm_uframes_t frames;
-       if (!pcm) {
-               errno = EBADFD;
-               result = -1;
-               goto _end;
-       }
-       frames = n / str->frame_bytes;
- _again:
-       result = snd_pcm_readi(pcm, buf, frames);
-       if (result == -EPIPE && 
-           snd_pcm_state(pcm) == SND_PCM_STATE_XRUN &&
-           (result = snd_pcm_prepare(pcm)) == 0)
-               goto _again;
-       if (result == -EPIPE && 
-           snd_pcm_state(pcm) == SND_PCM_STATE_SUSPENDED) {
-               while ((result = snd_pcm_resume(pcm)) == -EAGAIN)
-                       sleep(1);
-               if (result < 0 && (result = snd_pcm_prepare(pcm)) == 0)
-                       goto _again;
-       }
-       if (result < 0) {
-               errno = -result;
-               result = -1;
-               goto _end;
-       }
-       result *= str->frame_bytes;
-       str->oss.bytes += result;
- _end:
-       DEBUG("read(%d, %p, %ld) -> %ld", fd, buf, (long)n, (long)result);
-       if (result < 0)
-               DEBUG("(errno=%d)\n", errno);
-       else
-               DEBUG("\n");
-       return result;
-}
-
-#define USE_REWIND 1
-
-static void oss_dsp_mmap_update(oss_dsp_t *dsp, snd_pcm_stream_t stream,
-                               snd_pcm_sframes_t delay)
-{
-       oss_dsp_stream_t *str = &dsp->streams[stream];
-       snd_pcm_t *pcm = str->pcm;
-       snd_pcm_sframes_t err;
-       snd_pcm_uframes_t size;
-       const snd_pcm_channel_area_t *areas;
-       switch (stream) {
-       case SND_PCM_STREAM_PLAYBACK:
-               if (delay < 0) {
-                       snd_pcm_reset(pcm);
-                       str->mmap_advance -= delay;
-                       if (str->mmap_advance > dsp->rate / 10)
-                               str->mmap_advance = dsp->rate / 10;
-//                     fprintf(stderr, "mmap_advance=%ld\n", str->mmap_advance);
-               }
-#if USE_REWIND
-               err = snd_pcm_rewind(pcm, str->alsa.buffer_size);
-               if (err < 0)
-                       return;
-               size = str->mmap_advance;
-//             fprintf(stderr, "delay=%ld rewind=%ld forward=%ld offset=%ld\n",
-//                     delay, err, size, snd_pcm_mmap_offset(pcm));
-#else
-               size = str->mmap_advance - delay;
-#endif
-               while (size > 0) {
-                       snd_pcm_uframes_t ofs;
-                       snd_pcm_uframes_t frames = size;
-                       snd_pcm_mmap_begin(pcm, &areas, &ofs, &frames);
-//                     fprintf(stderr, "copy %ld %ld %d\n", ofs, frames, dsp->format);
-                       snd_pcm_areas_copy(areas, ofs, str->mmap_areas, ofs, 
-                                          dsp->channels, frames,
-                                          dsp->format);
-                       err = snd_pcm_mmap_commit(pcm, ofs, frames);
-                       assert(err == (snd_pcm_sframes_t) frames);
-                       size -= frames;
-               }
-               break;
-       case SND_PCM_STREAM_CAPTURE:
-               break;
-       }
-}
-
-
-static int oss_dsp_ioctl(int fd, unsigned long cmd, ...)
-{
-       int result, err = 0;
-       va_list args;
-       void *arg;
-       oss_dsp_t *dsp = fds[fd]->private;
-       oss_dsp_stream_t *str;
-       snd_pcm_t *pcm;
+       long arg;
 
        va_start(args, cmd);
-       arg = va_arg(args, void *);
+       arg = va_arg(args, long);
        va_end(args);
-       DEBUG("ioctl(%d, ", fd);
+
        switch (cmd) {
-       case OSS_GETVERSION:
-               *(int*)arg = SOUND_VERSION;
-               DEBUG("OSS_GETVERSION, %p) -> [%d]\n", arg, *(int*)arg);
-               break;
-       case SNDCTL_DSP_RESET:
-       {
-               int k;
-               DEBUG("SNDCTL_DSP_RESET)\n");
-               result = 0;
-               for (k = 0; k < 2; ++k) {
-                       str = &dsp->streams[k];
-                       pcm = str->pcm;
-                       if (!pcm)
-                               continue;
-                       err = snd_pcm_drop(pcm);
-                       if (err >= 0)
-                               err = snd_pcm_prepare(pcm);
-                       if (err < 0)
-                               result = err;
-                       str->oss.bytes = 0;
-               }
-               err = result;
-               break;
-       }
-       case SNDCTL_DSP_SYNC:
-       {
-               int k;
-               DEBUG("SNDCTL_DSP_SYNC)\n");
-               result = 0;
-               for (k = 0; k < 2; ++k) {
-                       str = &dsp->streams[k];
-                       pcm = str->pcm;
-                       if (!pcm)
-                               continue;
-                       err = snd_pcm_drain(pcm);
-                       if (err >= 0)
-                               err = snd_pcm_prepare(pcm);
-                       if (err < 0)
-                               result = err;
-                       
-               }
-               err = result;
-               break;
-       }
-       case SNDCTL_DSP_SPEED:
-               dsp->rate = *(int *)arg;
-               err = oss_dsp_params(dsp);
-               DEBUG("SNDCTL_DSP_SPEED, %p[%d]) -> [%d]\n", arg, *(int *)arg, 
dsp->rate);
-               *(int *)arg = dsp->rate;
-               break;
-       case SNDCTL_DSP_STEREO:
-               if (*(int *)arg)
-                       dsp->channels = 2;
-               else
-                       dsp->channels = 1;
-               err = oss_dsp_params(dsp);
-               DEBUG("SNDCTL_DSP_STEREO, %p[%d]) -> [%d]\n", arg, *(int *)arg, 
dsp->channels - 1);
-               *(int *)arg = dsp->channels - 1;
-               break;
-       case SNDCTL_DSP_CHANNELS:
-               dsp->channels = (*(int *)arg);
-               err = oss_dsp_params(dsp);
-               if (err < 0)
-                       break;
-               DEBUG("SNDCTL_DSP_CHANNELS, %p[%d]) -> [%d]\n", arg, *(int *)arg, 
dsp->channels);
-               *(int *)arg = dsp->channels;
-               break;
-       case SNDCTL_DSP_SETFMT:
-               if (*(int *)arg != AFMT_QUERY) {
-                       dsp->oss_format = *(int *)arg;
-                       err = oss_dsp_params(dsp);
-                       if (err < 0)
-                               break;
-               }
-               DEBUG("SNDCTL_DSP_SETFMT, %p[%d]) -> [%d]\n", arg, *(int *)arg, 
dsp->oss_format);
-               *(int *) arg = dsp->oss_format;
-               break;
-       case SNDCTL_DSP_GETBLKSIZE:
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               if (!str->pcm)
-                       str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               pcm = str->pcm;
-               *(int *) arg = str->oss.period_size * str->frame_bytes;
-               DEBUG("SNDCTL_DSP_GETBLKSIZE, %p) -> [%d]\n", arg, *(int *)arg);
-               break;
-       case SNDCTL_DSP_POST:
-               DEBUG("SNDCTL_DSP_POST)\n");
-               break;
-       case SNDCTL_DSP_SUBDIVIDE:
-               DEBUG("SNDCTL_DSP_SUBDIVIDE, %p[%d])\n", arg, *(int *)arg);
-               dsp->subdivision = *(int *)arg;
-               if (dsp->subdivision < 1)
-                       dsp->subdivision = 1;
-               err = oss_dsp_params(dsp);
-               break;
-       case SNDCTL_DSP_SETFRAGMENT:
-       {
-               DEBUG("SNDCTL_DSP_SETFRAGMENT, %p[%x])\n", arg, *(int *)arg);
-               dsp->fragshift = *(int *)arg & 0xffff;
-               if (dsp->fragshift < 4)
-                       dsp->fragshift = 4;
-               dsp->maxfrags = ((*(int *)arg) >> 16) & 0xffff;
-               if (dsp->maxfrags < 2)
-                       dsp->maxfrags = 2;
-               err = oss_dsp_params(dsp);
-               break;
-       }
-       case SNDCTL_DSP_GETFMTS:
-       {
-               *(int *)arg = (AFMT_MU_LAW | AFMT_A_LAW | AFMT_IMA_ADPCM | 
-                              AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | 
-                              AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE);
-               DEBUG("SNDCTL_DSP_GETFMTS, %p) -> [%d]\n", arg, *(int *)arg);
-               break;
-       }
-       case SNDCTL_DSP_NONBLOCK:
-       {
-               int k;
-               DEBUG("SNDCTL_DSP_NONBLOCK)\n");
-               result = 0;
-               for (k = 0; k < 2; ++k) {
-                       pcm = dsp->streams[k].pcm;
-                       if (!pcm)
-                               continue;
-                       err = snd_pcm_nonblock(pcm, 1);
-                       if (err < 0)
-                               result = err;
-               }
-               result = err;
-               break;
-       }
-       case SNDCTL_DSP_GETCAPS:
-       {
-               result = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
-               if (dsp->streams[SND_PCM_STREAM_PLAYBACK].pcm && 
-                   dsp->streams[SND_PCM_STREAM_CAPTURE].pcm)
-                       result |= DSP_CAP_DUPLEX;
-               *(int*)arg = result;
-               DEBUG("SNDCTL_DSP_GETCAPS, %p) -> [%d]\n", arg, *(int*)arg);
-               break;
-       }
-       case SNDCTL_DSP_GETTRIGGER:
-       {
-               int s = 0;
-               pcm = dsp->streams[SND_PCM_STREAM_PLAYBACK].pcm;
-               if (pcm) {
-                       if (snd_pcm_state(pcm) == SND_PCM_STATE_RUNNING)
-                               s |= PCM_ENABLE_OUTPUT;
-               }
-               pcm = dsp->streams[SND_PCM_STREAM_CAPTURE].pcm;
-               if (pcm) {
-                       if (snd_pcm_state(pcm) == SND_PCM_STATE_RUNNING)
-                               s |= PCM_ENABLE_INPUT;
-               }
-               *(int*)arg = s;
-               DEBUG("SNDCTL_DSP_GETTRIGGER, %p) -> [%d]\n", arg, *(int*)arg);
-               break;
-       }               
-       case SNDCTL_DSP_SETTRIGGER:
-       {
-               DEBUG("SNDCTL_DSP_SETTRIGGER, %p[%d])\n", arg, *(int*)arg);
-               result = *(int*) arg;
-               str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               pcm = str->pcm;
-               if (pcm) {
-                       if (result & PCM_ENABLE_INPUT) {
-                               if (str->stopped) {
-                                       str->stopped = 0;
-                                       err = oss_dsp_sw_params(dsp);
-                                       if (err < 0)
-                                               break;
-                                       err = snd_pcm_start(pcm);
-                                       if (err < 0)
-                                               break;
-                               }
-                       } else {
-                               if (!str->stopped) {
-                                       str->stopped = 1;
-                                       err = snd_pcm_drop(pcm);
-                                       if (err < 0)
-                                               break;
-                                       err = oss_dsp_sw_params(dsp);
-                                       if (err < 0)
-                                               break;
-                                       err = snd_pcm_prepare(pcm);
-                                       if (err < 0)
-                                               break;
-                               }
-                       }
-               }
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               pcm = str->pcm;
-               if (pcm) {
-                       if (result & PCM_ENABLE_OUTPUT) {
-                               if (str->stopped) {
-                                       str->stopped = 0;
-                                       err = oss_dsp_sw_params(dsp);
-                                       if (err < 0)
-                                               break;
-                                       if (str->mmap_buffer) {
-                                               const snd_pcm_channel_area_t *areas;
-                                               snd_pcm_uframes_t offset;
-                                               snd_pcm_uframes_t size = 
str->alsa.buffer_size;
-                                               snd_pcm_mmap_begin(pcm, &areas, 
&offset, &size);
-                                               snd_pcm_areas_copy(areas, 0, 
str->mmap_areas, 0,
-                                                                  dsp->channels, size,
-                                                                  dsp->format);
-                                               snd_pcm_mmap_commit(pcm, offset, size);
-                                       }
-                                       err = snd_pcm_start(pcm);
-                                       if (err < 0)
-                                               break;
-                               }
-                       } else {
-                               if (!str->stopped) {
-                                       str->stopped = 1;
-                                       err = snd_pcm_drop(pcm);
-                                       if (err < 0)
-                                               break;
-                                       err = oss_dsp_sw_params(dsp);
-                                       if (err < 0)
-                                               break;
-                                       err = snd_pcm_prepare(pcm);
-                                       if (err < 0)
-                                               break;
-                               }
-                       }
-               }
-               break;
-       }
-       case SNDCTL_DSP_GETISPACE:
-       {
-               snd_pcm_sframes_t avail, delay;
-               snd_pcm_state_t state;
-               audio_buf_info *info = arg;
-               str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               pcm = str->pcm;
-               if (!pcm) {
-                       err = -EINVAL;
-                       break;
-               }
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_RUNNING) {
-                       snd_pcm_delay(pcm, &delay);
-                       if (str->mmap_buffer)
-                               oss_dsp_mmap_update(dsp, SND_PCM_STREAM_CAPTURE, 
delay);
-               }
-               avail = snd_pcm_avail_update(pcm);
-               if (avail < 0)
-                       avail = 0;
-               if ((snd_pcm_uframes_t)avail > str->oss.buffer_size)
-                       avail = str->oss.buffer_size;
-               info->fragsize = str->oss.period_size * str->frame_bytes;
-               info->fragstotal = str->oss.periods;
-               info->bytes = avail * str->frame_bytes;
-               info->fragments = avail / str->oss.period_size;
-               DEBUG("SNDCTL_DSP_GETISPACE, %p) -> {%d, %d, %d, %d}\n", arg,
-                     info->fragments,
-                     info->fragstotal,
-                     info->fragsize,
-                     info->bytes);
-               break;
-       }
-       case SNDCTL_DSP_GETOSPACE:
-       {
-               snd_pcm_sframes_t avail, delay;
-               snd_pcm_state_t state;
-               audio_buf_info *info = arg;
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               pcm = str->pcm;
-               if (!pcm) {
-                       err = -EINVAL;
-                       break;
-               }
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_RUNNING || 
-                   state == SND_PCM_STATE_DRAINING) {
-                       snd_pcm_delay(pcm, &delay);
-                       if (str->mmap_buffer)
-                               oss_dsp_mmap_update(dsp, SND_PCM_STREAM_PLAYBACK, 
delay);
-               }
-               avail = snd_pcm_avail_update(pcm);
-               if (avail < 0 || (snd_pcm_uframes_t)avail > str->oss.buffer_size)
-                       avail = str->oss.buffer_size;
-               info->fragsize = str->oss.period_size * str->frame_bytes;
-               info->fragstotal = str->oss.periods;
-               info->bytes = avail * str->frame_bytes;
-               info->fragments = avail / str->oss.period_size;
-               DEBUG("SNDCTL_DSP_GETOSPACE, %p) -> {%d %d %d %d}\n", arg,
-                     info->fragments,
-                     info->fragstotal,
-                     info->fragsize,
-                     info->bytes);
-               break;
-       }
-       case SNDCTL_DSP_GETIPTR:
-       {
-               snd_pcm_sframes_t delay = 0;
-               snd_pcm_uframes_t hw_ptr;
-               snd_pcm_state_t state;
-               count_info *info = arg;
-               str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               pcm = str->pcm;
-               if (!pcm) {
-                       err = -EINVAL;
-                       break;
-               }
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_RUNNING) {
-                       snd_pcm_delay(pcm, &delay);
-                       if (str->mmap_buffer)
-                               oss_dsp_mmap_update(dsp, SND_PCM_STREAM_CAPTURE, 
delay);
-               }
-               /* FIXME */
-               hw_ptr = _snd_pcm_mmap_hw_ptr(pcm);
-               info->bytes = hw_ptr;
-               info->bytes *= str->frame_bytes;
-               info->ptr = hw_ptr % str->oss.buffer_size;
-               info->ptr *= str->frame_bytes;
-               if (str->mmap_buffer) {
-                       ssize_t n = (hw_ptr / str->oss.period_size) - 
(str->alsa.old_hw_ptr / str->oss.period_size);
-                       if (n < 0)
-                               n += str->alsa.boundary / str->oss.period_size;
-                       info->blocks = n;
-                       str->alsa.old_hw_ptr = hw_ptr;
-               } else
-                       info->blocks = delay / str->oss.period_size;
-               DEBUG("SNDCTL_DSP_GETIPTR, %p) -> {%d %d %d}\n", arg,
-                     info->bytes,
-                     info->blocks,
-                     info->ptr);
-               break;
-       }
-       case SNDCTL_DSP_GETOPTR:
-       {
-               snd_pcm_sframes_t delay = 0;
-               snd_pcm_uframes_t hw_ptr;
-               snd_pcm_state_t state;
-               count_info *info = arg;
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               pcm = str->pcm;
-               if (!pcm) {
-                       err = -EINVAL;
-                       break;
-               }
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_RUNNING || 
-                   state == SND_PCM_STATE_DRAINING) {
-                       snd_pcm_delay(pcm, &delay);
-                       if (str->mmap_buffer)
-                               oss_dsp_mmap_update(dsp, SND_PCM_STREAM_PLAYBACK, 
delay);
-               }
-               /* FIXME */
-               hw_ptr = _snd_pcm_mmap_hw_ptr(pcm);
-               info->bytes = hw_ptr;
-               info->bytes *= str->frame_bytes;
-               info->ptr = hw_ptr % str->oss.buffer_size;
-               info->ptr *= str->frame_bytes;
-               if (str->mmap_buffer) {
-                       ssize_t n = (hw_ptr / str->oss.period_size) - 
(str->alsa.old_hw_ptr / str->oss.period_size);
-                       if (n < 0)
-                               n += str->alsa.boundary / str->oss.period_size;
-                       info->blocks = n;
-                       str->alsa.old_hw_ptr = hw_ptr;
-               } else
-                       info->blocks = delay / str->oss.period_size;
-               DEBUG("SNDCTL_DSP_GETOPTR, %p) -> {%d %d %d}\n", arg,
-                     info->bytes,
-                     info->blocks,
-                     info->ptr);
-               break;
-       }
-       case SNDCTL_DSP_GETODELAY:
-       {
-               snd_pcm_sframes_t delay = 0;
-               snd_pcm_state_t state;
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               pcm = str->pcm;
-               if (!pcm) {
-                       err = -EINVAL;
-                       break;
-               }
-               state = snd_pcm_state(pcm);
-               if (state == SND_PCM_STATE_RUNNING || 
-                   state == SND_PCM_STATE_DRAINING) {
-                       snd_pcm_delay(pcm, &delay);
-                       if (str->mmap_buffer)
-                               oss_dsp_mmap_update(dsp, SND_PCM_STREAM_PLAYBACK, 
delay);
-               }
-               *(int *)arg = delay * str->frame_bytes;
-               DEBUG("SNDCTL_DSP_GETODELAY, %p) -> [%d]\n", arg, *(int*)arg); 
-               break;
-       }
-       case SNDCTL_DSP_SETDUPLEX:
-               DEBUG("SNDCTL_DSP_SETDUPLEX)\n"); 
-               break;
-       case SOUND_PCM_READ_RATE:
-       {
-               *(int *)arg = dsp->rate;
-               DEBUG("SOUND_PCM_READ_RATE, %p) -> [%d]\n", arg, *(int*)arg); 
-               break;
-       }
-       case SOUND_PCM_READ_CHANNELS:
-       {
-               *(int *)arg = dsp->channels;
-               DEBUG("SOUND_PCM_READ_CHANNELS, %p) -> [%d]\n", arg, *(int*)arg); 
-               break;
-       }
-       case SOUND_PCM_READ_BITS:
-       {
-               *(int *)arg = snd_pcm_format_width(dsp->format);
-               DEBUG("SOUND_PCM_READ_BITS, %p) -> [%d]\n", arg, *(int*)arg); 
-               break;
-       }
-       case SNDCTL_DSP_MAPINBUF:
-               DEBUG("SNDCTL_DSP_MAPINBUF)\n");
-               err = -EINVAL;
-               break;
-       case SNDCTL_DSP_MAPOUTBUF:
-               DEBUG("SNDCTL_DSP_MAPOUTBUF)\n");
-               err = -EINVAL;
-               break;
-       case SNDCTL_DSP_SETSYNCRO:
-               DEBUG("SNDCTL_DSP_SETSYNCRO)\n");
-               err = -EINVAL;
-               break;
-       case SOUND_PCM_READ_FILTER:
-               DEBUG("SOUND_PCM_READ_FILTER)\n");
-               err = -EINVAL;
-               break;
-       case SOUND_PCM_WRITE_FILTER:
-               DEBUG("SOUND_PCM_WRITE_FILTER)\n");
-               err = -EINVAL;
-               break;
+        case F_SETFL:
+               result = lib_oss_pcm_nonblock(fd, (arg & O_NONBLOCK) ? 1 : 0);
+                if (result < 0) {
+                        errno = -result;
+                        return -1;
+                }
+                return 0;
        default:
-               DEBUG("%lx, %p)\n", cmd, arg);
-               // return oss_mixer_ioctl(...);
-               err = -ENXIO;
-               break;
+               DEBUG("pcm_fcntl(%d, ", fd);
+               result = _fcntl(fd, cmd, arg);
+               if (result < 0)
+                       return result;
+               DEBUG("%x, %ld)\n", cmd, arg);
+               return result;
        }
-       if (err >= 0)
-               return 0;
-       DEBUG("dsp ioctl error = %d\n", err);
-       errno = -err;
        return -1;
 }
 
-static int oss_dsp_fcntl(int fd, int cmd, ...)
+static int oss_mixer_fcntl(int fd, int cmd, ...)
 {
        int result;
        va_list args;
@@ -1370,447 +119,63 @@
        va_start(args, cmd);
        arg = va_arg(args, long);
        va_end(args);
-       
-       DEBUG("fcntl(%d, ", fd);
-       result = _fcntl(fd, cmd, arg);
-       if (result < 0)
-               return result;
+
        switch (cmd) {
-       case F_DUPFD:
-               DEBUG("F_DUPFD, %ld)\n", arg);
-               fds[arg] = fds[fd];
-               return result;
-       case F_SETFL:
-       {
-               int k;
-               int err;
-               snd_pcm_t *pcm;
-               oss_dsp_t *dsp = fds[fd]->private;
-               DEBUG("F_SETFL, %ld)\n", arg);
-               for (k = 0; k < 2; ++k) {
-                       pcm = dsp->streams[k].pcm;
-                       if (!pcm)
-                               continue;
-                       err = snd_pcm_nonblock(pcm, !!(arg & O_NONBLOCK));
-                       if (err < 0)
-                               result = err;
-               }
-               if (result < 0) {
-                       errno = -result;
-                       return -1;
-               }
-               return 0;
-       }
        default:
+               DEBUG("mixer_fcntl(%d, ", fd);
+               result = _fcntl(fd, cmd, arg);
+               if (result < 0)
+                       return result;
                DEBUG("%x, %ld)\n", cmd, arg);
                return result;
        }
        return -1;
 }
 
-static void *oss_dsp_mmap(void *addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED, 
int prot, int flags ATTRIBUTE_UNUSED, int fd, off_t offset ATTRIBUTE_UNUSED)
+static ssize_t bad_write(int fd ATTRIBUTE_UNUSED, const void *buf ATTRIBUTE_UNUSED, 
size_t n ATTRIBUTE_UNUSED)
 {
-       int err;
-       void *result;
-       oss_dsp_t *dsp = fds[fd]->private;
-       oss_dsp_stream_t *str;
-       switch (prot & (PROT_READ | PROT_WRITE)) {
-       case PROT_READ:
-               str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               break;
-       case PROT_WRITE:
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               break;
-       case PROT_READ | PROT_WRITE:
-               str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-               if (!str->pcm)
-                       str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-               break;
-       default:
-               errno = EINVAL;
-               result = MAP_FAILED;
-               goto _end;
-       }
-       if (!str->pcm) {
-               errno = EBADFD;
-               result = MAP_FAILED;
-               goto _end;
-       }
-       assert(!str->mmap_buffer);
-       result = malloc(len);
-       if (!result) {
-               result = MAP_FAILED;
-               goto _end;
-       }
-       str->mmap_buffer = result;
-       str->mmap_bytes = len;
-       str->alsa.mmap_period_bytes = str->oss.period_size * str->frame_bytes;
-       str->alsa.mmap_buffer_bytes = str->oss.buffer_size * str->frame_bytes;
-       err = oss_dsp_params(dsp);
-       if (err < 0) {
-               free(result);
-               errno = -err;
-               result = MAP_FAILED;
-               goto _end;
-       }
- _end:
-       DEBUG("mmap(%p, %lu, %d, %d, %d, %ld) -> %p\n", addr, (unsigned long)len, 
prot, flags, fd, offset, result);
-       return result;
-}
-
-static int oss_dsp_munmap(int fd, void *addr ATTRIBUTE_UNUSED, size_t len 
ATTRIBUTE_UNUSED)
-{
-       int err;
-       oss_dsp_t *dsp = fds[fd]->private;
-       oss_dsp_stream_t *str;
-       DEBUG("munmap(%p, %lu)\n", addr, (unsigned long)len);
-       str = &dsp->streams[SND_PCM_STREAM_PLAYBACK];
-       if (!str->pcm)
-               str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
-       assert(str->mmap_buffer);
-       free(str->mmap_buffer);
-       str->mmap_buffer = 0;
-       str->mmap_bytes = 0;
-       err = oss_dsp_params(dsp);
-       if (err < 0) {
-               errno = -err;
-               return -1;
-       }
-       return 0;
-}
-
-static ssize_t oss_mixer_write(int fd ATTRIBUTE_UNUSED, const void *buf 
ATTRIBUTE_UNUSED, size_t n ATTRIBUTE_UNUSED)
-{
-       errno = -EBADFD;
+       errno = EBADFD;
        return -1;
 }
 
-static ssize_t oss_mixer_read(int fd ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED, 
size_t n ATTRIBUTE_UNUSED)
+static ssize_t bad_read(int fd ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED, size_t n 
ATTRIBUTE_UNUSED)
 {
-       errno = -EBADFD;
+       errno = EBADFD;
        return -1;
 }
 
-
-static int oss_mixer_read_recsrc(oss_mixer_t *mixer, unsigned int *ret)
+static void *bad_mmap(void *addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED,
+                     int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
+                     int fd ATTRIBUTE_UNUSED, off_t offset ATTRIBUTE_UNUSED)
 {
-       unsigned int mask = 0;
-       unsigned int k;
-       int err = 0;
-       for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-               snd_mixer_elem_t *elem = mixer->elems[k];
-               if (elem && 
-                   snd_mixer_selem_has_capture_switch(elem)) {
-                       int sw;
-                       err = snd_mixer_selem_get_capture_switch(elem, 
SND_MIXER_SCHN_FRONT_LEFT, &sw);
-                       if (err < 0)
-                               break;
-                       if (sw)
-                               mask |= 1 << k;
-               }
-       }
-       *ret = mask;
-       return err;
+       errno = EBADFD;
+       return NULL;
 }
 
-
-static int oss_mixer_ioctl(int fd, unsigned long cmd, ...)
+static int bad_munmap(void* addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED)
 {
-       int err = 0;
-       va_list args;
-       void *arg;
-       oss_mixer_t *mixer = fds[fd]->private;
-       snd_mixer_t *mix = mixer->mix;
-       unsigned int dev;
-
-       va_start(args, cmd);
-       arg = va_arg(args, void *);
-       va_end(args);
-       DEBUG("ioctl(%d, ", fd);
-       switch (cmd) {
-       case OSS_GETVERSION:
-               *(int*)arg = SOUND_VERSION;
-               DEBUG("OSS_GETVERSION, %p) -> [%d]\n", arg, *(int*)arg);
-               break;
-       case SOUND_MIXER_INFO:
-       {
-               mixer_info *info = arg;
-               snd_mixer_handle_events(mix);
-               strcpy(info->id, "alsa-oss");
-               strcpy(info->name, "alsa-oss");
-               info->modify_counter = mixer->modify_counter;
-               DEBUG("SOUND_MIXER_INFO, %p) -> {%s, %s, %d}\n", info, info->id, 
info->name, info->modify_counter);
-               break;
-       }
-       case SOUND_OLD_MIXER_INFO:
-       {
-               _old_mixer_info *info = arg;
-               strcpy(info->id, "alsa-oss");
-               strcpy(info->name, "alsa-oss");
-               DEBUG("SOUND_OLD_MIXER_INFO, %p) -> {%s, %s}\n", info, info->id, 
info->name);
-               break;
-       }
-       case SOUND_MIXER_WRITE_RECSRC:
-       {
-               unsigned int k, mask = *(unsigned int *) arg;
-               unsigned int old;
-               int excl = 0;
-               DEBUG("SOUND_MIXER_WRITE_RECSRC, %p) -> [%x]", arg, mask);
-               err = oss_mixer_read_recsrc(mixer, &old);
-               if (err < 0)
-                       break;
-               for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-                       snd_mixer_elem_t *elem = mixer->elems[k];
-                       if (elem && 
-                           snd_mixer_selem_has_capture_switch(elem)) {
-                               if (!excl &&
-                                   snd_mixer_selem_has_capture_switch_exclusive(elem) 
&&
-                                   mask & ~old) {
-                                       mask &= ~old;
-                                       excl = 1;
-                               }
-                               err = snd_mixer_selem_set_capture_switch_all(elem, 
!!(mask & 1 << k));
-                               if (err < 0)
-                                       break;
-                       }
-               }
-               if (err < 0)
-                       break;
-               goto __read_recsrc;
-       }
-       case SOUND_MIXER_READ_RECSRC:
-       {
-               unsigned int mask;
-               DEBUG("SOUND_MIXER_READ_RECSRC, %p) ->", arg);
-       __read_recsrc:
-               err = oss_mixer_read_recsrc(mixer, &mask);
-               *(int *)arg = mask;
-               DEBUG(" [%x]\n", mask);
-               break;
-       }
-       case SOUND_MIXER_READ_DEVMASK:
-       {
-               int k, mask = 0;
-               for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-                       snd_mixer_elem_t *elem = mixer->elems[k];
-                       if (elem && 
-                           snd_mixer_selem_has_playback_volume(elem))
-                               mask |= 1 << k;
-               }
-               *(int *)arg = mask;
-               DEBUG("SOUND_MIXER_READ_DEVMASK, %p) -> [%x]\n", arg, mask);
-               break;
-       }
-       case SOUND_MIXER_READ_RECMASK:
-       {
-               int k, mask = 0;
-               for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-                       snd_mixer_elem_t *elem = mixer->elems[k];
-                       if (elem &&
-                           snd_mixer_selem_has_capture_switch(elem))
-                               mask |= 1 << k;
-               }
-               *(int *)arg = mask;
-               DEBUG("SOUND_MIXER_READ_RECMASK, %p) -> [%x]\n", arg, mask);
-               break;
-       }
-       case SOUND_MIXER_READ_STEREODEVS:
-       {
-               int k, mask = 0;
-               for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-                       snd_mixer_elem_t *elem = mixer->elems[k];
-                       if (elem && 
-                           snd_mixer_selem_has_playback_volume(elem) &&
-                           !snd_mixer_selem_is_playback_mono(elem))
-                               mask |= 1 << k;
-               }
-               *(int *)arg = mask;
-               DEBUG("SOUND_MIXER_READ_STEREODEVS, %p) -> [%x]\n", arg, mask);
-               break;
-       }
-       case SOUND_MIXER_READ_CAPS:
-       {
-               int k;
-               *(int *)arg = 0;
-               for (k = 0; k < SOUND_MIXER_NRDEVICES; k++) {
-                       snd_mixer_elem_t *elem = mixer->elems[k];
-                       if (elem && 
-                           snd_mixer_selem_has_capture_switch_exclusive(elem)) {
-                               * (int*) arg = SOUND_CAP_EXCL_INPUT;
-                               break;
-                       }
-               }
-               DEBUG("SOUND_MIXER_READ_CAPS, %p) -> [%x]\n", arg, *(int*) arg);
-               break;
-       }
-       default:
-               if (cmd >= MIXER_WRITE(0) && cmd < MIXER_WRITE(SOUND_MIXER_NRDEVICES)) 
{
-                       snd_mixer_elem_t *elem;
-                       long lvol, rvol;
-                       dev = cmd & 0xff;
-                       lvol = *(int *)arg & 0xff;
-                       if (lvol > 100)
-                               lvol = 100;
-                       rvol = (*(int *)arg >> 8) & 0xff;
-                       if (rvol > 100)
-                               rvol = 100;
-                       DEBUG("SOUND_MIXER_WRITE[%d], %p) -> {%ld, %ld}", dev, arg, 
lvol, rvol);
-                       elem = mixer->elems[dev];
-                       if (!elem) {
-                               err = -EINVAL;
-                               break;
-                       }
-                       if (!snd_mixer_selem_has_playback_volume(elem)) {
-                               err = -EINVAL;
-                               break;
-                       }
-                       err = snd_mixer_selem_set_playback_volume(elem, 
SND_MIXER_SCHN_FRONT_LEFT, lvol);
-                       if (err < 0) 
-                               break;
-                       if (snd_mixer_selem_is_playback_mono(elem)) {
-                               if (snd_mixer_selem_has_playback_switch(elem))
-                                       err = 
snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, lvol != 0);
-                               if (err < 0) 
-                                       break;
-                       } else {
-                               err = snd_mixer_selem_set_playback_volume(elem, 
SND_MIXER_SCHN_FRONT_RIGHT, rvol);
-                               if (err < 0) 
-                                       break;
-                               if (snd_mixer_selem_has_playback_switch(elem)) {
-                                       if 
(snd_mixer_selem_has_playback_switch_joined(elem))
-                                               err = 
snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, lvol != 0 || rvol 
!= 0);
-                                       else {
-                                               err = 
snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, lvol != 0);
-                                               if (err < 0) 
-                                                       break;
-                                               err = 
snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, rvol != 0);
-                                               if (err < 0) 
-                                                       break;
-                                       }
-                               }
-                       }
-                       if (!snd_mixer_selem_has_capture_volume(elem))
-                               break;
-                       err = snd_mixer_selem_set_capture_volume(elem, 
SND_MIXER_SCHN_FRONT_LEFT, lvol);
-                       if (err < 0) 
-                               break;
-                       if (!snd_mixer_selem_is_capture_mono(elem)) {
-                               err = snd_mixer_selem_set_capture_volume(elem, 
SND_MIXER_SCHN_FRONT_RIGHT, rvol);
-                               if (err < 0) 
-                                       break;
-                       }
-                       goto __read;
-               }
-               if (cmd >= MIXER_READ(0) && cmd < MIXER_READ(SOUND_MIXER_NRDEVICES)) {
-                       snd_mixer_elem_t *elem;
-                       long lvol, rvol;
-                       int sw;
-                       dev = cmd & 0xff;
-                       DEBUG("SOUND_MIXER_READ[%d], %p) ->", dev, arg);
-               __read:
-                       elem = mixer->elems[dev];
-                       if (!elem) {
-                               err = -EINVAL;
-                               break;
-                       }
-                       if (!snd_mixer_selem_has_playback_volume(elem)) {
-                               err = -EINVAL;
-                               break;
-                       }
-                       err = snd_mixer_selem_get_playback_switch(elem, 
SND_MIXER_SCHN_FRONT_LEFT, &sw);
-                       if (err < 0) 
-                               break;
-                       if (sw) {
-                               err = snd_mixer_selem_get_playback_volume(elem, 
SND_MIXER_SCHN_FRONT_LEFT, &lvol);
-                               if (err < 0) 
-                                       break;
-                       } else
-                               lvol = 0;
-                       if (snd_mixer_selem_is_playback_mono(elem)) {
-                               rvol = lvol;
-                       } else {
-                               err = snd_mixer_selem_get_playback_switch(elem, 
SND_MIXER_SCHN_FRONT_RIGHT, &sw);
-                               if (err < 0) 
-                                       break;
-                               if (sw) {
-                                       err = 
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &rvol);
-                                       if (err < 0) 
-                                               break;
-                               } else
-                                       rvol = 0;
-                       }
-                       * (int*) arg = lvol | (rvol << 8);
-                       DEBUG("{%ld, %ld}\n", lvol, rvol);
-                       break;
-               }
-               DEBUG("%lx, %p)\n", cmd, arg);
-               err = -ENXIO;
-               break;
-       }
-       if (err >= 0)
-               return 0;
-       errno = -err;
-       return -1;
-}
-
-static int oss_mixer_fcntl(int fd, int cmd, ...)
-{
-       int result;
-       va_list args;
-       long arg;
-
-       va_start(args, cmd);
-       arg = va_arg(args, long);
-       va_end(args);
-       
-       DEBUG("fcntl(%d, ", fd);
-       result = _fcntl(fd, cmd, arg);
-       if (result < 0)
-               return result;
-       switch (cmd) {
-       case F_DUPFD:
-               DEBUG("F_DUPFD, %ld)\n", arg);
-               fds[arg] = fds[fd];
-               return result;
-       default:
-               DEBUG("%x, %ld)\n", cmd, arg);
-               return result;
-       }
-       return -1;
-}
-
-static void *oss_mixer_mmap(void *addr ATTRIBUTE_UNUSED, size_t len ATTRIBUTE_UNUSED, 
int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, int fd ATTRIBUTE_UNUSED, off_t 
offset ATTRIBUTE_UNUSED)
-{
-       errno = -EBADFD;
-       return MAP_FAILED;
-}
-
-static int oss_mixer_munmap(int fd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED, 
size_t len ATTRIBUTE_UNUSED)
-{
-       errno = -EBADFD;
+       errno = EBADFD;
        return -1;
 }
 
 static ops_t ops[FD_CLASSES] = {
-       [FD_OSS_DSP] = {
-               open: oss_open,
-               close: oss_dsp_close,
-               write: oss_dsp_write,
-               read: oss_dsp_read,
-               ioctl: oss_dsp_ioctl,
-               fcntl: oss_dsp_fcntl,
-               mmap: oss_dsp_mmap,
-               munmap: oss_dsp_munmap,
-       },
-       [FD_OSS_MIXER] = {
-               open: oss_open,
-               close: oss_mixer_close,
-               write: oss_mixer_write,
-               read: oss_mixer_read,
-               ioctl: oss_mixer_ioctl,
+        [FD_OSS_DSP] = {
+               close: lib_oss_pcm_close,
+               write: lib_oss_pcm_write,
+               read: lib_oss_pcm_read,
+               ioctl: lib_oss_pcm_ioctl,
+               fcntl: oss_pcm_fcntl,
+               mmap: lib_oss_pcm_mmap,
+               munmap: lib_oss_pcm_munmap,
+        },
+        [FD_OSS_MIXER] = {
+               close: lib_oss_mixer_close,
+               write: bad_write,
+               read: bad_read,
+               ioctl: lib_oss_mixer_ioctl,
                fcntl: oss_mixer_fcntl,
-               mmap: oss_mixer_mmap,
-               munmap: oss_mixer_munmap,
+               mmap: bad_mmap,
+               munmap: bad_munmap,
        },
 };
 
@@ -1818,7 +183,6 @@
 {
        va_list args;
        mode_t mode = 0;
-       int k;
        int fd;
 
        if (oflag & O_CREAT) {
@@ -1826,40 +190,44 @@
                mode = va_arg(args, mode_t);
                va_end(args);
        }
-       for (k = 0; k < FD_CLASSES; ++k) {
-               if (!ops[k].open)
-                       continue;
-               fd = ops[k].open(file, oflag, mode);
-               if (fd != RETRY) {
-                       if (fd >= 0)
-                               fds[fd]->count++;
-                       return fd;
-               }
+       if (!strncmp(file, "/dev/dsp", 8) ||
+           !strncmp(file, "/dev/adsp", 9) ||
+           !strncmp(file, "/dev/audio", 10)) {
+               fd = lib_oss_pcm_open(file, oflag);
+               if (fd >= 0) {
+                       fds[fd]->class = FD_OSS_DSP;
+                       poll_fds_add += lib_oss_pcm_poll_fds(fd);
+               }
+       } else if (!strncmp(file, "/dev/mixer", 10)) {
+               fd = lib_oss_mixer_open(file, oflag);
+               fds[fd]->class = FD_OSS_MIXER;
+       } else {
+               fd = _open(file, oflag, mode);
+               if (fd >= 0)
+                       assert(fds[fd] == NULL);
        }
-       fd = _open(file, oflag, mode);
-       if (fd >= 0)
-               assert(!fds[fd]);
        return fd;
 }
 
 int close(int fd)
 {
-       int result = _close(fd);
-       if (result < 0 || fd < 0 || fd >= open_max || !fds[fd])
-               return result;
-       if (--fds[fd]->count == 0) {
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL) {
+               return _close(fd);
+       } else {
+               fd_t *xfd = fds[fd];
                int err;
-               err = ops[fds[fd]->class].close(fd);
+               
+               fds[fd] = NULL;
+               poll_fds_add -= lib_oss_pcm_poll_fds(fd);
+               err = ops[xfd->class].close(fd);
                assert(err >= 0);
-               free(fds[fd]);
+               return err;
        }
-       fds[fd] = 0;
-       return result;
 }
 
 ssize_t write(int fd, const void *buf, size_t n)
 {
-       if (fd < 0 || fd >= open_max || !fds[fd])
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL)
                return _write(fd, buf, n);
        else
                return ops[fds[fd]->class].write(fd, buf, n);
@@ -1867,7 +235,7 @@
 
 ssize_t read(int fd, void *buf, size_t n)
 {
-       if (fd < 0 || fd >= open_max || !fds[fd])
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL)
                return _read(fd, buf, n);
        else
                return ops[fds[fd]->class].read(fd, buf, n);
@@ -1881,7 +249,7 @@
        va_start(args, request);
        arg = va_arg(args, void *);
        va_end(args);
-       if (fd < 0 || fd >= open_max || !fds[fd])
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL)
                return _ioctl(fd, request, arg);
        else 
                return ops[fds[fd]->class].ioctl(fd, request, arg);
@@ -1895,7 +263,7 @@
        va_start(args, cmd);
        arg = va_arg(args, void *);
        va_end(args);
-       if (fd < 0 || fd >= open_max || !fds[fd])
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL)
                return _fcntl(fd, cmd, arg);
        else
                return ops[fds[fd]->class].fcntl(fd, cmd, arg);
@@ -1904,7 +272,7 @@
 void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
 {
        void *result;
-       if (fd < 0 || fd >= open_max || !fds[fd])
+       if (fd < 0 || fd >= open_max || fds[fd] == NULL)
                return _mmap(addr, len, prot, flags, fd, offset);
        result = ops[fds[fd]->class].mmap(addr, len, prot, flags, fd, offset);
        if (result != NULL && result != MAP_FAILED)
@@ -1922,7 +290,7 @@
        if (fd >= open_max)
                return _munmap(addr, len);
        fds[fd]->mmap_area = 0;
-       return ops[fds[fd]->class].munmap(fd, addr, len);
+       return ops[fds[fd]->class].munmap(addr, len);
 }
 
 #ifdef DEBUG_POLL
@@ -1980,22 +348,13 @@
 }
 #endif
 
-int snd_pcm_poll_descriptor(snd_pcm_t *pcm)
-{
-       int err;
-       struct pollfd pfds[2];
-       err = snd_pcm_poll_descriptors(pcm, pfds, 2);
-       assert(err == 1);
-       return pfds[0].fd;
-}
-
 int poll(struct pollfd *pfds, unsigned long nfds, int timeout)
 {
        unsigned int k;
        unsigned int nfds1;
        int count, count1;
        int direct = 1;
-       struct pollfd pfds1[nfds * 2];
+       struct pollfd pfds1[nfds + poll_fds_add + 16];
        nfds1 = 0;
        for (k = 0; k < nfds; ++k) {
                int fd = pfds[k].fd;
@@ -2005,18 +364,8 @@
                switch (fds[fd]->class) {
                case FD_OSS_DSP:
                {
-                       oss_dsp_t *dsp = fds[fd]->private;
-                       oss_dsp_stream_t *str;
-                       int j;
-                       for (j = 0; j < 2; ++j) {
-                               str = &dsp->streams[j];
-                               if (str->pcm) {
-                                       pfds1[nfds1].fd = 
snd_pcm_poll_descriptor(str->pcm);
-                                       pfds1[nfds1].events = pfds[k].events;
-                                       pfds1[nfds1].revents = 0;
-                                       nfds1++;
-                               }
-                       }
+                       lib_oss_pcm_poll_prepare(fd, &pfds1[nfds1]);
+                       nfds1 += lib_oss_pcm_poll_fds(fd);
                        direct = 0;
                        break;
                }
@@ -2032,7 +381,7 @@
        if (direct)
                return _poll(pfds, nfds, timeout);
 #ifdef DEBUG_POLL
-       if (debug) {
+       if (alsa_oss_debug) {
                fprintf(stderr, "Orig enter ");
                dump_poll(pfds, nfds, timeout);
                fprintf(stderr, "Changed enter ");
@@ -2052,16 +401,14 @@
                switch (fds[fd]->class) {
                case FD_OSS_DSP:
                {
-                       oss_dsp_t *dsp = fds[fd]->private;
-                       oss_dsp_stream_t *str;
-                       int j;
+                       int result = lib_oss_pcm_poll_result(fd, &pfds1[nfds1]);
                        revents = 0;
-                       for (j = 0; j < 2; ++j) {
-                               str = &dsp->streams[j];
-                               if (str->pcm) {
-                                       revents |= pfds1[nfds1].revents;
-                                       nfds1++;
-                               }
+                       if (result < 0) {
+                               revents |= POLLNVAL;
+                       } else {
+                               revents |= ((result & OSS_WAIT_EVENT_ERROR) ? POLLERR 
: 0) |
+                                          ((result & OSS_WAIT_EVENT_READ) ? POLLIN : 
0) |
+                                          ((result & OSS_WAIT_EVENT_WRITE) ? POLLOUT 
: 0);
                        }
                        break;
                }
@@ -2076,7 +423,7 @@
                        count1++;
        }
 #ifdef DEBUG_POLL
-       if (debug) {
+       if (alsa_oss_debug) {
                fprintf(stderr, "Changed exit ");
                dump_poll(pfds1, nfds1, timeout);
                fprintf(stderr, "Orig exit ");
@@ -2121,29 +468,9 @@
                switch (fds[fd]->class) {
                case FD_OSS_DSP:
                {
-                       oss_dsp_t *dsp = fds[fd]->private;
-                       oss_dsp_stream_t *str;
-                       int j;
-                       if (r)
-                               FD_CLR(fd, rfds1);
-                       if (w)
-                               FD_CLR(fd, wfds1);
-                       if (e)
-                               FD_CLR(fd, efds1);
-                       for (j = 0; j < 2; ++j) {
-                               str = &dsp->streams[j];
-                               if (str->pcm) {
-                                       int fd1 = snd_pcm_poll_descriptor(str->pcm);
-                                       if (fd1 >= nfds1)
-                                               nfds1 = fd1 + 1;
-                                       if (r)
-                                               FD_SET(fd1, rfds1);
-                                       if (w)
-                                               FD_SET(fd1, wfds1);
-                                       if (e)
-                                               FD_SET(fd1, efds1);
-                               }
-                       }
+                       lib_oss_pcm_select_prepare(fd, r ? rfds1 : NULL,
+                                                      w ? wfds1 : NULL,
+                                                      e ? efds1 : NULL);
                        direct = 0;
                        break;
                }
@@ -2154,7 +481,7 @@
        if (direct)
                return _select(nfds, rfds, wfds, efds, timeout);
 #ifdef DEBUG_SELECT
-       if (debug) {
+       if (alsa_oss_debug) {
                fprintf(stderr, "Orig enter ");
                dump_select(nfds, rfds, wfds, efds, timeout);
                fprintf(stderr, "Changed enter ");
@@ -2186,21 +513,20 @@
                switch (fds[fd]->class) {
                case FD_OSS_DSP:
                {
-                       oss_dsp_t *dsp = fds[fd]->private;
-                       oss_dsp_stream_t *str;
-                       int j;
+                       int result = lib_oss_pcm_select_result(fd, rfds1, wfds1, 
efds1);
                        r1 = w1 = e1 = 0;
-                       for (j = 0; j < 2; ++j) {
-                               str = &dsp->streams[j];
-                               if (str->pcm) {
-                                       int fd1 = snd_pcm_poll_descriptor(str->pcm);
-                                       if (r && FD_ISSET(fd1, rfds1))
-                                               r1++;
-                                       if (w && FD_ISSET(fd1, wfds1))
-                                               w1++;
-                                       if (e && FD_ISSET(fd1, efds1))
-                                               e1++;
-                               }
+                       if (result < 0 && e) {
+                               FD_SET(fd, efds);
+                               e1 = 1;
+                       } else if (result & OSS_WAIT_EVENT_ERROR) {
+                               FD_SET(fd, efds);
+                               e1 = 1;
+                       } else if (result & OSS_WAIT_EVENT_READ) {
+                               FD_SET(fd, rfds);
+                               r1 = 1;
+                       } else if (result & OSS_WAIT_EVENT_WRITE) {
+                               FD_SET(fd, wfds);
+                               w1 = 1;
                        }
                        break;
                }
@@ -2220,7 +546,7 @@
                        count1++;
        }
 #ifdef DEBUG_SELECT
-       if (debug) {
+       if (alsa_oss_debug) {
                fprintf(stderr, "Changed exit ");
                dump_select(nfds1, rfds1, wfds1, efds1, timeout);
                fprintf(stderr, "Orig exit ");
@@ -2293,9 +619,12 @@
 
 static void initialize()
 {
-       char *s = getenv("ALSA_OSS_DEBUG");
+       char *s = getenv("ALSA_OSS_WRAPPER");
+       if (s == NULL)
+               return;
+       s = getenv("ALSA_OSS_DEBUG");
        if (s)
-               debug = 1;
+               alsa_oss_debug = 1;
        open_max = sysconf(_SC_OPEN_MAX);
        if (open_max < 0)
                exit(1);
@@ -2313,4 +642,3 @@
        _select = dlsym(RTLD_NEXT, "select");
        _poll = dlsym(RTLD_NEXT, "poll");
 }
-

Index: aoss.in
===================================================================
RCS file: /cvsroot/alsa/alsa-oss/alsa/aoss.in,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- aoss.in     9 Feb 2004 12:36:39 -0000       1.1
+++ aoss.in     10 Feb 2004 13:39:55 -0000      1.2
@@ -6,4 +6,4 @@
 
 [EMAIL PROTECTED]@
 [EMAIL PROTECTED]@
[EMAIL PROTECTED]@/libaoss.so $*
+ALSA_OSS_WRAPPER=1 [EMAIL PROTECTED]@/libaoss.so $*



-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to