PATCH: fixes problems with multply listed audio codecs

Waldeck Schutzer schutzer at math.rutgers.edu
Mon Jan 20 14:26:06 CST 2003


This patch adresses the following issues:

1. Audio codecs were being incorrectly listed several times.

2. An ideosyncrasy of acmStreamOpen would occasioanally cause some 
applications to crash.

Waldeck
-------------- next part --------------
Index: wine/dlls/msacm/format.c
===================================================================
RCS file: /home/wine/wine/dlls/msacm/format.c,v
retrieving revision 1.20
diff -u -p -r1.20 format.c
--- wine/dlls/msacm/format.c	2 Dec 2002 18:10:59 -0000	1.20
+++ wine/dlls/msacm/format.c	20 Jan 2003 20:02:45 -0000
@@ -758,36 +758,74 @@ MMRESULT WINAPI acmFormatTagEnumW(HACMDR
 
     if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
 
-    if (had) FIXME("had != NULL, not supported\n");
+    /* (WS) MSDN info page says that if had != 0, then we should find
+     * the specific driver to get its tags from. Therefore I'm removing
+     * the FIXME call and adding a search block below. It also seems
+     * that the lack of this functionality was the responsible for 
+     * codecs to be multiply and incorrectly listed. 
+     */
+
+    /* if (had) FIXME("had != NULL, not supported\n"); */
+
+    if (had) {
+
+       if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR)
+          return MMSYSERR_INVALHANDLE;
+
+       for (i = 0; i < padid->cFormatTags; i++) {
+	  paftd->dwFormatTagIndex = i;
+	  if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
+	  (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
+	     if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
+	        if (paftd->szFormatTag[0] == 0)
+		   MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
+			 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
+		/* (WS) I'm preserving this PCM hack since it seems to be
+		 * correct. Please notice this block was borrowed from
+		 * below.
+	  	 */
+		if (bPcmDone) continue;
+		   bPcmDone = TRUE;
+	     }
+	     if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) 
+                return MMSYSERR_NOERROR;
+	  }
+       }
 
-    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
-	/* should check for codec only */
-	if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
-	    acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
-	    for (i = 0; i < padid->cFormatTags; i++) {
-		paftd->dwFormatTagIndex = i;
-		if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-				  (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
-		    if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
-			if (paftd->szFormatTag[0] == 0)
-			    MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
-						 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
-			/* FIXME (EPP): I'm not sure this is the correct
-			 * algorithm (should make more sense to apply the same
-			 * for all already loaded formats, but this will do
-			 * for now
-			 */
-			if (bPcmDone) continue;
-			bPcmDone = TRUE;
-		    }
-		    if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
-                        acmDriverClose(had, 0);
-                        return MMSYSERR_NOERROR;
-		    }
-		}
-	    }
-	}
-	acmDriverClose(had, 0);
+    }
+
+    /* if had==0 then search for the first suitable driver */
+    else {
+       for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
+          /* should check for codec only */
+          if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
+	     acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
+	     for (i = 0; i < padid->cFormatTags; i++) {
+	        paftd->dwFormatTagIndex = i;
+	        if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
+	           (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
+	           if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
+		      if (paftd->szFormatTag[0] == 0)
+		         MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
+				 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
+		      /* FIXME (EPP): I'm not sure this is the correct
+		       * algorithm (should make more sense to apply the same
+		       * for all already loaded formats, but this will do
+	  	       * for now
+	       	       */
+		      if (bPcmDone) continue;
+		         bPcmDone = TRUE;
+		   }
+		   if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
+                      acmDriverClose(had, 0);
+                      return MMSYSERR_NOERROR;
+		   }
+	        }
+	     }
+          }
+          acmDriverClose(had, 0);
+       }
     }
     return MMSYSERR_NOERROR;
 }
+
Index: wine/dlls/msacm/stream.c
===================================================================
RCS file: /home/wine/wine/dlls/msacm/stream.c,v
retrieving revision 1.12
diff -u -p -r1.12 stream.c
--- wine/dlls/msacm/stream.c	2 Dec 2002 18:10:59 -0000	1.12
+++ wine/dlls/msacm/stream.c	20 Jan 2003 20:02:45 -0000
@@ -147,7 +147,14 @@ MMRESULT WINAPI acmStreamOpen(PHACMSTREA
 	  pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
 	  pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
 
+    /* (WS) I'm removing the following test and making some other changes
+     * herein because the info page on MSDN says that in query mode the 
+     * parameter phas should (and not must) be NULL. Otherwise some
+     * applications will crash because phas is garbage.
+
     if ((fdwOpen & ACM_STREAMOPENF_QUERY) && phas) return MMSYSERR_INVALPARAM;
+    */
+
     if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) return MMSYSERR_INVALPARAM;
 
     wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX);
@@ -230,14 +237,25 @@ MMRESULT WINAPI acmStreamOpen(PHACMSTREA
     ret = MMSYSERR_NOERROR;
     was->drvInst.has = (HACMSTREAM)was;
     if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
-	if (phas)
-	    *phas = (HACMSTREAM)was;
-	TRACE("=> (%d)\n", ret);
-	return ret;
+       /* if not in query mode, return pointer to allocated heap */
+       if (phas)
+	  *phas = (HACMSTREAM)was;
     }
+    else
+       /* otherwise, release memory to avoid leaks */ 
+       HeapFree(MSACM_hHeap, 0, was);
+    TRACE("=> (%d)\n", ret);
+    return ret;
+
 errCleanUp:
-    if (phas)
+    if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
+       /* (WS) As I explained above, this is supposed to be closer to what
+	* is expected from this function. In query mode phas is not needed 
+	* and hence will not be used at all.
+	*/
+       if (phas)
 	*phas = NULL;
+    }
     HeapFree(MSACM_hHeap, 0, was);
     TRACE("=> (%d)\n", ret);
     return ret;


More information about the wine-patches mailing list