Release 9.12.
[wine.git] / dlls / msacm32 / format.c
blob6aab538fffb1404f83f5f0c479fe9c6cb4f5d69f
1 /*
2 * MSACM32 library
4 * Copyright 1998 Patrik Stridvall
5 * 2000 Eric Pouech
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "winerror.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/debug.h"
31 #include "mmsystem.h"
32 #include "mmreg.h"
33 #include "msacm.h"
34 #include "msacmdrv.h"
35 #include "wineacm.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
39 struct MSACM_FillFormatData {
40 HWND hWnd;
41 #define WINE_ACMFF_TAG 0
42 #define WINE_ACMFF_FORMAT 1
43 #define WINE_ACMFF_WFX 2
44 int mode;
45 WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
46 PACMFORMATCHOOSEW afc;
47 DWORD ret;
50 static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid,
51 PACMFORMATTAGDETAILSW paftd,
52 DWORD_PTR dwInstance,
53 DWORD fdwSupport)
55 struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance;
57 switch (affd->mode) {
58 case WINE_ACMFF_TAG:
59 if (paftd->cStandardFormats > 0)
61 if (SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
62 CB_FINDSTRINGEXACT, -1,
63 (LPARAM)paftd->szFormatTag) == CB_ERR)
65 int index = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
66 CB_ADDSTRING, 0, (LPARAM)paftd->szFormatTag);
67 if (((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
68 (paftd->dwFormatTag == affd->afc->pwfx->wFormatTag)) ||
69 (!(affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
70 (paftd->dwFormatTag == WAVE_FORMAT_PCM)))
71 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
72 CB_SETCURSEL, index, 0);
75 break;
76 case WINE_ACMFF_FORMAT:
77 if (lstrcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) {
78 HACMDRIVER had;
80 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
81 ACMFORMATDETAILSW afd = {0};
82 unsigned int i, len;
83 MMRESULT mmr;
84 WCHAR buffer[ACMFORMATDETAILS_FORMAT_CHARS+16];
86 afd.cbStruct = sizeof(afd);
87 afd.dwFormatTag = paftd->dwFormatTag;
88 afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize);
89 if (!afd.pwfx) return FALSE;
90 afd.pwfx->wFormatTag = paftd->dwFormatTag;
91 if (paftd->dwFormatTag != WAVE_FORMAT_PCM)
92 afd.pwfx->cbSize = paftd->cbFormatSize - sizeof(WAVEFORMATEX);
93 afd.cbwfx = paftd->cbFormatSize;
95 for (i = 0; i < paftd->cStandardFormats; i++) {
96 int j, index;
98 afd.dwFormatIndex = i;
99 afd.fdwSupport = 0;
100 mmr = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX);
101 if (mmr == MMSYSERR_NOERROR) {
102 lstrcpynW(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS + 1);
103 len = lstrlenW(buffer);
104 for (j = len; j < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; j++)
105 buffer[j] = ' ';
106 wsprintfW(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
107 L"%d Ko/s", (afd.pwfx->nAvgBytesPerSec + 512) / 1024);
108 index = SendDlgItemMessageW(affd->hWnd,
109 IDD_ACMFORMATCHOOSE_CMB_FORMAT,
110 CB_ADDSTRING, 0, (LPARAM)buffer);
111 if ((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) &&
112 affd->afc->cbwfx >= paftd->cbFormatSize &&
113 !memcmp(afd.pwfx, affd->afc->pwfx, paftd->cbFormatSize))
114 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
115 CB_SETCURSEL, index, 0);
118 acmDriverClose(had, 0);
119 HeapFree(MSACM_hHeap, 0, afd.pwfx);
122 break;
123 case WINE_ACMFF_WFX:
124 if (lstrcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) {
125 HACMDRIVER had;
127 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
128 ACMFORMATDETAILSW afd = {0};
130 afd.cbStruct = sizeof(afd);
131 afd.dwFormatTag = paftd->dwFormatTag;
132 afd.pwfx = affd->afc->pwfx;
133 afd.cbwfx = affd->afc->cbwfx;
135 afd.dwFormatIndex = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
136 CB_GETCURSEL, 0, 0);
137 affd->ret = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX);
138 acmDriverClose(had, 0);
139 return TRUE;
142 break;
143 default:
144 FIXME("Unknown mode (%d)\n", affd->mode);
145 break;
147 return TRUE;
150 static BOOL MSACM_FillFormatTags(HWND hWnd, PACMFORMATCHOOSEW afc)
152 ACMFORMATTAGDETAILSW aftd;
153 struct MSACM_FillFormatData affd;
155 memset(&aftd, 0, sizeof(aftd));
156 aftd.cbStruct = sizeof(aftd);
158 affd.hWnd = hWnd;
159 affd.mode = WINE_ACMFF_TAG;
160 affd.afc = afc;
162 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
163 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_GETCURSEL, 0, 0) == CB_ERR)
164 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0);
165 return TRUE;
168 static BOOL MSACM_FillFormat(HWND hWnd, PACMFORMATCHOOSEW afc)
170 ACMFORMATTAGDETAILSW aftd;
171 struct MSACM_FillFormatData affd;
173 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0);
175 memset(&aftd, 0, sizeof(aftd));
176 aftd.cbStruct = sizeof(aftd);
178 affd.hWnd = hWnd;
179 affd.mode = WINE_ACMFF_FORMAT;
180 affd.afc = afc;
181 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
182 CB_GETLBTEXT,
183 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
184 CB_GETCURSEL, 0, 0),
185 (LPARAM)affd.szFormatTag);
187 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
188 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0) == CB_ERR)
189 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0);
190 return TRUE;
193 static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEW afc)
195 ACMFORMATTAGDETAILSW aftd;
196 struct MSACM_FillFormatData affd;
198 memset(&aftd, 0, sizeof(aftd));
199 aftd.cbStruct = sizeof(aftd);
201 affd.hWnd = hWnd;
202 affd.mode = WINE_ACMFF_WFX;
203 affd.afc = afc;
204 affd.ret = MMSYSERR_NOERROR;
205 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
206 CB_GETLBTEXT,
207 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
208 CB_GETCURSEL, 0, 0),
209 (LPARAM)affd.szFormatTag);
211 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0);
212 return affd.ret;
215 static INT_PTR CALLBACK FormatChooseDlgProc(HWND hWnd, UINT msg,
216 WPARAM wParam, LPARAM lParam)
218 ACMFORMATCHOOSEW *afc = (ACMFORMATCHOOSEW *)GetPropW(hWnd, L"acmprop");
220 TRACE("hwnd=%p msg=%i 0x%08Ix 0x%08Ix\n", hWnd, msg, wParam, lParam);
222 switch (msg) {
223 case WM_INITDIALOG:
224 afc = (PACMFORMATCHOOSEW)lParam;
225 SetPropW(hWnd, L"acmprop", (HANDLE)afc);
226 MSACM_FillFormatTags(hWnd, afc);
227 MSACM_FillFormat(hWnd, afc);
228 if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP|
229 ACMFORMATCHOOSE_STYLEF_SHOWHELP|
230 ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT|
231 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE|
232 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE)) != 0)
233 FIXME("Unsupported style %08lx\n", afc->fdwStyle);
234 if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP))
235 ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE);
236 return TRUE;
238 case WM_COMMAND:
239 switch (LOWORD(wParam)) {
240 case IDOK:
241 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
242 return TRUE;
243 case IDCANCEL:
244 EndDialog(hWnd, ACMERR_CANCELED);
245 return TRUE;
246 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
247 switch (HIWORD(wParam)) {
248 case CBN_SELCHANGE:
249 MSACM_FillFormat(hWnd, afc);
250 break;
251 default:
252 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08Ix\n",
253 HIWORD(wParam), lParam);
254 break;
256 break;
257 case IDD_ACMFORMATCHOOSE_BTN_HELP:
258 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
259 SendMessageW(afc->hwndOwner,
260 RegisterWindowMessageW(ACMHELPMSGSTRINGW), 0L, 0L);
261 break;
263 default:
264 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08Ix\n",
265 LOWORD(wParam), HIWORD(wParam), lParam);
266 break;
268 break;
269 case WM_CONTEXTMENU:
270 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
271 SendMessageW(afc->hwndOwner,
272 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW),
273 wParam, lParam);
274 break;
275 #if defined(WM_CONTEXTHELP)
276 case WM_CONTEXTHELP:
277 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
278 SendMessageW(afc->hwndOwner,
279 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW),
280 wParam, lParam);
281 break;
282 #endif
283 default:
284 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08Ix 0x%08Ix\n",
285 hWnd, msg, wParam, lParam );
286 break;
288 return FALSE;
291 /***********************************************************************
292 * acmFormatChooseA (MSACM32.@)
294 MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc)
296 ACMFORMATCHOOSEW afcw;
297 MMRESULT ret;
298 LPWSTR title = NULL;
299 LPWSTR name = NULL;
300 LPWSTR templ = NULL;
301 DWORD sz;
303 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEA))
304 return MMSYSERR_INVALPARAM;
306 afcw.cbStruct = sizeof(afcw);
307 afcw.fdwStyle = pafmtc->fdwStyle;
308 afcw.hwndOwner = pafmtc->hwndOwner;
309 afcw.pwfx = pafmtc->pwfx;
310 afcw.cbwfx = pafmtc->cbwfx;
311 if (pafmtc->pszTitle)
313 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, NULL, 0);
314 if (!(title = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
316 ret = MMSYSERR_NOMEM;
317 goto done;
319 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, title, sz);
321 afcw.pszTitle = title;
322 if (pafmtc->pszName)
324 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, NULL, 0);
325 if (!(name = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
327 ret = MMSYSERR_NOMEM;
328 goto done;
330 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, name, sz);
332 afcw.pszName = name;
333 afcw.cchName = pafmtc->cchName;
334 afcw.fdwEnum = pafmtc->fdwEnum;
335 afcw.pwfxEnum = pafmtc->pwfxEnum;
336 afcw.hInstance = pafmtc->hInstance;
337 if (pafmtc->pszTemplateName)
339 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, NULL, 0);
340 if (!(templ = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR))))
342 ret = MMSYSERR_NOMEM;
343 goto done;
345 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, templ, sz);
347 afcw.pszTemplateName = templ;
348 /* FIXME: hook procs not supported yet */
349 if (pafmtc->pfnHook)
351 FIXME("Unsupported hook procs\n");
352 ret = MMSYSERR_NOTSUPPORTED;
353 goto done;
355 ret = acmFormatChooseW(&afcw);
356 if (ret == MMSYSERR_NOERROR)
358 WideCharToMultiByte(CP_ACP, 0, afcw.szFormatTag, -1, pafmtc->szFormatTag, sizeof(pafmtc->szFormatTag),
359 NULL, NULL);
360 WideCharToMultiByte(CP_ACP, 0, afcw.szFormat, -1, pafmtc->szFormat, sizeof(pafmtc->szFormat),
361 NULL, NULL);
362 if (pafmtc->pszName)
363 WideCharToMultiByte(CP_ACP, 0, afcw.pszName, -1, pafmtc->pszName, pafmtc->cchName, NULL, NULL);
365 done:
366 HeapFree(GetProcessHeap(), 0, title);
367 HeapFree(GetProcessHeap(), 0, name);
368 HeapFree(GetProcessHeap(), 0, templ);
369 return ret;
372 /***********************************************************************
373 * acmFormatChooseW (MSACM32.@)
375 MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc)
377 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEW))
378 return MMSYSERR_INVALPARAM;
380 if (!pafmtc->pwfx)
381 return MMSYSERR_INVALPARAM;
383 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE)
384 return DialogBoxIndirectParamW(MSACM_hInstance32, (LPCDLGTEMPLATEW)pafmtc->hInstance,
385 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
387 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE)
388 return DialogBoxParamW(pafmtc->hInstance, pafmtc->pszTemplateName,
389 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
391 return DialogBoxParamW(MSACM_hInstance32, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID),
392 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc);
395 /***********************************************************************
396 * acmFormatDetailsA (MSACM32.@)
398 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
399 DWORD fdwDetails)
401 ACMFORMATDETAILSW afdw;
402 MMRESULT mmr;
404 if (!pafd)
405 return MMSYSERR_INVALPARAM;
407 memset(&afdw, 0, sizeof(afdw));
408 afdw.cbStruct = sizeof(afdw);
409 afdw.dwFormatIndex = pafd->dwFormatIndex;
410 afdw.dwFormatTag = pafd->dwFormatTag;
411 afdw.fdwSupport = pafd->fdwSupport;
412 afdw.pwfx = pafd->pwfx;
413 afdw.cbwfx = pafd->cbwfx;
415 mmr = acmFormatDetailsW(had, &afdw, fdwDetails);
416 if (mmr == MMSYSERR_NOERROR) {
417 pafd->dwFormatTag = afdw.dwFormatTag;
418 pafd->fdwSupport = afdw.fdwSupport;
419 WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1,
420 pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL );
422 return mmr;
425 /***********************************************************************
426 * acmFormatDetailsW (MSACM32.@)
428 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
430 MMRESULT mmr;
431 ACMFORMATTAGDETAILSW aftd = {0};
433 TRACE("(%p, %p, %ld)\n", had, pafd, fdwDetails);
435 if (!pafd)
436 return MMSYSERR_INVALPARAM;
438 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
440 if (!pafd->pwfx)
441 return MMSYSERR_INVALPARAM;
443 if (pafd->cbwfx < sizeof(PCMWAVEFORMAT))
444 return MMSYSERR_INVALPARAM;
446 if (pafd->fdwSupport)
447 return MMSYSERR_INVALPARAM;
449 if (pafd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
450 return MMSYSERR_INVALPARAM;
452 switch (fdwDetails) {
453 case ACM_FORMATDETAILSF_FORMAT:
454 if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) {
455 mmr = MMSYSERR_INVALPARAM;
456 break;
458 if (had == NULL) {
459 PWINE_ACMDRIVERID padid;
461 mmr = ACMERR_NOTPOSSIBLE;
462 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
463 /* should check for codec only */
464 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
465 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
466 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
467 acmDriverClose(had, 0);
468 if (mmr == MMSYSERR_NOERROR) break;
471 } else {
472 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
474 break;
475 case ACM_FORMATDETAILSF_INDEX:
476 aftd.cbStruct = sizeof(aftd);
477 aftd.dwFormatTag = pafd->dwFormatTag;
478 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG);
479 if (mmr != MMSYSERR_NOERROR)
480 break;
481 if (pafd->dwFormatIndex >= aftd.cStandardFormats)
483 mmr = MMSYSERR_INVALPARAM;
484 break;
486 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
487 break;
488 default:
489 WARN("Unknown fdwDetails %08lx\n", fdwDetails);
490 mmr = MMSYSERR_INVALFLAG;
491 break;
494 if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == 0) {
495 wsprintfW(pafd->szFormat, L"%d Hz", pafd->pwfx->nSamplesPerSec);
496 if (pafd->pwfx->wBitsPerSample) {
497 wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), L"; %d bits",
498 pafd->pwfx->wBitsPerSample);
500 MultiByteToWideChar(CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1,
501 pafd->szFormat + lstrlenW(pafd->szFormat),
502 ARRAY_SIZE(pafd->szFormat) - lstrlenW(pafd->szFormat));
505 TRACE("=> %d\n", mmr);
506 return mmr;
509 struct MSACM_FormatEnumWtoA_Instance {
510 PACMFORMATDETAILSA pafda;
511 DWORD_PTR dwInstance;
512 ACMFORMATENUMCBA fnCallback;
515 static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid,
516 PACMFORMATDETAILSW pafdw,
517 DWORD_PTR dwInstance,
518 DWORD fdwSupport)
520 struct MSACM_FormatEnumWtoA_Instance* pafei;
522 pafei = (struct MSACM_FormatEnumWtoA_Instance*)dwInstance;
524 pafei->pafda->dwFormatIndex = pafdw->dwFormatIndex;
525 pafei->pafda->dwFormatTag = pafdw->dwFormatTag;
526 pafei->pafda->fdwSupport = pafdw->fdwSupport;
527 WideCharToMultiByte( CP_ACP, 0, pafdw->szFormat, -1,
528 pafei->pafda->szFormat, sizeof(pafei->pafda->szFormat), NULL, NULL );
530 return (pafei->fnCallback)(hadid, pafei->pafda,
531 pafei->dwInstance, fdwSupport);
534 /***********************************************************************
535 * acmFormatEnumA (MSACM32.@)
537 MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda,
538 ACMFORMATENUMCBA fnCallback,
539 DWORD_PTR dwInstance, DWORD fdwEnum)
541 ACMFORMATDETAILSW afdw;
542 struct MSACM_FormatEnumWtoA_Instance afei;
544 if (!pafda)
545 return MMSYSERR_INVALPARAM;
547 if (!fnCallback)
548 return MMSYSERR_INVALPARAM;
550 if (pafda->cbStruct < sizeof(*pafda))
551 return MMSYSERR_INVALPARAM;
553 memset(&afdw, 0, sizeof(afdw));
554 afdw.cbStruct = sizeof(afdw);
555 afdw.dwFormatIndex = pafda->dwFormatIndex;
556 afdw.dwFormatTag = pafda->dwFormatTag;
557 afdw.fdwSupport = pafda->fdwSupport;
558 afdw.pwfx = pafda->pwfx;
559 afdw.cbwfx = pafda->cbwfx;
561 afei.pafda = pafda;
562 afei.dwInstance = dwInstance;
563 afei.fnCallback = fnCallback;
565 return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA,
566 (DWORD_PTR)&afei, fdwEnum);
569 /***********************************************************************
570 * acmFormatEnumW (MSACM32.@)
572 static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
573 PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef,
574 ACMFORMATENUMCBW fnCallback,
575 DWORD_PTR dwInstance, DWORD fdwEnum)
577 ACMFORMATTAGDETAILSW aftd;
578 unsigned int i, j;
580 if (fdwEnum & ACM_FORMATENUMF_SUGGEST) {
581 HDRVR hdrvr;
582 ACMDRVFORMATSUGGEST adfs;
583 pafd->dwFormatIndex = 0;
584 memset(&aftd, 0, sizeof(aftd));
585 aftd.cbStruct = sizeof(aftd);
586 memset(&adfs, 0, sizeof(adfs));
587 adfs.cbStruct = sizeof(adfs);
589 for (i = 0; i < padid->cFormatTags; i++) {
590 aftd.dwFormatTag = i;
591 pafd->dwFormatTag = aftd.dwFormatTag;
592 pafd->pwfx->wFormatTag = pafd->dwFormatTag;
594 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
595 continue;
597 adfs.cbwfxSrc = aftd.cbFormatSize;
598 adfs.cbwfxDst = aftd.cbFormatSize;
599 adfs.pwfxSrc = pwfxRef;
600 adfs.pwfxDst = pafd->pwfx;
601 pafd->fdwSupport = padid->fdwSupport;
603 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
604 aftd.dwFormatTag != pwfxRef->wFormatTag)
605 continue;
607 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
608 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
609 continue;
611 hdrvr = OpenDriver(padid->pszFileName,0,0);
612 SendDriverMessage(hdrvr,ACMDM_FORMAT_SUGGEST,(LPARAM)&adfs,(fdwEnum & 0x000000FFL));
614 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_FORMAT) != MMSYSERR_NOERROR)
615 continue;
617 pafd->cbwfx = sizeof(*(pafd->pwfx));
619 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
620 return FALSE;
622 } else {
623 for (i = 0; i < padid->cFormatTags; i++) {
624 memset(&aftd, 0, sizeof(aftd));
625 aftd.cbStruct = sizeof(aftd);
626 aftd.dwFormatTagIndex = i;
627 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
628 continue;
630 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
631 continue;
633 for (j = 0; j < aftd.cStandardFormats; j++) {
634 pafd->dwFormatIndex = j;
635 pafd->dwFormatTag = aftd.dwFormatTag;
636 pafd->fdwSupport = 0;
637 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR)
638 continue;
640 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
641 pafd->pwfx->nChannels != pwfxRef->nChannels)
642 continue;
643 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
644 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
645 continue;
646 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
647 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
648 continue;
649 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
650 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
651 continue;
653 /* more checks to be done on fdwEnum */
655 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
656 return FALSE;
658 /* the "formats" used by the filters are also reported */
661 return TRUE;
664 /**********************************************************************/
666 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
667 ACMFORMATENUMCBW fnCallback,
668 DWORD_PTR dwInstance, DWORD fdwEnum)
670 PWINE_ACMDRIVERID padid;
671 WAVEFORMATEX wfxRef;
672 BOOL ret;
673 DWORD cbwfxMax;
674 MMRESULT mmr;
676 TRACE("(%p, %p, %p, %Id, %ld)\n",
677 had, pafd, fnCallback, dwInstance, fdwEnum);
679 if (!pafd)
680 return MMSYSERR_INVALPARAM;
682 if (!fnCallback)
683 return MMSYSERR_INVALPARAM;
685 if (pafd->cbStruct < sizeof(*pafd))
686 return MMSYSERR_INVALPARAM;
688 if (pafd->fdwSupport)
689 return MMSYSERR_INVALPARAM;
691 if (!pafd->pwfx)
692 return MMSYSERR_INVALPARAM;
694 if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS|
695 ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE|
696 ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST))
697 wfxRef = *pafd->pwfx;
699 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
700 !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)))
701 return MMSYSERR_INVALPARAM;
703 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
704 (pafd->dwFormatTag != pafd->pwfx->wFormatTag))
705 return MMSYSERR_INVALPARAM;
707 if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))
708 FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum);
710 mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &cbwfxMax);
711 if (mmr != MMSYSERR_NOERROR)
712 return mmr;
713 if (pafd->cbwfx < cbwfxMax)
714 return MMSYSERR_INVALPARAM;
716 if (had) {
717 HACMDRIVERID hadid;
719 if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR)
720 return MMSYSERR_INVALHANDLE;
721 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef,
722 fnCallback, dwInstance, fdwEnum);
723 return MMSYSERR_NOERROR;
725 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
726 /* should check for codec only */
727 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
728 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
729 continue;
730 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
731 fnCallback, dwInstance, fdwEnum);
732 acmDriverClose(had, 0);
733 if (!ret) break;
735 return MMSYSERR_NOERROR;
738 /***********************************************************************
739 * acmFormatSuggest (MSACM32.@)
741 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
742 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
744 ACMFORMATTAGDETAILSW aftd = {0};
745 ACMDRVFORMATSUGGEST adfg;
746 MMRESULT mmr;
748 TRACE("(%p, %p, %p, %ld, %ld)\n",
749 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
751 if (!pwfxSrc || !pwfxDst)
752 return MMSYSERR_INVALPARAM;
754 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
755 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
756 return MMSYSERR_INVALFLAG;
758 /* if we were given PCM, try to convert to PCM */
759 if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && !had &&
760 !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
762 ACMFORMATDETAILSW afd = {0};
763 afd.cbStruct = sizeof(afd);
764 afd.dwFormatTag = WAVE_FORMAT_PCM;
765 afd.pwfx = pwfxSrc;
766 afd.cbwfx = sizeof(PCMWAVEFORMAT);
767 if (!acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_FORMAT))
769 memcpy(pwfxDst, pwfxSrc, sizeof(PCMWAVEFORMAT));
770 return MMSYSERR_NOERROR;
774 aftd.cbStruct = sizeof(aftd);
775 if (fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)
776 aftd.dwFormatTag = pwfxDst->wFormatTag;
777 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);
778 if ((fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) && mmr == ACMERR_NOTPOSSIBLE)
779 return ACMERR_NOTPOSSIBLE;
781 if (cbwfxDst < aftd.cbFormatSize)
782 return MMSYSERR_INVALPARAM;
784 adfg.cbStruct = sizeof(adfg);
785 adfg.fdwSuggest = fdwSuggest;
786 adfg.pwfxSrc = pwfxSrc;
787 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
788 sizeof(WAVEFORMATEX) : (sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
789 adfg.pwfxDst = pwfxDst;
790 adfg.cbwfxDst = cbwfxDst;
792 if (had == NULL) {
793 PWINE_ACMDRIVERID padid;
795 /* MS doc says: ACM finds the best suggestion.
796 * Well, first found will be the "best"
798 mmr = ACMERR_NOTPOSSIBLE;
799 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
800 /* should check for codec only */
801 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
802 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
803 continue;
805 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
806 mmr = MMSYSERR_NOERROR;
807 break;
809 acmDriverClose(had, 0);
811 } else {
812 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
814 return mmr;
817 /***********************************************************************
818 * acmFormatTagDetailsA (MSACM32.@)
820 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
821 DWORD fdwDetails)
823 ACMFORMATTAGDETAILSW aftdw;
824 MMRESULT mmr;
826 memset(&aftdw, 0, sizeof(aftdw));
827 aftdw.cbStruct = sizeof(aftdw);
828 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
829 aftdw.dwFormatTag = paftda->dwFormatTag;
831 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
832 if (mmr == MMSYSERR_NOERROR) {
833 paftda->dwFormatTag = aftdw.dwFormatTag;
834 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
835 paftda->cbFormatSize = aftdw.cbFormatSize;
836 paftda->fdwSupport = aftdw.fdwSupport;
837 paftda->cStandardFormats = aftdw.cStandardFormats;
838 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
839 sizeof(paftda->szFormatTag), NULL, NULL );
841 return mmr;
844 /***********************************************************************
845 * acmFormatTagDetailsW (MSACM32.@)
847 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
848 DWORD fdwDetails)
850 PWINE_ACMDRIVERID padid;
851 MMRESULT mmr = ACMERR_NOTPOSSIBLE;
853 TRACE("(%p, %p, %ld)\n", had, paftd, fdwDetails);
855 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
856 ACM_FORMATTAGDETAILSF_LARGESTSIZE))
857 return MMSYSERR_INVALFLAG;
859 switch (fdwDetails) {
860 case ACM_FORMATTAGDETAILSF_FORMATTAG:
861 if (had == NULL) {
862 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
863 /* should check for codec only */
864 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
865 MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
866 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
867 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
868 acmDriverClose(had, 0);
869 if (mmr == MMSYSERR_NOERROR) break;
872 } else {
873 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
875 if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
876 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
878 break;
880 case ACM_FORMATTAGDETAILSF_INDEX:
881 if (had != NULL) {
882 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
884 if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
885 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
887 break;
889 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
890 if (had == NULL) {
891 ACMFORMATTAGDETAILSW tmp;
892 DWORD ft = paftd->dwFormatTag;
894 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
895 /* should check for codec only */
896 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
897 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
899 memset(&tmp, 0, sizeof(tmp));
900 tmp.cbStruct = sizeof(tmp);
901 tmp.dwFormatTag = ft;
903 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
904 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
905 if (mmr == ACMERR_NOTPOSSIBLE ||
906 paftd->cbFormatSize < tmp.cbFormatSize) {
907 *paftd = tmp;
908 mmr = MMSYSERR_NOERROR;
911 acmDriverClose(had, 0);
914 } else {
915 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
917 break;
919 default:
920 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
921 mmr = MMSYSERR_ERROR;
924 if (mmr == MMSYSERR_NOERROR &&
925 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
926 MultiByteToWideChar(CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
927 ARRAY_SIZE(paftd->szFormatTag));
929 return mmr;
932 struct MSACM_FormatTagEnumWtoA_Instance {
933 PACMFORMATTAGDETAILSA paftda;
934 DWORD_PTR dwInstance;
935 ACMFORMATTAGENUMCBA fnCallback;
938 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
939 PACMFORMATTAGDETAILSW paftdw,
940 DWORD_PTR dwInstance,
941 DWORD fdwSupport)
943 struct MSACM_FormatTagEnumWtoA_Instance* paftei;
945 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
947 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
948 paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
949 paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
950 paftei->paftda->fdwSupport = paftdw->fdwSupport;
951 paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
952 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
953 sizeof(paftei->paftda->szFormatTag), NULL, NULL );
955 return (paftei->fnCallback)(hadid, paftei->paftda,
956 paftei->dwInstance, fdwSupport);
959 /***********************************************************************
960 * acmFormatTagEnumA (MSACM32.@)
962 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
963 ACMFORMATTAGENUMCBA fnCallback,
964 DWORD_PTR dwInstance, DWORD fdwEnum)
966 ACMFORMATTAGDETAILSW aftdw;
967 struct MSACM_FormatTagEnumWtoA_Instance aftei;
969 if (!paftda)
970 return MMSYSERR_INVALPARAM;
972 if (paftda->cbStruct < sizeof(*paftda))
973 return MMSYSERR_INVALPARAM;
975 if (fdwEnum != 0)
976 return MMSYSERR_INVALFLAG;
978 memset(&aftdw, 0, sizeof(aftdw));
979 aftdw.cbStruct = sizeof(aftdw);
980 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
981 aftdw.dwFormatTag = paftda->dwFormatTag;
983 aftei.paftda = paftda;
984 aftei.dwInstance = dwInstance;
985 aftei.fnCallback = fnCallback;
987 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
988 (DWORD_PTR)&aftei, fdwEnum);
991 /***********************************************************************
992 * acmFormatTagEnumW (MSACM32.@)
994 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
995 ACMFORMATTAGENUMCBW fnCallback,
996 DWORD_PTR dwInstance, DWORD fdwEnum)
998 PWINE_ACMDRIVERID padid;
999 unsigned int i;
1000 BOOL bPcmDone = FALSE;
1002 TRACE("(%p, %p, %p, %Id, %ld)\n",
1003 had, paftd, fnCallback, dwInstance, fdwEnum);
1005 if (!paftd)
1006 return MMSYSERR_INVALPARAM;
1008 if (paftd->cbStruct < sizeof(*paftd))
1009 return MMSYSERR_INVALPARAM;
1011 if (fdwEnum != 0)
1012 return MMSYSERR_INVALFLAG;
1014 /* (WS) MSDN info page says that if had != 0, then we should find
1015 * the specific driver to get its tags from. Therefore I'm removing
1016 * the FIXME call and adding a search block below. It also seems
1017 * that the lack of this functionality was the responsible for
1018 * codecs to be multiply and incorrectly listed.
1021 /* if (had) FIXME("had != NULL, not supported\n"); */
1023 if (had) {
1024 if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR)
1025 return MMSYSERR_INVALHANDLE;
1027 for (i = 0; i < padid->cFormatTags; i++) {
1028 paftd->dwFormatTagIndex = i;
1029 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
1030 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
1031 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
1032 if (paftd->szFormatTag[0] == 0)
1033 MultiByteToWideChar(CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
1034 ARRAY_SIZE(paftd->szFormatTag));
1035 /* (WS) I'm preserving this PCM hack since it seems to be
1036 * correct. Please notice this block was borrowed from
1037 * below.
1039 if (bPcmDone) continue;
1040 bPcmDone = TRUE;
1042 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport))
1043 return MMSYSERR_NOERROR;
1047 /* if had==0 then search for the first suitable driver */
1048 else {
1049 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
1050 /* should check for codec only */
1051 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
1052 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
1053 for (i = 0; i < padid->cFormatTags; i++) {
1054 paftd->dwFormatTagIndex = i;
1055 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
1056 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
1057 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
1058 if (paftd->szFormatTag[0] == 0)
1059 MultiByteToWideChar(CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
1060 ARRAY_SIZE(paftd->szFormatTag));
1061 /* FIXME (EPP): I'm not sure this is the correct
1062 * algorithm (should make more sense to apply the same
1063 * for all already loaded formats, but this will do
1064 * for now
1066 if (bPcmDone) continue;
1067 bPcmDone = TRUE;
1069 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
1070 acmDriverClose(had, 0);
1071 return MMSYSERR_NOERROR;
1075 acmDriverClose(had, 0);
1079 return MMSYSERR_NOERROR;