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
,
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 lstrcpynA(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
93 memset(buffer
+len
, ' ', ACMFORMATTAGDETAILS_FORMATTAG_CHARS
- len
);
94 wsprintfA(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
96 (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
97 SendDlgItemMessageA(affd
->hWnd
,
98 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
99 CB_ADDSTRING
, 0, (DWORD
)buffer
);
102 acmDriverClose(had
, 0);
103 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
105 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
110 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
113 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
114 ACMFORMATDETAILSA afd
;
116 afd
.cbStruct
= sizeof(afd
);
117 afd
.dwFormatTag
= paftd
->dwFormatTag
;
118 afd
.pwfx
= affd
->afc
->pwfx
;
119 afd
.cbwfx
= affd
->afc
->cbwfx
;
121 afd
.dwFormatIndex
= SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
123 affd
->ret
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
124 acmDriverClose(had
, 0);
130 FIXME("Unknown mode (%d)\n", affd
->mode
);
136 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
138 ACMFORMATTAGDETAILSA aftd
;
139 struct MSACM_FillFormatData affd
;
141 memset(&aftd
, 0, sizeof(aftd
));
142 aftd
.cbStruct
= sizeof(aftd
);
145 affd
.mode
= WINE_ACMFF_TAG
;
147 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
148 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
152 static BOOL
MSACM_FillFormat(HWND hWnd
)
154 ACMFORMATTAGDETAILSA aftd
;
155 struct MSACM_FillFormatData affd
;
157 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
159 memset(&aftd
, 0, sizeof(aftd
));
160 aftd
.cbStruct
= sizeof(aftd
);
163 affd
.mode
= WINE_ACMFF_FORMAT
;
164 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
166 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
168 (DWORD
)affd
.szFormatTag
);
170 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
171 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
175 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEA afc
)
177 ACMFORMATTAGDETAILSA aftd
;
178 struct MSACM_FillFormatData affd
;
180 memset(&aftd
, 0, sizeof(aftd
));
181 aftd
.cbStruct
= sizeof(aftd
);
184 affd
.mode
= WINE_ACMFF_WFX
;
186 affd
.ret
= MMSYSERR_NOERROR
;
187 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
189 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
191 (DWORD
)affd
.szFormatTag
);
193 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD
)&affd
, 0);
197 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
198 WPARAM wParam
, LPARAM lParam
)
201 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
205 afc
= (PACMFORMATCHOOSEA
)lParam
;
206 MSACM_FillFormatTags(hWnd
);
207 MSACM_FillFormat(hWnd
);
208 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
209 ACMFORMATCHOOSE_STYLEF_SHOWHELP
)) != 0)
210 FIXME("Unsupported style %08x\n", ((PACMFORMATCHOOSEA
)lParam
)->fdwStyle
);
211 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
212 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
216 switch (LOWORD(wParam
)) {
218 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
221 EndDialog(hWnd
, ACMERR_CANCELED
);
223 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
224 switch (HIWORD(wParam
)) {
226 MSACM_FillFormat(hWnd
);
229 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
230 HIWORD(wParam
), lParam
);
234 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
235 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
236 SendMessageA(afc
->hwndOwner
,
237 RegisterWindowMessageA(ACMHELPMSGSTRINGA
), 0L, 0L);
241 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
242 LOWORD(wParam
), HIWORD(wParam
), lParam
);
247 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
248 SendMessageA(afc
->hwndOwner
,
249 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA
),
252 #if defined(WM_CONTEXTHELP)
254 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
255 SendMessageA(afc
->hwndOwner
,
256 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA
),
261 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
262 hWnd
, msg
, wParam
, lParam
);
268 /***********************************************************************
269 * acmFormatChooseA (MSACM32.@)
271 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
273 return DialogBoxParamA(MSACM_hInstance32
, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID
),
274 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
277 /***********************************************************************
278 * acmFormatChooseW (MSACM32.@)
280 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
282 FIXME("(%p): stub\n", pafmtc
);
283 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
284 return MMSYSERR_ERROR
;
287 /***********************************************************************
288 * acmFormatDetailsA (MSACM32.@)
290 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
293 ACMFORMATDETAILSW afdw
;
296 memset(&afdw
, 0, sizeof(afdw
));
297 afdw
.cbStruct
= sizeof(afdw
);
298 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
299 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
300 afdw
.pwfx
= pafd
->pwfx
;
301 afdw
.cbwfx
= pafd
->cbwfx
;
303 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
304 if (mmr
== MMSYSERR_NOERROR
) {
305 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
306 pafd
->fdwSupport
= afdw
.fdwSupport
;
307 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
308 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
313 /***********************************************************************
314 * acmFormatDetailsW (MSACM32.@)
316 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
319 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
320 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
321 ACMFORMATTAGDETAILSA aftd
;
323 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
325 memset(&aftd
, 0, sizeof(aftd
));
326 aftd
.cbStruct
= sizeof(aftd
);
328 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
330 switch (fdwDetails
) {
331 case ACM_FORMATDETAILSF_FORMAT
:
332 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
333 mmr
= MMSYSERR_INVALPARAM
;
337 PWINE_ACMDRIVERID padid
;
339 mmr
= ACMERR_NOTPOSSIBLE
;
340 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
341 /* should check for codec only */
342 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
343 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
344 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
345 acmDriverClose(had
, 0);
346 if (mmr
== MMSYSERR_NOERROR
) break;
350 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
353 case ACM_FORMATDETAILSF_INDEX
:
354 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
355 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
358 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
359 mmr
= MMSYSERR_INVALFLAG
;
363 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
364 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
365 if (pafd
->pwfx
->wBitsPerSample
) {
366 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
367 pafd
->pwfx
->wBitsPerSample
);
369 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
370 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
371 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
374 TRACE("=> %d\n", mmr
);
378 struct MSACM_FormatEnumWtoA_Instance
{
379 PACMFORMATDETAILSA pafda
;
381 ACMFORMATENUMCBA fnCallback
;
384 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
385 PACMFORMATDETAILSW pafdw
,
389 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
391 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
393 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
394 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
395 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
396 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
397 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
399 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
400 pafei
->dwInstance
, fdwSupport
);
403 /***********************************************************************
404 * acmFormatEnumA (MSACM32.@)
406 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
407 ACMFORMATENUMCBA fnCallback
, DWORD dwInstance
,
410 ACMFORMATDETAILSW afdw
;
411 struct MSACM_FormatEnumWtoA_Instance afei
;
414 return MMSYSERR_INVALPARAM
;
416 if (pafda
->cbStruct
< sizeof(*pafda
))
417 return MMSYSERR_INVALPARAM
;
419 memset(&afdw
, 0, sizeof(afdw
));
420 afdw
.cbStruct
= sizeof(afdw
);
421 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
422 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
423 afdw
.pwfx
= pafda
->pwfx
;
424 afdw
.cbwfx
= pafda
->cbwfx
;
427 afei
.dwInstance
= dwInstance
;
428 afei
.fnCallback
= fnCallback
;
430 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
431 (DWORD
)&afei
, fdwEnum
);
434 /***********************************************************************
435 * acmFormatEnumW (MSACM32.@)
437 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
438 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
439 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
442 ACMFORMATTAGDETAILSW aftd
;
445 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
446 memset(&aftd
, 0, sizeof(aftd
));
447 aftd
.cbStruct
= sizeof(aftd
);
448 aftd
.dwFormatTagIndex
= i
;
449 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
452 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
455 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
456 pafd
->dwFormatIndex
= j
;
457 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
458 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
461 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
462 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
464 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
465 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
467 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
468 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
470 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
471 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
474 /* more checks to be done on fdwEnum */
476 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
479 /* the "formats" used by the filters are also reported */
484 /**********************************************************************/
486 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
487 ACMFORMATENUMCBW fnCallback
, DWORD dwInstance
,
490 PWINE_ACMDRIVERID padid
;
494 TRACE("(%p, %p, %p, %d, %d)\n",
495 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
498 return MMSYSERR_INVALPARAM
;
500 if (pafd
->cbStruct
< sizeof(*pafd
))
501 return MMSYSERR_INVALPARAM
;
503 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
504 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
505 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
506 wfxRef
= *pafd
->pwfx
;
508 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
509 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
510 return MMSYSERR_INVALPARAM
;
512 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
513 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
514 return MMSYSERR_INVALPARAM
;
516 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
|
517 ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
518 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
523 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
524 return MMSYSERR_INVALHANDLE
;
525 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
526 fnCallback
, dwInstance
, fdwEnum
);
527 return MMSYSERR_NOERROR
;
529 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
530 /* should check for codec only */
531 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
532 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
534 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
535 fnCallback
, dwInstance
, fdwEnum
);
536 acmDriverClose(had
, 0);
539 return MMSYSERR_NOERROR
;
542 /***********************************************************************
543 * acmFormatSuggest (MSACM32.@)
545 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
546 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
548 ACMDRVFORMATSUGGEST adfg
;
551 TRACE("(%p, %p, %p, %d, %d)\n",
552 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
554 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
555 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
556 return MMSYSERR_INVALFLAG
;
558 adfg
.cbStruct
= sizeof(adfg
);
559 adfg
.fdwSuggest
= fdwSuggest
;
560 adfg
.pwfxSrc
= pwfxSrc
;
561 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
562 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
563 adfg
.pwfxDst
= pwfxDst
;
564 adfg
.cbwfxDst
= cbwfxDst
;
567 PWINE_ACMDRIVERID padid
;
569 /* MS doc says: ACM finds the best suggestion.
570 * Well, first found will be the "best"
572 mmr
= ACMERR_NOTPOSSIBLE
;
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
)
579 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
580 mmr
= MMSYSERR_NOERROR
;
583 acmDriverClose(had
, 0);
586 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
591 /***********************************************************************
592 * acmFormatTagDetailsA (MSACM32.@)
594 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
597 ACMFORMATTAGDETAILSW aftdw
;
600 memset(&aftdw
, 0, sizeof(aftdw
));
601 aftdw
.cbStruct
= sizeof(aftdw
);
602 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
603 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
605 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
606 if (mmr
== MMSYSERR_NOERROR
) {
607 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
608 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
609 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
610 paftda
->fdwSupport
= aftdw
.fdwSupport
;
611 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
612 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
613 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
618 /***********************************************************************
619 * acmFormatTagDetailsW (MSACM32.@)
621 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
624 PWINE_ACMDRIVERID padid
;
625 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
627 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
629 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
630 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
631 return MMSYSERR_INVALFLAG
;
633 switch (fdwDetails
) {
634 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
636 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
637 /* should check for codec only */
638 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
639 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
640 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
641 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
642 acmDriverClose(had
, 0);
643 if (mmr
== MMSYSERR_NOERROR
) break;
647 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
649 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
650 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
654 case ACM_FORMATTAGDETAILSF_INDEX
:
656 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
658 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
659 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
663 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
665 ACMFORMATTAGDETAILSW tmp
;
666 DWORD ft
= paftd
->dwFormatTag
;
668 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
669 /* should check for codec only */
670 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
671 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
673 memset(&tmp
, 0, sizeof(tmp
));
674 tmp
.cbStruct
= sizeof(tmp
);
675 tmp
.dwFormatTag
= ft
;
677 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
678 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
679 if (mmr
== ACMERR_NOTPOSSIBLE
||
680 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
682 mmr
= MMSYSERR_NOERROR
;
685 acmDriverClose(had
, 0);
689 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
694 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
695 mmr
= MMSYSERR_ERROR
;
698 if (mmr
== MMSYSERR_NOERROR
&&
699 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
700 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
701 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
706 struct MSACM_FormatTagEnumWtoA_Instance
{
707 PACMFORMATTAGDETAILSA paftda
;
709 ACMFORMATTAGENUMCBA fnCallback
;
712 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
713 PACMFORMATTAGDETAILSW paftdw
,
717 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
719 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
721 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
722 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
723 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
724 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
725 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
726 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
727 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
729 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
730 paftei
->dwInstance
, fdwSupport
);
733 /***********************************************************************
734 * acmFormatTagEnumA (MSACM32.@)
736 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
737 ACMFORMATTAGENUMCBA fnCallback
, DWORD dwInstance
,
740 ACMFORMATTAGDETAILSW aftdw
;
741 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
744 return MMSYSERR_INVALPARAM
;
746 if (paftda
->cbStruct
< sizeof(*paftda
))
747 return MMSYSERR_INVALPARAM
;
750 return MMSYSERR_INVALFLAG
;
752 memset(&aftdw
, 0, sizeof(aftdw
));
753 aftdw
.cbStruct
= sizeof(aftdw
);
754 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
755 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
757 aftei
.paftda
= paftda
;
758 aftei
.dwInstance
= dwInstance
;
759 aftei
.fnCallback
= fnCallback
;
761 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
762 (DWORD
)&aftei
, fdwEnum
);
765 /***********************************************************************
766 * acmFormatTagEnumW (MSACM32.@)
768 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
769 ACMFORMATTAGENUMCBW fnCallback
, DWORD dwInstance
,
772 PWINE_ACMDRIVERID padid
;
774 BOOL bPcmDone
= FALSE
;
776 TRACE("(%p, %p, %p, %d, %d)\n",
777 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
780 return MMSYSERR_INVALPARAM
;
782 if (paftd
->cbStruct
< sizeof(*paftd
))
783 return MMSYSERR_INVALPARAM
;
786 return MMSYSERR_INVALFLAG
;
788 /* (WS) MSDN info page says that if had != 0, then we should find
789 * the specific driver to get its tags from. Therefore I'm removing
790 * the FIXME call and adding a search block below. It also seems
791 * that the lack of this functionality was the responsible for
792 * codecs to be multiply and incorrectly listed.
795 /* if (had) FIXME("had != NULL, not supported\n"); */
799 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
800 return MMSYSERR_INVALHANDLE
;
802 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
803 paftd
->dwFormatTagIndex
= i
;
804 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
805 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
806 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
807 if (paftd
->szFormatTag
[0] == 0)
808 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
809 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
810 /* (WS) I'm preserving this PCM hack since it seems to be
811 * correct. Please notice this block was borrowed from
814 if (bPcmDone
) continue;
817 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
818 return MMSYSERR_NOERROR
;
824 /* if had==0 then search for the first suitable driver */
826 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
827 /* should check for codec only */
828 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
829 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
830 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
831 paftd
->dwFormatTagIndex
= i
;
832 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
833 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
834 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
835 if (paftd
->szFormatTag
[0] == 0)
836 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
837 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
838 /* FIXME (EPP): I'm not sure this is the correct
839 * algorithm (should make more sense to apply the same
840 * for all already loaded formats, but this will do
843 if (bPcmDone
) continue;
846 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
847 acmDriverClose(had
, 0);
848 return MMSYSERR_NOERROR
;
853 acmDriverClose(had
, 0);
856 return MMSYSERR_NOERROR
;