1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1998 Patrik Stridvall
16 #include "wine/unicode.h"
17 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(msacm);
25 static PACMFORMATCHOOSEA afc;
27 struct MSACM_FillFormatData {
29 #define WINE_ACMFF_TAG 0
30 #define WINE_ACMFF_FORMAT 1
31 #define WINE_ACMFF_WFX 2
33 char szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
34 PACMFORMATCHOOSEA afc;
38 static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid,
39 PACMFORMATTAGDETAILSA paftd,
40 DWORD dwInstance, DWORD fdwSupport)
42 struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance;
46 if (SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
48 (WPARAM)-1, (LPARAM)paftd->szFormatTag) == CB_ERR)
49 SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
50 CB_ADDSTRING, 0, (DWORD)paftd->szFormatTag);
52 case WINE_ACMFF_FORMAT:
53 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
56 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
57 ACMFORMATDETAILSA afd;
62 afd.cbStruct = sizeof(afd);
63 afd.dwFormatTag = paftd->dwFormatTag;
64 afd.pwfx = HeapAlloc(GetProcessHeap(), 0, paftd->cbFormatSize);
65 afd.pwfx->wFormatTag = paftd->dwFormatTag;
66 afd.pwfx->cbSize = paftd->cbFormatSize;
67 afd.cbwfx = paftd->cbFormatSize;
69 for (i = 0; i < paftd->cStandardFormats; i++) {
70 afd.dwFormatIndex = i;
71 mmr = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
72 if (mmr == MMSYSERR_NOERROR) {
73 strcpy(buffer, afd.szFormat);
74 for (idx = strlen(buffer);
75 idx < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; idx++)
77 wsprintfA(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
79 (afd.pwfx->nAvgBytesPerSec + 512) / 1024);
80 SendDlgItemMessageA(affd->hWnd,
81 IDD_ACMFORMATCHOOSE_CMB_FORMAT,
82 CB_ADDSTRING, 0, (DWORD)buffer);
85 acmDriverClose(had, 0);
86 SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
92 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
95 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
96 ACMFORMATDETAILSA afd;
98 afd.cbStruct = sizeof(afd);
99 afd.dwFormatTag = paftd->dwFormatTag;
100 afd.pwfx = affd->afc->pwfx;
101 afd.cbwfx = affd->afc->cbwfx;
103 afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0);;
104 affd->ret = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
105 acmDriverClose(had, 0);
111 FIXME("Unknown mode (%d)\n", affd->mode);
117 static BOOL MSACM_FillFormatTags(HWND hWnd)
119 ACMFORMATTAGDETAILSA aftd;
120 struct MSACM_FillFormatData affd;
122 memset(&aftd, 0, sizeof(aftd));
123 aftd.cbStruct = sizeof(aftd);
126 affd.mode = WINE_ACMFF_TAG;
128 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
129 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0);
133 static BOOL MSACM_FillFormat(HWND hWnd)
135 ACMFORMATTAGDETAILSA aftd;
136 struct MSACM_FillFormatData affd;
138 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0);
140 memset(&aftd, 0, sizeof(aftd));
141 aftd.cbStruct = sizeof(aftd);
144 affd.mode = WINE_ACMFF_FORMAT;
145 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
147 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
149 (DWORD)affd.szFormatTag);
151 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
152 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0);
156 static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEA afc)
158 ACMFORMATTAGDETAILSA aftd;
159 struct MSACM_FillFormatData affd;
161 memset(&aftd, 0, sizeof(aftd));
162 aftd.cbStruct = sizeof(aftd);
165 affd.mode = WINE_ACMFF_WFX;
167 affd.ret = MMSYSERR_NOERROR;
169 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
173 static BOOL WINAPI FormatChooseDlgProc(HWND hWnd, UINT msg,
174 WPARAM wParam, LPARAM lParam)
177 TRACE("hwnd=%i msg=%i 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam );
181 afc = (PACMFORMATCHOOSEA)lParam;
182 MSACM_FillFormatTags(hWnd);
183 MSACM_FillFormat(hWnd);
184 if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP|
185 ACMFORMATCHOOSE_STYLEF_SHOWHELP)) != 0)
186 FIXME("Unsupported style %08lx\n", ((PACMFORMATCHOOSEA)lParam)->fdwStyle);
187 if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP))
188 ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE);
192 switch (LOWORD(wParam)) {
194 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
197 EndDialog(hWnd, ACMERR_CANCELED);
199 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
200 switch (HIWORD(wParam)) {
202 MSACM_FillFormat(hWnd);
205 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
206 HIWORD(wParam), lParam);
210 case IDD_ACMFORMATCHOOSE_BTN_HELP:
211 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
212 SendMessageA(afc->hwndOwner,
213 RegisterWindowMessageA(ACMHELPMSGSTRINGA), 0L, 0L);
217 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
218 LOWORD(wParam), HIWORD(wParam), lParam);
223 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
224 SendMessageA(afc->hwndOwner,
225 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA),
228 #if defined(WM_CONTEXTHELP)
230 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
231 SendMessageA(afc->hwndOwner,
232 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA),
237 TRACE("Dropped dlgMsg: hwnd=%i msg=%i 0x%08x 0x%08lx\n",
238 hWnd, msg, wParam, lParam );
244 /***********************************************************************
245 * acmFormatChooseA (MSACM32.23)
247 MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc)
249 return DialogBoxParamA(MSACM_hInstance32, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID),
250 pafmtc->hwndOwner, FormatChooseDlgProc, (INT)pafmtc);
253 /***********************************************************************
254 * acmFormatChooseW (MSACM32.24)
256 MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc)
258 FIXME("(%p): stub\n", pafmtc);
259 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
260 return MMSYSERR_ERROR;
263 /***********************************************************************
264 * acmFormatDetailsA (MSACM32.25)
266 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
269 ACMFORMATDETAILSW afdw;
272 memset(&afdw, 0, sizeof(afdw));
273 afdw.cbStruct = sizeof(afdw);
274 afdw.dwFormatIndex = pafd->dwFormatIndex;
275 afdw.dwFormatTag = pafd->dwFormatTag;
276 afdw.pwfx = pafd->pwfx;
277 afdw.cbwfx = pafd->cbwfx;
279 mmr = acmFormatDetailsW(had, &afdw, fdwDetails);
280 if (mmr == MMSYSERR_NOERROR) {
281 pafd->dwFormatTag = afdw.dwFormatTag;
282 pafd->fdwSupport = afdw.fdwSupport;
283 WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1,
284 pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL );
289 /***********************************************************************
290 * acmFormatDetailsW (MSACM32.26)
292 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
296 static WCHAR fmt1[] = {'%','d',' ','H','z',0};
297 static WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0};
298 ACMFORMATTAGDETAILSA aftd;
300 TRACE("(0x%08x, %p, %ld)\n", had, pafd, fdwDetails);
302 memset(&aftd, 0, sizeof(aftd));
303 aftd.cbStruct = sizeof(aftd);
305 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
307 switch (fdwDetails) {
308 case ACM_FORMATDETAILSF_FORMAT:
309 if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) {
310 mmr = MMSYSERR_INVALPARAM;
313 if (had == (HACMDRIVER)NULL) {
314 PWINE_ACMDRIVERID padid;
316 mmr = ACMERR_NOTPOSSIBLE;
317 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
318 /* should check for codec only */
319 if (padid->bEnabled &&
320 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
321 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
322 (LPARAM)pafd, (LPARAM)fdwDetails);
323 acmDriverClose(had, 0);
324 if (mmr == MMSYSERR_NOERROR) break;
328 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
329 (LPARAM)pafd, (LPARAM)fdwDetails);
332 case ACM_FORMATDETAILSF_INDEX:
333 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
334 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS,
335 (LPARAM)pafd, (LPARAM)fdwDetails);
338 WARN("Unknown fdwDetails %08lx\n", fdwDetails);
339 mmr = MMSYSERR_INVALFLAG;
343 if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == (WCHAR)0) {
344 wsprintfW(pafd->szFormat, fmt1, pafd->pwfx->nSamplesPerSec);
345 if (pafd->pwfx->wBitsPerSample) {
346 wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), fmt2,
347 pafd->pwfx->wBitsPerSample);
349 MultiByteToWideChar( CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1,
350 pafd->szFormat + strlenW(pafd->szFormat),
351 sizeof(pafd->szFormat)/sizeof(WCHAR) - strlenW(pafd->szFormat) );
354 TRACE("=> %d\n", mmr);
358 struct MSACM_FormatEnumWtoA_Instance {
359 PACMFORMATDETAILSA pafda;
361 ACMFORMATENUMCBA fnCallback;
364 static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid,
365 PACMFORMATDETAILSW pafdw,
369 struct MSACM_FormatEnumWtoA_Instance* pafei;
371 pafei = (struct MSACM_FormatEnumWtoA_Instance*)dwInstance;
373 pafei->pafda->dwFormatIndex = pafdw->dwFormatIndex;
374 pafei->pafda->dwFormatTag = pafdw->dwFormatTag;
375 pafei->pafda->fdwSupport = pafdw->fdwSupport;
376 WideCharToMultiByte( CP_ACP, 0, pafdw->szFormat, -1,
377 pafei->pafda->szFormat, sizeof(pafei->pafda->szFormat), NULL, NULL );
379 return (pafei->fnCallback)(hadid, pafei->pafda,
380 pafei->dwInstance, fdwSupport);
383 /***********************************************************************
384 * acmFormatEnumA (MSACM32.27)
386 MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda,
387 ACMFORMATENUMCBA fnCallback, DWORD dwInstance,
390 ACMFORMATDETAILSW afdw;
391 struct MSACM_FormatEnumWtoA_Instance afei;
393 memset(&afdw, 0, sizeof(afdw));
394 afdw.cbStruct = sizeof(afdw);
395 afdw.dwFormatIndex = pafda->dwFormatIndex;
396 afdw.dwFormatTag = pafda->dwFormatTag;
397 afdw.pwfx = pafda->pwfx;
398 afdw.cbwfx = pafda->cbwfx;
401 afei.dwInstance = dwInstance;
402 afei.fnCallback = fnCallback;
404 return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA,
405 (DWORD)&afei, fdwEnum);
408 /***********************************************************************
409 * acmFormatEnumW (MSACM32.28)
411 static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
412 PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef,
413 ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
416 ACMDRIVERDETAILSW add;
417 ACMFORMATTAGDETAILSW aftd;
420 add.cbStruct = sizeof(add);
422 if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) != MMSYSERR_NOERROR) return FALSE;
424 for (i = 0; i < add.cFormatTags; i++) {
425 memset(&aftd, 0, sizeof(aftd));
426 aftd.cbStruct = sizeof(aftd);
427 aftd.dwFormatTagIndex = i;
428 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
431 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
434 for (j = 0; j < aftd.cStandardFormats; j++) {
435 pafd->dwFormatIndex = j;
436 pafd->dwFormatTag = aftd.dwFormatTag;
437 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR)
440 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
441 pafd->pwfx->nChannels != pwfxRef->nChannels)
443 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
444 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
446 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
447 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
449 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
450 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
453 /* more checks to be done on fdwEnum */
455 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, add.fdwSupport))
458 /* the "formats" used by the filters are also reported */
463 /**********************************************************************/
465 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
466 ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
469 PWINE_ACMDRIVERID padid;
473 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
474 had, pafd, fnCallback, dwInstance, fdwEnum);
476 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
478 if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS|
479 ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE|
480 ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST))
481 wfxRef = *pafd->pwfx;
483 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
484 !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)))
485 return MMSYSERR_INVALPARAM;
487 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
488 (pafd->dwFormatTag != pafd->pwfx->wFormatTag))
489 return MMSYSERR_INVALPARAM;
491 if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST|
492 ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))
493 FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum);
498 if (acmDriverID(had, &hadid, 0) != MMSYSERR_NOERROR)
499 return MMSYSERR_INVALHANDLE;
500 return MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef,
501 fnCallback, dwInstance, fdwEnum);
503 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
504 /* should check for codec only */
505 if (!padid->bEnabled || acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
507 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
508 fnCallback, dwInstance, fdwEnum);
509 acmDriverClose(had, 0);
512 return MMSYSERR_NOERROR;
515 /***********************************************************************
516 * acmFormatSuggest (MSACM32.29)
518 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
519 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
521 ACMDRVFORMATSUGGEST adfg;
524 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
525 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
527 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
528 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
529 return MMSYSERR_INVALFLAG;
531 adfg.cbStruct = sizeof(adfg);
532 adfg.fdwSuggest = fdwSuggest;
533 adfg.pwfxSrc = pwfxSrc;
534 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
535 sizeof(WAVEFORMATEX) : pwfxSrc->cbSize;
536 adfg.pwfxDst = pwfxDst;
537 adfg.cbwfxDst = cbwfxDst;
539 if (had == (HACMDRIVER)NULL) {
540 PWINE_ACMDRIVERID padid;
542 /* MS doc says: ACM finds the best suggestion.
543 * Well, first found will be the "best"
545 mmr = ACMERR_NOTPOSSIBLE;
546 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
547 /* should check for codec only */
548 if (!padid->bEnabled ||
549 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
552 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST,
553 (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
554 mmr = MMSYSERR_NOERROR;
557 acmDriverClose(had, 0);
560 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
565 /***********************************************************************
566 * acmFormatTagDetailsA (MSACM32.30)
568 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
571 ACMFORMATTAGDETAILSW aftdw;
574 memset(&aftdw, 0, sizeof(aftdw));
575 aftdw.cbStruct = sizeof(aftdw);
576 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
577 aftdw.dwFormatTag = paftda->dwFormatTag;
579 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
580 if (mmr == MMSYSERR_NOERROR) {
581 paftda->dwFormatTag = aftdw.dwFormatTag;
582 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
583 paftda->cbFormatSize = aftdw.cbFormatSize;
584 paftda->fdwSupport = aftdw.fdwSupport;
585 paftda->cStandardFormats = aftdw.cStandardFormats;
586 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
587 sizeof(paftda->szFormatTag), NULL, NULL );
592 /***********************************************************************
593 * acmFormatTagDetailsW (MSACM32.31)
595 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
598 PWINE_ACMDRIVERID padid;
601 TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
603 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
604 ACM_FORMATTAGDETAILSF_LARGESTSIZE))
605 return MMSYSERR_INVALFLAG;
607 switch (fdwDetails) {
608 case ACM_FORMATTAGDETAILSF_FORMATTAG:
609 if (had == (HACMDRIVER)NULL) {
610 mmr = ACMERR_NOTPOSSIBLE;
611 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
612 /* should check for codec only */
613 if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
614 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
615 (LPARAM)paftd, (LPARAM)fdwDetails);
616 acmDriverClose(had, 0);
617 if (mmr == MMSYSERR_NOERROR) break;
621 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
622 (LPARAM)paftd, (LPARAM)fdwDetails);
626 case ACM_FORMATTAGDETAILSF_INDEX:
627 /* FIXME should check paftd->dwFormatTagIndex < add.cFormatTags */
628 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
629 (LPARAM)paftd, (LPARAM)fdwDetails);
632 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
633 if (had == (HACMDRIVER)NULL) {
634 ACMFORMATTAGDETAILSW tmp;
635 DWORD ft = paftd->dwFormatTag;
637 mmr = ACMERR_NOTPOSSIBLE;
638 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
639 /* should check for codec only */
640 if (padid->bEnabled &&
641 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
643 memset(&tmp, 0, sizeof(tmp));
644 tmp.cbStruct = sizeof(tmp);
645 tmp.dwFormatTag = ft;
647 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
649 (LPARAM)fdwDetails) == MMSYSERR_NOERROR) {
650 if (mmr == ACMERR_NOTPOSSIBLE ||
651 paftd->cbFormatSize < tmp.cbFormatSize) {
653 mmr = MMSYSERR_NOERROR;
656 acmDriverClose(had, 0);
660 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
661 (LPARAM)paftd, (LPARAM)fdwDetails);
666 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
667 mmr = MMSYSERR_ERROR;
670 if (mmr == MMSYSERR_NOERROR &&
671 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
672 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
673 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
678 struct MSACM_FormatTagEnumWtoA_Instance {
679 PACMFORMATTAGDETAILSA paftda;
681 ACMFORMATTAGENUMCBA fnCallback;
684 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
685 PACMFORMATTAGDETAILSW paftdw,
689 struct MSACM_FormatTagEnumWtoA_Instance* paftei;
691 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
693 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
694 paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
695 paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
696 paftei->paftda->fdwSupport = paftdw->fdwSupport;
697 paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
698 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
699 sizeof(paftei->paftda->szFormatTag), NULL, NULL );
701 return (paftei->fnCallback)(hadid, paftei->paftda,
702 paftei->dwInstance, fdwSupport);
705 /***********************************************************************
706 * acmFormatTagEnumA (MSACM32.32)
708 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
709 ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance,
712 ACMFORMATTAGDETAILSW aftdw;
713 struct MSACM_FormatTagEnumWtoA_Instance aftei;
715 memset(&aftdw, 0, sizeof(aftdw));
716 aftdw.cbStruct = sizeof(aftdw);
717 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
718 aftdw.dwFormatTag = paftda->dwFormatTag;
720 aftei.paftda = paftda;
721 aftei.dwInstance = dwInstance;
722 aftei.fnCallback = fnCallback;
724 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
725 (DWORD)&aftei, fdwEnum);
728 /***********************************************************************
729 * acmFormatTagEnumW (MSACM32.33)
731 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
732 ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance,
735 PWINE_ACMDRIVERID padid;
736 ACMDRIVERDETAILSW add;
738 BOOL bPcmDone = FALSE;
740 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
741 had, paftd, fnCallback, dwInstance, fdwEnum);
743 if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
745 if (had) FIXME("had != NULL, not supported\n");
747 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
748 /* should check for codec only */
749 if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
750 add.cbStruct = sizeof(add);
752 if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) == MMSYSERR_NOERROR) {
753 for (i = 0; i < add.cFormatTags; i++) {
754 paftd->dwFormatTagIndex = i;
755 if (acmFormatTagDetailsW(had, paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
756 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
757 /* FIXME (EPP): I'm not sure this is the correct
758 * algorithm (should make more sense to apply the same
759 * for all already loaded formats, but this will do
762 if (bPcmDone) continue;
765 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance,
774 acmDriverClose(had, 0);
776 return MMSYSERR_NOERROR;