msacm enhancement

eric pouech eric.pouech at wanadoo.fr
Fri Apr 20 14:11:53 CDT 2001


as for the native MSACM32 DLL, the builtin one now supports the
following feature:
- some heavily used data about known drivers are stored into the
registry (and gotten
from there) instead of actually loading the driver and getting the info
from it
- this provides some better performance
- the way information is stored into the registry is the same as Win98

the patch also contains a few fixes as well as robustness enhancements

A+
-- 
---------------
Eric Pouech (http://perso.wanadoo.fr/eric.pouech/)
"The future will be better tomorrow", Vice President Dan Quayle
-------------- next part --------------
Name: msacm_cache
ChangeLog: Added cache for drivers information
	fixed a few bugs (memory handling, version info...)
	enhanced validity checks
GenDate: 2001/04/20 19:05:07 UTC
ModifiedFiles: dlls/msacm/driver.c dlls/msacm/filter.c dlls/msacm/format.c dlls/msacm/internal.c dlls/msacm/msacm32_main.c dlls/msacm/pcmconverter.c dlls/msacm/stream.c dlls/msacm/wineacm.h
AddedFiles: 
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/driver.c,v
retrieving revision 1.8
diff -u -u -r1.8 driver.c
--- dlls/msacm/driver.c	2001/04/13 22:28:19	1.8
+++ dlls/msacm/driver.c	2001/04/17 18:49:55
@@ -166,25 +166,24 @@
  */
 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
 {
-    PWINE_ACMDRIVERID	p;
-    ACMDRIVERDETAILSW	add;
+    PWINE_ACMDRIVERID	padid;
+    DWORD		fdwSupport;
 
     if (!fnCallback) return MMSYSERR_INVALPARAM;
     
     if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED))
 	return MMSYSERR_INVALFLAG;
     
-    add.cbStruct = sizeof(add);
-    for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
-	if (acmDriverDetailsW((HACMDRIVERID)p, &add, 0) != MMSYSERR_NOERROR)
-	    continue;
-	if (!p->bEnabled) {
+    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
+	fdwSupport = padid->fdwSupport;
+	
+	if (!padid->bEnabled) {
 	    if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
-		add.fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
+		fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
 	    else
 		continue;
 	}
-	if (!(*fnCallback)((HACMDRIVERID)p, dwInstance, add.fdwSupport))
+	if (!(*fnCallback)((HACMDRIVERID)padid, dwInstance, fdwSupport))
 	    break;
     }
     
Index: dlls/msacm/filter.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/filter.c,v
retrieving revision 1.7
diff -u -u -r1.7 filter.c
--- dlls/msacm/filter.c	2001/02/12 01:28:12	1.7
+++ dlls/msacm/filter.c	2001/04/17 18:49:55
@@ -101,14 +101,12 @@
 		}
 	    }		    
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
-				(LPARAM)pafd, (LPARAM)fdwDetails);
+	    mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails);
 	}
 	break;
     case ACM_FILTERDETAILSF_INDEX:
 	/* should check pafd->dwFilterIndex < aftd->cStandardFilters */
-	mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
-			    (LPARAM)pafd, (LPARAM)fdwDetails);
+	mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails);
 	break;
     default:
 	WARN("Unknown fdwDetails %08lx\n", fdwDetails);
@@ -175,15 +173,10 @@
 				   ACMFILTERENUMCBW fnCallback, DWORD dwInstance,  
 				   DWORD fdwEnum)
 {
-    ACMDRIVERDETAILSW		add;
     ACMFILTERTAGDETAILSW	aftd;
     int				i, j;
 
-    add.cbStruct = sizeof(add);
-    
-    if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) != MMSYSERR_NOERROR) return FALSE;
-
-    for (i = 0; i < add.cFilterTags; i++) {
+    for (i = 0; i < padid->cFilterTags; i++) {
 	memset(&aftd, 0, sizeof(aftd));
 	aftd.cbStruct = sizeof(aftd);
 	aftd.dwFilterTagIndex = i;
@@ -200,7 +193,7 @@
 	    if (acmFilterDetailsW(had, pafd, ACM_FILTERDETAILSF_INDEX) != MMSYSERR_NOERROR) 
 		continue;
 	    
-	    if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, add.fdwSupport))
+	    if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
 		return FALSE; 
 	}
     }
@@ -295,22 +288,19 @@
 	    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
 		/* should check for codec only */
 		if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
-		    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
-					(LPARAM)paftd, (LPARAM)fdwDetails);
+		    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 		    acmDriverClose(had, 0);
 		    if (mmr == MMSYSERR_NOERROR) break;
 		}
 	    }
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
-				(LPARAM)paftd, (LPARAM)fdwDetails);
+	    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 	}
 	break;
 
     case ACM_FILTERTAGDETAILSF_INDEX:
 	/* FIXME should check paftd->dwFilterTagIndex < add.cFilterTags */
-	mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
-			    (LPARAM)paftd, (LPARAM)fdwDetails);
+	mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 	break;
 
     case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
@@ -328,9 +318,8 @@
 		    tmp.cbStruct = sizeof(tmp);
 		    tmp.dwFilterTag = ft;
 
-		    if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
-				      (LPARAM)&tmp, 
-				      (LPARAM)fdwDetails) == MMSYSERR_NOERROR) {
+		    if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, 
+				      (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
 			if (mmr == ACMERR_NOTPOSSIBLE ||
 			    paftd->cbFilterSize < tmp.cbFilterSize) {
 			    *paftd = tmp;
@@ -341,8 +330,7 @@
 		}
 	    }
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
-				(LPARAM)paftd, (LPARAM)fdwDetails);
+	    mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 	}
 	break;
 
@@ -417,7 +405,6 @@
 				  DWORD fdwEnum)
 {
     PWINE_ACMDRIVERID		padid;
-    ACMDRIVERDETAILSW		add;
     int				i;
 
     TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
@@ -430,17 +417,13 @@
     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
 	/* should check for codec only */
 	if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
-	    add.cbStruct = sizeof(add);
 
-	    if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) == MMSYSERR_NOERROR) {
-		for (i = 0; i < add.cFilterTags; i++) {
-		    paftd->dwFilterTagIndex = i;
-		    if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
-			if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, 
-					  add.fdwSupport)) {
-			    padid = NULL;
-			    break;
-			}
+	    for (i = 0; i < padid->cFilterTags; i++) {
+		paftd->dwFilterTagIndex = i;
+		if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
+		    if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
+			padid = NULL;
+			break;
 		    }
 		}
 	    }
Index: dlls/msacm/format.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/format.c,v
retrieving revision 1.9
diff -u -u -r1.9 format.c
--- dlls/msacm/format.c	2001/02/12 01:28:12	1.9
+++ dlls/msacm/format.c	2001/04/19 19:56:53
@@ -58,11 +58,12 @@
 		ACMFORMATDETAILSA	afd;
 		int			i, idx;
 		MMRESULT		mmr;
-		char			buffer[64];
+		char			buffer[ACMFORMATDETAILS_FORMAT_CHARS+16];
 
 		afd.cbStruct = sizeof(afd);
 		afd.dwFormatTag = paftd->dwFormatTag;
-		afd.pwfx = HeapAlloc(GetProcessHeap(), 0, paftd->cbFormatSize);
+		afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize);
+		if (!afd.pwfx) return FALSE;
 		afd.pwfx->wFormatTag = paftd->dwFormatTag;
 		afd.pwfx->cbSize = paftd->cbFormatSize;
 		afd.cbwfx = paftd->cbFormatSize;
@@ -71,7 +72,7 @@
 		    afd.dwFormatIndex = i;
 		    mmr = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
 		    if (mmr == MMSYSERR_NOERROR) {
-			strcpy(buffer, afd.szFormat);
+			strncpy(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS);
 			for (idx = strlen(buffer); 
 			     idx < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; idx++)
 			    buffer[idx] = ' ';
@@ -86,6 +87,7 @@
 		acmDriverClose(had, 0);
 		SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, 
 				    CB_SETCURSEL, 0, 0);
+		HeapFree(MSACM_hHeap, 0, afd.pwfx);
 	    } 
 	}
 	break;
@@ -101,7 +103,8 @@
 		afd.pwfx = affd->afc->pwfx;
 		afd.cbwfx = affd->afc->cbwfx;
 
-		afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0);;
+		afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, 
+							CB_GETCURSEL, 0, 0);;
 		affd->ret = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
 		acmDriverClose(had, 0);
 		return TRUE;
@@ -290,8 +293,7 @@
 /***********************************************************************
  *           acmFormatDetailsW (MSACM32.26)
  */
-MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, 
-				  DWORD fdwDetails)
+MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
 {
     MMRESULT			mmr;
     static WCHAR		fmt1[] = {'%','d',' ','H','z',0};
@@ -319,21 +321,18 @@
 		/* should check for codec only */
 		if (padid->bEnabled && 
 		    acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
-		    mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
-					(LPARAM)pafd, (LPARAM)fdwDetails);
+		    mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
 		    acmDriverClose(had, 0);
 		    if (mmr == MMSYSERR_NOERROR) break;
 		}
 	    }		    
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
-				(LPARAM)pafd, (LPARAM)fdwDetails);
+	    mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
 	}
 	break;
     case ACM_FORMATDETAILSF_INDEX:
 	/* should check pafd->dwFormatIndex < aftd->cStandardFormats */
-	mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
-			    (LPARAM)pafd, (LPARAM)fdwDetails);
+	mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
 	break;
     default:
 	WARN("Unknown fdwDetails %08lx\n", fdwDetails);
@@ -414,15 +413,10 @@
 				   ACMFORMATENUMCBW fnCallback, DWORD dwInstance,  
 				   DWORD fdwEnum)
 {
-    ACMDRIVERDETAILSW		add;
     ACMFORMATTAGDETAILSW	aftd;
     int				i, j;
-
-    add.cbStruct = sizeof(add);
-    
-    if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) != MMSYSERR_NOERROR) return FALSE;
 
-    for (i = 0; i < add.cFormatTags; i++) {
+    for (i = 0; i < padid->cFormatTags; i++) {
 	memset(&aftd, 0, sizeof(aftd));
 	aftd.cbStruct = sizeof(aftd);
 	aftd.dwFormatTagIndex = i;
@@ -453,7 +447,7 @@
 	    
 	    /* more checks to be done on fdwEnum */
 
-	    if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, add.fdwSupport))
+	    if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
 		return FALSE; 
 	}
 	/* the "formats" used by the filters are also reported */
@@ -551,8 +545,7 @@
 		acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
 		continue;
 	    
-	    if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, 
-			      (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
+	    if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
 		mmr = MMSYSERR_NOERROR;
 		break;
 	    }
@@ -598,7 +591,7 @@
 				     DWORD fdwDetails)
 {
     PWINE_ACMDRIVERID	padid;
-    MMRESULT		mmr;
+    MMRESULT		mmr = ACMERR_NOTPOSSIBLE;
 
     TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
 
@@ -609,26 +602,31 @@
     switch (fdwDetails) {
     case ACM_FORMATTAGDETAILSF_FORMATTAG:
 	if (had == (HACMDRIVER)NULL) {
-	    mmr = ACMERR_NOTPOSSIBLE;
 	    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
 		/* should check for codec only */
-		if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
-		    mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-					(LPARAM)paftd, (LPARAM)fdwDetails);
+		if (padid->bEnabled && 
+		    MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
+		    acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
+		    mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 		    acmDriverClose(had, 0);
 		    if (mmr == MMSYSERR_NOERROR) break;
 		}
 	    }
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-				(LPARAM)paftd, (LPARAM)fdwDetails);
+	    PWINE_ACMDRIVER	pad = MSACM_GetDriver(had);
+	    
+	    if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
+		mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 	}
 	break;
 
     case ACM_FORMATTAGDETAILSF_INDEX:
-	/* FIXME should check paftd->dwFormatTagIndex < add.cFormatTags */
-	mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-			    (LPARAM)paftd, (LPARAM)fdwDetails);
+	if (had != (HACMDRIVER)NULL) {
+	    PWINE_ACMDRIVER	pad = MSACM_GetDriver(had);
+	    
+	    if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
+		mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
+	} 
 	break;
 
     case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
@@ -636,7 +634,6 @@
 	    ACMFORMATTAGDETAILSW	tmp;
 	    DWORD			ft = paftd->dwFormatTag;
 
-	    mmr = ACMERR_NOTPOSSIBLE;
 	    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
 		/* should check for codec only */
 		if (padid->bEnabled && 
@@ -646,9 +643,8 @@
 		    tmp.cbStruct = sizeof(tmp);
 		    tmp.dwFormatTag = ft;
 
-		    if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-				      (LPARAM)&tmp, 
-				      (LPARAM)fdwDetails) == MMSYSERR_NOERROR) {
+		    if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, 
+				      (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
 			if (mmr == ACMERR_NOTPOSSIBLE ||
 			    paftd->cbFormatSize < tmp.cbFormatSize) {
 			    *paftd = tmp;
@@ -659,8 +655,7 @@
 		}
 	    }
 	} else {
-	    mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
-				(LPARAM)paftd, (LPARAM)fdwDetails);
+	    mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
 	}
 	break;
 
@@ -735,7 +730,6 @@
 				  DWORD fdwEnum)
 {
     PWINE_ACMDRIVERID		padid;
-    ACMDRIVERDETAILSW		add;
     int				i;
     BOOL			bPcmDone = FALSE;
 
@@ -749,26 +743,26 @@
     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
 	/* should check for codec only */
 	if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
-	    add.cbStruct = sizeof(add);
 
-	    if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) == MMSYSERR_NOERROR) {
-		for (i = 0; i < add.cFormatTags; i++) {
-		    paftd->dwFormatTagIndex = i;
-		    if (acmFormatTagDetailsW(had, paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
-			if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
-			    /* 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, 
-					  add.fdwSupport)) {
-			    padid = NULL;
-			    break;
-			}
+	    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)) {
+			padid = NULL; /* to exist the two nested for loops */
+			break;
 		    }
 		}
 	    }
Index: dlls/msacm/internal.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/internal.c,v
retrieving revision 1.8
diff -u -u -r1.8 internal.c
--- dlls/msacm/internal.c	2000/11/13 04:16:05	1.8
+++ dlls/msacm/internal.c	2001/04/19 19:41:25
@@ -14,6 +14,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "winerror.h"
+#include "winreg.h"
 #include "mmsystem.h"
 #include "msacm.h"
 #include "msacmdrv.h"
@@ -28,7 +29,196 @@
 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
 
+#if 0
 /***********************************************************************
+ *           MSACM_DumpCache
+ */
+static	void MSACM_DumpCache(PWINE_ACMDRIVERID padid) 
+{
+    unsigned 	i;
+
+    TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
+	  padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
+    for (i = 0; i < padid->cache->cFormatTags; i++) {
+	TRACE("\tdwFormatTag=%lu cbwfx=%lu\n", 
+	      padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
+    }
+}
+#endif
+
+/***********************************************************************
+ *           MSACM_FindFormatTagInCache 		[internal]
+ * 
+ *	Returns TRUE is the format tag fmtTag is present in the cache.
+ *	If so, idx is set to its index.
+ */
+BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
+{
+    unsigned 	i;
+
+    for (i = 0; i < padid->cFormatTags; i++) {
+	if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
+	    if (idx) *idx = i;
+	    return TRUE;
+	}
+    }
+    return FALSE;
+}
+
+/***********************************************************************
+ *           MSACM_FillCache
+ */
+static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid) 
+{
+    HACMDRIVER		had = 0;
+    int			ntag;
+    ACMDRIVERDETAILSW	add;
+    ACMFORMATDETAILSW	aftd;
+    WAVEFORMATEX	wfx;
+
+    if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
+	return FALSE;
+
+    padid->aFormatTag = NULL;
+    add.cbStruct = sizeof(add);
+    if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add,  0))
+	goto errCleanUp;
+
+    if (add.cFormatTags > 0) {
+	padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, 
+				      add.cFormatTags * sizeof(padid->aFormatTag[0]));
+	if (!padid->aFormatTag) goto errCleanUp;
+    }
+
+    padid->cFormatTags = add.cFormatTags;
+    padid->cFilterTags = add.cFilterTags;
+    padid->fdwSupport  = add.fdwSupport;
+
+    aftd.cbStruct = sizeof(aftd);
+    /* don't care about retrieving full struct... so a bare WAVEFORMATEX should do */
+    aftd.pwfx = &wfx;
+    aftd.cbwfx = sizeof(wfx);
+
+    for (ntag = 0; ntag < add.cFormatTags; ntag++) {
+	aftd.dwFormatIndex = ntag;
+	if (MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)&aftd, ACM_FORMATDETAILSF_INDEX)) {
+	    TRACE("IIOs (%s)\n", padid->pszDriverAlias);
+	    goto errCleanUp;
+	}
+	padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
+	padid->aFormatTag[ntag].cbwfx = aftd.cbwfx;
+    }
+	    
+    acmDriverClose(had, 0);
+
+    return TRUE;
+
+errCleanUp:
+    if (had) acmDriverClose(had, 0);
+    HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
+    padid->aFormatTag = NULL;
+    return FALSE;
+}
+
+/***********************************************************************
+ *           MSACM_GetRegistryKey
+ */
+static	LPSTR	MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
+{
+    static const char*	baseKey = "Software\\Microsoft\\AudioCompressionManager\\DriverCache\\";
+    LPSTR	ret;
+    int		len;
+
+    if (!padid->pszDriverAlias) {
+	ERR("No alias needed for registry entry\n");
+	return NULL;
+    }
+    len = strlen(baseKey);
+    ret = HeapAlloc(MSACM_hHeap, 0, len + strlen(padid->pszDriverAlias) + 1);
+    if (!ret) return NULL;
+
+    strcpy(ret, baseKey);
+    strcpy(ret + len, padid->pszDriverAlias);
+    CharLowerA(ret + len);
+    return ret;
+}
+
+/***********************************************************************
+ *           MSACM_ReadCache
+ */
+static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
+{
+    LPSTR	key = MSACM_GetRegistryKey(padid);
+    HKEY	hKey;
+    DWORD	type, size;
+
+    if (!key) return FALSE;
+
+    padid->aFormatTag = NULL;
+
+    if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
+	goto errCleanUp;
+
+    size = sizeof(padid->cFormatTags);
+    if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
+	goto errCleanUp;
+    size = sizeof(padid->cFilterTags);
+    if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
+	goto errCleanUp;
+    size = sizeof(padid->fdwSupport);
+    if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
+	goto errCleanUp;
+
+    if (padid->cFormatTags > 0) {
+	size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
+	padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
+	if (!padid->aFormatTag) goto errCleanUp;
+	if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
+	    goto errCleanUp;
+    }
+    HeapFree(MSACM_hHeap, 0, key);
+    return TRUE;
+
+ errCleanUp:
+    HeapFree(MSACM_hHeap, 0, key);
+    HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
+    padid->aFormatTag = NULL;
+    RegCloseKey(hKey);
+    return FALSE;
+}
+
+/***********************************************************************
+ *           MSACM_WriteCache
+ */
+static	BOOL MSACM_WriteCache(PWINE_ACMDRIVERID padid)
+{
+    LPSTR	key = MSACM_GetRegistryKey(padid);
+    HKEY	hKey;
+
+    if (!key) return FALSE;
+
+    if (RegCreateKeyA(HKEY_LOCAL_MACHINE, key, &hKey))
+	goto errCleanUp;
+
+    if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (void*)&padid->cFormatTags, sizeof(DWORD)))
+	goto errCleanUp;
+    if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (void*)&padid->cFilterTags, sizeof(DWORD)))
+	goto errCleanUp;
+    if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (void*)&padid->fdwSupport, sizeof(DWORD)))
+	goto errCleanUp;
+    if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY, 
+		       (void*)padid->aFormatTag, 
+		       padid->cFormatTags * sizeof(padid->aFormatTag[0])))
+	goto errCleanUp;
+    HeapFree(MSACM_hHeap, 0, key);
+    return TRUE;
+
+ errCleanUp:
+    HeapFree(MSACM_hHeap, 0, key);
+    return FALSE;
+}
+
+/***********************************************************************
  *           MSACM_RegisterDriver() 
  */
 PWINE_ACMDRIVERID MSACM_RegisterDriver(LPSTR pszDriverAlias, LPSTR pszFileName,
@@ -54,6 +244,7 @@
         strcpy( padid->pszFileName, pszFileName );
     }
     padid->hInstModule = hinstModule;
+	
     padid->bEnabled = TRUE;
     padid->pACMDriverList = NULL;
     padid->pNextACMDriverID = NULL;
@@ -63,7 +254,12 @@
     MSACM_pLastACMDriverID = padid;
     if (!MSACM_pFirstACMDriverID)
 	MSACM_pFirstACMDriverID = padid;
-    
+    /* disable the driver if we cannot load the cache */
+    if (!MSACM_ReadCache(padid) && !MSACM_FillCache(padid)) {
+	WARN("Couldn't load cache for ACM driver (%s)\n", pszFileName);
+	MSACM_UnregisterDriver(padid);
+	return NULL;
+    }
     return padid;
 }
 
@@ -82,7 +278,7 @@
     if (MSACM_pFirstACMDriverID)
 	return;
     
-    /* FIXME: Do not work! How do I determine the section length? */
+    /* FIXME: Does not work! How do I determine the section length? */
     dwBufferLength = 1024;
 /* EPP 	GetPrivateProfileSectionA("drivers32", NULL, 0, "system.ini"); */
     
@@ -122,7 +318,8 @@
 	HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
     if (p->pszFileName)
 	HeapFree(MSACM_hHeap, 0, p->pszFileName);
-    
+    HeapFree(MSACM_hHeap, 0, p->aFormatTag);
+
     if (p == MSACM_pFirstACMDriverID)
 	MSACM_pFirstACMDriverID = p->pNextACMDriverID;
     if (p == MSACM_pLastACMDriverID)
@@ -142,14 +339,15 @@
 
 /***********************************************************************
  *           MSACM_UnregisterAllDrivers()
- * FIXME
- *   Where should this function be called?
  */
 void MSACM_UnregisterAllDrivers(void)
 {
-    PWINE_ACMDRIVERID p;
+    PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID; 
 
-    for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
+    while (p) {
+	MSACM_WriteCache(p);
+	p = MSACM_UnregisterDriver(p);
+    }
 }
 
 /***********************************************************************
Index: dlls/msacm/msacm32_main.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/msacm32_main.c,v
retrieving revision 1.5
diff -u -u -r1.5 msacm32_main.c
--- dlls/msacm/msacm32_main.c	2001/04/18 17:40:27	1.5
+++ dlls/msacm/msacm32_main.c	2001/04/19 18:52:14
@@ -37,7 +37,7 @@
     case DLL_PROCESS_DETACH:
         MSACM_UnregisterAllDrivers();
         HeapDestroy(MSACM_hHeap);
-        MSACM_hHeap = (HANDLE) NULL;
+        MSACM_hHeap = (HANDLE)NULL;
         MSACM_hInstance32 = (HINSTANCE)NULL;
 	break;
     case DLL_THREAD_ATTACH:
@@ -62,16 +62,19 @@
 DWORD WINAPI acmGetVersion(void)
 {
     OSVERSIONINFOA version;
-    GetVersionExA( &version );
-    switch(version.dwPlatformId)
-    {
+
+    version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+    if (!GetVersionExA( &version ))
+	return 0x04030000;
+
+    switch (version.dwPlatformId) {
     case VER_PLATFORM_WIN32_NT:
 	return 0x04000565; /* 4.0.1381 */
     default:
-        FIXME("%ld not supported\n",version.dwPlatformId);
+        FIXME("%lx not supported\n", version.dwPlatformId);
     case VER_PLATFORM_WIN32_WINDOWS:
-	return 0x04000000; /* 4.0.0 */
-  }
+	return 0x04030000; /* 4.3.0 */
+    }
 }
 
 /***********************************************************************
@@ -89,32 +92,33 @@
     BOOL 		bLocal = TRUE;
     PWINE_ACMDRIVERID	padid;
     DWORD		val = 0;
+    int			i;
     MMRESULT		mmr = MMSYSERR_NOERROR;
 
     TRACE("(0x%08x, %d, %p);\n", hao, uMetric, pMetric);
     
+#define CheckLocal(padid) (!bLocal || ((padid)->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL))
+
     switch (uMetric) {
     case ACM_METRIC_COUNT_DRIVERS:
 	bLocal = FALSE;
 	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_DRIVERS:
-	if (!pao)
-	    return MMSYSERR_INVALHANDLE;
+	if (hao) return MMSYSERR_INVALHANDLE;
 	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
-	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+	    if (padid->bEnabled && CheckLocal(padid))
 		val++;
 	*(LPDWORD)pMetric = val;
 	break;
 
     case ACM_METRIC_COUNT_CODECS:
-	if (!pao)
-	    return MMSYSERR_INVALHANDLE;
 	bLocal = FALSE;
 	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_CODECS:
-	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	if (hao) return MMSYSERR_INVALHANDLE;
 	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
-	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+	    if (padid->bEnabled && (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
+		&& CheckLocal(padid))
 		val++;
 	*(LPDWORD)pMetric = val;
 	break;
@@ -123,9 +127,10 @@
 	bLocal = FALSE;
 	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_CONVERTERS:
-	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	if (hao) return MMSYSERR_INVALHANDLE;
 	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
-	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+	    if (padid->bEnabled && (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER)
+		&& CheckLocal(padid))
 		val++;
 	*(LPDWORD)pMetric = val;
 	break;
@@ -134,9 +139,10 @@
 	bLocal = FALSE;
 	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_FILTERS:
-	/* FIXME: don't know how to differentiate codec, converters & filters yet */
+	if (hao) return MMSYSERR_INVALHANDLE;
 	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
-	    if (padid->bEnabled /* && (local(padid) || !bLocal) */)
+	    if (padid->bEnabled && (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER)
+		&& CheckLocal(padid))
 		val++;
 	*(LPDWORD)pMetric = val;
 	break;
@@ -145,37 +151,42 @@
 	bLocal = FALSE;
 	/* fall thru */
     case ACM_METRIC_COUNT_LOCAL_DISABLED:
-	if (!pao)
-	    return MMSYSERR_INVALHANDLE;  
+	if (hao) return MMSYSERR_INVALHANDLE;
 	for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID)
-	    if (!padid->bEnabled /* && (local(padid) || !bLocal) */)
+	    if (!padid->bEnabled && CheckLocal(padid))
 		val++;
 	*(LPDWORD)pMetric = val;
 	break;
     
     case ACM_METRIC_MAX_SIZE_FORMAT:
-	{
-	    ACMFORMATTAGDETAILSW	aftd;
-
-	    aftd.cbStruct = sizeof(aftd);
-	    aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN;
-
-	    if (hao == (HACMOBJ)NULL) {
-		mmr = acmFormatTagDetailsW((HACMDRIVER)NULL, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);
-	    } else if (MSACM_GetObj(hao, WINE_ACMOBJ_DRIVER)) {
-		mmr = acmFormatTagDetailsW((HACMDRIVER)hao, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);
-	    } else if (MSACM_GetObj(hao, WINE_ACMOBJ_DRIVERID)) {
-		HACMDRIVER	had;
-		
-		if (acmDriverOpen(&had, (HACMDRIVERID)hao, 0) == 0) {
-		    mmr = acmFormatTagDetailsW((HACMDRIVER)hao, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);
-		    acmDriverClose(had, 0);
+	if (hao == (HACMOBJ)NULL) {
+	    for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
+		if (padid->bEnabled) {
+		    for (i = 0; i < padid->cFormatTags; i++) {
+			if (val < padid->aFormatTag[i].cbwfx)
+			    val = padid->aFormatTag[i].cbwfx;
+		    }
+		}
+	    }
+	} else if (pao != NULL) {
+	    switch (pao->dwType) {
+	    case WINE_ACMOBJ_DRIVER:
+	    case WINE_ACMOBJ_DRIVERID:
+		padid = pao->pACMDriverID;
+		break;
+	    default:
+		return MMSYSERR_INVALHANDLE;
+	    }
+	    if (padid->bEnabled) {
+		for (i = 0; i < padid->cFormatTags; i++) {
+		    if (val < padid->aFormatTag[i].cbwfx)
+			val = padid->aFormatTag[i].cbwfx;
 		}
-	    } else {
-		mmr = MMSYSERR_INVALHANDLE;
 	    }
-	    if (mmr == MMSYSERR_NOERROR) *(LPDWORD)pMetric = aftd.cbFormatSize;
+	} else {
+	    return MMSYSERR_INVALHANDLE;
 	}
+	*(LPDWORD)pMetric = val;
         break;
 
     case ACM_METRIC_COUNT_HARDWARE:
Index: dlls/msacm/pcmconverter.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/pcmconverter.c,v
retrieving revision 1.5
diff -u -u -r1.5 pcmconverter.c
--- dlls/msacm/pcmconverter.c	2001/04/13 22:28:35	1.5
+++ dlls/msacm/pcmconverter.c	2001/04/18 06:32:37
@@ -778,7 +778,8 @@
     afd->dwFormatTag = WAVE_FORMAT_PCM;
     afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER;
     afd->szFormat[0] = 0; /* let MSACM format this for us... */
-    
+    afd->cbwfx = sizeof(PCMWAVEFORMAT);
+
     return MMSYSERR_NOERROR;
 }
 
Index: dlls/msacm/stream.c
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/stream.c,v
retrieving revision 1.5
diff -u -u -r1.5 stream.c
--- dlls/msacm/stream.c	2001/01/26 20:43:43	1.5
+++ dlls/msacm/stream.c	2001/03/28 19:22:13
@@ -181,25 +181,30 @@
 	
 	ret = ACMERR_NOTPOSSIBLE;
 	for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) {
+	    if (!wadi->bEnabled || 
+		!MSACM_FindFormatTagInCache(wadi, pwfxSrc->wFormatTag, NULL) ||
+		!MSACM_FindFormatTagInCache(wadi, pwfxDst->wFormatTag, NULL))
+		continue;
 	    ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
-	    if (ret == MMSYSERR_NOERROR) {
-		if ((wad = MSACM_GetDriver(had)) != 0) {
-		    was->obj.dwType = WINE_ACMOBJ_STREAM;
-		    was->obj.pACMDriverID = wad->obj.pACMDriverID;
-		    was->pDrv = wad;
-		    was->hAcmDriver = had;
-		    
-		    ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
-		    if (ret == MMSYSERR_NOERROR) {
-			if (fdwOpen & ACM_STREAMOPENF_QUERY) {
-			    acmDriverClose(had, 0L);
-			}
-			break;
+	    if (ret != MMSYSERR_NOERROR)
+		continue;
+	    if ((wad = MSACM_GetDriver(had)) != 0) {
+		was->obj.dwType = WINE_ACMOBJ_STREAM;
+		was->obj.pACMDriverID = wad->obj.pACMDriverID;
+		was->pDrv = wad;
+		was->hAcmDriver = had;
+		
+		ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
+		TRACE("%s => %08x\n", wadi->pszFileName, ret);
+		if (ret == MMSYSERR_NOERROR) {
+		    if (fdwOpen & ACM_STREAMOPENF_QUERY) {
+			acmDriverClose(had, 0L);
 		    }
+		    break;
 		}
-		/* no match, close this acm driver and try next one */
-		acmDriverClose(had, 0L);
 	    }
+	    /* no match, close this acm driver and try next one */
+	    acmDriverClose(had, 0L);
 	}
 	if (ret != MMSYSERR_NOERROR) {
 	    ret = ACMERR_NOTPOSSIBLE;
Index: dlls/msacm/wineacm.h
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/msacm/wineacm.h,v
retrieving revision 1.5
diff -u -u -r1.5 wineacm.h
--- dlls/msacm/wineacm.h	2001/01/04 20:58:05	1.5
+++ dlls/msacm/wineacm.h	2001/04/17 19:34:34
@@ -307,6 +307,14 @@
     PWINE_ACMDRIVER     pACMDriverList;
     PWINE_ACMDRIVERID   pNextACMDriverID;
     PWINE_ACMDRIVERID	pPrevACMDriverID;
+    /* information about the driver itself, either gotten from registry or driver itself */
+    DWORD		cFilterTags;
+    DWORD		cFormatTags;
+    DWORD		fdwSupport;
+    struct {
+	DWORD			dwFormatTag;
+	DWORD			cbwfx;
+    }* 			aFormatTag;
 } WINE_ACMDRIVERID;
 
 /* From internal.c */
@@ -323,6 +331,7 @@
 extern PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type);
 
 extern MMRESULT MSACM_Message(HACMDRIVER, UINT, LPARAM, LPARAM);
+extern BOOL MSACM_FindFormatTagInCache(WINE_ACMDRIVERID*, DWORD, LPDWORD);
 
 /* From msacm32.c */
 extern HINSTANCE MSACM_hInstance32;


More information about the wine-patches mailing list