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
22 #define WIN32_NO_STATUS
27 //#include "winbase.h"
29 //#include "winerror.h"
32 #include <wine/unicode.h>
33 #include <wine/debug.h>
34 //#include "mmsystem.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
42 struct MSACM_FillFormatData
{
44 #define WINE_ACMFF_TAG 0
45 #define WINE_ACMFF_FORMAT 1
46 #define WINE_ACMFF_WFX 2
48 WCHAR szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
49 PACMFORMATCHOOSEW afc
;
53 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
54 PACMFORMATTAGDETAILSW paftd
,
58 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
62 if (SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
63 CB_FINDSTRINGEXACT
, -1,
64 (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
65 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
66 CB_ADDSTRING
, 0, (LPARAM
)paftd
->szFormatTag
);
68 case WINE_ACMFF_FORMAT
:
69 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
72 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
73 ACMFORMATDETAILSW afd
;
76 WCHAR buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
78 afd
.cbStruct
= sizeof(afd
);
79 afd
.dwFormatTag
= paftd
->dwFormatTag
;
80 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
81 if (!afd
.pwfx
) return FALSE
;
82 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
83 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
84 afd
.cbwfx
= paftd
->cbFormatSize
;
86 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
87 static const WCHAR fmtW
[] = {'%','d',' ','K','o','/','s','\0'};
90 afd
.dwFormatIndex
= i
;
91 mmr
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
92 if (mmr
== MMSYSERR_NOERROR
) {
93 lstrcpynW(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
94 len
= strlenW(buffer
);
95 for (j
= len
; j
< ACMFORMATTAGDETAILS_FORMATTAG_CHARS
; j
++)
97 wsprintfW(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
98 fmtW
, (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
99 SendDlgItemMessageW(affd
->hWnd
,
100 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
101 CB_ADDSTRING
, 0, (LPARAM
)buffer
);
104 acmDriverClose(had
, 0);
105 SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
107 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
112 if (strcmpW(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
115 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
116 ACMFORMATDETAILSW afd
;
118 afd
.cbStruct
= sizeof(afd
);
119 afd
.dwFormatTag
= paftd
->dwFormatTag
;
120 afd
.pwfx
= affd
->afc
->pwfx
;
121 afd
.cbwfx
= affd
->afc
->cbwfx
;
123 afd
.dwFormatIndex
= SendDlgItemMessageW(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
125 affd
->ret
= acmFormatDetailsW(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
126 acmDriverClose(had
, 0);
132 FIXME("Unknown mode (%d)\n", affd
->mode
);
138 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
140 ACMFORMATTAGDETAILSW aftd
;
141 struct MSACM_FillFormatData affd
;
143 memset(&aftd
, 0, sizeof(aftd
));
144 aftd
.cbStruct
= sizeof(aftd
);
147 affd
.mode
= WINE_ACMFF_TAG
;
149 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
150 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
154 static BOOL
MSACM_FillFormat(HWND hWnd
)
156 ACMFORMATTAGDETAILSW aftd
;
157 struct MSACM_FillFormatData affd
;
159 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
161 memset(&aftd
, 0, sizeof(aftd
));
162 aftd
.cbStruct
= sizeof(aftd
);
165 affd
.mode
= WINE_ACMFF_FORMAT
;
166 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
168 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
170 (LPARAM
)affd
.szFormatTag
);
172 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
173 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
177 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEW afc
)
179 ACMFORMATTAGDETAILSW aftd
;
180 struct MSACM_FillFormatData affd
;
182 memset(&aftd
, 0, sizeof(aftd
));
183 aftd
.cbStruct
= sizeof(aftd
);
186 affd
.mode
= WINE_ACMFF_WFX
;
188 affd
.ret
= MMSYSERR_NOERROR
;
189 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
191 SendDlgItemMessageW(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
193 (LPARAM
)affd
.szFormatTag
);
195 acmFormatTagEnumW(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
199 static const WCHAR fmt_prop
[] = {'a','c','m','p','r','o','p','\0'};
201 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
202 WPARAM wParam
, LPARAM lParam
)
204 PACMFORMATCHOOSEW afc
= (PACMFORMATCHOOSEW
)GetPropW(hWnd
, fmt_prop
);
206 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
210 afc
= (PACMFORMATCHOOSEW
)lParam
;
211 SetPropW(hWnd
, fmt_prop
, (HANDLE
)afc
);
212 MSACM_FillFormatTags(hWnd
);
213 MSACM_FillFormat(hWnd
);
214 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
215 ACMFORMATCHOOSE_STYLEF_SHOWHELP
|
216 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
|
217 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)) != 0)
218 FIXME("Unsupported style %08x\n", afc
->fdwStyle
);
219 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
220 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
224 switch (LOWORD(wParam
)) {
226 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
229 EndDialog(hWnd
, ACMERR_CANCELED
);
231 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
232 switch (HIWORD(wParam
)) {
234 MSACM_FillFormat(hWnd
);
237 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
238 HIWORD(wParam
), lParam
);
242 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
243 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
244 SendMessageW(afc
->hwndOwner
,
245 RegisterWindowMessageW(ACMHELPMSGSTRINGW
), 0L, 0L);
249 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
250 LOWORD(wParam
), HIWORD(wParam
), lParam
);
255 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
256 SendMessageW(afc
->hwndOwner
,
257 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW
),
260 #if defined(WM_CONTEXTHELP)
262 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
263 SendMessageW(afc
->hwndOwner
,
264 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW
),
269 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
270 hWnd
, msg
, wParam
, lParam
);
276 /***********************************************************************
277 * acmFormatChooseA (MSACM32.@)
279 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
281 ACMFORMATCHOOSEW afcw
;
288 afcw
.cbStruct
= sizeof(afcw
);
289 afcw
.fdwStyle
= pafmtc
->fdwStyle
;
290 afcw
.hwndOwner
= pafmtc
->hwndOwner
;
291 afcw
.pwfx
= pafmtc
->pwfx
;
292 afcw
.cbwfx
= pafmtc
->cbwfx
;
293 if (pafmtc
->pszTitle
)
295 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, NULL
, 0);
296 if (!(title
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
298 ret
= MMSYSERR_NOMEM
;
301 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTitle
, -1, title
, sz
);
303 afcw
.pszTitle
= title
;
306 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, NULL
, 0);
307 if (!(name
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
309 ret
= MMSYSERR_NOMEM
;
312 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszName
, -1, name
, sz
);
315 afcw
.cchName
= pafmtc
->cchName
;
316 afcw
.fdwEnum
= pafmtc
->fdwEnum
;
317 afcw
.pwfxEnum
= pafmtc
->pwfxEnum
;
318 afcw
.hInstance
= pafmtc
->hInstance
;
319 if (pafmtc
->pszTemplateName
)
321 sz
= MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, NULL
, 0);
322 if (!(templ
= HeapAlloc(GetProcessHeap(), 0, sz
* sizeof(WCHAR
))))
324 ret
= MMSYSERR_NOMEM
;
327 MultiByteToWideChar(CP_ACP
, 0, pafmtc
->pszTemplateName
, -1, templ
, sz
);
329 afcw
.pszTemplateName
= templ
;
330 /* FIXME: hook procs not supported yet */
333 FIXME("Unsupported hook procs\n");
334 ret
= MMSYSERR_NOTSUPPORTED
;
337 ret
= acmFormatChooseW(&afcw
);
338 if (ret
== MMSYSERR_NOERROR
)
340 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormatTag
, -1, pafmtc
->szFormatTag
, sizeof(pafmtc
->szFormatTag
),
342 WideCharToMultiByte(CP_ACP
, 0, afcw
.szFormat
, -1, pafmtc
->szFormat
, sizeof(pafmtc
->szFormat
),
345 WideCharToMultiByte(CP_ACP
, 0, afcw
.pszName
, -1, pafmtc
->pszName
, pafmtc
->cchName
, NULL
, NULL
);
348 HeapFree(GetProcessHeap(), 0, title
);
349 HeapFree(GetProcessHeap(), 0, name
);
350 HeapFree(GetProcessHeap(), 0, templ
);
354 /***********************************************************************
355 * acmFormatChooseW (MSACM32.@)
357 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
359 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE
)
360 return DialogBoxIndirectParamW(MSACM_hInstance32
, (LPCDLGTEMPLATEW
)pafmtc
->hInstance
,
361 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
363 if (pafmtc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE
)
364 return DialogBoxParamW(pafmtc
->hInstance
, pafmtc
->pszTemplateName
,
365 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
367 return DialogBoxParamW(MSACM_hInstance32
, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID
),
368 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
371 /***********************************************************************
372 * acmFormatDetailsA (MSACM32.@)
374 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
377 ACMFORMATDETAILSW afdw
;
380 memset(&afdw
, 0, sizeof(afdw
));
381 afdw
.cbStruct
= sizeof(afdw
);
382 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
383 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
384 afdw
.pwfx
= pafd
->pwfx
;
385 afdw
.cbwfx
= pafd
->cbwfx
;
387 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
388 if (mmr
== MMSYSERR_NOERROR
) {
389 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
390 pafd
->fdwSupport
= afdw
.fdwSupport
;
391 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
392 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
397 /***********************************************************************
398 * acmFormatDetailsW (MSACM32.@)
400 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
403 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
404 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
405 ACMFORMATTAGDETAILSA aftd
;
407 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
409 memset(&aftd
, 0, sizeof(aftd
));
410 aftd
.cbStruct
= sizeof(aftd
);
412 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
414 switch (fdwDetails
) {
415 case ACM_FORMATDETAILSF_FORMAT
:
416 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
417 mmr
= MMSYSERR_INVALPARAM
;
421 PWINE_ACMDRIVERID padid
;
423 mmr
= ACMERR_NOTPOSSIBLE
;
424 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
425 /* should check for codec only */
426 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
427 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
428 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
429 acmDriverClose(had
, 0);
430 if (mmr
== MMSYSERR_NOERROR
) break;
434 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
437 case ACM_FORMATDETAILSF_INDEX
:
438 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
439 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
442 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
443 mmr
= MMSYSERR_INVALFLAG
;
447 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
448 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
449 if (pafd
->pwfx
->wBitsPerSample
) {
450 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
451 pafd
->pwfx
->wBitsPerSample
);
453 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
454 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
455 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
458 TRACE("=> %d\n", mmr
);
462 struct MSACM_FormatEnumWtoA_Instance
{
463 PACMFORMATDETAILSA pafda
;
464 DWORD_PTR dwInstance
;
465 ACMFORMATENUMCBA fnCallback
;
468 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
469 PACMFORMATDETAILSW pafdw
,
470 DWORD_PTR dwInstance
,
473 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
475 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
477 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
478 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
479 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
480 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
481 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
483 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
484 pafei
->dwInstance
, fdwSupport
);
487 /***********************************************************************
488 * acmFormatEnumA (MSACM32.@)
490 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
491 ACMFORMATENUMCBA fnCallback
,
492 DWORD_PTR dwInstance
, DWORD fdwEnum
)
494 ACMFORMATDETAILSW afdw
;
495 struct MSACM_FormatEnumWtoA_Instance afei
;
498 return MMSYSERR_INVALPARAM
;
500 if (pafda
->cbStruct
< sizeof(*pafda
))
501 return MMSYSERR_INVALPARAM
;
503 memset(&afdw
, 0, sizeof(afdw
));
504 afdw
.cbStruct
= sizeof(afdw
);
505 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
506 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
507 afdw
.pwfx
= pafda
->pwfx
;
508 afdw
.cbwfx
= pafda
->cbwfx
;
511 afei
.dwInstance
= dwInstance
;
512 afei
.fnCallback
= fnCallback
;
514 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
515 (DWORD_PTR
)&afei
, fdwEnum
);
518 /***********************************************************************
519 * acmFormatEnumW (MSACM32.@)
521 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
522 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
523 ACMFORMATENUMCBW fnCallback
,
524 DWORD_PTR dwInstance
, DWORD fdwEnum
)
526 ACMFORMATTAGDETAILSW aftd
;
529 if (fdwEnum
& ACM_FORMATENUMF_SUGGEST
) {
531 ACMDRVFORMATSUGGEST adfs
;
532 pafd
->dwFormatIndex
= 0;
533 memset(&aftd
, 0, sizeof(aftd
));
534 aftd
.cbStruct
= sizeof(aftd
);
535 memset(&adfs
, 0, sizeof(adfs
));
536 adfs
.cbStruct
= sizeof(adfs
);
538 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
539 aftd
.dwFormatTag
= i
;
540 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
541 pafd
->pwfx
->wFormatTag
= pafd
->dwFormatTag
;
543 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
546 adfs
.cbwfxSrc
= aftd
.cbFormatSize
;
547 adfs
.cbwfxDst
= aftd
.cbFormatSize
;
548 adfs
.pwfxSrc
= pwfxRef
;
549 adfs
.pwfxDst
= pafd
->pwfx
;
550 pafd
->fdwSupport
= padid
->fdwSupport
;
552 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
553 aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
556 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
557 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
560 hdrvr
= OpenDriver(padid
->pszFileName
,0,0);
561 SendDriverMessage(hdrvr
,ACMDM_FORMAT_SUGGEST
,(LPARAM
)&adfs
,(fdwEnum
& 0x000000FFL
));
563 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_FORMAT
) != MMSYSERR_NOERROR
)
566 pafd
->cbwfx
= sizeof(*(pafd
->pwfx
));
568 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
572 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
573 memset(&aftd
, 0, sizeof(aftd
));
574 aftd
.cbStruct
= sizeof(aftd
);
575 aftd
.dwFormatTagIndex
= i
;
576 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
579 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
582 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
583 pafd
->dwFormatIndex
= j
;
584 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
585 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
588 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
589 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
591 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
592 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
594 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
595 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
597 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
598 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
601 /* more checks to be done on fdwEnum */
603 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
606 /* the "formats" used by the filters are also reported */
612 /**********************************************************************/
614 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
615 ACMFORMATENUMCBW fnCallback
,
616 DWORD_PTR dwInstance
, DWORD fdwEnum
)
618 PWINE_ACMDRIVERID padid
;
622 TRACE("(%p, %p, %p, %ld, %d)\n",
623 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
626 return MMSYSERR_INVALPARAM
;
628 if (pafd
->cbStruct
< sizeof(*pafd
))
629 return MMSYSERR_INVALPARAM
;
631 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
632 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
633 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
634 wfxRef
= *pafd
->pwfx
;
636 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
637 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
638 return MMSYSERR_INVALPARAM
;
640 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
641 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
642 return MMSYSERR_INVALPARAM
;
644 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
645 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
650 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
651 return MMSYSERR_INVALHANDLE
;
652 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
653 fnCallback
, dwInstance
, fdwEnum
);
654 return MMSYSERR_NOERROR
;
656 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
657 /* should check for codec only */
658 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
659 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
661 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
662 fnCallback
, dwInstance
, fdwEnum
);
663 acmDriverClose(had
, 0);
666 return MMSYSERR_NOERROR
;
669 /***********************************************************************
670 * acmFormatSuggest (MSACM32.@)
672 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
673 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
675 ACMDRVFORMATSUGGEST adfg
;
678 TRACE("(%p, %p, %p, %d, %d)\n",
679 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
681 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
682 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
683 return MMSYSERR_INVALFLAG
;
685 adfg
.cbStruct
= sizeof(adfg
);
686 adfg
.fdwSuggest
= fdwSuggest
;
687 adfg
.pwfxSrc
= pwfxSrc
;
688 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
689 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
690 adfg
.pwfxDst
= pwfxDst
;
691 adfg
.cbwfxDst
= cbwfxDst
;
694 PWINE_ACMDRIVERID padid
;
696 /* MS doc says: ACM finds the best suggestion.
697 * Well, first found will be the "best"
699 mmr
= ACMERR_NOTPOSSIBLE
;
700 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
701 /* should check for codec only */
702 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
703 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
706 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
707 mmr
= MMSYSERR_NOERROR
;
710 acmDriverClose(had
, 0);
713 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
718 /***********************************************************************
719 * acmFormatTagDetailsA (MSACM32.@)
721 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
724 ACMFORMATTAGDETAILSW aftdw
;
727 memset(&aftdw
, 0, sizeof(aftdw
));
728 aftdw
.cbStruct
= sizeof(aftdw
);
729 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
730 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
732 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
733 if (mmr
== MMSYSERR_NOERROR
) {
734 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
735 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
736 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
737 paftda
->fdwSupport
= aftdw
.fdwSupport
;
738 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
739 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
740 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
745 /***********************************************************************
746 * acmFormatTagDetailsW (MSACM32.@)
748 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
751 PWINE_ACMDRIVERID padid
;
752 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
754 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
756 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
757 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
758 return MMSYSERR_INVALFLAG
;
760 switch (fdwDetails
) {
761 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
763 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
764 /* should check for codec only */
765 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
766 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
767 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
768 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
769 acmDriverClose(had
, 0);
770 if (mmr
== MMSYSERR_NOERROR
) break;
774 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
776 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
777 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
781 case ACM_FORMATTAGDETAILSF_INDEX
:
783 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
785 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
786 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
790 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
792 ACMFORMATTAGDETAILSW tmp
;
793 DWORD ft
= paftd
->dwFormatTag
;
795 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
796 /* should check for codec only */
797 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
798 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
800 memset(&tmp
, 0, sizeof(tmp
));
801 tmp
.cbStruct
= sizeof(tmp
);
802 tmp
.dwFormatTag
= ft
;
804 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
805 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
806 if (mmr
== ACMERR_NOTPOSSIBLE
||
807 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
809 mmr
= MMSYSERR_NOERROR
;
812 acmDriverClose(had
, 0);
816 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
821 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
822 mmr
= MMSYSERR_ERROR
;
825 if (mmr
== MMSYSERR_NOERROR
&&
826 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
827 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
828 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
833 struct MSACM_FormatTagEnumWtoA_Instance
{
834 PACMFORMATTAGDETAILSA paftda
;
835 DWORD_PTR dwInstance
;
836 ACMFORMATTAGENUMCBA fnCallback
;
839 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
840 PACMFORMATTAGDETAILSW paftdw
,
841 DWORD_PTR dwInstance
,
844 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
846 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
848 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
849 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
850 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
851 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
852 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
853 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
854 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
856 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
857 paftei
->dwInstance
, fdwSupport
);
860 /***********************************************************************
861 * acmFormatTagEnumA (MSACM32.@)
863 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
864 ACMFORMATTAGENUMCBA fnCallback
,
865 DWORD_PTR dwInstance
, DWORD fdwEnum
)
867 ACMFORMATTAGDETAILSW aftdw
;
868 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
871 return MMSYSERR_INVALPARAM
;
873 if (paftda
->cbStruct
< sizeof(*paftda
))
874 return MMSYSERR_INVALPARAM
;
877 return MMSYSERR_INVALFLAG
;
879 memset(&aftdw
, 0, sizeof(aftdw
));
880 aftdw
.cbStruct
= sizeof(aftdw
);
881 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
882 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
884 aftei
.paftda
= paftda
;
885 aftei
.dwInstance
= dwInstance
;
886 aftei
.fnCallback
= fnCallback
;
888 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
889 (DWORD_PTR
)&aftei
, fdwEnum
);
892 /***********************************************************************
893 * acmFormatTagEnumW (MSACM32.@)
895 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
896 ACMFORMATTAGENUMCBW fnCallback
,
897 DWORD_PTR dwInstance
, DWORD fdwEnum
)
899 PWINE_ACMDRIVERID padid
;
901 BOOL bPcmDone
= FALSE
;
903 TRACE("(%p, %p, %p, %ld, %d)\n",
904 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
907 return MMSYSERR_INVALPARAM
;
909 if (paftd
->cbStruct
< sizeof(*paftd
))
910 return MMSYSERR_INVALPARAM
;
913 return MMSYSERR_INVALFLAG
;
915 /* (WS) MSDN info page says that if had != 0, then we should find
916 * the specific driver to get its tags from. Therefore I'm removing
917 * the FIXME call and adding a search block below. It also seems
918 * that the lack of this functionality was the responsible for
919 * codecs to be multiply and incorrectly listed.
922 /* if (had) FIXME("had != NULL, not supported\n"); */
925 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
926 return MMSYSERR_INVALHANDLE
;
928 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
929 paftd
->dwFormatTagIndex
= i
;
930 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
931 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
932 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
933 if (paftd
->szFormatTag
[0] == 0)
934 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
935 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
936 /* (WS) I'm preserving this PCM hack since it seems to be
937 * correct. Please notice this block was borrowed from
940 if (bPcmDone
) continue;
943 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
944 return MMSYSERR_NOERROR
;
948 /* if had==0 then search for the first suitable driver */
950 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
951 /* should check for codec only */
952 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
953 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
954 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
955 paftd
->dwFormatTagIndex
= i
;
956 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
957 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
958 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
959 if (paftd
->szFormatTag
[0] == 0)
960 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
961 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
962 /* FIXME (EPP): I'm not sure this is the correct
963 * algorithm (should make more sense to apply the same
964 * for all already loaded formats, but this will do
967 if (bPcmDone
) continue;
970 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
971 acmDriverClose(had
, 0);
972 return MMSYSERR_NOERROR
;
976 acmDriverClose(had
, 0);
980 return MMSYSERR_NOERROR
;