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
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
,
57 DWORD dwInstance
, DWORD fdwSupport
)
59 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
63 if (SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
65 (WPARAM
)-1, (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
66 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
67 CB_ADDSTRING
, 0, (DWORD
)paftd
->szFormatTag
);
69 case WINE_ACMFF_FORMAT
:
70 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
73 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
74 ACMFORMATDETAILSA afd
;
77 char buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
79 afd
.cbStruct
= sizeof(afd
);
80 afd
.dwFormatTag
= paftd
->dwFormatTag
;
81 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
82 if (!afd
.pwfx
) return FALSE
;
83 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
84 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
85 afd
.cbwfx
= paftd
->cbFormatSize
;
87 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
88 afd
.dwFormatIndex
= i
;
89 mmr
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
90 if (mmr
== MMSYSERR_NOERROR
) {
91 strncpy(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
);
92 for (idx
= strlen(buffer
);
93 idx
< ACMFORMATTAGDETAILS_FORMATTAG_CHARS
; idx
++)
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, (DWORD
)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
)&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 (DWORD
)affd
.szFormatTag
);
171 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&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 (DWORD
)affd
.szFormatTag
);
194 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
198 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
199 WPARAM wParam
, LPARAM lParam
)
202 TRACE("hwnd=%p msg=%i 0x%08x 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 %08lx\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%08x 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
, (INT
)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, %ld)\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 %08lx\n", fdwDetails
);
360 mmr
= MMSYSERR_INVALFLAG
;
364 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == (WCHAR
)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
;
382 ACMFORMATENUMCBA fnCallback
;
385 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
386 PACMFORMATDETAILSW pafdw
,
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
, DWORD dwInstance
,
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
)&afei
, fdwEnum
);
435 /***********************************************************************
436 * acmFormatEnumW (MSACM32.@)
438 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
439 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
440 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
443 ACMFORMATTAGDETAILSW aftd
;
446 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
447 memset(&aftd
, 0, sizeof(aftd
));
448 aftd
.cbStruct
= sizeof(aftd
);
449 aftd
.dwFormatTagIndex
= i
;
450 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
453 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
456 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
457 pafd
->dwFormatIndex
= j
;
458 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
459 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
462 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
463 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
465 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
466 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
468 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
469 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
471 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
472 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
475 /* more checks to be done on fdwEnum */
477 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
480 /* the "formats" used by the filters are also reported */
485 /**********************************************************************/
487 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
488 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
491 PWINE_ACMDRIVERID padid
;
495 TRACE("(%p, %p, %p, %ld, %ld)\n",
496 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
499 return MMSYSERR_INVALPARAM
;
501 if (pafd
->cbStruct
< sizeof(*pafd
))
502 return MMSYSERR_INVALPARAM
;
504 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
505 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
506 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
507 wfxRef
= *pafd
->pwfx
;
509 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
510 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
511 return MMSYSERR_INVALPARAM
;
513 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
514 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
515 return MMSYSERR_INVALPARAM
;
517 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
|
518 ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
519 FIXME("Unsupported fdwEnum values %08lx\n", fdwEnum
);
524 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
525 return MMSYSERR_INVALHANDLE
;
526 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
527 fnCallback
, dwInstance
, fdwEnum
);
528 return MMSYSERR_NOERROR
;
530 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
531 /* should check for codec only */
532 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
533 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
535 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
536 fnCallback
, dwInstance
, fdwEnum
);
537 acmDriverClose(had
, 0);
540 return MMSYSERR_NOERROR
;
543 /***********************************************************************
544 * acmFormatSuggest (MSACM32.@)
546 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
547 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
549 ACMDRVFORMATSUGGEST adfg
;
552 TRACE("(%p, %p, %p, %ld, %ld)\n",
553 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
555 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
556 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
557 return MMSYSERR_INVALFLAG
;
559 adfg
.cbStruct
= sizeof(adfg
);
560 adfg
.fdwSuggest
= fdwSuggest
;
561 adfg
.pwfxSrc
= pwfxSrc
;
562 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
563 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
564 adfg
.pwfxDst
= pwfxDst
;
565 adfg
.cbwfxDst
= cbwfxDst
;
568 PWINE_ACMDRIVERID padid
;
570 /* MS doc says: ACM finds the best suggestion.
571 * Well, first found will be the "best"
573 mmr
= ACMERR_NOTPOSSIBLE
;
574 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
575 /* should check for codec only */
576 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
577 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
580 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
581 mmr
= MMSYSERR_NOERROR
;
584 acmDriverClose(had
, 0);
587 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
592 /***********************************************************************
593 * acmFormatTagDetailsA (MSACM32.@)
595 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
598 ACMFORMATTAGDETAILSW aftdw
;
601 memset(&aftdw
, 0, sizeof(aftdw
));
602 aftdw
.cbStruct
= sizeof(aftdw
);
603 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
604 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
606 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
607 if (mmr
== MMSYSERR_NOERROR
) {
608 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
609 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
610 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
611 paftda
->fdwSupport
= aftdw
.fdwSupport
;
612 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
613 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
614 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
619 /***********************************************************************
620 * acmFormatTagDetailsW (MSACM32.@)
622 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
625 PWINE_ACMDRIVERID padid
;
626 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
628 TRACE("(%p, %p, %ld)\n", had
, paftd
, fdwDetails
);
630 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
631 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
632 return MMSYSERR_INVALFLAG
;
634 switch (fdwDetails
) {
635 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
637 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
638 /* should check for codec only */
639 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
640 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
641 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
642 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
643 acmDriverClose(had
, 0);
644 if (mmr
== MMSYSERR_NOERROR
) break;
648 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
650 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
651 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
655 case ACM_FORMATTAGDETAILSF_INDEX
:
657 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
659 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
660 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
664 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
666 ACMFORMATTAGDETAILSW tmp
;
667 DWORD ft
= paftd
->dwFormatTag
;
669 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
670 /* should check for codec only */
671 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
672 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
674 memset(&tmp
, 0, sizeof(tmp
));
675 tmp
.cbStruct
= sizeof(tmp
);
676 tmp
.dwFormatTag
= ft
;
678 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
679 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
680 if (mmr
== ACMERR_NOTPOSSIBLE
||
681 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
683 mmr
= MMSYSERR_NOERROR
;
686 acmDriverClose(had
, 0);
690 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
695 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails
);
696 mmr
= MMSYSERR_ERROR
;
699 if (mmr
== MMSYSERR_NOERROR
&&
700 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
701 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
702 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
707 struct MSACM_FormatTagEnumWtoA_Instance
{
708 PACMFORMATTAGDETAILSA paftda
;
710 ACMFORMATTAGENUMCBA fnCallback
;
713 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
714 PACMFORMATTAGDETAILSW paftdw
,
718 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
720 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
722 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
723 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
724 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
725 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
726 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
727 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
728 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
730 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
731 paftei
->dwInstance
, fdwSupport
);
734 /***********************************************************************
735 * acmFormatTagEnumA (MSACM32.@)
737 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
738 ACMFORMATTAGENUMCBA fnCallback
, DWORD dwInstance
,
741 ACMFORMATTAGDETAILSW aftdw
;
742 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
745 return MMSYSERR_INVALPARAM
;
747 if (paftda
->cbStruct
< sizeof(*paftda
))
748 return MMSYSERR_INVALPARAM
;
751 return MMSYSERR_INVALFLAG
;
753 memset(&aftdw
, 0, sizeof(aftdw
));
754 aftdw
.cbStruct
= sizeof(aftdw
);
755 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
756 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
758 aftei
.paftda
= paftda
;
759 aftei
.dwInstance
= dwInstance
;
760 aftei
.fnCallback
= fnCallback
;
762 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
763 (DWORD
)&aftei
, fdwEnum
);
766 /***********************************************************************
767 * acmFormatTagEnumW (MSACM32.@)
769 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
770 ACMFORMATTAGENUMCBW fnCallback
, DWORD dwInstance
,
773 PWINE_ACMDRIVERID padid
;
775 BOOL bPcmDone
= FALSE
;
777 TRACE("(%p, %p, %p, %ld, %ld)\n",
778 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
781 return MMSYSERR_INVALPARAM
;
783 if (paftd
->cbStruct
< sizeof(*paftd
))
784 return MMSYSERR_INVALPARAM
;
787 return MMSYSERR_INVALFLAG
;
789 /* (WS) MSDN info page says that if had != 0, then we should find
790 * the specific driver to get its tags from. Therefore I'm removing
791 * the FIXME call and adding a search block below. It also seems
792 * that the lack of this functionality was the responsible for
793 * codecs to be multiply and incorrectly listed.
796 /* if (had) FIXME("had != NULL, not supported\n"); */
800 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
801 return MMSYSERR_INVALHANDLE
;
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 /* (WS) I'm preserving this PCM hack since it seems to be
812 * correct. Please notice this block was borrowed from
815 if (bPcmDone
) continue;
818 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
819 return MMSYSERR_NOERROR
;
825 /* if had==0 then search for the first suitable driver */
827 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
828 /* should check for codec only */
829 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
830 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
831 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
832 paftd
->dwFormatTagIndex
= i
;
833 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
834 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
835 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
836 if (paftd
->szFormatTag
[0] == 0)
837 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
838 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
839 /* FIXME (EPP): I'm not sure this is the correct
840 * algorithm (should make more sense to apply the same
841 * for all already loaded formats, but this will do
844 if (bPcmDone
) continue;
847 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
848 acmDriverClose(had
, 0);
849 return MMSYSERR_NOERROR
;
854 acmDriverClose(had
, 0);
857 return MMSYSERR_NOERROR
;