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
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
40 struct MSACM_FillFormatData
{
42 #define WINE_ACMFF_TAG 0
43 #define WINE_ACMFF_FORMAT 1
44 #define WINE_ACMFF_WFX 2
46 WCHAR szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
47 PACMFORMATCHOOSEW afc
;
51 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
52 PACMFORMATTAGDETAILSW paftd
,
56 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
60 if (SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
61 CB_FINDSTRINGEXACT
, -1,
62 (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
63 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
64 CB_ADDSTRING
, 0, (LPARAM
)paftd
->szFormatTag
);
66 case WINE_ACMFF_FORMAT
:
67 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
70 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
71 ACMFORMATDETAILSW afd
;
74 WCHAR buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
76 afd
.cbStruct
= sizeof(afd
);
77 afd
.dwFormatTag
= paftd
->dwFormatTag
;
78 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
79 if (!afd
.pwfx
) return FALSE
;
80 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
81 if (paftd
->dwFormatTag
!= WAVE_FORMAT_PCM
)
82 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
- sizeof(WAVEFORMATEX
);
83 afd
.cbwfx
= paftd
->cbFormatSize
;
85 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
86 static const WCHAR fmtW
[] = {'%','d',' ','K','o','/','s','\0'};
89 afd
.dwFormatIndex
= i
;
90 mmr
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
91 if (mmr
== MMSYSERR_NOERROR
) {
92 lstrcpynW(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
93 len
= strlenW(buffer
);
94 for (j
= len
; j
< ACMFORMATTAGDETAILS_FORMATTAG_CHARS
; j
++)
96 wsprintfW(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
97 fmtW
, (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
98 SendDlgItemMessageW(affd
->hWnd
,
99 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
100 CB_ADDSTRING
, 0, (LPARAM
)buffer
);
103 acmDriverClose(had
, 0);
104 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
106 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
111 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
114 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
115 ACMFORMATDETAILSW afd
;
117 afd
.cbStruct
= sizeof(afd
);
118 afd
.dwFormatTag
= paftd
->dwFormatTag
;
119 afd
.pwfx
= affd
->afc
->pwfx
;
120 afd
.cbwfx
= affd
->afc
->cbwfx
;
122 afd
.dwFormatIndex
= SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
124 affd
->ret
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
125 acmDriverClose(had
, 0);
131 FIXME("Unknown mode (%d)\n", affd
->mode
);
137 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
139 ACMFORMATTAGDETAILSW aftd
;
140 struct MSACM_FillFormatData affd
;
142 memset(&aftd
, 0, sizeof(aftd
));
143 aftd
.cbStruct
= sizeof(aftd
);
146 affd
.mode
= WINE_ACMFF_TAG
;
148 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
149 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
153 static BOOL
MSACM_FillFormat(HWND hWnd
)
155 ACMFORMATTAGDETAILSW aftd
;
156 struct MSACM_FillFormatData affd
;
158 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
160 memset(&aftd
, 0, sizeof(aftd
));
161 aftd
.cbStruct
= sizeof(aftd
);
164 affd
.mode
= WINE_ACMFF_FORMAT
;
165 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
167 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
169 (LPARAM
)affd
.szFormatTag
);
171 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
172 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
176 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEW afc
)
178 ACMFORMATTAGDETAILSW aftd
;
179 struct MSACM_FillFormatData affd
;
181 memset(&aftd
, 0, sizeof(aftd
));
182 aftd
.cbStruct
= sizeof(aftd
);
185 affd
.mode
= WINE_ACMFF_WFX
;
187 affd
.ret
= MMSYSERR_NOERROR
;
188 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
190 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
192 (LPARAM
)affd
.szFormatTag
);
194 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
198 static const WCHAR fmt_prop
[] = {'a','c','m','p','r','o','p','\0'};
200 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
201 WPARAM wParam
, LPARAM lParam
)
203 PACMFORMATCHOOSEW afc
= (PACMFORMATCHOOSEW
)GetPropW(hWnd
, fmt_prop
);
205 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
209 afc
= (PACMFORMATCHOOSEW
)lParam
;
210 SetPropW(hWnd
, fmt_prop
, (HANDLE
)afc
);
211 MSACM_FillFormatTags(hWnd
);
212 MSACM_FillFormat(hWnd
);
213 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
214 ACMFORMATCHOOSE_STYLEF_SHOWHELP
|
215 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
|
216 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)) != 0)
217 FIXME("Unsupported style %08x\n", afc
->fdwStyle
);
218 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
219 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
223 switch (LOWORD(wParam
)) {
225 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
228 EndDialog(hWnd
, ACMERR_CANCELED
);
230 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
231 switch (HIWORD(wParam
)) {
233 MSACM_FillFormat(hWnd
);
236 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
237 HIWORD(wParam
), lParam
);
241 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
242 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
243 SendMessageW(afc
->hwndOwner
,
244 RegisterWindowMessageW(ACMHELPMSGSTRINGW
), 0L, 0L);
248 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
249 LOWORD(wParam
), HIWORD(wParam
), lParam
);
254 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
255 SendMessageW(afc
->hwndOwner
,
256 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW
),
259 #if defined(WM_CONTEXTHELP)
261 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
262 SendMessageW(afc
->hwndOwner
,
263 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW
),
268 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
269 hWnd
, msg
, wParam
, lParam
);
275 /***********************************************************************
276 * acmFormatChooseA (MSACM32.@)
278 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
280 ACMFORMATCHOOSEW afcw
;
287 afcw
.cbStruct
= sizeof(afcw
);
288 afcw
.fdwStyle
= pafmtc
->fdwStyle
;
289 afcw
.hwndOwner
= pafmtc
->hwndOwner
;
290 afcw
.pwfx
= pafmtc
->pwfx
;
291 afcw
.cbwfx
= pafmtc
->cbwfx
;
292 if (pafmtc
->pszTitle
)
294 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, NULL
, 0);
295 if (!(title
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
297 ret
= MMSYSERR_NOMEM
;
300 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, title
, sz
);
302 afcw
.pszTitle
= title
;
305 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, NULL
, 0);
306 if (!(name
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
308 ret
= MMSYSERR_NOMEM
;
311 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, name
, sz
);
314 afcw
.cchName
= pafmtc
->cchName
;
315 afcw
.fdwEnum
= pafmtc
->fdwEnum
;
316 afcw
.pwfxEnum
= pafmtc
->pwfxEnum
;
317 afcw
.hInstance
= pafmtc
->hInstance
;
318 if (pafmtc
->pszTemplateName
)
320 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, NULL
, 0);
321 if (!(templ
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
323 ret
= MMSYSERR_NOMEM
;
326 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, templ
, sz
);
328 afcw
.pszTemplateName
= templ
;
329 /* FIXME: hook procs not supported yet */
332 FIXME("Unsupported hook procs\n");
333 ret
= MMSYSERR_NOTSUPPORTED
;
336 ret
= acmFormatChooseW(&afcw
);
337 if (ret
== MMSYSERR_NOERROR
)
339 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormatTag
, -1, pafmtc
->szFormatTag
, sizeof(pafmtc
->szFormatTag
),
341 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormat
, -1, pafmtc
->szFormat
, sizeof(pafmtc
->szFormat
),
344 WideCharToMultiByte(CP_ACP
, 0, afcw
.pszName
, -1, pafmtc
->pszName
, pafmtc
->cchName
, NULL
, NULL
);
347 HeapFree(GetProcessHeap(), 0, title
);
348 HeapFree(GetProcessHeap(), 0, name
);
349 HeapFree(GetProcessHeap(), 0, templ
);
353 /***********************************************************************
354 * acmFormatChooseW (MSACM32.@)
356 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
358 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
)
359 return DialogBoxIndirectParamW(MSACM_hInstance32
, (LPCDLGTEMPLATEW
)pafmtc
->hInstance
,
360 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
362 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)
363 return DialogBoxParamW(pafmtc
->hInstance
, pafmtc
->pszTemplateName
,
364 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
366 return DialogBoxParamW(MSACM_hInstance32
, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID
),
367 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
370 /***********************************************************************
371 * acmFormatDetailsA (MSACM32.@)
373 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
376 ACMFORMATDETAILSW afdw
;
379 memset(&afdw
, 0, sizeof(afdw
));
380 afdw
.cbStruct
= sizeof(afdw
);
381 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
382 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
383 afdw
.pwfx
= pafd
->pwfx
;
384 afdw
.cbwfx
= pafd
->cbwfx
;
386 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
387 if (mmr
== MMSYSERR_NOERROR
) {
388 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
389 pafd
->fdwSupport
= afdw
.fdwSupport
;
390 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
391 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
396 /***********************************************************************
397 * acmFormatDetailsW (MSACM32.@)
399 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
402 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
403 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
405 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
407 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
409 switch (fdwDetails
) {
410 case ACM_FORMATDETAILSF_FORMAT
:
411 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
412 mmr
= MMSYSERR_INVALPARAM
;
416 PWINE_ACMDRIVERID padid
;
418 mmr
= ACMERR_NOTPOSSIBLE
;
419 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
420 /* should check for codec only */
421 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
422 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
423 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
424 acmDriverClose(had
, 0);
425 if (mmr
== MMSYSERR_NOERROR
) break;
429 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
432 case ACM_FORMATDETAILSF_INDEX
:
433 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
434 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
437 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
438 mmr
= MMSYSERR_INVALFLAG
;
442 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
443 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
444 if (pafd
->pwfx
->wBitsPerSample
) {
445 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
446 pafd
->pwfx
->wBitsPerSample
);
448 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
449 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
450 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
453 TRACE("=> %d\n", mmr
);
457 struct MSACM_FormatEnumWtoA_Instance
{
458 PACMFORMATDETAILSA pafda
;
459 DWORD_PTR dwInstance
;
460 ACMFORMATENUMCBA fnCallback
;
463 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
464 PACMFORMATDETAILSW pafdw
,
465 DWORD_PTR dwInstance
,
468 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
470 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
472 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
473 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
474 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
475 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
476 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
478 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
479 pafei
->dwInstance
, fdwSupport
);
482 /***********************************************************************
483 * acmFormatEnumA (MSACM32.@)
485 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
486 ACMFORMATENUMCBA fnCallback
,
487 DWORD_PTR dwInstance
, DWORD fdwEnum
)
489 ACMFORMATDETAILSW afdw
;
490 struct MSACM_FormatEnumWtoA_Instance afei
;
493 return MMSYSERR_INVALPARAM
;
495 if (pafda
->cbStruct
< sizeof(*pafda
))
496 return MMSYSERR_INVALPARAM
;
498 memset(&afdw
, 0, sizeof(afdw
));
499 afdw
.cbStruct
= sizeof(afdw
);
500 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
501 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
502 afdw
.pwfx
= pafda
->pwfx
;
503 afdw
.cbwfx
= pafda
->cbwfx
;
506 afei
.dwInstance
= dwInstance
;
507 afei
.fnCallback
= fnCallback
;
509 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
510 (DWORD_PTR
)&afei
, fdwEnum
);
513 /***********************************************************************
514 * acmFormatEnumW (MSACM32.@)
516 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
517 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
518 ACMFORMATENUMCBW fnCallback
,
519 DWORD_PTR dwInstance
, DWORD fdwEnum
)
521 ACMFORMATTAGDETAILSW aftd
;
524 if (fdwEnum
& ACM_FORMATENUMF_SUGGEST
) {
526 ACMDRVFORMATSUGGEST adfs
;
527 pafd
->dwFormatIndex
= 0;
528 memset(&aftd
, 0, sizeof(aftd
));
529 aftd
.cbStruct
= sizeof(aftd
);
530 memset(&adfs
, 0, sizeof(adfs
));
531 adfs
.cbStruct
= sizeof(adfs
);
533 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
534 aftd
.dwFormatTag
= i
;
535 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
536 pafd
->pwfx
->wFormatTag
= pafd
->dwFormatTag
;
538 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
541 adfs
.cbwfxSrc
= aftd
.cbFormatSize
;
542 adfs
.cbwfxDst
= aftd
.cbFormatSize
;
543 adfs
.pwfxSrc
= pwfxRef
;
544 adfs
.pwfxDst
= pafd
->pwfx
;
545 pafd
->fdwSupport
= padid
->fdwSupport
;
547 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
548 aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
551 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
552 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
555 hdrvr
= OpenDriver(padid
->pszFileName
,0,0);
556 SendDriverMessage(hdrvr
,ACMDM_FORMAT_SUGGEST
,(LPARAM
)&adfs
,(fdwEnum
& 0x000000FFL
));
558 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_FORMAT
) != MMSYSERR_NOERROR
)
561 pafd
->cbwfx
= sizeof(*(pafd
->pwfx
));
563 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
567 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
568 memset(&aftd
, 0, sizeof(aftd
));
569 aftd
.cbStruct
= sizeof(aftd
);
570 aftd
.dwFormatTagIndex
= i
;
571 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
574 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
577 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
578 pafd
->dwFormatIndex
= j
;
579 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
580 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
583 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
584 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
586 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
587 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
589 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
590 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
592 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
593 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
596 /* more checks to be done on fdwEnum */
598 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
601 /* the "formats" used by the filters are also reported */
607 /**********************************************************************/
609 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
610 ACMFORMATENUMCBW fnCallback
,
611 DWORD_PTR dwInstance
, DWORD fdwEnum
)
613 PWINE_ACMDRIVERID padid
;
617 TRACE("(%p, %p, %p, %ld, %d)\n",
618 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
621 return MMSYSERR_INVALPARAM
;
623 if (pafd
->cbStruct
< sizeof(*pafd
))
624 return MMSYSERR_INVALPARAM
;
626 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
627 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
628 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
629 wfxRef
= *pafd
->pwfx
;
631 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
632 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
633 return MMSYSERR_INVALPARAM
;
635 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
636 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
637 return MMSYSERR_INVALPARAM
;
639 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
640 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
645 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
646 return MMSYSERR_INVALHANDLE
;
647 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
648 fnCallback
, dwInstance
, fdwEnum
);
649 return MMSYSERR_NOERROR
;
651 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
652 /* should check for codec only */
653 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
654 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
656 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
657 fnCallback
, dwInstance
, fdwEnum
);
658 acmDriverClose(had
, 0);
661 return MMSYSERR_NOERROR
;
664 /***********************************************************************
665 * acmFormatSuggest (MSACM32.@)
667 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
668 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
670 ACMDRVFORMATSUGGEST adfg
;
673 TRACE("(%p, %p, %p, %d, %d)\n",
674 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
676 if (!pwfxSrc
|| !pwfxDst
)
677 return MMSYSERR_INVALPARAM
;
679 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
680 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
681 return MMSYSERR_INVALFLAG
;
683 adfg
.cbStruct
= sizeof(adfg
);
684 adfg
.fdwSuggest
= fdwSuggest
;
685 adfg
.pwfxSrc
= pwfxSrc
;
686 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
687 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
688 adfg
.pwfxDst
= pwfxDst
;
689 adfg
.cbwfxDst
= cbwfxDst
;
692 PWINE_ACMDRIVERID padid
;
694 /* MS doc says: ACM finds the best suggestion.
695 * Well, first found will be the "best"
697 mmr
= ACMERR_NOTPOSSIBLE
;
698 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
699 /* should check for codec only */
700 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
701 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
704 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
705 mmr
= MMSYSERR_NOERROR
;
708 acmDriverClose(had
, 0);
711 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
716 /***********************************************************************
717 * acmFormatTagDetailsA (MSACM32.@)
719 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
722 ACMFORMATTAGDETAILSW aftdw
;
725 memset(&aftdw
, 0, sizeof(aftdw
));
726 aftdw
.cbStruct
= sizeof(aftdw
);
727 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
728 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
730 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
731 if (mmr
== MMSYSERR_NOERROR
) {
732 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
733 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
734 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
735 paftda
->fdwSupport
= aftdw
.fdwSupport
;
736 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
737 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
738 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
743 /***********************************************************************
744 * acmFormatTagDetailsW (MSACM32.@)
746 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
749 PWINE_ACMDRIVERID padid
;
750 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
752 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
754 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
755 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
756 return MMSYSERR_INVALFLAG
;
758 switch (fdwDetails
) {
759 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
761 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
762 /* should check for codec only */
763 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
764 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
765 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
766 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
767 acmDriverClose(had
, 0);
768 if (mmr
== MMSYSERR_NOERROR
) break;
772 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
774 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
775 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
779 case ACM_FORMATTAGDETAILSF_INDEX
:
781 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
783 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
784 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
788 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
790 ACMFORMATTAGDETAILSW tmp
;
791 DWORD ft
= paftd
->dwFormatTag
;
793 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
794 /* should check for codec only */
795 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
796 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
798 memset(&tmp
, 0, sizeof(tmp
));
799 tmp
.cbStruct
= sizeof(tmp
);
800 tmp
.dwFormatTag
= ft
;
802 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
803 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
804 if (mmr
== ACMERR_NOTPOSSIBLE
||
805 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
807 mmr
= MMSYSERR_NOERROR
;
810 acmDriverClose(had
, 0);
814 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
819 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
820 mmr
= MMSYSERR_ERROR
;
823 if (mmr
== MMSYSERR_NOERROR
&&
824 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
825 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
826 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
831 struct MSACM_FormatTagEnumWtoA_Instance
{
832 PACMFORMATTAGDETAILSA paftda
;
833 DWORD_PTR dwInstance
;
834 ACMFORMATTAGENUMCBA fnCallback
;
837 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
838 PACMFORMATTAGDETAILSW paftdw
,
839 DWORD_PTR dwInstance
,
842 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
844 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
846 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
847 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
848 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
849 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
850 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
851 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
852 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
854 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
855 paftei
->dwInstance
, fdwSupport
);
858 /***********************************************************************
859 * acmFormatTagEnumA (MSACM32.@)
861 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
862 ACMFORMATTAGENUMCBA fnCallback
,
863 DWORD_PTR dwInstance
, DWORD fdwEnum
)
865 ACMFORMATTAGDETAILSW aftdw
;
866 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
869 return MMSYSERR_INVALPARAM
;
871 if (paftda
->cbStruct
< sizeof(*paftda
))
872 return MMSYSERR_INVALPARAM
;
875 return MMSYSERR_INVALFLAG
;
877 memset(&aftdw
, 0, sizeof(aftdw
));
878 aftdw
.cbStruct
= sizeof(aftdw
);
879 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
880 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
882 aftei
.paftda
= paftda
;
883 aftei
.dwInstance
= dwInstance
;
884 aftei
.fnCallback
= fnCallback
;
886 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
887 (DWORD_PTR
)&aftei
, fdwEnum
);
890 /***********************************************************************
891 * acmFormatTagEnumW (MSACM32.@)
893 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
894 ACMFORMATTAGENUMCBW fnCallback
,
895 DWORD_PTR dwInstance
, DWORD fdwEnum
)
897 PWINE_ACMDRIVERID padid
;
899 BOOL bPcmDone
= FALSE
;
901 TRACE("(%p, %p, %p, %ld, %d)\n",
902 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
905 return MMSYSERR_INVALPARAM
;
907 if (paftd
->cbStruct
< sizeof(*paftd
))
908 return MMSYSERR_INVALPARAM
;
911 return MMSYSERR_INVALFLAG
;
913 /* (WS) MSDN info page says that if had != 0, then we should find
914 * the specific driver to get its tags from. Therefore I'm removing
915 * the FIXME call and adding a search block below. It also seems
916 * that the lack of this functionality was the responsible for
917 * codecs to be multiply and incorrectly listed.
920 /* if (had) FIXME("had != NULL, not supported\n"); */
923 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
924 return MMSYSERR_INVALHANDLE
;
926 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
927 paftd
->dwFormatTagIndex
= i
;
928 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
929 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
930 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
931 if (paftd
->szFormatTag
[0] == 0)
932 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
933 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
934 /* (WS) I'm preserving this PCM hack since it seems to be
935 * correct. Please notice this block was borrowed from
938 if (bPcmDone
) continue;
941 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
942 return MMSYSERR_NOERROR
;
946 /* if had==0 then search for the first suitable driver */
948 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
949 /* should check for codec only */
950 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
951 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
952 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
953 paftd
->dwFormatTagIndex
= i
;
954 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
955 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
956 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
957 if (paftd
->szFormatTag
[0] == 0)
958 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
959 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
960 /* FIXME (EPP): I'm not sure this is the correct
961 * algorithm (should make more sense to apply the same
962 * for all already loaded formats, but this will do
965 if (bPcmDone
) continue;
968 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
969 acmDriverClose(had
, 0);
970 return MMSYSERR_NOERROR
;
974 acmDriverClose(had
, 0);
978 return MMSYSERR_NOERROR
;