4 * Copyright 1998 Patrik Stridvall
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
24 struct MSACM_FillFormatData
{
26 #define WINE_ACMFF_TAG 0
27 #define WINE_ACMFF_FORMAT 1
28 #define WINE_ACMFF_WFX 2
30 WCHAR szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
31 PACMFORMATCHOOSEW afc
;
35 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
36 PACMFORMATTAGDETAILSW paftd
,
40 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
44 if (SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
45 CB_FINDSTRINGEXACT
, -1,
46 (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
47 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
48 CB_ADDSTRING
, 0, (LPARAM
)paftd
->szFormatTag
);
50 case WINE_ACMFF_FORMAT
:
51 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
54 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
55 ACMFORMATDETAILSW afd
;
58 WCHAR buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
60 afd
.cbStruct
= sizeof(afd
);
61 afd
.dwFormatTag
= paftd
->dwFormatTag
;
62 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
63 if (!afd
.pwfx
) return FALSE
;
64 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
65 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
66 afd
.cbwfx
= paftd
->cbFormatSize
;
68 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
69 static const WCHAR fmtW
[] = {'%','d',' ','K','o','/','s','\0'};
72 afd
.dwFormatIndex
= i
;
73 mmr
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
74 if (mmr
== MMSYSERR_NOERROR
) {
75 lstrcpynW(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
76 len
= strlenW(buffer
);
77 for (j
= len
; j
< ACMFORMATTAGDETAILS_FORMATTAG_CHARS
; j
++)
79 wsprintfW(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
80 fmtW
, (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
81 SendDlgItemMessageW(affd
->hWnd
,
82 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
83 CB_ADDSTRING
, 0, (LPARAM
)buffer
);
86 acmDriverClose(had
, 0);
87 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
89 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
94 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
97 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
98 ACMFORMATDETAILSW afd
;
100 afd
.cbStruct
= sizeof(afd
);
101 afd
.dwFormatTag
= paftd
->dwFormatTag
;
102 afd
.pwfx
= affd
->afc
->pwfx
;
103 afd
.cbwfx
= affd
->afc
->cbwfx
;
105 afd
.dwFormatIndex
= SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
107 affd
->ret
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
108 acmDriverClose(had
, 0);
114 FIXME("Unknown mode (%d)\n", affd
->mode
);
120 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
122 ACMFORMATTAGDETAILSW aftd
;
123 struct MSACM_FillFormatData affd
;
125 memset(&aftd
, 0, sizeof(aftd
));
126 aftd
.cbStruct
= sizeof(aftd
);
129 affd
.mode
= WINE_ACMFF_TAG
;
131 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
132 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
136 static BOOL
MSACM_FillFormat(HWND hWnd
)
138 ACMFORMATTAGDETAILSW aftd
;
139 struct MSACM_FillFormatData affd
;
141 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
143 memset(&aftd
, 0, sizeof(aftd
));
144 aftd
.cbStruct
= sizeof(aftd
);
147 affd
.mode
= WINE_ACMFF_FORMAT
;
148 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
150 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
152 (LPARAM
)affd
.szFormatTag
);
154 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
155 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
159 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEW afc
)
161 ACMFORMATTAGDETAILSW aftd
;
162 struct MSACM_FillFormatData affd
;
164 memset(&aftd
, 0, sizeof(aftd
));
165 aftd
.cbStruct
= sizeof(aftd
);
168 affd
.mode
= WINE_ACMFF_WFX
;
170 affd
.ret
= MMSYSERR_NOERROR
;
171 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
173 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
175 (LPARAM
)affd
.szFormatTag
);
177 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
181 static const WCHAR fmt_prop
[] = {'a','c','m','p','r','o','p','\0'};
183 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
184 WPARAM wParam
, LPARAM lParam
)
186 PACMFORMATCHOOSEW afc
= (PACMFORMATCHOOSEW
)GetPropW(hWnd
, fmt_prop
);
188 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
192 afc
= (PACMFORMATCHOOSEW
)lParam
;
193 SetPropW(hWnd
, fmt_prop
, (HANDLE
)afc
);
194 MSACM_FillFormatTags(hWnd
);
195 MSACM_FillFormat(hWnd
);
196 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
197 ACMFORMATCHOOSE_STYLEF_SHOWHELP
|
198 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
|
199 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)) != 0)
200 FIXME("Unsupported style %08x\n", afc
->fdwStyle
);
201 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
202 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
206 switch (LOWORD(wParam
)) {
208 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
211 EndDialog(hWnd
, ACMERR_CANCELED
);
213 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
214 switch (HIWORD(wParam
)) {
216 MSACM_FillFormat(hWnd
);
219 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
220 HIWORD(wParam
), lParam
);
224 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
225 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
226 SendMessageW(afc
->hwndOwner
,
227 RegisterWindowMessageW(ACMHELPMSGSTRINGW
), 0L, 0L);
231 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
232 LOWORD(wParam
), HIWORD(wParam
), lParam
);
237 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
238 SendMessageW(afc
->hwndOwner
,
239 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW
),
242 #if defined(WM_CONTEXTHELP)
244 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
245 SendMessageW(afc
->hwndOwner
,
246 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW
),
251 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
252 hWnd
, msg
, wParam
, lParam
);
258 /***********************************************************************
259 * acmFormatChooseA (MSACM32.@)
261 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
263 ACMFORMATCHOOSEW afcw
;
270 afcw
.cbStruct
= sizeof(afcw
);
271 afcw
.fdwStyle
= pafmtc
->fdwStyle
;
272 afcw
.hwndOwner
= pafmtc
->hwndOwner
;
273 afcw
.pwfx
= pafmtc
->pwfx
;
274 afcw
.cbwfx
= pafmtc
->cbwfx
;
275 if (pafmtc
->pszTitle
)
277 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, NULL
, 0);
278 if (!(title
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
280 ret
= MMSYSERR_NOMEM
;
283 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, title
, sz
);
285 afcw
.pszTitle
= title
;
288 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, NULL
, 0);
289 if (!(name
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
291 ret
= MMSYSERR_NOMEM
;
294 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, name
, sz
);
297 afcw
.cchName
= pafmtc
->cchName
;
298 afcw
.fdwEnum
= pafmtc
->fdwEnum
;
299 afcw
.pwfxEnum
= pafmtc
->pwfxEnum
;
300 afcw
.hInstance
= pafmtc
->hInstance
;
301 if (pafmtc
->pszTemplateName
)
303 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, NULL
, 0);
304 if (!(templ
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
306 ret
= MMSYSERR_NOMEM
;
309 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, templ
, sz
);
311 afcw
.pszTemplateName
= templ
;
312 /* FIXME: hook procs not supported yet */
315 FIXME("Unsupported hook procs\n");
316 ret
= MMSYSERR_NOTSUPPORTED
;
319 ret
= acmFormatChooseW(&afcw
);
320 if (ret
== MMSYSERR_NOERROR
)
322 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormatTag
, -1, pafmtc
->szFormatTag
, sizeof(pafmtc
->szFormatTag
),
324 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormat
, -1, pafmtc
->szFormat
, sizeof(pafmtc
->szFormat
),
327 WideCharToMultiByte(CP_ACP
, 0, afcw
.pszName
, -1, pafmtc
->pszName
, pafmtc
->cchName
, NULL
, NULL
);
330 HeapFree(GetProcessHeap(), 0, title
);
331 HeapFree(GetProcessHeap(), 0, name
);
332 HeapFree(GetProcessHeap(), 0, templ
);
336 /***********************************************************************
337 * acmFormatChooseW (MSACM32.@)
339 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
341 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
)
342 return DialogBoxIndirectParamW(MSACM_hInstance32
, (LPCDLGTEMPLATEW
)pafmtc
->hInstance
,
343 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
345 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)
346 return DialogBoxParamW(pafmtc
->hInstance
, pafmtc
->pszTemplateName
,
347 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
349 return DialogBoxParamW(MSACM_hInstance32
, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID
),
350 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
353 /***********************************************************************
354 * acmFormatDetailsA (MSACM32.@)
356 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
359 ACMFORMATDETAILSW afdw
;
362 memset(&afdw
, 0, sizeof(afdw
));
363 afdw
.cbStruct
= sizeof(afdw
);
364 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
365 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
366 afdw
.pwfx
= pafd
->pwfx
;
367 afdw
.cbwfx
= pafd
->cbwfx
;
369 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
370 if (mmr
== MMSYSERR_NOERROR
) {
371 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
372 pafd
->fdwSupport
= afdw
.fdwSupport
;
373 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
374 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
379 /***********************************************************************
380 * acmFormatDetailsW (MSACM32.@)
382 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
385 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
386 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
387 ACMFORMATTAGDETAILSA aftd
;
389 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
391 memset(&aftd
, 0, sizeof(aftd
));
392 aftd
.cbStruct
= sizeof(aftd
);
394 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
396 switch (fdwDetails
) {
397 case ACM_FORMATDETAILSF_FORMAT
:
398 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
399 mmr
= MMSYSERR_INVALPARAM
;
403 PWINE_ACMDRIVERID padid
;
405 mmr
= ACMERR_NOTPOSSIBLE
;
406 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
407 /* should check for codec only */
408 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
409 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
410 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
411 acmDriverClose(had
, 0);
412 if (mmr
== MMSYSERR_NOERROR
) break;
416 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
419 case ACM_FORMATDETAILSF_INDEX
:
420 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
421 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
424 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
425 mmr
= MMSYSERR_INVALFLAG
;
429 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
430 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
431 if (pafd
->pwfx
->wBitsPerSample
) {
432 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
433 pafd
->pwfx
->wBitsPerSample
);
435 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
436 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
437 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
440 TRACE("=> %d\n", mmr
);
444 struct MSACM_FormatEnumWtoA_Instance
{
445 PACMFORMATDETAILSA pafda
;
446 DWORD_PTR dwInstance
;
447 ACMFORMATENUMCBA fnCallback
;
450 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
451 PACMFORMATDETAILSW pafdw
,
452 DWORD_PTR dwInstance
,
455 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
457 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
459 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
460 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
461 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
462 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
463 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
465 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
466 pafei
->dwInstance
, fdwSupport
);
469 /***********************************************************************
470 * acmFormatEnumA (MSACM32.@)
472 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
473 ACMFORMATENUMCBA fnCallback
,
474 DWORD_PTR dwInstance
, DWORD fdwEnum
)
476 ACMFORMATDETAILSW afdw
;
477 struct MSACM_FormatEnumWtoA_Instance afei
;
480 return MMSYSERR_INVALPARAM
;
482 if (pafda
->cbStruct
< sizeof(*pafda
))
483 return MMSYSERR_INVALPARAM
;
485 memset(&afdw
, 0, sizeof(afdw
));
486 afdw
.cbStruct
= sizeof(afdw
);
487 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
488 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
489 afdw
.pwfx
= pafda
->pwfx
;
490 afdw
.cbwfx
= pafda
->cbwfx
;
493 afei
.dwInstance
= dwInstance
;
494 afei
.fnCallback
= fnCallback
;
496 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
497 (DWORD_PTR
)&afei
, fdwEnum
);
500 /***********************************************************************
501 * acmFormatEnumW (MSACM32.@)
503 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
504 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
505 ACMFORMATENUMCBW fnCallback
,
506 DWORD_PTR dwInstance
, DWORD fdwEnum
)
508 ACMFORMATTAGDETAILSW aftd
;
511 if (fdwEnum
& ACM_FORMATENUMF_SUGGEST
) {
513 ACMDRVFORMATSUGGEST adfs
;
514 pafd
->dwFormatIndex
= 0;
515 memset(&aftd
, 0, sizeof(aftd
));
516 aftd
.cbStruct
= sizeof(aftd
);
517 memset(&adfs
, 0, sizeof(adfs
));
518 adfs
.cbStruct
= sizeof(adfs
);
520 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
521 aftd
.dwFormatTag
= i
;
522 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
523 pafd
->pwfx
->wFormatTag
= pafd
->dwFormatTag
;
525 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
528 adfs
.cbwfxSrc
= aftd
.cbFormatSize
;
529 adfs
.cbwfxDst
= aftd
.cbFormatSize
;
530 adfs
.pwfxSrc
= pwfxRef
;
531 adfs
.pwfxDst
= pafd
->pwfx
;
532 pafd
->fdwSupport
= padid
->fdwSupport
;
534 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
535 aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
538 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
539 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
542 hdrvr
= OpenDriver(padid
->pszFileName
,0,0);
543 SendDriverMessage(hdrvr
,ACMDM_FORMAT_SUGGEST
,(LPARAM
)&adfs
,(fdwEnum
& 0x000000FFL
));
545 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_FORMAT
) != MMSYSERR_NOERROR
)
548 pafd
->cbwfx
= sizeof(*(pafd
->pwfx
));
550 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
554 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
555 memset(&aftd
, 0, sizeof(aftd
));
556 aftd
.cbStruct
= sizeof(aftd
);
557 aftd
.dwFormatTagIndex
= i
;
558 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
561 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
564 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
565 pafd
->dwFormatIndex
= j
;
566 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
567 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
570 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
571 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
573 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
574 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
576 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
577 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
579 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
580 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
583 /* more checks to be done on fdwEnum */
585 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
588 /* the "formats" used by the filters are also reported */
594 /**********************************************************************/
596 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
597 ACMFORMATENUMCBW fnCallback
,
598 DWORD_PTR dwInstance
, DWORD fdwEnum
)
600 PWINE_ACMDRIVERID padid
;
604 TRACE("(%p, %p, %p, %ld, %d)\n",
605 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
608 return MMSYSERR_INVALPARAM
;
610 if (pafd
->cbStruct
< sizeof(*pafd
))
611 return MMSYSERR_INVALPARAM
;
613 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
614 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
615 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
616 wfxRef
= *pafd
->pwfx
;
618 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
619 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
620 return MMSYSERR_INVALPARAM
;
622 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
623 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
624 return MMSYSERR_INVALPARAM
;
626 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
627 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
632 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
633 return MMSYSERR_INVALHANDLE
;
634 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
635 fnCallback
, dwInstance
, fdwEnum
);
636 return MMSYSERR_NOERROR
;
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) != MMSYSERR_NOERROR
)
643 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
644 fnCallback
, dwInstance
, fdwEnum
);
645 acmDriverClose(had
, 0);
648 return MMSYSERR_NOERROR
;
651 /***********************************************************************
652 * acmFormatSuggest (MSACM32.@)
654 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
655 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
657 ACMDRVFORMATSUGGEST adfg
;
660 TRACE("(%p, %p, %p, %d, %d)\n",
661 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
663 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
664 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
665 return MMSYSERR_INVALFLAG
;
667 adfg
.cbStruct
= sizeof(adfg
);
668 adfg
.fdwSuggest
= fdwSuggest
;
669 adfg
.pwfxSrc
= pwfxSrc
;
670 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
671 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
672 adfg
.pwfxDst
= pwfxDst
;
673 adfg
.cbwfxDst
= cbwfxDst
;
676 PWINE_ACMDRIVERID padid
;
678 /* MS doc says: ACM finds the best suggestion.
679 * Well, first found will be the "best"
681 mmr
= ACMERR_NOTPOSSIBLE
;
682 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
683 /* should check for codec only */
684 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
685 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
688 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
689 mmr
= MMSYSERR_NOERROR
;
692 acmDriverClose(had
, 0);
695 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
700 /***********************************************************************
701 * acmFormatTagDetailsA (MSACM32.@)
703 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
706 ACMFORMATTAGDETAILSW aftdw
;
709 memset(&aftdw
, 0, sizeof(aftdw
));
710 aftdw
.cbStruct
= sizeof(aftdw
);
711 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
712 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
714 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
715 if (mmr
== MMSYSERR_NOERROR
) {
716 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
717 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
718 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
719 paftda
->fdwSupport
= aftdw
.fdwSupport
;
720 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
721 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
722 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
727 /***********************************************************************
728 * acmFormatTagDetailsW (MSACM32.@)
730 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
733 PWINE_ACMDRIVERID padid
;
734 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
736 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
738 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
739 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
740 return MMSYSERR_INVALFLAG
;
742 switch (fdwDetails
) {
743 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
745 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
746 /* should check for codec only */
747 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
748 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
749 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
750 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
751 acmDriverClose(had
, 0);
752 if (mmr
== MMSYSERR_NOERROR
) break;
756 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
758 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
759 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
763 case ACM_FORMATTAGDETAILSF_INDEX
:
765 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
767 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
768 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
772 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
774 ACMFORMATTAGDETAILSW tmp
;
775 DWORD ft
= paftd
->dwFormatTag
;
777 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
778 /* should check for codec only */
779 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
780 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
782 memset(&tmp
, 0, sizeof(tmp
));
783 tmp
.cbStruct
= sizeof(tmp
);
784 tmp
.dwFormatTag
= ft
;
786 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
787 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
788 if (mmr
== ACMERR_NOTPOSSIBLE
||
789 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
791 mmr
= MMSYSERR_NOERROR
;
794 acmDriverClose(had
, 0);
798 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
803 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
804 mmr
= MMSYSERR_ERROR
;
807 if (mmr
== MMSYSERR_NOERROR
&&
808 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
809 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
810 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
815 struct MSACM_FormatTagEnumWtoA_Instance
{
816 PACMFORMATTAGDETAILSA paftda
;
817 DWORD_PTR dwInstance
;
818 ACMFORMATTAGENUMCBA fnCallback
;
821 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
822 PACMFORMATTAGDETAILSW paftdw
,
823 DWORD_PTR dwInstance
,
826 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
828 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
830 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
831 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
832 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
833 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
834 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
835 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
836 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
838 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
839 paftei
->dwInstance
, fdwSupport
);
842 /***********************************************************************
843 * acmFormatTagEnumA (MSACM32.@)
845 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
846 ACMFORMATTAGENUMCBA fnCallback
,
847 DWORD_PTR dwInstance
, DWORD fdwEnum
)
849 ACMFORMATTAGDETAILSW aftdw
;
850 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
853 return MMSYSERR_INVALPARAM
;
855 if (paftda
->cbStruct
< sizeof(*paftda
))
856 return MMSYSERR_INVALPARAM
;
859 return MMSYSERR_INVALFLAG
;
861 memset(&aftdw
, 0, sizeof(aftdw
));
862 aftdw
.cbStruct
= sizeof(aftdw
);
863 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
864 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
866 aftei
.paftda
= paftda
;
867 aftei
.dwInstance
= dwInstance
;
868 aftei
.fnCallback
= fnCallback
;
870 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
871 (DWORD_PTR
)&aftei
, fdwEnum
);
874 /***********************************************************************
875 * acmFormatTagEnumW (MSACM32.@)
877 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
878 ACMFORMATTAGENUMCBW fnCallback
,
879 DWORD_PTR dwInstance
, DWORD fdwEnum
)
881 PWINE_ACMDRIVERID padid
;
883 BOOL bPcmDone
= FALSE
;
885 TRACE("(%p, %p, %p, %ld, %d)\n",
886 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
889 return MMSYSERR_INVALPARAM
;
891 if (paftd
->cbStruct
< sizeof(*paftd
))
892 return MMSYSERR_INVALPARAM
;
895 return MMSYSERR_INVALFLAG
;
897 /* (WS) MSDN info page says that if had != 0, then we should find
898 * the specific driver to get its tags from. Therefore I'm removing
899 * the FIXME call and adding a search block below. It also seems
900 * that the lack of this functionality was the responsible for
901 * codecs to be multiply and incorrectly listed.
904 /* if (had) FIXME("had != NULL, not supported\n"); */
907 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
908 return MMSYSERR_INVALHANDLE
;
910 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
911 paftd
->dwFormatTagIndex
= i
;
912 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
913 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
914 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
915 if (paftd
->szFormatTag
[0] == 0)
916 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
917 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
918 /* (WS) I'm preserving this PCM hack since it seems to be
919 * correct. Please notice this block was borrowed from
922 if (bPcmDone
) continue;
925 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
926 return MMSYSERR_NOERROR
;
930 /* if had==0 then search for the first suitable driver */
932 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
933 /* should check for codec only */
934 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
935 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
936 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
937 paftd
->dwFormatTagIndex
= i
;
938 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
939 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
940 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
941 if (paftd
->szFormatTag
[0] == 0)
942 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
943 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
944 /* FIXME (EPP): I'm not sure this is the correct
945 * algorithm (should make more sense to apply the same
946 * for all already loaded formats, but this will do
949 if (bPcmDone
) continue;
952 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
953 acmDriverClose(had
, 0);
954 return MMSYSERR_NOERROR
;
958 acmDriverClose(had
, 0);
962 return MMSYSERR_NOERROR
;