1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1998 Patrik Stridvall
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
42 static PACMFORMATCHOOSEA afc
;
44 struct MSACM_FillFormatData
{
46 #define WINE_ACMFF_TAG 0
47 #define WINE_ACMFF_FORMAT 1
48 #define WINE_ACMFF_WFX 2
50 char szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
51 PACMFORMATCHOOSEA afc
;
55 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
56 PACMFORMATTAGDETAILSA paftd
,
60 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
64 if (SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
65 CB_FINDSTRINGEXACT
, -1,
66 (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
67 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
68 CB_ADDSTRING
, 0, (LPARAM
)paftd
->szFormatTag
);
70 case WINE_ACMFF_FORMAT
:
71 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
74 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
75 ACMFORMATDETAILSA afd
;
78 char buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
80 afd
.cbStruct
= sizeof(afd
);
81 afd
.dwFormatTag
= paftd
->dwFormatTag
;
82 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
83 if (!afd
.pwfx
) return FALSE
;
84 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
85 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
86 afd
.cbwfx
= paftd
->cbFormatSize
;
88 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
89 afd
.dwFormatIndex
= i
;
90 mmr
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
91 if (mmr
== MMSYSERR_NOERROR
) {
92 lstrcpynA(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
94 memset(buffer
+len
, ' ', ACMFORMATTAGDETAILS_FORMATTAG_CHARS
- len
);
95 wsprintfA(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
97 (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
98 SendDlgItemMessageA(affd
->hWnd
,
99 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
100 CB_ADDSTRING
, 0, (LPARAM
)buffer
);
103 acmDriverClose(had
, 0);
104 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
106 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
111 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
114 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
115 ACMFORMATDETAILSA 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
= SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
124 affd
->ret
= acmFormatDetailsA(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 ACMFORMATTAGDETAILSA aftd
;
140 struct MSACM_FillFormatData affd
;
142 memset(&aftd
, 0, sizeof(aftd
));
143 aftd
.cbStruct
= sizeof(aftd
);
146 affd
.mode
= WINE_ACMFF_TAG
;
148 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
149 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
153 static BOOL
MSACM_FillFormat(HWND hWnd
)
155 ACMFORMATTAGDETAILSA aftd
;
156 struct MSACM_FillFormatData affd
;
158 SendDlgItemMessageA(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 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
167 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
169 (LPARAM
)affd
.szFormatTag
);
171 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
172 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
176 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEA afc
)
178 ACMFORMATTAGDETAILSA 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 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
190 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
192 (LPARAM
)affd
.szFormatTag
);
194 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
198 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
199 WPARAM wParam
, LPARAM lParam
)
202 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
206 afc
= (PACMFORMATCHOOSEA
)lParam
;
207 MSACM_FillFormatTags(hWnd
);
208 MSACM_FillFormat(hWnd
);
209 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
210 ACMFORMATCHOOSE_STYLEF_SHOWHELP
)) != 0)
211 FIXME("Unsupported style %08x\n", ((PACMFORMATCHOOSEA
)lParam
)->fdwStyle
);
212 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
213 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
217 switch (LOWORD(wParam
)) {
219 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
222 EndDialog(hWnd
, ACMERR_CANCELED
);
224 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
225 switch (HIWORD(wParam
)) {
227 MSACM_FillFormat(hWnd
);
230 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
231 HIWORD(wParam
), lParam
);
235 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
236 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
237 SendMessageA(afc
->hwndOwner
,
238 RegisterWindowMessageA(ACMHELPMSGSTRINGA
), 0L, 0L);
242 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
243 LOWORD(wParam
), HIWORD(wParam
), lParam
);
248 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
249 SendMessageA(afc
->hwndOwner
,
250 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA
),
253 #if defined(WM_CONTEXTHELP)
255 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
256 SendMessageA(afc
->hwndOwner
,
257 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA
),
262 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
263 hWnd
, msg
, wParam
, lParam
);
269 /***********************************************************************
270 * acmFormatChooseA (MSACM32.@)
272 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
274 return DialogBoxParamA(MSACM_hInstance32
, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID
),
275 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
278 /***********************************************************************
279 * acmFormatChooseW (MSACM32.@)
281 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
283 FIXME("(%p): stub\n", pafmtc
);
284 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
285 return MMSYSERR_ERROR
;
288 /***********************************************************************
289 * acmFormatDetailsA (MSACM32.@)
291 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
294 ACMFORMATDETAILSW afdw
;
297 memset(&afdw
, 0, sizeof(afdw
));
298 afdw
.cbStruct
= sizeof(afdw
);
299 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
300 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
301 afdw
.pwfx
= pafd
->pwfx
;
302 afdw
.cbwfx
= pafd
->cbwfx
;
304 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
305 if (mmr
== MMSYSERR_NOERROR
) {
306 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
307 pafd
->fdwSupport
= afdw
.fdwSupport
;
308 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
309 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
314 /***********************************************************************
315 * acmFormatDetailsW (MSACM32.@)
317 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
320 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
321 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
322 ACMFORMATTAGDETAILSA aftd
;
324 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
326 memset(&aftd
, 0, sizeof(aftd
));
327 aftd
.cbStruct
= sizeof(aftd
);
329 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
331 switch (fdwDetails
) {
332 case ACM_FORMATDETAILSF_FORMAT
:
333 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
334 mmr
= MMSYSERR_INVALPARAM
;
338 PWINE_ACMDRIVERID padid
;
340 mmr
= ACMERR_NOTPOSSIBLE
;
341 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
342 /* should check for codec only */
343 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
344 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
345 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
346 acmDriverClose(had
, 0);
347 if (mmr
== MMSYSERR_NOERROR
) break;
351 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
354 case ACM_FORMATDETAILSF_INDEX
:
355 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
356 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
359 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
360 mmr
= MMSYSERR_INVALFLAG
;
364 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
365 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
366 if (pafd
->pwfx
->wBitsPerSample
) {
367 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
368 pafd
->pwfx
->wBitsPerSample
);
370 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
371 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
372 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
375 TRACE("=> %d\n", mmr
);
379 struct MSACM_FormatEnumWtoA_Instance
{
380 PACMFORMATDETAILSA pafda
;
381 DWORD_PTR dwInstance
;
382 ACMFORMATENUMCBA fnCallback
;
385 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
386 PACMFORMATDETAILSW pafdw
,
387 DWORD_PTR dwInstance
,
390 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
392 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
394 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
395 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
396 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
397 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
398 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
400 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
401 pafei
->dwInstance
, fdwSupport
);
404 /***********************************************************************
405 * acmFormatEnumA (MSACM32.@)
407 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
408 ACMFORMATENUMCBA fnCallback
,
409 DWORD_PTR dwInstance
, DWORD fdwEnum
)
411 ACMFORMATDETAILSW afdw
;
412 struct MSACM_FormatEnumWtoA_Instance afei
;
415 return MMSYSERR_INVALPARAM
;
417 if (pafda
->cbStruct
< sizeof(*pafda
))
418 return MMSYSERR_INVALPARAM
;
420 memset(&afdw
, 0, sizeof(afdw
));
421 afdw
.cbStruct
= sizeof(afdw
);
422 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
423 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
424 afdw
.pwfx
= pafda
->pwfx
;
425 afdw
.cbwfx
= pafda
->cbwfx
;
428 afei
.dwInstance
= dwInstance
;
429 afei
.fnCallback
= fnCallback
;
431 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
432 (DWORD_PTR
)&afei
, fdwEnum
);
435 /***********************************************************************
436 * acmFormatEnumW (MSACM32.@)
438 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
439 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
440 ACMFORMATENUMCBW fnCallback
,
441 DWORD_PTR dwInstance
, DWORD fdwEnum
)
443 ACMFORMATTAGDETAILSW aftd
;
446 if (fdwEnum
& ACM_FORMATENUMF_SUGGEST
) {
448 ACMDRVFORMATSUGGEST adfs
;
449 pafd
->dwFormatIndex
= 0;
450 memset(&aftd
, 0, sizeof(aftd
));
451 aftd
.cbStruct
= sizeof(aftd
);
452 memset(&adfs
, 0, sizeof(adfs
));
453 adfs
.cbStruct
= sizeof(adfs
);
455 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
456 aftd
.dwFormatTag
= i
;
457 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
458 pafd
->pwfx
->wFormatTag
= pafd
->dwFormatTag
;
460 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
463 adfs
.cbwfxSrc
= aftd
.cbFormatSize
;
464 adfs
.cbwfxDst
= aftd
.cbFormatSize
;
465 adfs
.pwfxSrc
= pwfxRef
;
466 adfs
.pwfxDst
= pafd
->pwfx
;
467 pafd
->fdwSupport
= padid
->fdwSupport
;
469 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
470 aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
473 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
474 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
477 hdrvr
= OpenDriver(padid
->pszFileName
,0,0);
478 SendDriverMessage(hdrvr
,ACMDM_FORMAT_SUGGEST
,(LPARAM
)&adfs
,(fdwEnum
& 0x000000FFL
));
480 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_FORMAT
) != MMSYSERR_NOERROR
)
483 pafd
->cbwfx
= sizeof(*(pafd
->pwfx
));
485 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
489 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
490 memset(&aftd
, 0, sizeof(aftd
));
491 aftd
.cbStruct
= sizeof(aftd
);
492 aftd
.dwFormatTagIndex
= i
;
493 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
496 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
499 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
500 pafd
->dwFormatIndex
= j
;
501 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
502 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
505 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
506 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
508 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
509 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
511 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
512 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
514 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
515 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
518 /* more checks to be done on fdwEnum */
520 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
523 /* the "formats" used by the filters are also reported */
529 /**********************************************************************/
531 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
532 ACMFORMATENUMCBW fnCallback
,
533 DWORD_PTR dwInstance
, DWORD fdwEnum
)
535 PWINE_ACMDRIVERID padid
;
539 TRACE("(%p, %p, %p, %ld, %d)\n",
540 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
543 return MMSYSERR_INVALPARAM
;
545 if (pafd
->cbStruct
< sizeof(*pafd
))
546 return MMSYSERR_INVALPARAM
;
548 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
549 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
550 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
551 wfxRef
= *pafd
->pwfx
;
553 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
554 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
555 return MMSYSERR_INVALPARAM
;
557 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
558 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
559 return MMSYSERR_INVALPARAM
;
561 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
562 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
567 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
568 return MMSYSERR_INVALHANDLE
;
569 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
570 fnCallback
, dwInstance
, fdwEnum
);
571 return MMSYSERR_NOERROR
;
573 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
574 /* should check for codec only */
575 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
576 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
578 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
579 fnCallback
, dwInstance
, fdwEnum
);
580 acmDriverClose(had
, 0);
583 return MMSYSERR_NOERROR
;
586 /***********************************************************************
587 * acmFormatSuggest (MSACM32.@)
589 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
590 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
592 ACMDRVFORMATSUGGEST adfg
;
595 TRACE("(%p, %p, %p, %d, %d)\n",
596 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
598 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
599 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
600 return MMSYSERR_INVALFLAG
;
602 adfg
.cbStruct
= sizeof(adfg
);
603 adfg
.fdwSuggest
= fdwSuggest
;
604 adfg
.pwfxSrc
= pwfxSrc
;
605 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
606 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
607 adfg
.pwfxDst
= pwfxDst
;
608 adfg
.cbwfxDst
= cbwfxDst
;
611 PWINE_ACMDRIVERID padid
;
613 /* MS doc says: ACM finds the best suggestion.
614 * Well, first found will be the "best"
616 mmr
= ACMERR_NOTPOSSIBLE
;
617 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
618 /* should check for codec only */
619 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
620 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
623 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
624 mmr
= MMSYSERR_NOERROR
;
627 acmDriverClose(had
, 0);
630 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
635 /***********************************************************************
636 * acmFormatTagDetailsA (MSACM32.@)
638 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
641 ACMFORMATTAGDETAILSW aftdw
;
644 memset(&aftdw
, 0, sizeof(aftdw
));
645 aftdw
.cbStruct
= sizeof(aftdw
);
646 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
647 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
649 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
650 if (mmr
== MMSYSERR_NOERROR
) {
651 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
652 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
653 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
654 paftda
->fdwSupport
= aftdw
.fdwSupport
;
655 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
656 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
657 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
662 /***********************************************************************
663 * acmFormatTagDetailsW (MSACM32.@)
665 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
668 PWINE_ACMDRIVERID padid
;
669 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
671 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
673 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
674 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
675 return MMSYSERR_INVALFLAG
;
677 switch (fdwDetails
) {
678 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
680 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
681 /* should check for codec only */
682 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
683 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
684 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
685 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
686 acmDriverClose(had
, 0);
687 if (mmr
== MMSYSERR_NOERROR
) break;
691 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
693 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
694 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
698 case ACM_FORMATTAGDETAILSF_INDEX
:
700 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
702 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
703 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
707 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
709 ACMFORMATTAGDETAILSW tmp
;
710 DWORD ft
= paftd
->dwFormatTag
;
712 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
713 /* should check for codec only */
714 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
715 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
717 memset(&tmp
, 0, sizeof(tmp
));
718 tmp
.cbStruct
= sizeof(tmp
);
719 tmp
.dwFormatTag
= ft
;
721 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
722 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
723 if (mmr
== ACMERR_NOTPOSSIBLE
||
724 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
726 mmr
= MMSYSERR_NOERROR
;
729 acmDriverClose(had
, 0);
733 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
738 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
739 mmr
= MMSYSERR_ERROR
;
742 if (mmr
== MMSYSERR_NOERROR
&&
743 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
744 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
745 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
750 struct MSACM_FormatTagEnumWtoA_Instance
{
751 PACMFORMATTAGDETAILSA paftda
;
752 DWORD_PTR dwInstance
;
753 ACMFORMATTAGENUMCBA fnCallback
;
756 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
757 PACMFORMATTAGDETAILSW paftdw
,
758 DWORD_PTR dwInstance
,
761 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
763 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
765 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
766 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
767 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
768 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
769 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
770 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
771 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
773 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
774 paftei
->dwInstance
, fdwSupport
);
777 /***********************************************************************
778 * acmFormatTagEnumA (MSACM32.@)
780 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
781 ACMFORMATTAGENUMCBA fnCallback
,
782 DWORD_PTR dwInstance
, DWORD fdwEnum
)
784 ACMFORMATTAGDETAILSW aftdw
;
785 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
788 return MMSYSERR_INVALPARAM
;
790 if (paftda
->cbStruct
< sizeof(*paftda
))
791 return MMSYSERR_INVALPARAM
;
794 return MMSYSERR_INVALFLAG
;
796 memset(&aftdw
, 0, sizeof(aftdw
));
797 aftdw
.cbStruct
= sizeof(aftdw
);
798 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
799 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
801 aftei
.paftda
= paftda
;
802 aftei
.dwInstance
= dwInstance
;
803 aftei
.fnCallback
= fnCallback
;
805 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
806 (DWORD_PTR
)&aftei
, fdwEnum
);
809 /***********************************************************************
810 * acmFormatTagEnumW (MSACM32.@)
812 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
813 ACMFORMATTAGENUMCBW fnCallback
,
814 DWORD_PTR dwInstance
, DWORD fdwEnum
)
816 PWINE_ACMDRIVERID padid
;
818 BOOL bPcmDone
= FALSE
;
820 TRACE("(%p, %p, %p, %ld, %d)\n",
821 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
824 return MMSYSERR_INVALPARAM
;
826 if (paftd
->cbStruct
< sizeof(*paftd
))
827 return MMSYSERR_INVALPARAM
;
830 return MMSYSERR_INVALFLAG
;
832 /* (WS) MSDN info page says that if had != 0, then we should find
833 * the specific driver to get its tags from. Therefore I'm removing
834 * the FIXME call and adding a search block below. It also seems
835 * that the lack of this functionality was the responsible for
836 * codecs to be multiply and incorrectly listed.
839 /* if (had) FIXME("had != NULL, not supported\n"); */
843 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
844 return MMSYSERR_INVALHANDLE
;
846 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
847 paftd
->dwFormatTagIndex
= i
;
848 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
849 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
850 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
851 if (paftd
->szFormatTag
[0] == 0)
852 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
853 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
854 /* (WS) I'm preserving this PCM hack since it seems to be
855 * correct. Please notice this block was borrowed from
858 if (bPcmDone
) continue;
861 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
862 return MMSYSERR_NOERROR
;
868 /* if had==0 then search for the first suitable driver */
870 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
871 /* should check for codec only */
872 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
873 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
874 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
875 paftd
->dwFormatTagIndex
= i
;
876 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
877 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
878 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
879 if (paftd
->szFormatTag
[0] == 0)
880 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
881 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
882 /* FIXME (EPP): I'm not sure this is the correct
883 * algorithm (should make more sense to apply the same
884 * for all already loaded formats, but this will do
887 if (bPcmDone
) continue;
890 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
891 acmDriverClose(had
, 0);
892 return MMSYSERR_NOERROR
;
896 acmDriverClose(had
, 0);
900 return MMSYSERR_NOERROR
;