OSS/Commercial workaround

Eric Pouech eric.pouech at wanadoo.fr
Sun Oct 6 14:29:06 CDT 2002


this patch is the port of Ove's patch for working around ugly
OSS/Commercial (which doesn't allow a proper SNDCTL_DSP_RESET ioctl, and
request to close/reopen the device before going any further)
I also added a few other goodies

A+
-------------- next part --------------
Name:          oss_reset
ChangeLog:     Ove Kaaven:
	OSS Commercial doesn't properly handle SNDCTL_DSP_RESET, so close/open device to workaround this issue
Eric Pouech:
	added support for several soundcard
	remove non full duplex mode in code
License:       X11
GenDate:       2002/10/06 19:17:36 UTC
ModifiedFiles: dlls/winmm/wineoss/audio.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/wineoss/audio.c,v
retrieving revision 1.61
diff -u -u -r1.61 audio.c
--- dlls/winmm/wineoss/audio.c	26 Aug 2002 21:49:42 -0000	1.61
+++ dlls/winmm/wineoss/audio.c	6 Oct 2002 16:11:49 -0000
@@ -5,6 +5,7 @@
  * Copyright 1994 Martin Ayotte
  *           1999 Eric Pouech (async playing in waveOut/waveIn)
  *	     2000 Eric Pouech (loops in waveOut)
+ *           2002 Eric Pouech (full duplex)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,8 +24,6 @@
 /*
  * FIXME:
  *	pause in waveOut does not work correctly in loop mode
- *      experimental full duplex mode
- *      only one sound card is currently supported
  */
 
 /*#define EMULATE_SB16*/
@@ -73,7 +72,7 @@
 
 #ifdef HAVE_OSS
 
-#define MAX_WAVEDRV 	(1)
+#define MAX_WAVEDRV 	(3)
 
 /* state diagram for waveOut writing:
  *
@@ -144,8 +143,26 @@
     CRITICAL_SECTION		msg_crst;
 } OSS_MSG_RING;
 
+typedef struct tagOSS_DEVICE {
+    const char*                 dev_name;
+    const char*                 mixer_name;
+    unsigned                    open_count;
+    WAVEOUTCAPSA                out_caps;
+    WAVEINCAPSA		        in_caps;
+    unsigned                    open_access;
+    int                         fd;
+    DWORD                       owner_tid;
+    unsigned                    sample_rate;
+    unsigned                    stereo;
+    unsigned                    format;
+    unsigned                    audio_fragment;
+    BOOL                        full_duplex;
+} OSS_DEVICE;
+
+static OSS_DEVICE   OSS_Devices[MAX_WAVEDRV];
+
 typedef struct {
-    int				unixdev;
+    OSS_DEVICE*                 ossdev;
     volatile int		state;			/* one of the WINE_WS_ manifest constants */
     WAVEOPENDESC		waveDesc;
     WORD			wFlags;
@@ -177,7 +194,7 @@
 } WINE_WAVEOUT;
 
 typedef struct {
-    int				unixdev;
+    OSS_DEVICE*                 ossdev;
     volatile int		state;
     DWORD			dwFragmentSize;		/* OpenSound '/dev/dsp' give us that size */
     WAVEOPENDESC		waveDesc;
@@ -215,27 +232,55 @@
 /*======================================================================*
  *                  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
-    unsigned            open_access;
-    int                 fd;
-    DWORD               owner_tid;
-    unsigned            sample_rate;
-    unsigned            stereo;
-    unsigned            format;
-    unsigned            audio_fragment;
-#endif
-    BOOL                full_duplex;
-} OSS_DEVICE;
+/******************************************************************
+ *		OSS_RawOpenDevice
+ *
+ * Low level device opening (from values stored in ossdev)
+ */
+static int      OSS_RawOpenDevice(OSS_DEVICE* ossdev, int* frag)
+{
+    int fd, val;
 
-OSS_DEVICE   OSS_Devices[MAX_WAVEDRV];
+    if ((fd = open(ossdev->dev_name, ossdev->open_access|O_NDELAY, 0)) == -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 (ossdev->open_access == O_RDWR && ossdev->full_duplex)
+        ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
+
+    if (ossdev->audio_fragment)
+    {
+        ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossdev->audio_fragment);
+    }
+
+    /* First size and stereo then samplerate */
+    if (ossdev->format)
+    {
+        val = ossdev->format;
+        ioctl(fd, SNDCTL_DSP_SETFMT, &val);
+        if (val != ossdev->format)
+            ERR("Can't set format to %d (%d)\n", ossdev->format, val);
+    }
+    if (ossdev->stereo)
+    {
+        val = ossdev->stereo;
+        ioctl(fd, SNDCTL_DSP_STEREO, &val);
+        if (val != ossdev->stereo)
+            ERR("Can't set stereo to %u (%d)\n", ossdev->stereo, val);
+    }
+    if (ossdev->sample_rate)
+    {
+        val = ossdev->sample_rate;
+        ioctl(fd, SNDCTL_DSP_SPEED, &ossdev->sample_rate);
+        if (!NEAR_MATCH(val, ossdev->sample_rate))
+            ERR("Can't set sample_rate to %u (%d)\n", ossdev->sample_rate, val);
+    }
+    return fd;
+}
 
 /******************************************************************
  *		OSS_OpenDevice
@@ -244,71 +289,29 @@
  * open the device for both waveout and wavein streams...
  * this is hackish, but it's the way OSS interface is done...
  */
-static DWORD	OSS_OpenDevice(unsigned wDevID, int* pfd, unsigned req_access,
+static DWORD	OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
                                int* frag, int sample_rate, int stereo, int fmt)
 {
-    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 */
+    /* FIXME: this should be protected, and it also contains a race with OSS_CloseDevice */
     if (ossdev->open_count == 0)
     {
 	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", 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 && 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
+
+        if ((ossdev->fd = OSS_RawOpenDevice(ossdev, frag)) == -1)
+            return MMSYSERR_ERROR;
     }
     else
     {
-#ifdef USE_FULLDUPLEX
         /* check we really open with the same parameters */
         if (ossdev->open_access != req_access)
         {
@@ -337,13 +340,10 @@
             WARN("Another thread is trying to access audio...\n");
             return MMSYSERR_ERROR;
         }
-#endif
     }
 
-#ifdef USE_FULLDUPLEX
     ossdev->open_count++;
-#endif
-    *pfd = fd;
+
     return MMSYSERR_NOERROR;
 }
 
@@ -352,19 +352,30 @@
  *
  *
  */
-static void	OSS_CloseDevice(unsigned wDevID, int fd)
+static void	OSS_CloseDevice(OSS_DEVICE* ossdev)
 {
-    OSS_DEVICE* ossdev;
-
-    if (wDevID >= MAX_WAVEDRV) return;
-#ifdef USE_FULLDUPLEX
-    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_ResetDevice
+ *
+ * Resets the device. OSS Commercial requires the device to be closed
+ * after a SNDCTL_DSP_RESET ioctl call... this function implements
+ * this behavior...
+ */
+static int     OSS_ResetDevice(OSS_DEVICE* ossdev)
+{
+    if (ioctl(ossdev->fd, SNDCTL_DSP_RESET, NULL) == -1) 
+    {
+	perror("ioctl SNDCTL_DSP_RESET");
+        return -1;
+    }
+    TRACE("Changing fd from %d to ", ossdev->fd);
+    close(ossdev->fd);
+    OSS_RawOpenDevice(ossdev, &ossdev->audio_fragment);
+    TRACE("%d\n", ossdev->fd);
+    return ossdev->fd;
 }
 
 /******************************************************************
@@ -374,7 +385,6 @@
  */
 static void     OSS_WaveOutInit(unsigned devID, OSS_DEVICE* ossdev)
 {
-    int                 audio;
     int	                smplrate;
     int	                samplesize = 16;
     int	                dsp_stereo = 1;
@@ -382,13 +392,14 @@
     int                 caps;
     int                 mask;
 
-    WOutDev[devID].unixdev = -1;
+    WOutDev[devID].state = WINE_WS_CLOSED;
+    WOutDev[devID].ossdev = ossdev;
     memset(&ossdev->out_caps, 0, sizeof(ossdev->out_caps));
 
-    if (OSS_OpenDevice(devID, &audio, O_WRONLY, NULL, 0, 0, 0) != 0) return;
+    if (OSS_OpenDevice(WOutDev[devID].ossdev, O_WRONLY, NULL, 0, 0, 0) != 0) return;
     numOutDev++;
 
-    ioctl(audio, SNDCTL_DSP_RESET, 0);
+    ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
 
     /* FIXME: some programs compare this string against the content of the registry
      * for MM drivers. The names have to match in order for the program to work
@@ -408,17 +419,17 @@
     ossdev->out_caps.dwFormats = 0x00000000;
     ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
 
-    ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
+    ioctl(ossdev->fd, 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;
+    bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
 
-    ossdev->out_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
+    ossdev->out_caps.wChannels = (ioctl(ossdev->fd, 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 (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_4M08;
 	    if (ossdev->out_caps.wChannels > 1)
@@ -431,7 +442,7 @@
 	}
     }
     smplrate = 22050;
-    if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_2M08;
 	    if (ossdev->out_caps.wChannels > 1)
@@ -444,7 +455,7 @@
 	}
     }
     smplrate = 11025;
-    if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->out_caps.dwFormats |= WAVE_FORMAT_1M08;
 	    if (ossdev->out_caps.wChannels > 1)
@@ -456,7 +467,7 @@
 		ossdev->out_caps.dwFormats |= WAVE_FORMAT_1S16;
 	}
     }
-    if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) {
 	TRACE("OSS dsp out caps=%08X\n", caps);
 	if ((caps & DSP_CAP_REALTIME) && !(caps & DSP_CAP_BATCH)) {
 	    ossdev->out_caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;
@@ -466,7 +477,7 @@
 	    !(caps & DSP_CAP_BATCH))
 	    ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
     }
-    OSS_CloseDevice(devID, audio);
+    OSS_CloseDevice(ossdev);
     TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
 	  ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);
 
@@ -479,7 +490,6 @@
  */
 static void OSS_WaveInInit(unsigned devID, OSS_DEVICE* ossdev)
 {
-    int                 audio;
     int	                smplrate;
     int	                samplesize = 16;
     int	                dsp_stereo = 1;
@@ -490,14 +500,15 @@
     samplesize = 16;
     dsp_stereo = 1;
 
-    WInDev[devID].unixdev = -1;
+    WInDev[devID].state = WINE_WS_CLOSED;
+    WInDev[devID].ossdev = ossdev;
 
     memset(&ossdev->in_caps, 0, sizeof(ossdev->in_caps));
 
-    if (OSS_OpenDevice(0, &audio, O_RDONLY, NULL, 0, 0, 0) != 0) return;
+    if (OSS_OpenDevice(WInDev[devID].ossdev, O_RDONLY, NULL, 0, 0, 0) != 0) return;
     numInDev++;
 
-    ioctl(audio, SNDCTL_DSP_RESET, 0);
+    ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
 
 #ifdef EMULATE_SB16
     ossdev->in_caps.wMid = 0x0002;
@@ -509,21 +520,21 @@
     strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
 #endif
     ossdev->in_caps.dwFormats = 0x00000000;
-    ossdev->in_caps.wChannels = (ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
+    ossdev->in_caps.wChannels = (ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &dsp_stereo) != 0) ? 1 : 2;
 
     WInDev[devID].bTriggerSupport = FALSE;
-    if (ioctl(audio, SNDCTL_DSP_GETCAPS, &caps) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) {
 	TRACE("OSS dsp in caps=%08X\n", caps);
 	if (caps & DSP_CAP_TRIGGER)
             WInDev[devID].bTriggerSupport = TRUE;
     }
 
-    ioctl(audio, SNDCTL_DSP_GETFMTS, &mask);
+    ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &mask);
     TRACE("OSS in dsp mask=%08x\n", mask);
 
-    bytespersmpl = (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
+    bytespersmpl = (ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) != 0) ? 1 : 2;
     smplrate = 44100;
-    if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_4M08;
 	    if (ossdev->in_caps.wChannels > 1)
@@ -536,7 +547,7 @@
 	}
     }
     smplrate = 22050;
-    if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_2M08;
 	    if (ossdev->in_caps.wChannels > 1)
@@ -549,7 +560,7 @@
 	}
     }
     smplrate = 11025;
-    if (ioctl(audio, SNDCTL_DSP_SPEED, &smplrate) == 0) {
+    if (ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &smplrate) == 0) {
 	if (mask & AFMT_U8) {
 	    ossdev->in_caps.dwFormats |= WAVE_FORMAT_1M08;
 	    if (ossdev->in_caps.wChannels > 1)
@@ -561,7 +572,7 @@
 		ossdev->in_caps.dwFormats |= WAVE_FORMAT_1S16;
 	}
     }
-    OSS_CloseDevice(devID, audio);
+    OSS_CloseDevice(ossdev);
     TRACE("in dwFormats = %08lX\n", ossdev->in_caps.dwFormats);
 }
 
@@ -570,19 +581,16 @@
  *
  *
  */
-static void OSS_WaveFullDuplexInit(unsigned devID, OSS_DEVICE* ossdev)
+static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
 {
-#ifdef USE_FULLDUPLEX
-    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)
+    if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0, 0, 0) != 0) return;
+    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)
     {
 	ossdev->full_duplex = (caps & DSP_CAP_DUPLEX);
     }
-    OSS_CloseDevice(devID, audio);
-#endif
+    OSS_CloseDevice(ossdev);
 }
 
 /******************************************************************
@@ -596,8 +604,16 @@
 
     /* FIXME: only one device is supported */
     memset(&OSS_Devices, 0, sizeof(OSS_Devices));
-    OSS_Devices[0].dev_name = "/dev/dsp";
+    /* FIXME: should check that dsp actually points to dsp0, or that dsp0 exists
+     * we should also be able to configure (bitmap) which devices we want to use...
+     * - or even store the name of all drivers in our configuration
+     */
+    OSS_Devices[0].dev_name   = "/dev/dsp";
     OSS_Devices[0].mixer_name = "/dev/mixer";
+    OSS_Devices[1].dev_name   = "/dev/dsp1";
+    OSS_Devices[1].mixer_name = "/dev/mixer1";
+    OSS_Devices[2].dev_name   = "/dev/dsp2";
+    OSS_Devices[2].mixer_name = "/dev/mixer2";
 
     /* start with output device */
     for (i = 0; i < MAX_WAVEDRV; ++i)
@@ -609,7 +625,7 @@
 
     /* finish with the full duplex bits */
     for (i = 0; i < MAX_WAVEDRV; i++)
-        OSS_WaveFullDuplexInit(i, &OSS_Devices[i]);
+        OSS_WaveFullDuplexInit(&OSS_Devices[i]);
 
     return 0;
 }
@@ -773,7 +789,7 @@
     audio_buf_info dspspace;
     if (!info) info = &dspspace;
 
-    if (ioctl(wwo->unixdev, SNDCTL_DSP_GETOSPACE, info) < 0) {
+    if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) {
         ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n");
         return FALSE;
     }
@@ -894,7 +910,7 @@
 
     if (toWrite > 0)
     {
-        written = write(wwo->unixdev, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
+        written = write(wwo->ossdev->fd, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
         if (written <= 0) return FALSE;
     }
     else
@@ -961,8 +997,8 @@
     wodPlayer_NotifyCompletions(wwo, FALSE);
 
     /* flush all possible output */
-    if (ioctl(wwo->unixdev, SNDCTL_DSP_RESET, 0) == -1) {
-	perror("ioctl SNDCTL_DSP_RESET");
+    if (OSS_ResetDevice(wwo->ossdev) == -1)
+    {
 	wwo->hThread = 0;
 	wwo->state = WINE_WS_STOPPED;
 	ExitThread(-1);
@@ -1136,7 +1172,7 @@
             /* OSS doesn't start before it gets either 2 fragments or a SNDCTL_DSP_POST;
              * if it didn't get one, we give it the other */
             if (wwo->dwBufferSize < availInQ + 2 * wwo->dwFragmentSize)
-                ioctl(wwo->unixdev, SNDCTL_DSP_POST, 0);
+                ioctl(wwo->ossdev->fd, SNDCTL_DSP_POST, 0);
             wwo->bNeedPost = FALSE;
         }
     }
@@ -1176,7 +1212,7 @@
 		wodPlayer_ProcessMessages(wwo);
 		if (!wwo->lpPlayPtr) {
 		    TRACE("flushing\n");
-		    ioctl(wwo->unixdev, SNDCTL_DSP_SYNC, 0);
+		    ioctl(wwo->ossdev->fd, SNDCTL_DSP_SYNC, 0);
 		    wwo->dwPlayedTotal = wwo->dwWrittenTotal;
 		}
 		else {
@@ -1267,16 +1303,17 @@
 	/* 16 fragments max, 2^10=1024 bytes per fragment */
 	audio_fragment = 0x000F000A;
     }
-    if (wwo->unixdev != -1) return MMSYSERR_ALLOCATED;
+    if (wwo->state != WINE_WS_CLOSED) 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,
+    ret = OSS_OpenDevice(wwo->ossdev,
                          (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->state = WINE_WS_STOPPED;
 
     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
 
@@ -1291,10 +1328,10 @@
 	    wwo->format.wf.nChannels;
     }
     /* Read output space info for future reference */
-    if (ioctl(wwo->unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+    if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
 	ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n");
-        OSS_CloseDevice(wDevID, wwo->unixdev);
-	wwo->unixdev = -1;
+        OSS_CloseDevice(wwo->ossdev);
+	wwo->state = WINE_WS_CLOSED;
 	return MMSYSERR_NOTENABLED;
     }
 
@@ -1327,7 +1364,7 @@
     wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
 
     TRACE("fd=%d fragmentSize=%ld\n",
-	  wwo->unixdev, wwo->dwFragmentSize);
+	  wwo->ossdev->fd, wwo->dwFragmentSize);
     if (wwo->dwFragmentSize % wwo->format.wf.nBlockAlign)
 	ERR("Fragment doesn't contain an integral number of data blocks\n");
 
@@ -1349,7 +1386,7 @@
 
     TRACE("(%u);\n", wDevID);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1369,8 +1406,8 @@
 
         OSS_DestroyRingMessage(&wwo->msgRing);
 
-        OSS_CloseDevice(wDevID, wwo->unixdev);
-	wwo->unixdev = -1;
+        OSS_CloseDevice(wwo->ossdev);
+	wwo->state = WINE_WS_CLOSED;
 	wwo->dwFragmentSize = 0;
 	ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
     }
@@ -1386,7 +1423,7 @@
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
 
     /* first, do the sanity checks... */
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
         WARN("bad dev ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1460,7 +1497,7 @@
 {
     TRACE("(%u);!\n", wDevID);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1477,7 +1514,7 @@
 {
     TRACE("(%u);\n", wDevID);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1499,7 +1536,7 @@
 {
     TRACE("(%u);\n", wDevID);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1520,7 +1557,7 @@
 
     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1580,7 +1617,7 @@
 {
     TRACE("(%u);\n", wDevID);
 
-    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WOutDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("bad device ID !\n");
 	return MMSYSERR_BADDEVICEID;
     }
@@ -1724,7 +1761,7 @@
     WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
     if (!wwo->mapping) {
 	wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED,
-			    wwo->unixdev, 0);
+			    wwo->ossdev->fd, 0);
 	if (wwo->mapping == (LPBYTE)-1) {
 	    ERR("(%p): Could not map sound device for direct access (%s)\n", dsdb, strerror(errno));
 	    return DSERR_GENERIC;
@@ -1867,11 +1904,11 @@
     DWORD ptr;
 
     TRACE("(%p)\n",iface);
-    if (WOutDev[This->drv->wDevID].unixdev == -1) {
+    if (WOutDev[This->drv->wDevID].state == WINE_WS_CLOSED) {
 	ERR("device not open, but accessing?\n");
 	return DSERR_UNINITIALIZED;
     }
-    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_GETOPTR, &info) < 0) {
+    if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	return DSERR_GENERIC;
     }
@@ -1895,7 +1932,7 @@
     ICOM_THIS(IDsDriverBufferImpl,iface);
     int enable = PCM_ENABLE_OUTPUT;
     TRACE("(%p,%lx,%lx,%lx)\n",iface,dwRes1,dwRes2,dwFlags);
-    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
+    if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	return DSERR_GENERIC;
     }
@@ -1908,7 +1945,7 @@
     int enable = 0;
     TRACE("(%p)\n",iface);
     /* no more playing */
-    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
+    if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	return DSERR_GENERIC;
     }
@@ -1995,7 +2032,7 @@
 
     TRACE("(%p)\n",iface);
     /* make sure the card doesn't start playing before we want it to */
-    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
+    if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	return DSERR_GENERIC;
     }
@@ -2057,7 +2094,7 @@
     (*ippdsdb)->drv	= This;
 
     /* check how big the DMA buffer is now */
-    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+    if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	HeapFree(GetProcessHeap(),0,*ippdsdb);
 	*ippdsdb = NULL;
@@ -2078,7 +2115,7 @@
     *ppbBuffer		= WOutDev[This->wDevID].mapping;
 
     /* some drivers need some extra nudging after mapping */
-    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
+    if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
 	ERR("ioctl failed (%d)\n", errno);
 	return DSERR_GENERIC;
     }
@@ -2208,7 +2245,7 @@
     /* the soundblaster live needs a micro wake to get its recording started
      * (or GETISPACE will have 0 frags all the time)
      */
-    read(wwi->unixdev,&xs,4);
+    read(wwi->ossdev->fd, &xs, 4);
 
 	/* make sleep time to be # of ms to output a fragment */
     dwSleepTime = (wwi->dwFragmentSize * 1000) / wwi->format.wf.nAvgBytesPerSec;
@@ -2224,7 +2261,7 @@
         {
             lpWaveHdr = wwi->lpQueuePtr;
 
-	    ioctl(wwi->unixdev, SNDCTL_DSP_GETISPACE, &info);
+	    ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETISPACE, &info);
             TRACE("info={frag=%d fsize=%d ftotal=%d bytes=%d}\n", info.fragments, info.fragsize, info.fragstotal, info.bytes);
 
             /* read all the fragments accumulated so far */
@@ -2235,7 +2272,7 @@
                 if (lpWaveHdr->dwBufferLength - lpWaveHdr->dwBytesRecorded >= wwi->dwFragmentSize)
                 {
                     /* directly read fragment in wavehdr */
-                    bytesRead = read(wwi->unixdev,
+                    bytesRead = read(wwi->ossdev->fd,
 		      		     lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
                                      wwi->dwFragmentSize);
 
@@ -2265,7 +2302,7 @@
                 else
 		{
                     /* read the fragment in a local buffer */
-                    bytesRead = read(wwi->unixdev, buffer, wwi->dwFragmentSize);
+                    bytesRead = read(wwi->ossdev->fd, buffer, wwi->dwFragmentSize);
                     pOffset = buffer;
 
                     TRACE("bytesRead=%ld (local)\n", bytesRead);
@@ -2334,7 +2371,7 @@
                 if (wwi->bTriggerSupport)
                 {
                     /* start the recording */
-                    if (ioctl(wwi->unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0)
+                    if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0)
                     {
                         ERR("ioctl(SNDCTL_DSP_SETTRIGGER) failed (%d)\n", errno);
                     }
@@ -2343,7 +2380,7 @@
                 {
                     unsigned char data[4];
                     /* read 4 bytes to start the recording */
-                    read(wwi->unixdev, data, 4);
+                    read(wwi->ossdev->fd, data, 4);
                 }
 
 		SetEvent(ev);
@@ -2428,7 +2465,7 @@
 
     wwi = &WInDev[wDevID];
 
-    if (wwi->unixdev != -1) return MMSYSERR_ALLOCATED;
+    if (wwi->state != WINE_WS_CLOSED) return MMSYSERR_ALLOCATED;
     /* This is actually hand tuned to work so that my SB Live:
      * - does not skip
      * - does not buffer too much
@@ -2436,13 +2473,14 @@
      */
     /* 15 fragments max, 2^10 = 1024 bytes per fragment */
     audio_fragment = 0x000F000A;
-    ret = OSS_OpenDevice(wDevID, &wwi->unixdev,
-                         O_RDONLY, &audio_fragment,
+    ret = OSS_OpenDevice(wwi->ossdev, 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;
+    wwi->state = WINE_WS_STOPPED;
+
     if (wwi->lpQueuePtr) {
 	WARN("Should have an empty queue (%p)\n", wwi->lpQueuePtr);
 	wwi->lpQueuePtr = NULL;
@@ -2461,11 +2499,11 @@
 	    wwi->format.wf.nChannels;
     }
 
-    ioctl(wwi->unixdev, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
+    ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
     if (fragment_size == -1) {
 	WARN("IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
-        OSS_CloseDevice(wDevID, wwi->unixdev);
-	wwi->unixdev = -1;
+        OSS_CloseDevice(wwi->ossdev);
+	wwi->state = WINE_WS_CLOSED;
 	return MMSYSERR_NOTENABLED;
     }
     wwi->dwFragmentSize = fragment_size;
@@ -2494,7 +2532,7 @@
     WINE_WAVEIN*	wwi;
 
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't close !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2507,8 +2545,8 @@
     }
 
     OSS_AddRingMessage(&wwi->msgRing, WINE_WM_CLOSING, 0, TRUE);
-    OSS_CloseDevice(wDevID, wwi->unixdev);
-    wwi->unixdev = -1;
+    OSS_CloseDevice(wwi->ossdev);
+    wwi->state = WINE_WS_CLOSED;
     wwi->dwFragmentSize = 0;
     OSS_DestroyRingMessage(&wwi->msgRing);
     return widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
@@ -2521,7 +2559,7 @@
 {
     TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
 
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't do it !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2585,7 +2623,7 @@
 static DWORD widStart(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't start recording !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2600,7 +2638,7 @@
 static DWORD widStop(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't stop !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2616,7 +2654,7 @@
 static DWORD widReset(WORD wDevID)
 {
     TRACE("(%u);\n", wDevID);
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't reset !\n");
 	return MMSYSERR_INVALHANDLE;
     }
@@ -2634,7 +2672,7 @@
 
     TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
 
-    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].unixdev == -1) {
+    if (wDevID >= MAX_WAVEDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't get pos !\n");
 	return MMSYSERR_INVALHANDLE;
     }


More information about the wine-patches mailing list