OSS driver fixes

Eric Pouech eric.pouech at wanadoo.fr
Tue Jun 25 14:11:32 CDT 2002


this patch better implements the full duplex mode for OSS devices (when
reusing an existing opened device, we didn't check that the parameters
where the same)
however, the code when different parameters are to be used for input &
output doesn't do nothing special yet (it could map the buffers to the
first set of parameters format)
the patch also starts to implement proper support for several sound
cards

full duplex (if needed) can still be disabled by commenting the right
#define (USE_FULLDUPLEX)

A+
-------------- next part --------------
Name:          oss_audio
ChangeLog:     ensured full duplex mode is only used with same parameters in in/out streams
	some more work towards multiple audio cards support
License:       X11
GenDate:       2002/06/25 19:07:49 UTC
ModifiedFiles: dlls/winmm/wineoss/audio.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/wineoss/audio.c,v
retrieving revision 1.57
diff -u -u -r1.57 audio.c
--- dlls/winmm/wineoss/audio.c	31 May 2002 23:40:57 -0000	1.57
+++ dlls/winmm/wineoss/audio.c	1 Jun 2002 03:34:27 -0000
@@ -60,11 +60,7 @@
 
 #ifdef HAVE_OSS
 
-#define SOUND_DEV "/dev/dsp"
-#define MIXER_DEV "/dev/mixer"
-
-#define MAX_WAVEOUTDRV 	(1)
-#define MAX_WAVEINDRV 	(1)
+#define MAX_WAVEDRV 	(1)
 
 /* state diagram for waveOut writing:
  *
@@ -121,7 +117,6 @@
     WAVEOPENDESC		waveDesc;
     WORD			wFlags;
     PCMWAVEFORMAT		format;
-    WAVEOUTCAPSA		caps;
 
     /* OSS information */
     DWORD			dwFragmentSize;		/* size of OSS buffer fragment */
@@ -156,7 +151,6 @@
     PCMWAVEFORMAT		format;
     LPWAVEHDR			lpQueuePtr;
     DWORD			dwTotalRecorded;
-    WAVEINCAPSA			caps;
     BOOL                        bTriggerSupport;
 
     /* synchronization stuff */
@@ -166,8 +160,10 @@
     OSS_MSG_RING		msgRing;
 } WINE_WAVEIN;
 
-static WINE_WAVEOUT	WOutDev   [MAX_WAVEOUTDRV];
-static WINE_WAVEIN	WInDev    [MAX_WAVEINDRV ];
+static WINE_WAVEOUT	WOutDev   [MAX_WAVEDRV];
+static WINE_WAVEIN	WInDev    [MAX_WAVEDRV];
+static unsigned         numOutDev;
+static unsigned         numInDev;
 
 static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
 
@@ -186,13 +182,26 @@
  *                  Low level WAVE implementation			*
  *======================================================================*/
 #define USE_FULLDUPLEX
+
+typedef struct tagOSS_DEVICE {
+    const char*         dev_name;
+    const char*         mixer_name;
+    unsigned            open_count;
+    WAVEOUTCAPSA        out_caps;
+    WAVEINCAPSA		in_caps;
 #ifdef USE_FULLDUPLEX
-static unsigned OSS_OpenCount /* = 0 */;  /* number of times fd has been opened */
-static unsigned OSS_OpenAccess /* = 0 */; /* access used for opening... used to handle compat */
-static int      OSS_OpenFD;
-static DWORD    OSS_OwnerThreadID /* = 0 */;
+    unsigned            open_access;
+    int                 fd;
+    DWORD               owner_tid;
+    unsigned            sample_rate;
+    unsigned            stereo;
+    unsigned            format;
+    unsigned            audio_fragment;
 #endif
-static BOOL     OSS_FullDuplex;           /* set to non-zero if the device supports full duplex */
+    BOOL                full_duplex;
+} OSS_DEVICE;
+
+OSS_DEVICE   OSS_Devices[MAX_WAVEDRV];
 
 /******************************************************************
  *		OSS_OpenDevice
@@ -201,50 +210,107 @@
  * open the device for both waveout and wavein streams...
  * this is hackish, but it's the way OSS interface is done...
  */
-static int	OSS_OpenDevice(unsigned wDevID, unsigned req_access)
+static DWORD	OSS_OpenDevice(unsigned wDevID, int* pfd, unsigned req_access,
+                               int* frag, int sample_rate, int stereo, int fmt)
 {
-    /* wDevID: is not used yet, we handle only one global device /dev/dsp */
-#ifdef USE_FULLDUPLEX
-    /* FIXME: race */
-    if (OSS_OpenCount == 0)
+    OSS_DEVICE* ossdev;
+    int         val;
+    int         fd = -1;
+
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_BADDEVICEID;;
+    ossdev = &OSS_Devices[wDevID];
+
+    if (ossdev->full_duplex && (req_access == O_RDONLY || req_access == O_WRONLY))
+        req_access = O_RDWR;
+
+    /* FIXME: race with close */
+    if (ossdev->open_count == 0)
     {
-	if (access(SOUND_DEV, 0) != 0 ||
-            (OSS_OpenFD = open(SOUND_DEV, req_access|O_NDELAY, 0)) == -1)
+	if (access(ossdev->dev_name, 0) != 0) return MMSYSERR_NODRIVER;
+
+        if ((fd = open(ossdev->dev_name, req_access|O_NDELAY, 0)) == -1)
 	{
-	    WARN("Couldn't open out %s (%s)\n", SOUND_DEV, strerror(errno));
-	    return -1;
+	    WARN("Couldn't open out %s (%s)\n", ossdev->dev_name, strerror(errno));
+	    return (errno == EBUSY) ? MMSYSERR_ALLOCATED : MMSYSERR_ERROR;
 	}
+        fcntl(fd, F_SETFD, 1); /* set close on exec flag */
 	/* turn full duplex on if it has been requested */
-	if (req_access == O_RDWR && OSS_FullDuplex)
-	    ioctl(OSS_OpenFD, SNDCTL_DSP_SETDUPLEX, 0);
-	OSS_OpenAccess = req_access;
-        OSS_OwnerThreadID = GetCurrentThreadId();
+	if (req_access == O_RDWR && ossdev->full_duplex)
+	    ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
+
+        if (frag)       ioctl(fd, SNDCTL_DSP_SETFRAGMENT, frag);
+
+        /* First size and stereo then samplerate */
+        if (fmt)
+        {
+            val = fmt;
+            ioctl(fd, SNDCTL_DSP_SETFMT, &val);
+            if (val != fmt)
+                ERR("Can't set format to %d (%d)\n", fmt, val);
+        }
+        if (stereo)
+        {
+            val = stereo;
+            ioctl(fd, SNDCTL_DSP_STEREO, &val);
+            if (val != stereo)
+                ERR("Can't set stereo to %u (%d)\n", stereo, val);
+        }
+        if (sample_rate)
+        {
+            val = sample_rate;
+            ioctl(fd, SNDCTL_DSP_SPEED, &sample_rate);
+            if (!NEAR_MATCH(val, sample_rate))
+                ERR("Can't set sample_rate to %u (%d)\n", sample_rate, val);
+        }
+#ifdef USE_FULLDUPLEX
+        ossdev->audio_fragment = (frag) ? *frag : 0;
+        ossdev->sample_rate = sample_rate;
+        ossdev->stereo = stereo;
+        ossdev->format = fmt;
+        ossdev->open_access = req_access;
+        ossdev->owner_tid = GetCurrentThreadId();
+        ossdev->fd = fd;
+#endif
     }
     else
     {
-        if (OSS_OpenAccess != req_access)
+#ifdef USE_FULLDUPLEX
+        /* check we really open with the same parameters */
+        if (ossdev->open_access != req_access)
         {
             WARN("Mismatch in access...\n");
-            return -1;
+            return WAVERR_BADFORMAT;
+        }
+        /* FIXME: if really needed, we could do, in this case, on the fly
+         * PCM conversion (using the MSACM ad hoc driver)
+         */
+        if (ossdev->audio_fragment != (frag ? *frag : 0) ||
+            ossdev->sample_rate != sample_rate ||
+            ossdev->stereo != stereo ||
+            ossdev->format != fmt)
+        {
+            WARN("FullDuplex: mismatch in PCM parameters for input and output\n"
+                 "OSS doesn't allow us different parameters\n"
+                 "audio_frag(%x/%x) sample_rate(%d/%d) stereo(%d/%d) fmt(%d/%d)\n",
+                 ossdev->audio_fragment, frag ? *frag : 0, 
+                 ossdev->sample_rate, sample_rate,
+                 ossdev->stereo, stereo,
+                 ossdev->format, fmt);
+            return WAVERR_BADFORMAT;
         }
-        if (GetCurrentThreadId() != OSS_OwnerThreadID)
+        if (GetCurrentThreadId() != ossdev->owner_tid)
         {
             WARN("Another thread is trying to access audio...\n");
-            return -1;
+            return MMSYSERR_ERROR;
         }
+#endif
     }
 
-    OSS_OpenCount++;
-    return OSS_OpenFD;
-#else
-    int fd;
-    if (access(SOUND_DEV, 0) != 0 || (fd = open(SOUND_DEV, req_access|O_NDELAY, 0)) == -1)
-    {
-        WARN("Couldn't open out %s (%s)\n", SOUND_DEV, strerror(errno));
-        return -1;
-    }
-    return fd;
+#ifdef USE_FULLDUPLEX
+    ossdev->open_count++;
 #endif
+    *pfd = fd;
+    return MMSYSERR_NOERROR;
 }
 
 /******************************************************************
@@ -254,47 +320,39 @@
  */
 static void	OSS_CloseDevice(unsigned wDevID, int fd)
 {
-    /* wDevID: is not used yet, we handle only one global device /dev/dsp */
+    OSS_DEVICE* ossdev;
+
+    if (wDevID >= MAX_WAVEDRV) return;
 #ifdef USE_FULLDUPLEX
-    if (fd != OSS_OpenFD) FIXME("What the heck????\n");
-    if (--OSS_OpenCount == 0)
-    {
-	close(OSS_OpenFD);
-    }
+    ossdev = &OSS_Devices[wDevID];
+    if (fd != ossdev->fd) FIXME("What the heck????\n");
+    if (--ossdev->open_count == 0) close(ossdev->fd);
 #else
+    /* wDevID: is not used yet, we handle only one global device /dev/dsp */
     close(fd);
 #endif
 }
 
 /******************************************************************
- *		OSS_WaveInit
+ *		OSS_WaveOutInit
+ *
  *
- * Initialize internal structures from OSS information
  */
-LONG OSS_WaveInit(void)
+static void     OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
 {
-    int 	audio;
-    int		smplrate;
-    int		samplesize = 16;
-    int		dsp_stereo = 1;
-    int		bytespersmpl;
-    int 	caps;
-    int		mask;
-    int 	i;
-
-
-    /* start with output device */
+    int                 audio;
+    int	                smplrate;
+    int	                samplesize = 16;
+    int	                dsp_stereo = 1;
+    int	                bytespersmpl;
+    int                 caps;
+    int                 mask;
 
-    /* initialize all device handles to -1 */
-    for (i = 0; i < MAX_WAVEOUTDRV; ++i)
-    {
-	WOutDev[i].unixdev = -1;
-    }
-
-    /* FIXME: only one device is supported */
-    memset(&WOutDev[0].caps, 0, sizeof(WOutDev[0].caps));
+    WOutDev[devID].unixdev = -1;
+    memset(&ossdev->out_caps, 0, sizeof(ossdev->out_caps));
 
-    if ((audio = OSS_OpenDevice(0, O_WRONLY)) == -1) return -1;
+    if (OSS_OpenDevice(devID, &audio, O_WRONLY, NULL, 0, 0, 0) != 0) return;
+    numOutDev++;
 
     ioctl(audio, SNDCTL_DSP_RESET, 0);
 
@@ -303,113 +361,127 @@
      * (e.g. MS win9x mplayer.exe)
      */
 #ifdef EMULATE_SB16
-    WOutDev[0].caps.wMid = 0x0002;
-    WOutDev[0].caps.wPid = 0x0104;
-    strcpy(WOutDev[0].caps.szPname, "SB16 Wave Out");
+    ossdev->out_caps.wMid = 0x0002;
+    ossdev->out_caps.wPid = 0x0104;
+    strcpy(ossdev->out_caps.szPname, "SB16 Wave Out");
 #else
-    WOutDev[0].caps.wMid = 0x00FF; 	/* Manufac ID */
-    WOutDev[0].caps.wPid = 0x0001; 	/* Product ID */
-    /*    strcpy(WOutDev[0].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
-    strcpy(WOutDev[0].caps.szPname, "CS4236/37/38");
+    ossdev->out_caps.wMid = 0x00FF; 	/* Manufac ID */
+    ossdev->out_caps.wPid = 0x0001; 	/* Product ID */
+    /*    strcpy(ossdev->out_caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
+    strcpy(ossdev->out_caps.szPname, "CS4236/37/38");
 #endif
-    WOutDev[0].caps.vDriverVersion = 0x0100;
-    WOutDev[0].caps.dwFormats = 0x00000000;
-    WOutDev[0].caps.dwSupport = WAVECAPS_VOLUME;
-
+    ossdev->out_caps.vDriverVersion = 0x0100;
+    ossdev->out_caps.dwFormats = 0x00000000;
+    ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
+    
     ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
     TRACE("OSS dsp out mask=%08x\n", mask);
 
     /* First bytespersampl, then stereo */
     bytespersmpl = (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
-
-    WOutDev[0].caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
-    if (WOutDev[0].caps.wChannels > 1) WOutDev[0].caps.dwSupport |= WAVECAPS_LRVOLUME;
-
+    
+    ossdev->out_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
+    if (ossdev->out_caps.wChannels > 1) ossdev->out_caps.dwSupport |= WAVECAPS_LRVOLUME;
+    
     smplrate = 44100;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4M08;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4S08;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_4M08;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_4S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4M16;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4S16;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_4M16;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_4S16;
 	}
     }
     smplrate = 22050;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2M08;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2S08;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_2M08;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_2S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2M16;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2S16;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_2M16;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_2S16;
 	}
     }
     smplrate = 11025;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1M08;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1S08;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_1M08;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1M16;
-	    if (WOutDev[0].caps.wChannels > 1)
-		WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1S16;
+	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_1M16;
+	    if (ossdev->out_caps.wChannels > 1)
+		ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S16;
 	}
     }
     if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
 	TRACE("OSS dsp out caps=%08X\n", caps);
 	if ((caps & DSP_CAP_REALTIME) && !(caps & DSP_CAP_BATCH)) {
-	    WOutDev[0].caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;
+	    ossdev->out_caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;
 	}
 	/* well, might as well use the DirectSound cap flag for something */
 	if ((caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
 	    !(caps & DSP_CAP_BATCH))
-	    WOutDev[0].caps.dwSupport |= WAVECAPS_DIRECTSOUND;
+	    ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
     }
-    OSS_CloseDevice(0, audio);
+    OSS_CloseDevice(devID, audio);
     TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
-	  WOutDev[0].caps.dwFormats, WOutDev[0].caps.dwSupport);
+	  ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);
 
-    /* then do input device */
-    samplesize = 16;
-    dsp_stereo = 1;
+}
 
-    for (i = 0; i < MAX_WAVEINDRV; ++i)
-    {
-        WInDev[i].unixdev = -1;
-    }
+/******************************************************************
+ *		OSS_WaveInInit
+ *
+ *
+ */
+static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
+{
+    int                 audio;
+    int	                smplrate;
+    int	                samplesize = 16;
+    int	                dsp_stereo = 1;
+    int	                bytespersmpl;
+    int                 caps;
+    int                 mask;
 
-    memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps));
+    samplesize = 16;
+    dsp_stereo = 1;
+   
+    WInDev[devID].unixdev = -1;
+    
+    memset(&ossdev->in_caps, 0, sizeof(ossdev->in_caps));
 
-    if ((audio = OSS_OpenDevice(0, O_RDONLY)) == -1) return -1;
+    if (OSS_OpenDevice(0, &audio, O_RDONLY, NULL, 0, 0, 0) != 0) return;
+    numInDev++;
 
     ioctl(audio, SNDCTL_DSP_RESET, 0);
 
 #ifdef EMULATE_SB16
-    WInDev[0].caps.wMid = 0x0002;
-    WInDev[0].caps.wPid = 0x0004;
-    strcpy(WInDev[0].caps.szPname, "SB16 Wave In");
+    ossdev->in_caps.wMid = 0x0002;
+    ossdev->in_caps.wPid = 0x0004;
+    strcpy(ossdev->in_caps.szPname, "SB16 Wave In");
 #else
-    WInDev[0].caps.wMid = 0x00FF; 	/* Manufac ID */
-    WInDev[0].caps.wPid = 0x0001; 	/* Product ID */
-    strcpy(WInDev[0].caps.szPname, "OpenSoundSystem WAVIN Driver");
+    ossdev->in_caps.wMid = 0x00FF; 	/* Manufac ID */
+    ossdev->in_caps.wPid = 0x0001; 	/* Product ID */
+    strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
 #endif
-    WInDev[0].caps.dwFormats = 0x00000000;
-    WInDev[0].caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
-
-    WInDev[0].bTriggerSupport = FALSE;
+    ossdev->in_caps.dwFormats = 0x00000000;
+    ossdev->in_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
+    
+    WInDev[devID].bTriggerSupport = FALSE;
     if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
 	TRACE("OSS dsp in caps=%08X\n", caps);
 	if (caps & DSP_CAP_TRIGGER)
-            WInDev[0].bTriggerSupport = TRUE;
+            WInDev[devID].bTriggerSupport = TRUE;
     }
 
     ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
@@ -419,52 +491,91 @@
     smplrate = 44100;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_4M08;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_4S08;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_4M08;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_4S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_4M16;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_4S16;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_4M16;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_4S16;
 	}
     }
     smplrate = 22050;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_2M08;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_2S08;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_2M08;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_2S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_2M16;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_2S16;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_2M16;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_2S16;
 	}
     }
     smplrate = 11025;
     if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_1M08;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_1S08;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_1M08;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S08;
 	}
 	if ((mask & AFMT_S16_LE) && bytespersmpl > 1) {
-	    WInDev[0].caps.dwFormats |= WAVE_FORMAT_1M16;
-	    if (WInDev[0].caps.wChannels > 1)
-		WInDev[0].caps.dwFormats |= WAVE_FORMAT_1S16;
+	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_1M16;
+	    if (ossdev->in_caps.wChannels > 1)
+		ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S16;
 	}
     }
-    OSS_CloseDevice(0, audio);
-    TRACE("in dwFormats = %08lX\n", WInDev[0].caps.dwFormats);
+    OSS_CloseDevice(devID, audio);
+    TRACE("in dwFormats = %08lX\n", ossdev->in_caps.dwFormats);
+}
 
+/******************************************************************
+ *		OSS_WaveFullDuplexInit
+ *
+ *
+ */
+static void OSS_WaveFullDuplexInit(unsigned devID, OSS_DEVICE* ossdev)
+{
 #ifdef USE_FULLDUPLEX
-    if ((audio = OSS_OpenDevice(0, O_RDWR)) == -1) return -1;
-    if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
-	OSS_FullDuplex = (caps & DSP_CAP_DUPLEX);
+    int 	audio;
+    int 	caps;
+
+    if (OSS_OpenDevice(devID, &audio, O_RDWR, NULL, 0, 0, 0) != 0) return;
+    if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) 
+    {
+	ossdev->full_duplex = (caps & DSP_CAP_DUPLEX);
     }
-    OSS_CloseDevice(0, audio);
+    OSS_CloseDevice(devID, audio);
 #endif
+}
+
+/******************************************************************
+ *		OSS_WaveInit
+ *
+ * Initialize internal structures from OSS information
+ */
+LONG OSS_WaveInit(void)
+{
+    int 	i;
+
+    /* FIXME: only one device is supported */
+    memset(&OSS_Devices, 0, sizeof(OSS_Devices));
+    OSS_Devices[0].dev_name = "/dev/dsp";
+    OSS_Devices[0].mixer_name = "/dev/mixer";
+    
+    /* start with output device */
+    for (i = 0; i < MAX_WAVEDRV; ++i)
+        OSS_WaveOutInit(i, &OSS_Devices[i]);
+
+    /* then do input device */
+    for (i = 0; i < MAX_WAVEDRV; ++i)
+        OSS_WaveInInit(i, &OSS_Devices[i]);
+
+    /* finish with the full duplex bits */
+    for (i = 0; i < MAX_WAVEDRV; i++)
+        OSS_WaveFullDuplexInit(i, &OSS_Devices[i]);
 
     return 0;
 }
@@ -1019,13 +1150,13 @@
     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
 
     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
-
-    if (wDevID >= MAX_WAVEOUTDRV) {
-	TRACE("MAX_WAVOUTDRV reached !\n");
+    
+    if (wDevID >= MAX_WAVEDRV) {
+	TRACE("MAX_WAVDRV reached !\n");
 	return MMSYSERR_BADDEVICEID;
     }
 
-    memcpy(lpCaps, &WOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
+    memcpy(lpCaps, &OSS_Devices[wDevID].out_caps, min(dwSize, sizeof(*lpCaps)));
     return MMSYSERR_NOERROR;
 }
 
@@ -1034,19 +1165,17 @@
  */
 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
 {
-    int			format;
-    int			sample_rate;
-    int			dsp_stereo;
     int			audio_fragment;
     WINE_WAVEOUT*	wwo;
     audio_buf_info      info;
+    DWORD               ret;
 
     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
     if (lpDesc == NULL) {
 	WARN("Invalid Parameter !\n");
 	return MMSYSERR_INVALPARAM;
     }
-    if (wDevID >= MAX_WAVEOUTDRV) {
+    if (wDevID >= MAX_WAVEDRV) {
 	TRACE("MAX_WAVOUTDRV reached !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1070,36 +1199,12 @@
 
     wwo = &WOutDev[wDevID];
 
-    if ((dwFlags & WAVE_DIRECTSOUND) && !(wwo->caps.dwSupport & WAVECAPS_DIRECTSOUND))
+    if ((dwFlags & WAVE_DIRECTSOUND) && !(OSS_Devices[wDevID].out_caps.dwSupport & WAVECAPS_DIRECTSOUND))
 	/* not supported, ignore it */
 	dwFlags &= ~WAVE_DIRECTSOUND;
 
-    if (access(SOUND_DEV, 0) != 0)
-	return MMSYSERR_NOTENABLED;
-    if (wwo->unixdev != -1) return MMSYSERR_ALLOCATED;
-    /* we want to be able to mmap() the device, which means it must be opened readable,
-     * otherwise mmap() will fail (at least under Linux) */
-    wwo->unixdev = OSS_OpenDevice(wDevID,
-                                  ((dwFlags & WAVE_DIRECTSOUND) || OSS_FullDuplex) ?
-                                  O_RDWR : O_WRONLY);
-    if (wwo->unixdev == -1) return MMSYSERR_ALLOCATED;
-
-    fcntl(wwo->unixdev, F_SETFD, 1); /* set close on exec flag */
-    wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
-
-    memcpy(&wwo->waveDesc, lpDesc, 	     sizeof(WAVEOPENDESC));
-    memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
-
-    if (wwo->format.wBitsPerSample == 0) {
-	WARN("Resetting zeroed wBitsPerSample\n");
-	wwo->format.wBitsPerSample = 8 *
-	    (wwo->format.wf.nAvgBytesPerSec /
-	     wwo->format.wf.nSamplesPerSec) /
-	    wwo->format.wf.nChannels;
-    }
-
     if (dwFlags & WAVE_DIRECTSOUND) {
-        if (wwo->caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
+        if (OSS_Devices[wDevID].out_caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
 	    /* we have realtime DirectSound, fragments just waste our time,
 	     * but a large buffer is good, so choose 64KB (32 * 2^11) */
 	    audio_fragment = 0x0020000B;
@@ -1114,27 +1219,29 @@
 	/* 16 fragments max, 2^10=1024 bytes per fragment */
 	audio_fragment = 0x000F000A;
     }
-    sample_rate = wwo->format.wf.nSamplesPerSec;
-    dsp_stereo = (wwo->format.wf.nChannels > 1) ? 1 : 0;
-    format = (wwo->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8;
-
-    ioctl(wwo->unixdev, SNDCTL_DSP_SETFRAGMENT, &audio_fragment);
-    /* First size and stereo then samplerate */
-    ioctl(wwo->unixdev, SNDCTL_DSP_SETFMT, &format);
-    ioctl(wwo->unixdev, SNDCTL_DSP_STEREO, &dsp_stereo);
-    ioctl(wwo->unixdev, SNDCTL_DSP_SPEED, &sample_rate);
-
-    /* paranoid checks */
-    if (format != ((wwo->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8))
-	ERR("Can't set format to %d (%d)\n",
-	    (wwo->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8, format);
-    if (dsp_stereo != (wwo->format.wf.nChannels > 1) ? 1 : 0)
-	ERR("Can't set stereo to %u (%d)\n",
-	    (wwo->format.wf.nChannels > 1) ? 1 : 0, dsp_stereo);
-    if (!NEAR_MATCH(sample_rate, wwo->format.wf.nSamplesPerSec))
-	ERR("Can't set sample_rate to %lu (%d)\n",
-	    wwo->format.wf.nSamplesPerSec, sample_rate);
+    if (wwo->unixdev != -1) return MMSYSERR_ALLOCATED;
+    /* we want to be able to mmap() the device, which means it must be opened readable,
+     * otherwise mmap() will fail (at least under Linux) */
+    ret = OSS_OpenDevice(wDevID, &wwo->unixdev,
+                         (dwFlags & WAVE_DIRECTSOUND) ? O_RDWR : O_WRONLY,
+                         &audio_fragment, lpDesc->lpFormat->nSamplesPerSec,
+                         (lpDesc->lpFormat->nChannels > 1) ? 1 : 0,
+                         (lpDesc->lpFormat->wBitsPerSample == 16) 
+                             ? AFMT_S16_LE : AFMT_U8);
+    if (ret != 0) return ret;
+
+    wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
+
+    memcpy(&wwo->waveDesc, lpDesc, 	     sizeof(WAVEOPENDESC));
+    memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
 
+    if (wwo->format.wBitsPerSample == 0) {
+	WARN("Resetting zeroed wBitsPerSample\n");
+	wwo->format.wBitsPerSample = 8 *
+	    (wwo->format.wf.nAvgBytesPerSec /
+	     wwo->format.wf.nSamplesPerSec) /
+	    wwo->format.wf.nChannels;
+    }
     /* Read output space info for future reference */
     if (ioctl(wwo->unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {
 	ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n");
@@ -1192,8 +1299,8 @@
     WINE_WAVEOUT*	wwo;
 
     TRACE("(%u);\n", wDevID);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1230,7 +1337,7 @@
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
 
     /* first, do the sanity checks... */
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
         WARN("bad dev ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1245,6 +1352,12 @@
     lpWaveHdr->dwFlags |= WHDR_INQUEUE;
     lpWaveHdr->lpNext = 0;
 
+    if ((lpWaveHdr->dwBufferLength & ~(WOutDev[wDevID].format.wf.nBlockAlign - 1)) != 0)
+    {
+        WARN("WaveHdr length isn't a multiple of the PCM block size\n");
+        lpWaveHdr->dwBufferLength &= ~(WOutDev[wDevID].format.wf.nBlockAlign - 1);
+    }
+
     OSS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
 
     return MMSYSERR_NOERROR;
@@ -1256,8 +1369,8 @@
 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
-
-    if (wDevID >= MAX_WAVEOUTDRV) {
+    
+    if (wDevID >= MAX_WAVEDRV) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1276,8 +1389,8 @@
 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
-
-    if (wDevID >= MAX_WAVEOUTDRV) {
+    
+    if (wDevID >= MAX_WAVEDRV) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1297,8 +1410,8 @@
 static DWORD wodPause(WORD wDevID)
 {
     TRACE("(%u);!\n", wDevID);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1314,8 +1427,8 @@
 static DWORD wodRestart(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1336,8 +1449,8 @@
 static DWORD wodReset(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1357,8 +1470,8 @@
     WINE_WAVEOUT*	wwo;
 
     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1415,8 +1528,8 @@
 static DWORD wodBreakLoop(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-
-    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].unixdev == -1) {
+    
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1437,7 +1550,9 @@
 
     if (lpdwVol == NULL)
 	return MMSYSERR_NOTENABLED;
-    if ((mixer = open(MIXER_DEV, O_RDONLY|O_NDELAY)) < 0) {
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_INVALPARAM;
+
+    if ((mixer = open(OSS_Devices[wDevID].mixer_name, O_RDONLY|O_NDELAY)) < 0) {
 	WARN("mixer device not available !\n");
 	return MMSYSERR_NOTENABLED;
     }
@@ -1467,8 +1582,10 @@
     left  = (LOWORD(dwParam) * 100) / 0xFFFFl;
     right = (HIWORD(dwParam) * 100) / 0xFFFFl;
     volume = left + (right << 8);
+    
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_INVALPARAM;
 
-    if ((mixer = open(MIXER_DEV, O_WRONLY|O_NDELAY)) < 0) {
+    if ((mixer = open(OSS_Devices[wDevID].mixer_name, O_WRONLY|O_NDELAY)) < 0) {
 	WARN("mixer device not available !\n");
 	return MMSYSERR_NOTENABLED;
     }
@@ -1483,24 +1600,6 @@
 }
 
 /**************************************************************************
- * 				wodGetNumDevs			[internal]
- */
-static	DWORD	wodGetNumDevs(void)
-{
-    DWORD	ret = 1;
-    /* FIXME: For now, only one sound device (SOUND_DEV) is allowed */
-    int audio = OSS_OpenDevice(0, OSS_FullDuplex ? O_RDWR : O_WRONLY);
-
-    if (audio == -1) {
-	if (errno != EBUSY)
-	    ret = 0;
-    } else {
-        OSS_CloseDevice(0, audio);
-    }
-    return ret;
-}
-
-/**************************************************************************
  * 				wodMessage (WINEOSS.7)
  */
 DWORD WINAPI OSS_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
@@ -1525,7 +1624,7 @@
     case WODM_PREPARE:	 	return wodPrepare	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);
     case WODM_UNPREPARE: 	return wodUnprepare	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);
     case WODM_GETDEVCAPS:	return wodGetDevCaps	(wDevID, (LPWAVEOUTCAPSA)dwParam1,	dwParam2);
-    case WODM_GETNUMDEVS:	return wodGetNumDevs	();
+    case WODM_GETNUMDEVS:	return numOutDev;
     case WODM_GETPITCH:	 	return MMSYSERR_NOTSUPPORTED;
     case WODM_SETPITCH:	 	return MMSYSERR_NOTSUPPORTED;
     case WODM_GETPLAYBACKRATE:	return MMSYSERR_NOTSUPPORTED;
@@ -1729,7 +1828,7 @@
     if (lpdwPlay) *lpdwPlay = ptr;
     if (lpdwWrite) {
 	/* add some safety margin (not strictly necessary, but...) */
-	if (WOutDev[This->drv->wDevID].caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
+	if (OSS_Devices[This->drv->wDevID].out_caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
 	    *lpdwWrite = ptr + 32;
 	else
 	    *lpdwWrite = ptr + WOutDev[This->drv->wDevID].dwFragmentSize;
@@ -1966,7 +2065,7 @@
     IDsDriverImpl** idrv = (IDsDriverImpl**)drv;
 
     /* the HAL isn't much better than the HEL if we can't do mmap() */
-    if (!(WOutDev[wDevID].caps.dwSupport & WAVECAPS_DIRECTSOUND)) {
+    if (!(OSS_Devices[wDevID].out_caps.dwSupport & WAVECAPS_DIRECTSOUND)) {
 	ERR("DirectSound flag not set\n");
 	MESSAGE("This sound card's driver does not support direct access\n");
 	MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
@@ -2021,13 +2120,13 @@
     TRACE("(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
 
     if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
-
-    if (wDevID >= MAX_WAVEINDRV) {
-	TRACE("MAX_WAVINDRV reached !\n");
+    
+    if (wDevID >= MAX_WAVEDRV) {
+	TRACE("MAX_WAVDRV reached !\n");
 	return MMSYSERR_BADDEVICEID;
     }
 
-    memcpy(lpCaps, &WInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
+    memcpy(lpCaps, &OSS_Devices[wDevID].in_caps, min(dwSize, sizeof(*lpCaps)));
     return MMSYSERR_NOERROR;
 }
 
@@ -2246,19 +2345,17 @@
  */
 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
 {
-    int			fragment_size;
-    int			sample_rate;
-    int			format;
-    int			dsp_stereo;
     WINE_WAVEIN*	wwi;
-    int			audio_fragment;
+    int                 fragment_size;
+    int                 audio_fragment;
+    DWORD               ret;
 
     TRACE("(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
     if (lpDesc == NULL) {
 	WARN("Invalid Parameter !\n");
 	return MMSYSERR_INVALPARAM;
     }
-    if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_BADDEVICEID;
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_BADDEVICEID;
 
     /* only PCM format is supported so far... */
     if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
@@ -2278,10 +2375,22 @@
     }
 
     wwi = &WInDev[wDevID];
+
     if (wwi->unixdev != -1) return MMSYSERR_ALLOCATED;
-    if ((wwi->unixdev = OSS_OpenDevice(wDevID, OSS_FullDuplex ? O_RDWR : O_RDONLY)) == -1)
-	return MMSYSERR_ALLOCATED;
-    fcntl(wwi->unixdev, F_SETFD, 1); /* set close on exec flag */
+    /* This is actually hand tuned to work so that my SB Live:
+     * - does not skip
+     * - does not buffer too much
+     * when sending with the Shoutcast winamp plugin
+     */
+    /* 15 fragments max, 2^10 = 1024 bytes per fragment */
+    audio_fragment = 0x000F000A;
+    ret = OSS_OpenDevice(wDevID, &wwi->unixdev, 
+                         O_RDONLY, &audio_fragment, 
+                         lpDesc->lpFormat->nSamplesPerSec,
+                         (lpDesc->lpFormat->nChannels > 1) ? 1 : 0, 
+                         (lpDesc->lpFormat->wBitsPerSample == 16) 
+                         ? AFMT_S16_LE : AFMT_U8);
+    if (ret != 0) return ret;
     if (wwi->lpQueuePtr) {
 	WARN("Should have an empty queue (%p)\n", wwi->lpQueuePtr);
 	wwi->lpQueuePtr = NULL;
@@ -2300,34 +2409,6 @@
 	    wwi->format.wf.nChannels;
     }
 
-    sample_rate = wwi->format.wf.nSamplesPerSec;
-    dsp_stereo = (wwi->format.wf.nChannels > 1) ? TRUE : FALSE;
-    format = (wwi->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8;
-
-    ioctl(wwi->unixdev, SNDCTL_DSP_SETFMT, &format);
-    ioctl(wwi->unixdev, SNDCTL_DSP_STEREO, &dsp_stereo);
-    ioctl(wwi->unixdev, SNDCTL_DSP_SPEED,  &sample_rate);
-
-    /* This is actually hand tuned to work so that my SB Live:
-     * - does not skip
-     * - does not buffer too much
-     * when sending with the Shoutcast winamp plugin
-     */
-    /* 7 fragments max, 2^10 = 1024 bytes per fragment */
-    audio_fragment = 0x0007000A;
-    ioctl(wwi->unixdev, SNDCTL_DSP_SETFRAGMENT, &audio_fragment);
-
-    /* paranoid checks */
-    if (format != ((wwi->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8))
-	ERR("Can't set format to %d (%d)\n",
-	    (wwi->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8, format);
-    if (dsp_stereo != (wwi->format.wf.nChannels > 1) ? 1 : 0)
-	ERR("Can't set stereo to %u (%d)\n",
-	    (wwi->format.wf.nChannels > 1) ? 1 : 0, dsp_stereo);
-    if (!NEAR_MATCH(sample_rate, wwi->format.wf.nSamplesPerSec))
-	ERR("Can't set sample_rate to %lu (%d)\n",
-	    wwi->format.wf.nSamplesPerSec, sample_rate);
-
     ioctl(wwi->unixdev, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
     if (fragment_size == -1) {
 	WARN("IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
@@ -2361,7 +2442,7 @@
     WINE_WAVEIN*	wwi;
 
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't close !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2388,7 +2469,7 @@
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
 
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't do it !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2417,7 +2498,7 @@
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
 
-    if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_INVALHANDLE;
 
     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
 	return WAVERR_STILLPLAYING;
@@ -2435,7 +2516,7 @@
 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
-    if (wDevID >= MAX_WAVEINDRV) return MMSYSERR_INVALHANDLE;
+    if (wDevID >= MAX_WAVEDRV) return MMSYSERR_INVALHANDLE;
 
     if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
 	return WAVERR_STILLPLAYING;
@@ -2452,7 +2533,7 @@
 static DWORD widStart(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't start recording !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2467,7 +2548,7 @@
 static DWORD widStop(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't stop !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2483,7 +2564,7 @@
 static DWORD widReset(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't reset !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2501,7 +2582,7 @@
 
     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
 
-    if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
 	WARN("can't get pos !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2573,7 +2654,7 @@
     case WIDM_PREPARE:		return widPrepare    (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
     case WIDM_UNPREPARE:	return widUnprepare  (wDevID, (LPWAVEHDR)dwParam1, dwParam2);
     case WIDM_GETDEVCAPS:	return widGetDevCaps (wDevID, (LPWAVEINCAPSA)dwParam1, dwParam2);
-    case WIDM_GETNUMDEVS:	return wodGetNumDevs ();	/* same number of devices in output as in input */
+    case WIDM_GETNUMDEVS:	return numInDev;
     case WIDM_GETPOS:		return widGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
     case WIDM_RESET:		return widReset      (wDevID);
     case WIDM_START:		return widStart      (wDevID);


More information about the wine-patches mailing list