wineoss: Two fixes for OSS_RawOpenDevice

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




This patch fixes two bugs:
* I introduced the first bug a few days ago in with the following patch:
Fix DirectSound on i810 soundcards
The problem is that when OSS_RawOpenDevice opens the device in a different format than the one it was asked for it still returns WAVERR_BADFORMAT. That causes OSS_OpenDevice to think the open failed and not increment open_count. So when OSS_CloseDevice is called next open_count becomes negative. Then bad things happen if we then need to reopen the device from another thread (e.g. in case of underrun) because we think it's already in use (open_count==-1!=0).
So now we return MMSYS_NOERROR and things work better.

* the second bug has been there all along. Basically when DirectSound wants to open a device in mono, it sets ossdev->stereo to 0, and then OSS_RawOpenDevice check if ossdev->stereo!=0 and if yes then it does the ioctl. I guess this normally works because devices are supposed to be in mono by default. But apparently some are not (VT82C686+OSS) and this causes trouble. So now we use -1 to signal OSS_RawOpenDevice to not do ioctls on the device.


Changelog:

Francois Gouget <fgouget@codeweavers.com>

* dlls/winmm/wineoss/audio.c
Return MMSYS_NOERROR even if we don't open the device with the requested format, otherwise OSS_OpenDevice will not increment open_count.
Use -1 to signal OSS_RawOpenDevice not to do ioctls because 0 is ambiguous (also means mono as opposed to stereo).


--
Francois Gouget
fgouget@codeweavers.com

Index: dlls/winmm/wineoss/audio.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/wineoss/audio.c,v
retrieving revision 1.72
diff -u -r1.72 audio.c
--- dlls/winmm/wineoss/audio.c	15 Jan 2003 00:44:50 -0000	1.72
+++ dlls/winmm/wineoss/audio.c	15 Jan 2003 00:56:21 -0000
@@ -152,9 +152,9 @@
     unsigned                    open_access;
     int                         fd;
     DWORD                       owner_tid;
-    unsigned                    sample_rate;
-    unsigned                    stereo;
-    unsigned                    format;
+    int                         sample_rate;
+    int                         stereo;
+    int                         format;
     unsigned                    audio_fragment;
     BOOL                        full_duplex;
     BOOL                        bTriggerSupport;
@@ -240,7 +240,7 @@
  */
 static DWORD      OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
 {
-    int fd, val, err;
+    int fd, val, rc;
 
     if ((fd = open(ossdev->dev_name, ossdev->open_access|O_NDELAY, 0)) == -1)
     {
@@ -258,46 +258,42 @@
     }
 
     /* First size and stereo then samplerate */
-    err=MMSYSERR_NOERROR;
-    if (ossdev->format)
+    if (ossdev->format>=0)
     {
         val = ossdev->format;
-        ioctl(fd, SNDCTL_DSP_SETFMT, &ossdev->format);
-        if (val != ossdev->format) {
+        rc = ioctl(fd, SNDCTL_DSP_SETFMT, &ossdev->format);
+        if (rc != 0 || val != ossdev->format) {
             TRACE("Can't set format to %d (returned %d)\n", val, ossdev->format);
-            err=WAVERR_BADFORMAT;
             if (strict_format)
                 goto error;
         }
     }
-    if (ossdev->stereo)
+    if (ossdev->stereo>=0)
     {
         val = ossdev->stereo;
-        ioctl(fd, SNDCTL_DSP_STEREO, &ossdev->stereo);
-        if (val != ossdev->stereo) {
+        rc = ioctl(fd, SNDCTL_DSP_STEREO, &ossdev->stereo);
+        if (rc != 0 || val != ossdev->stereo) {
             TRACE("Can't set stereo to %u (returned %d)\n", val, ossdev->stereo);
-            err=WAVERR_BADFORMAT;
             if (strict_format)
                 goto error;
         }
     }
-    if (ossdev->sample_rate)
+    if (ossdev->sample_rate>=0)
     {
         val = ossdev->sample_rate;
-        ioctl(fd, SNDCTL_DSP_SPEED, &ossdev->sample_rate);
-        if (!NEAR_MATCH(val, ossdev->sample_rate)) {
+        rc = ioctl(fd, SNDCTL_DSP_SPEED, &ossdev->sample_rate);
+        if (rc != 0 || !NEAR_MATCH(val, ossdev->sample_rate)) {
             TRACE("Can't set sample_rate to %u (returned %d)\n", val, ossdev->sample_rate);
-            err=WAVERR_BADFORMAT;
             if (strict_format)
                 goto error;
         }
     }
     ossdev->fd = fd;
-    return err;
+    return MMSYSERR_NOERROR;
 
 error:
     close(fd);
-    return err;
+    return WAVERR_BADFORMAT;
 }
 
 /******************************************************************
@@ -428,7 +424,7 @@
     int rc,arg;
     int f,c,r;
 
-    if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0, 0, 0, 0) != 0) return FALSE;
+    if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0,-1,-1,-1) != 0) return FALSE;
     ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
 
     /* FIXME: some programs compare this string against the content of the
@@ -471,14 +467,19 @@
     for (f=0;f<2;f++) {
         arg=win_std_oss_fmts[f];
         rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
-        if (rc!=0 || arg!=win_std_oss_fmts[f])
+        if (rc!=0 || arg!=win_std_oss_fmts[f]) {
+            TRACE("DSP_SAMPLESIZE: rc=%d returned 0x%x for 0x%x\n",
+                  rc,arg,win_std_oss_fmts[f]);
             continue;
+        }
 
         for (c=0;c<2;c++) {
             arg=c;
             rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);
-            if (rc!=0 || arg!=c)
+            if (rc!=0 || arg!=c) {
+                TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c);
                 continue;
+            }
             if (c==1) {
                 ossdev->out_caps.wChannels=2;
                 ossdev->out_caps.dwSupport|=WAVECAPS_LRVOLUME;
@@ -521,7 +522,7 @@
     int rc,arg;
     int f,c,r;
 
-    if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0, 0, 0, 0) != 0) return FALSE;
+    if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0,-1,-1,-1) != 0) return FALSE;
     ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
 
     /* See comment in OSS_WaveOutInit */
@@ -553,14 +554,19 @@
     for (f=0;f<2;f++) {
         arg=win_std_oss_fmts[f];
         rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
-        if (rc!=0 || arg!=win_std_oss_fmts[f])
+        if (rc!=0 || arg!=win_std_oss_fmts[f]) {
+            TRACE("DSP_SAMPLESIZE: rc=%d returned 0x%x for 0x%x\n",
+                  rc,arg,win_std_oss_fmts[f]);
             continue;
+        }
 
         for (c=0;c<2;c++) {
             arg=c;
             rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);
-            if (rc!=0 || arg!=c)
+            if (rc!=0 || arg!=c) {
+                TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c);
                 continue;
+            }
             if (c==1) {
                 ossdev->in_caps.wChannels=2;
             }
@@ -594,7 +600,7 @@
 {
     int 	caps;
 
-    if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0, 0, 0, 0) != 0) return;
+    if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0,-1,-1,-1) != 0) return;
     if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)
     {
 	ossdev->full_duplex = (caps & DSP_CAP_DUPLEX);
@@ -1322,13 +1328,12 @@
                          (lpDesc->lpFormat->nChannels > 1) ? 1 : 0,
                          (lpDesc->lpFormat->wBitsPerSample == 16)
                              ? AFMT_S16_LE : AFMT_U8);
-    if ((ret==WAVERR_BADFORMAT) && (dwFlags & WAVE_DIRECTSOUND)) {
+    if ((ret==MMSYSERR_NOERROR) && (dwFlags & WAVE_DIRECTSOUND)) {
         lpDesc->lpFormat->nSamplesPerSec=wwo->ossdev->sample_rate;
         lpDesc->lpFormat->nChannels=(wwo->ossdev->stereo ? 2 : 1);
         lpDesc->lpFormat->wBitsPerSample=(wwo->ossdev->format == AFMT_U8 ? 8 : 16);
         lpDesc->lpFormat->nBlockAlign=lpDesc->lpFormat->nChannels*lpDesc->lpFormat->wBitsPerSample/8;
         lpDesc->lpFormat->nAvgBytesPerSec=lpDesc->lpFormat->nSamplesPerSec*lpDesc->lpFormat->nBlockAlign;
-        ret=MMSYSERR_NOERROR;
         TRACE("OSS_OpenDevice returned this format: %ldx%dx%d\n",
               lpDesc->lpFormat->nSamplesPerSec,
               lpDesc->lpFormat->wBitsPerSample,

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux