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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
40 static PACMFORMATCHOOSEA afc
;
42 struct MSACM_FillFormatData
{
44 #define WINE_ACMFF_TAG 0
45 #define WINE_ACMFF_FORMAT 1
46 #define WINE_ACMFF_WFX 2
48 char szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
49 PACMFORMATCHOOSEA afc
;
53 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
54 PACMFORMATTAGDETAILSA paftd
,
55 DWORD dwInstance
, DWORD fdwSupport
)
57 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
61 if (SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
63 (WPARAM
)-1, (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
64 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
65 CB_ADDSTRING
, 0, (DWORD
)paftd
->szFormatTag
);
67 case WINE_ACMFF_FORMAT
:
68 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
71 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
72 ACMFORMATDETAILSA afd
;
75 char buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
77 afd
.cbStruct
= sizeof(afd
);
78 afd
.dwFormatTag
= paftd
->dwFormatTag
;
79 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
80 if (!afd
.pwfx
) return FALSE
;
81 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
82 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
83 afd
.cbwfx
= paftd
->cbFormatSize
;
85 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
86 afd
.dwFormatIndex
= i
;
87 mmr
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
88 if (mmr
== MMSYSERR_NOERROR
) {
89 strncpy(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
);
90 for (idx
= strlen(buffer
);
91 idx
< ACMFORMATTAGDETAILS_FORMATTAG_CHARS
; idx
++)
93 wsprintfA(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
95 (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
96 SendDlgItemMessageA(affd
->hWnd
,
97 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
98 CB_ADDSTRING
, 0, (DWORD
)buffer
);
101 acmDriverClose(had
, 0);
102 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
104 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
109 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
112 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
113 ACMFORMATDETAILSA afd
;
115 afd
.cbStruct
= sizeof(afd
);
116 afd
.dwFormatTag
= paftd
->dwFormatTag
;
117 afd
.pwfx
= affd
->afc
->pwfx
;
118 afd
.cbwfx
= affd
->afc
->cbwfx
;
120 afd
.dwFormatIndex
= SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
122 affd
->ret
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
123 acmDriverClose(had
, 0);
129 FIXME("Unknown mode (%d)\n", affd
->mode
);
135 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
137 ACMFORMATTAGDETAILSA aftd
;
138 struct MSACM_FillFormatData affd
;
140 memset(&aftd
, 0, sizeof(aftd
));
141 aftd
.cbStruct
= sizeof(aftd
);
144 affd
.mode
= WINE_ACMFF_TAG
;
146 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
147 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
151 static BOOL
MSACM_FillFormat(HWND hWnd
)
153 ACMFORMATTAGDETAILSA aftd
;
154 struct MSACM_FillFormatData affd
;
156 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
158 memset(&aftd
, 0, sizeof(aftd
));
159 aftd
.cbStruct
= sizeof(aftd
);
162 affd
.mode
= WINE_ACMFF_FORMAT
;
163 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
165 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
167 (DWORD
)affd
.szFormatTag
);
169 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
170 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
174 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEA afc
)
176 ACMFORMATTAGDETAILSA aftd
;
177 struct MSACM_FillFormatData affd
;
179 memset(&aftd
, 0, sizeof(aftd
));
180 aftd
.cbStruct
= sizeof(aftd
);
183 affd
.mode
= WINE_ACMFF_WFX
;
185 affd
.ret
= MMSYSERR_NOERROR
;
186 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
188 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
190 (DWORD
)affd
.szFormatTag
);
192 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
196 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
197 WPARAM wParam
, LPARAM lParam
)
200 TRACE("hwnd=%p msg=%i 0x%08x 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
204 afc
= (PACMFORMATCHOOSEA
)lParam
;
205 MSACM_FillFormatTags(hWnd
);
206 MSACM_FillFormat(hWnd
);
207 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
208 ACMFORMATCHOOSE_STYLEF_SHOWHELP
)) != 0)
209 FIXME("Unsupported style %08lx\n", ((PACMFORMATCHOOSEA
)lParam
)->fdwStyle
);
210 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
211 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
215 switch (LOWORD(wParam
)) {
217 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
220 EndDialog(hWnd
, ACMERR_CANCELED
);
222 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
223 switch (HIWORD(wParam
)) {
225 MSACM_FillFormat(hWnd
);
228 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
229 HIWORD(wParam
), lParam
);
233 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
234 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
235 SendMessageA(afc
->hwndOwner
,
236 RegisterWindowMessageA(ACMHELPMSGSTRINGA
), 0L, 0L);
240 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
241 LOWORD(wParam
), HIWORD(wParam
), lParam
);
246 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
247 SendMessageA(afc
->hwndOwner
,
248 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA
),
251 #if defined(WM_CONTEXTHELP)
253 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
254 SendMessageA(afc
->hwndOwner
,
255 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA
),
260 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08x 0x%08lx\n",
261 hWnd
, msg
, wParam
, lParam
);
267 /***********************************************************************
268 * acmFormatChooseA (MSACM32.@)
270 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
272 return DialogBoxParamA(MSACM_hInstance32
, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID
),
273 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (INT
)pafmtc
);
276 /***********************************************************************
277 * acmFormatChooseW (MSACM32.@)
279 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
281 FIXME("(%p): stub\n", pafmtc
);
282 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
283 return MMSYSERR_ERROR
;
286 /***********************************************************************
287 * acmFormatDetailsA (MSACM32.@)
289 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
292 ACMFORMATDETAILSW afdw
;
295 memset(&afdw
, 0, sizeof(afdw
));
296 afdw
.cbStruct
= sizeof(afdw
);
297 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
298 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
299 afdw
.pwfx
= pafd
->pwfx
;
300 afdw
.cbwfx
= pafd
->cbwfx
;
302 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
303 if (mmr
== MMSYSERR_NOERROR
) {
304 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
305 pafd
->fdwSupport
= afdw
.fdwSupport
;
306 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
307 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
312 /***********************************************************************
313 * acmFormatDetailsW (MSACM32.@)
315 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
318 static WCHAR fmt1
[] = {'%','d',' ','H','z',0};
319 static WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
320 ACMFORMATTAGDETAILSA aftd
;
322 TRACE("(%p, %p, %ld)\n", had
, pafd
, fdwDetails
);
324 memset(&aftd
, 0, sizeof(aftd
));
325 aftd
.cbStruct
= sizeof(aftd
);
327 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
329 switch (fdwDetails
) {
330 case ACM_FORMATDETAILSF_FORMAT
:
331 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
332 mmr
= MMSYSERR_INVALPARAM
;
336 PWINE_ACMDRIVERID padid
;
338 mmr
= ACMERR_NOTPOSSIBLE
;
339 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
340 /* should check for codec only */
341 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
342 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
343 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
344 acmDriverClose(had
, 0);
345 if (mmr
== MMSYSERR_NOERROR
) break;
349 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
352 case ACM_FORMATDETAILSF_INDEX
:
353 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
354 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
357 WARN("Unknown fdwDetails %08lx\n", fdwDetails
);
358 mmr
= MMSYSERR_INVALFLAG
;
362 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == (WCHAR
)0) {
363 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
364 if (pafd
->pwfx
->wBitsPerSample
) {
365 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
366 pafd
->pwfx
->wBitsPerSample
);
368 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
369 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
370 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
373 TRACE("=> %d\n", mmr
);
377 struct MSACM_FormatEnumWtoA_Instance
{
378 PACMFORMATDETAILSA pafda
;
380 ACMFORMATENUMCBA fnCallback
;
383 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
384 PACMFORMATDETAILSW pafdw
,
388 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
390 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
392 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
393 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
394 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
395 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
396 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
398 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
399 pafei
->dwInstance
, fdwSupport
);
402 /***********************************************************************
403 * acmFormatEnumA (MSACM32.@)
405 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
406 ACMFORMATENUMCBA fnCallback
, DWORD dwInstance
,
409 ACMFORMATDETAILSW afdw
;
410 struct MSACM_FormatEnumWtoA_Instance afei
;
412 memset(&afdw
, 0, sizeof(afdw
));
413 afdw
.cbStruct
= sizeof(afdw
);
414 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
415 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
416 afdw
.pwfx
= pafda
->pwfx
;
417 afdw
.cbwfx
= pafda
->cbwfx
;
420 afei
.dwInstance
= dwInstance
;
421 afei
.fnCallback
= fnCallback
;
423 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
424 (DWORD
)&afei
, fdwEnum
);
427 /***********************************************************************
428 * acmFormatEnumW (MSACM32.@)
430 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
431 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
432 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
435 ACMFORMATTAGDETAILSW aftd
;
438 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
439 memset(&aftd
, 0, sizeof(aftd
));
440 aftd
.cbStruct
= sizeof(aftd
);
441 aftd
.dwFormatTagIndex
= i
;
442 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
445 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
448 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
449 pafd
->dwFormatIndex
= j
;
450 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
451 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
454 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
455 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
457 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
458 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
460 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
461 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
463 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
464 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
467 /* more checks to be done on fdwEnum */
469 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
472 /* the "formats" used by the filters are also reported */
477 /**********************************************************************/
479 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
480 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
483 PWINE_ACMDRIVERID padid
;
487 TRACE("(%p, %p, %p, %ld, %ld)\n",
488 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
490 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
492 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
493 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
494 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
495 wfxRef
= *pafd
->pwfx
;
497 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
498 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
499 return MMSYSERR_INVALPARAM
;
501 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
502 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
503 return MMSYSERR_INVALPARAM
;
505 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
|
506 ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
507 FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum
);
512 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
513 return MMSYSERR_INVALHANDLE
;
514 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
515 fnCallback
, dwInstance
, fdwEnum
);
516 return MMSYSERR_NOERROR
;
518 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
519 /* should check for codec only */
520 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
521 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
523 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
524 fnCallback
, dwInstance
, fdwEnum
);
525 acmDriverClose(had
, 0);
528 return MMSYSERR_NOERROR
;
531 /***********************************************************************
532 * acmFormatSuggest (MSACM32.@)
534 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
535 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
537 ACMDRVFORMATSUGGEST adfg
;
540 TRACE("(%p, %p, %p, %ld, %ld)\n",
541 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
543 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
544 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
545 return MMSYSERR_INVALFLAG
;
547 adfg
.cbStruct
= sizeof(adfg
);
548 adfg
.fdwSuggest
= fdwSuggest
;
549 adfg
.pwfxSrc
= pwfxSrc
;
550 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
551 sizeof(WAVEFORMATEX
) : pwfxSrc
->cbSize
;
552 adfg
.pwfxDst
= pwfxDst
;
553 adfg
.cbwfxDst
= cbwfxDst
;
556 PWINE_ACMDRIVERID padid
;
558 /* MS doc says: ACM finds the best suggestion.
559 * Well, first found will be the "best"
561 mmr
= ACMERR_NOTPOSSIBLE
;
562 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
563 /* should check for codec only */
564 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
565 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
568 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
569 mmr
= MMSYSERR_NOERROR
;
572 acmDriverClose(had
, 0);
575 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
580 /***********************************************************************
581 * acmFormatTagDetailsA (MSACM32.@)
583 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
586 ACMFORMATTAGDETAILSW aftdw
;
589 memset(&aftdw
, 0, sizeof(aftdw
));
590 aftdw
.cbStruct
= sizeof(aftdw
);
591 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
592 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
594 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
595 if (mmr
== MMSYSERR_NOERROR
) {
596 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
597 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
598 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
599 paftda
->fdwSupport
= aftdw
.fdwSupport
;
600 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
601 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
602 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
607 /***********************************************************************
608 * acmFormatTagDetailsW (MSACM32.@)
610 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
613 PWINE_ACMDRIVERID padid
;
614 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
616 TRACE("(%p, %p, %ld)\n", had
, paftd
, fdwDetails
);
618 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
619 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
620 return MMSYSERR_INVALFLAG
;
622 switch (fdwDetails
) {
623 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
625 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
626 /* should check for codec only */
627 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
628 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
629 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
630 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
631 acmDriverClose(had
, 0);
632 if (mmr
== MMSYSERR_NOERROR
) break;
636 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
638 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
639 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
643 case ACM_FORMATTAGDETAILSF_INDEX
:
645 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
647 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
648 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
652 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
654 ACMFORMATTAGDETAILSW tmp
;
655 DWORD ft
= paftd
->dwFormatTag
;
657 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
658 /* should check for codec only */
659 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
660 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
662 memset(&tmp
, 0, sizeof(tmp
));
663 tmp
.cbStruct
= sizeof(tmp
);
664 tmp
.dwFormatTag
= ft
;
666 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
667 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
668 if (mmr
== ACMERR_NOTPOSSIBLE
||
669 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
671 mmr
= MMSYSERR_NOERROR
;
674 acmDriverClose(had
, 0);
678 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
683 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails
);
684 mmr
= MMSYSERR_ERROR
;
687 if (mmr
== MMSYSERR_NOERROR
&&
688 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
689 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
690 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
695 struct MSACM_FormatTagEnumWtoA_Instance
{
696 PACMFORMATTAGDETAILSA paftda
;
698 ACMFORMATTAGENUMCBA fnCallback
;
701 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
702 PACMFORMATTAGDETAILSW paftdw
,
706 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
708 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
710 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
711 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
712 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
713 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
714 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
715 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
716 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
718 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
719 paftei
->dwInstance
, fdwSupport
);
722 /***********************************************************************
723 * acmFormatTagEnumA (MSACM32.@)
725 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
726 ACMFORMATTAGENUMCBA fnCallback
, DWORD dwInstance
,
729 ACMFORMATTAGDETAILSW aftdw
;
730 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
732 memset(&aftdw
, 0, sizeof(aftdw
));
733 aftdw
.cbStruct
= sizeof(aftdw
);
734 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
735 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
737 aftei
.paftda
= paftda
;
738 aftei
.dwInstance
= dwInstance
;
739 aftei
.fnCallback
= fnCallback
;
741 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
742 (DWORD
)&aftei
, fdwEnum
);
745 /***********************************************************************
746 * acmFormatTagEnumW (MSACM32.@)
748 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
749 ACMFORMATTAGENUMCBW fnCallback
, DWORD dwInstance
,
752 PWINE_ACMDRIVERID padid
;
754 BOOL bPcmDone
= FALSE
;
756 TRACE("(%p, %p, %p, %ld, %ld)\n",
757 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
759 if (paftd
->cbStruct
< sizeof(*paftd
)) return MMSYSERR_INVALPARAM
;
761 /* (WS) MSDN info page says that if had != 0, then we should find
762 * the specific driver to get its tags from. Therefore I'm removing
763 * the FIXME call and adding a search block below. It also seems
764 * that the lack of this functionality was the responsible for
765 * codecs to be multiply and incorrectly listed.
768 /* if (had) FIXME("had != NULL, not supported\n"); */
772 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
773 return MMSYSERR_INVALHANDLE
;
775 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
776 paftd
->dwFormatTagIndex
= i
;
777 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
778 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
779 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
780 if (paftd
->szFormatTag
[0] == 0)
781 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
782 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
783 /* (WS) I'm preserving this PCM hack since it seems to be
784 * correct. Please notice this block was borrowed from
787 if (bPcmDone
) continue;
790 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
791 return MMSYSERR_NOERROR
;
797 /* if had==0 then search for the first suitable driver */
799 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
800 /* should check for codec only */
801 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
802 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
803 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
804 paftd
->dwFormatTagIndex
= i
;
805 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
806 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
807 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
808 if (paftd
->szFormatTag
[0] == 0)
809 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
810 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
811 /* FIXME (EPP): I'm not sure this is the correct
812 * algorithm (should make more sense to apply the same
813 * for all already loaded formats, but this will do
816 if (bPcmDone
) continue;
819 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
820 acmDriverClose(had
, 0);
821 return MMSYSERR_NOERROR
;
826 acmDriverClose(had
, 0);
829 return MMSYSERR_NOERROR
;