1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1998 Patrik Stridvall
17 #include "wine/unicode.h"
18 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(msacm);
26 static PACMFORMATCHOOSEA afc;
28 struct MSACM_FillFormatData {
30 #define WINE_ACMFF_TAG 0
31 #define WINE_ACMFF_FORMAT 1
32 #define WINE_ACMFF_WFX 2
34 char szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
35 PACMFORMATCHOOSEA afc;
39 static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid,
40 PACMFORMATTAGDETAILSA paftd,
41 DWORD dwInstance, DWORD fdwSupport)
43 struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance;
47 if (SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
49 (WPARAM)-1, (LPARAM)paftd->szFormatTag) == CB_ERR)
50 SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
51 CB_ADDSTRING, 0, (DWORD)paftd->szFormatTag);
53 case WINE_ACMFF_FORMAT:
54 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
57 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
58 ACMFORMATDETAILSA afd;
61 char buffer[ACMFORMATDETAILS_FORMAT_CHARS+16];
63 afd.cbStruct = sizeof(afd);
64 afd.dwFormatTag = paftd->dwFormatTag;
65 afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize);
66 if (!afd.pwfx) return FALSE;
67 afd.pwfx->wFormatTag = paftd->dwFormatTag;
68 afd.pwfx->cbSize = paftd->cbFormatSize;
69 afd.cbwfx = paftd->cbFormatSize;
71 for (i = 0; i < paftd->cStandardFormats; i++) {
72 afd.dwFormatIndex = i;
73 mmr = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
74 if (mmr == MMSYSERR_NOERROR) {
75 strncpy(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS);
76 for (idx = strlen(buffer);
77 idx < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; idx++)
79 wsprintfA(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
81 (afd.pwfx->nAvgBytesPerSec + 512) / 1024);
82 SendDlgItemMessageA(affd->hWnd,
83 IDD_ACMFORMATCHOOSE_CMB_FORMAT,
84 CB_ADDSTRING, 0, (DWORD)buffer);
87 acmDriverClose(had, 0);
88 SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
90 HeapFree(MSACM_hHeap, 0, afd.pwfx);
95 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
98 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
99 ACMFORMATDETAILSA afd;
101 afd.cbStruct = sizeof(afd);
102 afd.dwFormatTag = paftd->dwFormatTag;
103 afd.pwfx = affd->afc->pwfx;
104 afd.cbwfx = affd->afc->cbwfx;
106 afd.dwFormatIndex = SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT,
107 CB_GETCURSEL, 0, 0);;
108 affd->ret = acmFormatDetailsA(had, &afd, ACM_FORMATDETAILSF_INDEX);
109 acmDriverClose(had, 0);
115 FIXME("Unknown mode (%d)\n", affd->mode);
121 static BOOL MSACM_FillFormatTags(HWND hWnd)
123 ACMFORMATTAGDETAILSA aftd;
124 struct MSACM_FillFormatData affd;
126 memset(&aftd, 0, sizeof(aftd));
127 aftd.cbStruct = sizeof(aftd);
130 affd.mode = WINE_ACMFF_TAG;
132 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
133 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0);
137 static BOOL MSACM_FillFormat(HWND hWnd)
139 ACMFORMATTAGDETAILSA aftd;
140 struct MSACM_FillFormatData affd;
142 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0);
144 memset(&aftd, 0, sizeof(aftd));
145 aftd.cbStruct = sizeof(aftd);
148 affd.mode = WINE_ACMFF_FORMAT;
149 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
151 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
153 (DWORD)affd.szFormatTag);
155 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
156 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0);
160 static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEA afc)
162 ACMFORMATTAGDETAILSA aftd;
163 struct MSACM_FillFormatData affd;
165 memset(&aftd, 0, sizeof(aftd));
166 aftd.cbStruct = sizeof(aftd);
169 affd.mode = WINE_ACMFF_WFX;
171 affd.ret = MMSYSERR_NOERROR;
173 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
177 static BOOL WINAPI FormatChooseDlgProc(HWND hWnd, UINT msg,
178 WPARAM wParam, LPARAM lParam)
181 TRACE("hwnd=%i msg=%i 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam );
185 afc = (PACMFORMATCHOOSEA)lParam;
186 MSACM_FillFormatTags(hWnd);
187 MSACM_FillFormat(hWnd);
188 if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP|
189 ACMFORMATCHOOSE_STYLEF_SHOWHELP)) != 0)
190 FIXME("Unsupported style %08lx\n", ((PACMFORMATCHOOSEA)lParam)->fdwStyle);
191 if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP))
192 ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE);
196 switch (LOWORD(wParam)) {
198 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
201 EndDialog(hWnd, ACMERR_CANCELED);
203 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
204 switch (HIWORD(wParam)) {
206 MSACM_FillFormat(hWnd);
209 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
210 HIWORD(wParam), lParam);
214 case IDD_ACMFORMATCHOOSE_BTN_HELP:
215 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
216 SendMessageA(afc->hwndOwner,
217 RegisterWindowMessageA(ACMHELPMSGSTRINGA), 0L, 0L);
221 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
222 LOWORD(wParam), HIWORD(wParam), lParam);
227 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
228 SendMessageA(afc->hwndOwner,
229 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA),
232 #if defined(WM_CONTEXTHELP)
234 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
235 SendMessageA(afc->hwndOwner,
236 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA),
241 TRACE("Dropped dlgMsg: hwnd=%i msg=%i 0x%08x 0x%08lx\n",
242 hWnd, msg, wParam, lParam );
248 /***********************************************************************
249 * acmFormatChooseA (MSACM32.23)
251 MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc)
253 return DialogBoxParamA(MSACM_hInstance32, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID),
254 pafmtc->hwndOwner, FormatChooseDlgProc, (INT)pafmtc);
257 /***********************************************************************
258 * acmFormatChooseW (MSACM32.24)
260 MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc)
262 FIXME("(%p): stub\n", pafmtc);
263 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
264 return MMSYSERR_ERROR;
267 /***********************************************************************
268 * acmFormatDetailsA (MSACM32.25)
270 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
273 ACMFORMATDETAILSW afdw;
276 memset(&afdw, 0, sizeof(afdw));
277 afdw.cbStruct = sizeof(afdw);
278 afdw.dwFormatIndex = pafd->dwFormatIndex;
279 afdw.dwFormatTag = pafd->dwFormatTag;
280 afdw.pwfx = pafd->pwfx;
281 afdw.cbwfx = pafd->cbwfx;
283 mmr = acmFormatDetailsW(had, &afdw, fdwDetails);
284 if (mmr == MMSYSERR_NOERROR) {
285 pafd->dwFormatTag = afdw.dwFormatTag;
286 pafd->fdwSupport = afdw.fdwSupport;
287 WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1,
288 pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL );
293 /***********************************************************************
294 * acmFormatDetailsW (MSACM32.26)
296 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
299 static WCHAR fmt1[] = {'%','d',' ','H','z',0};
300 static WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0};
301 ACMFORMATTAGDETAILSA aftd;
303 TRACE("(0x%08x, %p, %ld)\n", had, pafd, fdwDetails);
305 memset(&aftd, 0, sizeof(aftd));
306 aftd.cbStruct = sizeof(aftd);
308 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
310 switch (fdwDetails) {
311 case ACM_FORMATDETAILSF_FORMAT:
312 if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) {
313 mmr = MMSYSERR_INVALPARAM;
316 if (had == (HACMDRIVER)NULL) {
317 PWINE_ACMDRIVERID padid;
319 mmr = ACMERR_NOTPOSSIBLE;
320 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
321 /* should check for codec only */
322 if (padid->bEnabled &&
323 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
324 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
325 acmDriverClose(had, 0);
326 if (mmr == MMSYSERR_NOERROR) break;
330 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
333 case ACM_FORMATDETAILSF_INDEX:
334 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
335 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, 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 ACMFORMATTAGDETAILSW aftd;
419 for (i = 0; i < padid->cFormatTags; i++) {
420 memset(&aftd, 0, sizeof(aftd));
421 aftd.cbStruct = sizeof(aftd);
422 aftd.dwFormatTagIndex = i;
423 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
426 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
429 for (j = 0; j < aftd.cStandardFormats; j++) {
430 pafd->dwFormatIndex = j;
431 pafd->dwFormatTag = aftd.dwFormatTag;
432 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR)
435 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
436 pafd->pwfx->nChannels != pwfxRef->nChannels)
438 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
439 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
441 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
442 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
444 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
445 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
448 /* more checks to be done on fdwEnum */
450 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
453 /* the "formats" used by the filters are also reported */
458 /**********************************************************************/
460 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
461 ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
464 PWINE_ACMDRIVERID padid;
468 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
469 had, pafd, fnCallback, dwInstance, fdwEnum);
471 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
473 if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS|
474 ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE|
475 ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST))
476 wfxRef = *pafd->pwfx;
478 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
479 !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)))
480 return MMSYSERR_INVALPARAM;
482 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) &&
483 (pafd->dwFormatTag != pafd->pwfx->wFormatTag))
484 return MMSYSERR_INVALPARAM;
486 if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST|
487 ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))
488 FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum);
493 if (acmDriverID(had, &hadid, 0) != MMSYSERR_NOERROR)
494 return MMSYSERR_INVALHANDLE;
495 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef,
496 fnCallback, dwInstance, fdwEnum);
497 return MMSYSERR_NOERROR;
499 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
500 /* should check for codec only */
501 if (!padid->bEnabled || acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
503 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
504 fnCallback, dwInstance, fdwEnum);
505 acmDriverClose(had, 0);
508 return MMSYSERR_NOERROR;
511 /***********************************************************************
512 * acmFormatSuggest (MSACM32.29)
514 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
515 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
517 ACMDRVFORMATSUGGEST adfg;
520 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
521 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
523 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
524 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
525 return MMSYSERR_INVALFLAG;
527 adfg.cbStruct = sizeof(adfg);
528 adfg.fdwSuggest = fdwSuggest;
529 adfg.pwfxSrc = pwfxSrc;
530 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
531 sizeof(WAVEFORMATEX) : pwfxSrc->cbSize;
532 adfg.pwfxDst = pwfxDst;
533 adfg.cbwfxDst = cbwfxDst;
535 if (had == (HACMDRIVER)NULL) {
536 PWINE_ACMDRIVERID padid;
538 /* MS doc says: ACM finds the best suggestion.
539 * Well, first found will be the "best"
541 mmr = ACMERR_NOTPOSSIBLE;
542 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
543 /* should check for codec only */
544 if (!padid->bEnabled ||
545 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
548 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
549 mmr = MMSYSERR_NOERROR;
552 acmDriverClose(had, 0);
555 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
560 /***********************************************************************
561 * acmFormatTagDetailsA (MSACM32.30)
563 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
566 ACMFORMATTAGDETAILSW aftdw;
569 memset(&aftdw, 0, sizeof(aftdw));
570 aftdw.cbStruct = sizeof(aftdw);
571 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
572 aftdw.dwFormatTag = paftda->dwFormatTag;
574 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
575 if (mmr == MMSYSERR_NOERROR) {
576 paftda->dwFormatTag = aftdw.dwFormatTag;
577 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
578 paftda->cbFormatSize = aftdw.cbFormatSize;
579 paftda->fdwSupport = aftdw.fdwSupport;
580 paftda->cStandardFormats = aftdw.cStandardFormats;
581 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
582 sizeof(paftda->szFormatTag), NULL, NULL );
587 /***********************************************************************
588 * acmFormatTagDetailsW (MSACM32.31)
590 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
593 PWINE_ACMDRIVERID padid;
594 MMRESULT mmr = ACMERR_NOTPOSSIBLE;
596 TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
598 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
599 ACM_FORMATTAGDETAILSF_LARGESTSIZE))
600 return MMSYSERR_INVALFLAG;
602 switch (fdwDetails) {
603 case ACM_FORMATTAGDETAILSF_FORMATTAG:
604 if (had == (HACMDRIVER)NULL) {
605 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
606 /* should check for codec only */
607 if (padid->bEnabled &&
608 MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
609 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
610 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
611 acmDriverClose(had, 0);
612 if (mmr == MMSYSERR_NOERROR) break;
616 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
618 if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
619 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
623 case ACM_FORMATTAGDETAILSF_INDEX:
624 if (had != (HACMDRIVER)NULL) {
625 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
627 if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
628 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
632 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
633 if (had == (HACMDRIVER)NULL) {
634 ACMFORMATTAGDETAILSW tmp;
635 DWORD ft = paftd->dwFormatTag;
637 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
638 /* should check for codec only */
639 if (padid->bEnabled &&
640 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
642 memset(&tmp, 0, sizeof(tmp));
643 tmp.cbStruct = sizeof(tmp);
644 tmp.dwFormatTag = ft;
646 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
647 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
648 if (mmr == ACMERR_NOTPOSSIBLE ||
649 paftd->cbFormatSize < tmp.cbFormatSize) {
651 mmr = MMSYSERR_NOERROR;
654 acmDriverClose(had, 0);
658 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
663 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
664 mmr = MMSYSERR_ERROR;
667 if (mmr == MMSYSERR_NOERROR &&
668 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
669 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
670 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
675 struct MSACM_FormatTagEnumWtoA_Instance {
676 PACMFORMATTAGDETAILSA paftda;
678 ACMFORMATTAGENUMCBA fnCallback;
681 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
682 PACMFORMATTAGDETAILSW paftdw,
686 struct MSACM_FormatTagEnumWtoA_Instance* paftei;
688 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
690 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
691 paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
692 paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
693 paftei->paftda->fdwSupport = paftdw->fdwSupport;
694 paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
695 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
696 sizeof(paftei->paftda->szFormatTag), NULL, NULL );
698 return (paftei->fnCallback)(hadid, paftei->paftda,
699 paftei->dwInstance, fdwSupport);
702 /***********************************************************************
703 * acmFormatTagEnumA (MSACM32.32)
705 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
706 ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance,
709 ACMFORMATTAGDETAILSW aftdw;
710 struct MSACM_FormatTagEnumWtoA_Instance aftei;
712 memset(&aftdw, 0, sizeof(aftdw));
713 aftdw.cbStruct = sizeof(aftdw);
714 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
715 aftdw.dwFormatTag = paftda->dwFormatTag;
717 aftei.paftda = paftda;
718 aftei.dwInstance = dwInstance;
719 aftei.fnCallback = fnCallback;
721 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
722 (DWORD)&aftei, fdwEnum);
725 /***********************************************************************
726 * acmFormatTagEnumW (MSACM32.33)
728 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
729 ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance,
732 PWINE_ACMDRIVERID padid;
734 BOOL bPcmDone = FALSE;
736 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
737 had, paftd, fnCallback, dwInstance, fdwEnum);
739 if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
741 if (had) FIXME("had != NULL, not supported\n");
743 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
744 /* should check for codec only */
745 if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
747 for (i = 0; i < padid->cFormatTags; i++) {
748 paftd->dwFormatTagIndex = i;
749 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
750 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
751 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
752 if (paftd->szFormatTag[0] == 0)
753 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
754 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
755 /* FIXME (EPP): I'm not sure this is the correct
756 * algorithm (should make more sense to apply the same
757 * for all already loaded formats, but this will do
760 if (bPcmDone) continue;
763 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
764 padid = NULL; /* to exist the two nested for loops */
770 acmDriverClose(had, 0);
772 return MMSYSERR_NOERROR;