- Implement:
[wine.git] / dlls / msacm / format.c
blob728d0879748d5600d7430a15fefd61fc597baf3e
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MSACM32 library
6 * Copyright 1998 Patrik Stridvall
7 * 2000 Eric Pouech
8 */
10 #include <string.h>
11 #include "winbase.h"
12 #include "winnls.h"
13 #include "winerror.h"
14 #include "windef.h"
15 #include "wingdi.h"
16 #include "winuser.h"
17 #include "wine/unicode.h"
18 #include "debugtools.h"
19 #include "mmsystem.h"
20 #include "msacm.h"
21 #include "msacmdrv.h"
22 #include "wineacm.h"
24 DEFAULT_DEBUG_CHANNEL(msacm);
26 static PACMFORMATCHOOSEA afc;
28 struct MSACM_FillFormatData {
29 HWND hWnd;
30 #define WINE_ACMFF_TAG 0
31 #define WINE_ACMFF_FORMAT 1
32 #define WINE_ACMFF_WFX 2
33 int mode;
34 char szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
35 PACMFORMATCHOOSEA afc;
36 DWORD ret;
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;
45 switch (affd->mode) {
46 case WINE_ACMFF_TAG:
47 if (SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
48 CB_FINDSTRINGEXACT,
49 (WPARAM)-1, (LPARAM)paftd->szFormatTag) == CB_ERR)
50 SendDlgItemMessageA(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
51 CB_ADDSTRING, 0, (DWORD)paftd->szFormatTag);
52 break;
53 case WINE_ACMFF_FORMAT:
54 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
55 HACMDRIVER had;
57 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) {
58 ACMFORMATDETAILSA afd;
59 int i, idx;
60 MMRESULT mmr;
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++)
78 buffer[idx] = ' ';
79 wsprintfA(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS,
80 "%d Ko/s",
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,
89 CB_SETCURSEL, 0, 0);
90 HeapFree(MSACM_hHeap, 0, afd.pwfx);
93 break;
94 case WINE_ACMFF_WFX:
95 if (strcmp(affd->szFormatTag, paftd->szFormatTag) == 0) {
96 HACMDRIVER had;
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);
110 return TRUE;
113 break;
114 default:
115 FIXME("Unknown mode (%d)\n", affd->mode);
116 break;
118 return TRUE;
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);
129 affd.hWnd = hWnd;
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);
134 return TRUE;
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);
147 affd.hWnd = hWnd;
148 affd.mode = WINE_ACMFF_FORMAT;
149 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
150 CB_GETLBTEXT,
151 SendDlgItemMessageA(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG,
152 CB_GETCURSEL, 0, 0),
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);
157 return TRUE;
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);
168 affd.hWnd = hWnd;
169 affd.mode = WINE_ACMFF_WFX;
170 affd.afc = afc;
171 affd.ret = MMSYSERR_NOERROR;
173 acmFormatTagEnumA((HACMDRIVER)0, &aftd, MSACM_FillFormatTagsCB, (DWORD)&affd, 0);
174 return affd.ret;
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 );
183 switch (msg) {
184 case WM_INITDIALOG:
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);
193 return TRUE;
195 case WM_COMMAND:
196 switch (LOWORD(wParam)) {
197 case IDOK:
198 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc));
199 return TRUE;
200 case IDCANCEL:
201 EndDialog(hWnd, ACMERR_CANCELED);
202 return TRUE;
203 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG:
204 switch (HIWORD(wParam)) {
205 case CBN_SELCHANGE:
206 MSACM_FillFormat(hWnd);
207 break;
208 default:
209 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
210 HIWORD(wParam), lParam);
211 break;
213 break;
214 case IDD_ACMFORMATCHOOSE_BTN_HELP:
215 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)
216 SendMessageA(afc->hwndOwner,
217 RegisterWindowMessageA(ACMHELPMSGSTRINGA), 0L, 0L);
218 break;
220 default:
221 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
222 LOWORD(wParam), HIWORD(wParam), lParam);
223 break;
225 break;
226 case WM_CONTEXTMENU:
227 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
228 SendMessageA(afc->hwndOwner,
229 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA),
230 wParam, lParam);
231 break;
232 #if defined(WM_CONTEXTHELP)
233 case WM_CONTEXTHELP:
234 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP)
235 SendMessageA(afc->hwndOwner,
236 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA),
237 wParam, lParam);
238 break;
239 #endif
240 default:
241 TRACE("Dropped dlgMsg: hwnd=%i msg=%i 0x%08x 0x%08lx\n",
242 hWnd, msg, wParam, lParam );
243 break;
245 return FALSE;
248 /***********************************************************************
249 * acmFormatChooseA (MSACM32.@)
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.@)
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.@)
270 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd,
271 DWORD fdwDetails)
273 ACMFORMATDETAILSW afdw;
274 MMRESULT mmr;
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 );
290 return mmr;
293 /***********************************************************************
294 * acmFormatDetailsW (MSACM32.@)
296 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails)
298 MMRESULT mmr;
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;
314 break;
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->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
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;
329 } else {
330 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
332 break;
333 case ACM_FORMATDETAILSF_INDEX:
334 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
335 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails);
336 break;
337 default:
338 WARN("Unknown fdwDetails %08lx\n", fdwDetails);
339 mmr = MMSYSERR_INVALFLAG;
340 break;
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);
355 return mmr;
358 struct MSACM_FormatEnumWtoA_Instance {
359 PACMFORMATDETAILSA pafda;
360 DWORD dwInstance;
361 ACMFORMATENUMCBA fnCallback;
364 static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid,
365 PACMFORMATDETAILSW pafdw,
366 DWORD dwInstance,
367 DWORD fdwSupport)
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.@)
386 MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda,
387 ACMFORMATENUMCBA fnCallback, DWORD dwInstance,
388 DWORD fdwEnum)
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;
400 afei.pafda = pafda;
401 afei.dwInstance = dwInstance;
402 afei.fnCallback = fnCallback;
404 return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA,
405 (DWORD)&afei, fdwEnum);
408 /***********************************************************************
409 * acmFormatEnumW (MSACM32.@)
411 static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
412 PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef,
413 ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
414 DWORD fdwEnum)
416 ACMFORMATTAGDETAILSW aftd;
417 int i, j;
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)
424 continue;
426 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag)
427 continue;
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)
433 continue;
435 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) &&
436 pafd->pwfx->nChannels != pwfxRef->nChannels)
437 continue;
438 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) &&
439 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec)
440 continue;
441 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) &&
442 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample)
443 continue;
444 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) &&
445 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE))
446 continue;
448 /* more checks to be done on fdwEnum */
450 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
451 return FALSE;
453 /* the "formats" used by the filters are also reported */
455 return TRUE;
458 /**********************************************************************/
460 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd,
461 ACMFORMATENUMCBW fnCallback, DWORD dwInstance,
462 DWORD fdwEnum)
464 PWINE_ACMDRIVERID padid;
465 WAVEFORMATEX wfxRef;
466 BOOL ret;
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);
490 if (had) {
491 HACMDRIVERID hadid;
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->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
502 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
503 continue;
504 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef,
505 fnCallback, dwInstance, fdwEnum);
506 acmDriverClose(had, 0);
507 if (!ret) break;
509 return MMSYSERR_NOERROR;
512 /***********************************************************************
513 * acmFormatSuggest (MSACM32.@)
515 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
516 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest)
518 ACMDRVFORMATSUGGEST adfg;
519 MMRESULT mmr;
521 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
522 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest);
524 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC|
525 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG))
526 return MMSYSERR_INVALFLAG;
528 adfg.cbStruct = sizeof(adfg);
529 adfg.fdwSuggest = fdwSuggest;
530 adfg.pwfxSrc = pwfxSrc;
531 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ?
532 sizeof(WAVEFORMATEX) : pwfxSrc->cbSize;
533 adfg.pwfxDst = pwfxDst;
534 adfg.cbwfxDst = cbwfxDst;
536 if (had == (HACMDRIVER)NULL) {
537 PWINE_ACMDRIVERID padid;
539 /* MS doc says: ACM finds the best suggestion.
540 * Well, first found will be the "best"
542 mmr = ACMERR_NOTPOSSIBLE;
543 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
544 /* should check for codec only */
545 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
546 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
547 continue;
549 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) {
550 mmr = MMSYSERR_NOERROR;
551 break;
553 acmDriverClose(had, 0);
555 } else {
556 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L);
558 return mmr;
561 /***********************************************************************
562 * acmFormatTagDetailsA (MSACM32.@)
564 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
565 DWORD fdwDetails)
567 ACMFORMATTAGDETAILSW aftdw;
568 MMRESULT mmr;
570 memset(&aftdw, 0, sizeof(aftdw));
571 aftdw.cbStruct = sizeof(aftdw);
572 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
573 aftdw.dwFormatTag = paftda->dwFormatTag;
575 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails);
576 if (mmr == MMSYSERR_NOERROR) {
577 paftda->dwFormatTag = aftdw.dwFormatTag;
578 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex;
579 paftda->cbFormatSize = aftdw.cbFormatSize;
580 paftda->fdwSupport = aftdw.fdwSupport;
581 paftda->cStandardFormats = aftdw.cStandardFormats;
582 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag,
583 sizeof(paftda->szFormatTag), NULL, NULL );
585 return mmr;
588 /***********************************************************************
589 * acmFormatTagDetailsW (MSACM32.@)
591 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
592 DWORD fdwDetails)
594 PWINE_ACMDRIVERID padid;
595 MMRESULT mmr = ACMERR_NOTPOSSIBLE;
597 TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
599 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX|
600 ACM_FORMATTAGDETAILSF_LARGESTSIZE))
601 return MMSYSERR_INVALFLAG;
603 switch (fdwDetails) {
604 case ACM_FORMATTAGDETAILSF_FORMATTAG:
605 if (had == (HACMDRIVER)NULL) {
606 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
607 /* should check for codec only */
608 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
609 MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) &&
610 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
611 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
612 acmDriverClose(had, 0);
613 if (mmr == MMSYSERR_NOERROR) break;
616 } else {
617 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
619 if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL))
620 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
622 break;
624 case ACM_FORMATTAGDETAILSF_INDEX:
625 if (had != (HACMDRIVER)NULL) {
626 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
628 if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags)
629 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
631 break;
633 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
634 if (had == (HACMDRIVER)NULL) {
635 ACMFORMATTAGDETAILSW tmp;
636 DWORD ft = paftd->dwFormatTag;
638 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
639 /* should check for codec only */
640 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
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,
648 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) {
649 if (mmr == ACMERR_NOTPOSSIBLE ||
650 paftd->cbFormatSize < tmp.cbFormatSize) {
651 *paftd = tmp;
652 mmr = MMSYSERR_NOERROR;
655 acmDriverClose(had, 0);
658 } else {
659 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails);
661 break;
663 default:
664 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
665 mmr = MMSYSERR_ERROR;
668 if (mmr == MMSYSERR_NOERROR &&
669 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0)
670 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
671 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
673 return mmr;
676 struct MSACM_FormatTagEnumWtoA_Instance {
677 PACMFORMATTAGDETAILSA paftda;
678 DWORD dwInstance;
679 ACMFORMATTAGENUMCBA fnCallback;
682 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid,
683 PACMFORMATTAGDETAILSW paftdw,
684 DWORD dwInstance,
685 DWORD fdwSupport)
687 struct MSACM_FormatTagEnumWtoA_Instance* paftei;
689 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance;
691 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex;
692 paftei->paftda->dwFormatTag = paftdw->dwFormatTag;
693 paftei->paftda->cbFormatSize = paftdw->cbFormatSize;
694 paftei->paftda->fdwSupport = paftdw->fdwSupport;
695 paftei->paftda->cStandardFormats = paftdw->cStandardFormats;
696 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag,
697 sizeof(paftei->paftda->szFormatTag), NULL, NULL );
699 return (paftei->fnCallback)(hadid, paftei->paftda,
700 paftei->dwInstance, fdwSupport);
703 /***********************************************************************
704 * acmFormatTagEnumA (MSACM32.@)
706 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda,
707 ACMFORMATTAGENUMCBA fnCallback, DWORD dwInstance,
708 DWORD fdwEnum)
710 ACMFORMATTAGDETAILSW aftdw;
711 struct MSACM_FormatTagEnumWtoA_Instance aftei;
713 memset(&aftdw, 0, sizeof(aftdw));
714 aftdw.cbStruct = sizeof(aftdw);
715 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex;
716 aftdw.dwFormatTag = paftda->dwFormatTag;
718 aftei.paftda = paftda;
719 aftei.dwInstance = dwInstance;
720 aftei.fnCallback = fnCallback;
722 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA,
723 (DWORD)&aftei, fdwEnum);
726 /***********************************************************************
727 * acmFormatTagEnumW (MSACM32.@)
729 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd,
730 ACMFORMATTAGENUMCBW fnCallback, DWORD dwInstance,
731 DWORD fdwEnum)
733 PWINE_ACMDRIVERID padid;
734 int i;
735 BOOL bPcmDone = FALSE;
737 TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
738 had, paftd, fnCallback, dwInstance, fdwEnum);
740 if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
742 if (had) FIXME("had != NULL, not supported\n");
744 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
745 /* should check for codec only */
746 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) &&
747 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
748 for (i = 0; i < padid->cFormatTags; i++) {
749 paftd->dwFormatTagIndex = i;
750 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS,
751 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
752 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) {
753 if (paftd->szFormatTag[0] == 0)
754 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag,
755 sizeof(paftd->szFormatTag)/sizeof(WCHAR) );
756 /* FIXME (EPP): I'm not sure this is the correct
757 * algorithm (should make more sense to apply the same
758 * for all already loaded formats, but this will do
759 * for now
761 if (bPcmDone) continue;
762 bPcmDone = TRUE;
764 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) {
765 padid = NULL; /* to exist the two nested for loops */
766 break;
771 acmDriverClose(had, 0);
773 return MMSYSERR_NOERROR;