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
24 #define WIN32_NO_STATUS
29 //#include "winbase.h"
31 //#include "winerror.h"
34 #include <wine/unicode.h>
35 #include <wine/debug.h>
36 //#include "mmsystem.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msacm
);
44 static PACMFORMATCHOOSEA afc
;
46 struct MSACM_FillFormatData
{
48 #define WINE_ACMFF_TAG 0
49 #define WINE_ACMFF_FORMAT 1
50 #define WINE_ACMFF_WFX 2
52 char szFormatTag
[ACMFORMATTAGDETAILS_FORMATTAG_CHARS
];
53 PACMFORMATCHOOSEA afc
;
57 static BOOL CALLBACK
MSACM_FillFormatTagsCB(HACMDRIVERID hadid
,
58 PACMFORMATTAGDETAILSA paftd
,
62 struct MSACM_FillFormatData
* affd
= (struct MSACM_FillFormatData
*)dwInstance
;
66 if (SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
67 CB_FINDSTRINGEXACT
, -1,
68 (LPARAM
)paftd
->szFormatTag
) == CB_ERR
)
69 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
70 CB_ADDSTRING
, 0, (LPARAM
)paftd
->szFormatTag
);
72 case WINE_ACMFF_FORMAT
:
73 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
76 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
77 ACMFORMATDETAILSA afd
;
80 char buffer
[ACMFORMATDETAILS_FORMAT_CHARS
+16];
82 afd
.cbStruct
= sizeof(afd
);
83 afd
.dwFormatTag
= paftd
->dwFormatTag
;
84 afd
.pwfx
= HeapAlloc(MSACM_hHeap
, 0, paftd
->cbFormatSize
);
85 if (!afd
.pwfx
) return FALSE
;
86 afd
.pwfx
->wFormatTag
= paftd
->dwFormatTag
;
87 afd
.pwfx
->cbSize
= paftd
->cbFormatSize
;
88 afd
.cbwfx
= paftd
->cbFormatSize
;
90 for (i
= 0; i
< paftd
->cStandardFormats
; i
++) {
91 afd
.dwFormatIndex
= i
;
92 mmr
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
93 if (mmr
== MMSYSERR_NOERROR
) {
94 lstrcpynA(buffer
, afd
.szFormat
, ACMFORMATTAGDETAILS_FORMATTAG_CHARS
+ 1);
96 memset(buffer
+len
, ' ', ACMFORMATTAGDETAILS_FORMATTAG_CHARS
- len
);
97 wsprintfA(buffer
+ ACMFORMATTAGDETAILS_FORMATTAG_CHARS
,
99 (afd
.pwfx
->nAvgBytesPerSec
+ 512) / 1024);
100 SendDlgItemMessageA(affd
->hWnd
,
101 IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
102 CB_ADDSTRING
, 0, (LPARAM
)buffer
);
105 acmDriverClose(had
, 0);
106 SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
108 HeapFree(MSACM_hHeap
, 0, afd
.pwfx
);
113 if (strcmp(affd
->szFormatTag
, paftd
->szFormatTag
) == 0) {
116 if (acmDriverOpen(&had
, hadid
, 0) == MMSYSERR_NOERROR
) {
117 ACMFORMATDETAILSA afd
;
119 afd
.cbStruct
= sizeof(afd
);
120 afd
.dwFormatTag
= paftd
->dwFormatTag
;
121 afd
.pwfx
= affd
->afc
->pwfx
;
122 afd
.cbwfx
= affd
->afc
->cbwfx
;
124 afd
.dwFormatIndex
= SendDlgItemMessageA(affd
->hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
,
126 affd
->ret
= acmFormatDetailsA(had
, &afd
, ACM_FORMATDETAILSF_INDEX
);
127 acmDriverClose(had
, 0);
133 FIXME("Unknown mode (%d)\n", affd
->mode
);
139 static BOOL
MSACM_FillFormatTags(HWND hWnd
)
141 ACMFORMATTAGDETAILSA aftd
;
142 struct MSACM_FillFormatData affd
;
144 memset(&aftd
, 0, sizeof(aftd
));
145 aftd
.cbStruct
= sizeof(aftd
);
148 affd
.mode
= WINE_ACMFF_TAG
;
150 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
151 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
, CB_SETCURSEL
, 0, 0);
155 static BOOL
MSACM_FillFormat(HWND hWnd
)
157 ACMFORMATTAGDETAILSA aftd
;
158 struct MSACM_FillFormatData affd
;
160 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_RESETCONTENT
, 0, 0);
162 memset(&aftd
, 0, sizeof(aftd
));
163 aftd
.cbStruct
= sizeof(aftd
);
166 affd
.mode
= WINE_ACMFF_FORMAT
;
167 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
169 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
171 (LPARAM
)affd
.szFormatTag
);
173 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
174 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMAT
, CB_SETCURSEL
, 0, 0);
178 static MMRESULT
MSACM_GetWFX(HWND hWnd
, PACMFORMATCHOOSEA afc
)
180 ACMFORMATTAGDETAILSA aftd
;
181 struct MSACM_FillFormatData affd
;
183 memset(&aftd
, 0, sizeof(aftd
));
184 aftd
.cbStruct
= sizeof(aftd
);
187 affd
.mode
= WINE_ACMFF_WFX
;
189 affd
.ret
= MMSYSERR_NOERROR
;
190 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
192 SendDlgItemMessageA(hWnd
, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
,
194 (LPARAM
)affd
.szFormatTag
);
196 acmFormatTagEnumA(NULL
, &aftd
, MSACM_FillFormatTagsCB
, (DWORD_PTR
)&affd
, 0);
200 static INT_PTR CALLBACK
FormatChooseDlgProc(HWND hWnd
, UINT msg
,
201 WPARAM wParam
, LPARAM lParam
)
204 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
208 afc
= (PACMFORMATCHOOSEA
)lParam
;
209 MSACM_FillFormatTags(hWnd
);
210 MSACM_FillFormat(hWnd
);
211 if ((afc
->fdwStyle
& ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
|
212 ACMFORMATCHOOSE_STYLEF_SHOWHELP
)) != 0)
213 FIXME("Unsupported style %08x\n", ((PACMFORMATCHOOSEA
)lParam
)->fdwStyle
);
214 if (!(afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
))
215 ShowWindow(GetDlgItem(hWnd
, IDD_ACMFORMATCHOOSE_BTN_HELP
), SW_HIDE
);
219 switch (LOWORD(wParam
)) {
221 EndDialog(hWnd
, MSACM_GetWFX(hWnd
, afc
));
224 EndDialog(hWnd
, ACMERR_CANCELED
);
226 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG
:
227 switch (HIWORD(wParam
)) {
229 MSACM_FillFormat(hWnd
);
232 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n",
233 HIWORD(wParam
), lParam
);
237 case IDD_ACMFORMATCHOOSE_BTN_HELP
:
238 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_SHOWHELP
)
239 SendMessageA(afc
->hwndOwner
,
240 RegisterWindowMessageA(ACMHELPMSGSTRINGA
), 0L, 0L);
244 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n",
245 LOWORD(wParam
), HIWORD(wParam
), lParam
);
250 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
251 SendMessageA(afc
->hwndOwner
,
252 RegisterWindowMessageA(ACMHELPMSGCONTEXTMENUA
),
255 #if defined(WM_CONTEXTHELP)
257 if (afc
->fdwStyle
& ACMFORMATCHOOSE_STYLEF_CONTEXTHELP
)
258 SendMessageA(afc
->hwndOwner
,
259 RegisterWindowMessageA(ACMHELPMSGCONTEXTHELPA
),
264 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n",
265 hWnd
, msg
, wParam
, lParam
);
271 /***********************************************************************
272 * acmFormatChooseA (MSACM32.@)
274 MMRESULT WINAPI
acmFormatChooseA(PACMFORMATCHOOSEA pafmtc
)
276 return DialogBoxParamA(MSACM_hInstance32
, MAKEINTRESOURCEA(DLG_ACMFORMATCHOOSE_ID
),
277 pafmtc
->hwndOwner
, FormatChooseDlgProc
, (LPARAM
)pafmtc
);
280 /***********************************************************************
281 * acmFormatChooseW (MSACM32.@)
283 MMRESULT WINAPI
acmFormatChooseW(PACMFORMATCHOOSEW pafmtc
)
285 FIXME("(%p): stub\n", pafmtc
);
286 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
287 return MMSYSERR_ERROR
;
290 /***********************************************************************
291 * acmFormatDetailsA (MSACM32.@)
293 MMRESULT WINAPI
acmFormatDetailsA(HACMDRIVER had
, PACMFORMATDETAILSA pafd
,
296 ACMFORMATDETAILSW afdw
;
299 memset(&afdw
, 0, sizeof(afdw
));
300 afdw
.cbStruct
= sizeof(afdw
);
301 afdw
.dwFormatIndex
= pafd
->dwFormatIndex
;
302 afdw
.dwFormatTag
= pafd
->dwFormatTag
;
303 afdw
.pwfx
= pafd
->pwfx
;
304 afdw
.cbwfx
= pafd
->cbwfx
;
306 mmr
= acmFormatDetailsW(had
, &afdw
, fdwDetails
);
307 if (mmr
== MMSYSERR_NOERROR
) {
308 pafd
->dwFormatTag
= afdw
.dwFormatTag
;
309 pafd
->fdwSupport
= afdw
.fdwSupport
;
310 WideCharToMultiByte( CP_ACP
, 0, afdw
.szFormat
, -1,
311 pafd
->szFormat
, sizeof(pafd
->szFormat
), NULL
, NULL
);
316 /***********************************************************************
317 * acmFormatDetailsW (MSACM32.@)
319 MMRESULT WINAPI
acmFormatDetailsW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
, DWORD fdwDetails
)
322 static const WCHAR fmt1
[] = {'%','d',' ','H','z',0};
323 static const WCHAR fmt2
[] = {';',' ','%','d',' ','b','i','t','s',0};
324 ACMFORMATTAGDETAILSA aftd
;
326 TRACE("(%p, %p, %d)\n", had
, pafd
, fdwDetails
);
328 memset(&aftd
, 0, sizeof(aftd
));
329 aftd
.cbStruct
= sizeof(aftd
);
331 if (pafd
->cbStruct
< sizeof(*pafd
)) return MMSYSERR_INVALPARAM
;
333 switch (fdwDetails
) {
334 case ACM_FORMATDETAILSF_FORMAT
:
335 if (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
) {
336 mmr
= MMSYSERR_INVALPARAM
;
340 PWINE_ACMDRIVERID padid
;
342 mmr
= ACMERR_NOTPOSSIBLE
;
343 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
344 /* should check for codec only */
345 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
346 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
347 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
348 acmDriverClose(had
, 0);
349 if (mmr
== MMSYSERR_NOERROR
) break;
353 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
356 case ACM_FORMATDETAILSF_INDEX
:
357 /* should check pafd->dwFormatIndex < aftd->cStandardFormats */
358 mmr
= MSACM_Message(had
, ACMDM_FORMAT_DETAILS
, (LPARAM
)pafd
, fdwDetails
);
361 WARN("Unknown fdwDetails %08x\n", fdwDetails
);
362 mmr
= MMSYSERR_INVALFLAG
;
366 if (mmr
== MMSYSERR_NOERROR
&& pafd
->szFormat
[0] == 0) {
367 wsprintfW(pafd
->szFormat
, fmt1
, pafd
->pwfx
->nSamplesPerSec
);
368 if (pafd
->pwfx
->wBitsPerSample
) {
369 wsprintfW(pafd
->szFormat
+ lstrlenW(pafd
->szFormat
), fmt2
,
370 pafd
->pwfx
->wBitsPerSample
);
372 MultiByteToWideChar( CP_ACP
, 0, (pafd
->pwfx
->nChannels
== 1) ? "; Mono" : "; Stereo", -1,
373 pafd
->szFormat
+ strlenW(pafd
->szFormat
),
374 sizeof(pafd
->szFormat
)/sizeof(WCHAR
) - strlenW(pafd
->szFormat
) );
377 TRACE("=> %d\n", mmr
);
381 struct MSACM_FormatEnumWtoA_Instance
{
382 PACMFORMATDETAILSA pafda
;
383 DWORD_PTR dwInstance
;
384 ACMFORMATENUMCBA fnCallback
;
387 static BOOL CALLBACK
MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid
,
388 PACMFORMATDETAILSW pafdw
,
389 DWORD_PTR dwInstance
,
392 struct MSACM_FormatEnumWtoA_Instance
* pafei
;
394 pafei
= (struct MSACM_FormatEnumWtoA_Instance
*)dwInstance
;
396 pafei
->pafda
->dwFormatIndex
= pafdw
->dwFormatIndex
;
397 pafei
->pafda
->dwFormatTag
= pafdw
->dwFormatTag
;
398 pafei
->pafda
->fdwSupport
= pafdw
->fdwSupport
;
399 WideCharToMultiByte( CP_ACP
, 0, pafdw
->szFormat
, -1,
400 pafei
->pafda
->szFormat
, sizeof(pafei
->pafda
->szFormat
), NULL
, NULL
);
402 return (pafei
->fnCallback
)(hadid
, pafei
->pafda
,
403 pafei
->dwInstance
, fdwSupport
);
406 /***********************************************************************
407 * acmFormatEnumA (MSACM32.@)
409 MMRESULT WINAPI
acmFormatEnumA(HACMDRIVER had
, PACMFORMATDETAILSA pafda
,
410 ACMFORMATENUMCBA fnCallback
,
411 DWORD_PTR dwInstance
, DWORD fdwEnum
)
413 ACMFORMATDETAILSW afdw
;
414 struct MSACM_FormatEnumWtoA_Instance afei
;
417 return MMSYSERR_INVALPARAM
;
419 if (pafda
->cbStruct
< sizeof(*pafda
))
420 return MMSYSERR_INVALPARAM
;
422 memset(&afdw
, 0, sizeof(afdw
));
423 afdw
.cbStruct
= sizeof(afdw
);
424 afdw
.dwFormatIndex
= pafda
->dwFormatIndex
;
425 afdw
.dwFormatTag
= pafda
->dwFormatTag
;
426 afdw
.pwfx
= pafda
->pwfx
;
427 afdw
.cbwfx
= pafda
->cbwfx
;
430 afei
.dwInstance
= dwInstance
;
431 afei
.fnCallback
= fnCallback
;
433 return acmFormatEnumW(had
, &afdw
, MSACM_FormatEnumCallbackWtoA
,
434 (DWORD_PTR
)&afei
, fdwEnum
);
437 /***********************************************************************
438 * acmFormatEnumW (MSACM32.@)
440 static BOOL
MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid
, HACMDRIVER had
,
441 PACMFORMATDETAILSW pafd
, PWAVEFORMATEX pwfxRef
,
442 ACMFORMATENUMCBW fnCallback
,
443 DWORD_PTR dwInstance
, DWORD fdwEnum
)
445 ACMFORMATTAGDETAILSW aftd
;
448 if (fdwEnum
& ACM_FORMATENUMF_SUGGEST
) {
450 ACMDRVFORMATSUGGEST adfs
;
451 pafd
->dwFormatIndex
= 0;
452 memset(&aftd
, 0, sizeof(aftd
));
453 aftd
.cbStruct
= sizeof(aftd
);
454 memset(&adfs
, 0, sizeof(adfs
));
455 adfs
.cbStruct
= sizeof(adfs
);
457 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
458 aftd
.dwFormatTag
= i
;
459 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
460 pafd
->pwfx
->wFormatTag
= pafd
->dwFormatTag
;
462 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
465 adfs
.cbwfxSrc
= aftd
.cbFormatSize
;
466 adfs
.cbwfxDst
= aftd
.cbFormatSize
;
467 adfs
.pwfxSrc
= pwfxRef
;
468 adfs
.pwfxDst
= pafd
->pwfx
;
469 pafd
->fdwSupport
= padid
->fdwSupport
;
471 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
472 aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
475 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
476 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
479 hdrvr
= OpenDriver(padid
->pszFileName
,0,0);
480 SendDriverMessage(hdrvr
,ACMDM_FORMAT_SUGGEST
,(LPARAM
)&adfs
,(fdwEnum
& 0x000000FFL
));
482 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_FORMAT
) != MMSYSERR_NOERROR
)
485 pafd
->cbwfx
= sizeof(*(pafd
->pwfx
));
487 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
491 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
492 memset(&aftd
, 0, sizeof(aftd
));
493 aftd
.cbStruct
= sizeof(aftd
);
494 aftd
.dwFormatTagIndex
= i
;
495 if (acmFormatTagDetailsW(had
, &aftd
, ACM_FORMATTAGDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
498 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) && aftd
.dwFormatTag
!= pwfxRef
->wFormatTag
)
501 for (j
= 0; j
< aftd
.cStandardFormats
; j
++) {
502 pafd
->dwFormatIndex
= j
;
503 pafd
->dwFormatTag
= aftd
.dwFormatTag
;
504 if (acmFormatDetailsW(had
, pafd
, ACM_FORMATDETAILSF_INDEX
) != MMSYSERR_NOERROR
)
507 if ((fdwEnum
& ACM_FORMATENUMF_NCHANNELS
) &&
508 pafd
->pwfx
->nChannels
!= pwfxRef
->nChannels
)
510 if ((fdwEnum
& ACM_FORMATENUMF_NSAMPLESPERSEC
) &&
511 pafd
->pwfx
->nSamplesPerSec
!= pwfxRef
->nSamplesPerSec
)
513 if ((fdwEnum
& ACM_FORMATENUMF_WBITSPERSAMPLE
) &&
514 pafd
->pwfx
->wBitsPerSample
!= pwfxRef
->wBitsPerSample
)
516 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
517 !(pafd
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_HARDWARE
))
520 /* more checks to be done on fdwEnum */
522 if (!(fnCallback
)((HACMDRIVERID
)padid
, pafd
, dwInstance
, padid
->fdwSupport
))
525 /* the "formats" used by the filters are also reported */
531 /**********************************************************************/
533 MMRESULT WINAPI
acmFormatEnumW(HACMDRIVER had
, PACMFORMATDETAILSW pafd
,
534 ACMFORMATENUMCBW fnCallback
,
535 DWORD_PTR dwInstance
, DWORD fdwEnum
)
537 PWINE_ACMDRIVERID padid
;
541 TRACE("(%p, %p, %p, %ld, %d)\n",
542 had
, pafd
, fnCallback
, dwInstance
, fdwEnum
);
545 return MMSYSERR_INVALPARAM
;
547 if (pafd
->cbStruct
< sizeof(*pafd
))
548 return MMSYSERR_INVALPARAM
;
550 if (fdwEnum
& (ACM_FORMATENUMF_WFORMATTAG
|ACM_FORMATENUMF_NCHANNELS
|
551 ACM_FORMATENUMF_NSAMPLESPERSEC
|ACM_FORMATENUMF_WBITSPERSAMPLE
|
552 ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_SUGGEST
))
553 wfxRef
= *pafd
->pwfx
;
555 if ((fdwEnum
& ACM_FORMATENUMF_HARDWARE
) &&
556 !(fdwEnum
& (ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
)))
557 return MMSYSERR_INVALPARAM
;
559 if ((fdwEnum
& ACM_FORMATENUMF_WFORMATTAG
) &&
560 (pafd
->dwFormatTag
!= pafd
->pwfx
->wFormatTag
))
561 return MMSYSERR_INVALPARAM
;
563 if (fdwEnum
& (ACM_FORMATENUMF_CONVERT
|ACM_FORMATENUMF_INPUT
|ACM_FORMATENUMF_OUTPUT
))
564 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum
);
569 if (acmDriverID((HACMOBJ
)had
, &hadid
, 0) != MMSYSERR_NOERROR
)
570 return MMSYSERR_INVALHANDLE
;
571 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid
), had
, pafd
, &wfxRef
,
572 fnCallback
, dwInstance
, fdwEnum
);
573 return MMSYSERR_NOERROR
;
575 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
576 /* should check for codec only */
577 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
578 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
580 ret
= MSACM_FormatEnumHelper(padid
, had
, pafd
, &wfxRef
,
581 fnCallback
, dwInstance
, fdwEnum
);
582 acmDriverClose(had
, 0);
585 return MMSYSERR_NOERROR
;
588 /***********************************************************************
589 * acmFormatSuggest (MSACM32.@)
591 MMRESULT WINAPI
acmFormatSuggest(HACMDRIVER had
, PWAVEFORMATEX pwfxSrc
,
592 PWAVEFORMATEX pwfxDst
, DWORD cbwfxDst
, DWORD fdwSuggest
)
594 ACMDRVFORMATSUGGEST adfg
;
597 TRACE("(%p, %p, %p, %d, %d)\n",
598 had
, pwfxSrc
, pwfxDst
, cbwfxDst
, fdwSuggest
);
600 if (fdwSuggest
& ~(ACM_FORMATSUGGESTF_NCHANNELS
|ACM_FORMATSUGGESTF_NSAMPLESPERSEC
|
601 ACM_FORMATSUGGESTF_WBITSPERSAMPLE
|ACM_FORMATSUGGESTF_WFORMATTAG
))
602 return MMSYSERR_INVALFLAG
;
604 adfg
.cbStruct
= sizeof(adfg
);
605 adfg
.fdwSuggest
= fdwSuggest
;
606 adfg
.pwfxSrc
= pwfxSrc
;
607 adfg
.cbwfxSrc
= (pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
) ?
608 sizeof(WAVEFORMATEX
) : (sizeof(WAVEFORMATEX
) + pwfxSrc
->cbSize
);
609 adfg
.pwfxDst
= pwfxDst
;
610 adfg
.cbwfxDst
= cbwfxDst
;
613 PWINE_ACMDRIVERID padid
;
615 /* MS doc says: ACM finds the best suggestion.
616 * Well, first found will be the "best"
618 mmr
= ACMERR_NOTPOSSIBLE
;
619 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
620 /* should check for codec only */
621 if ((padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) ||
622 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) != MMSYSERR_NOERROR
)
625 if (MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L) == MMSYSERR_NOERROR
) {
626 mmr
= MMSYSERR_NOERROR
;
629 acmDriverClose(had
, 0);
632 mmr
= MSACM_Message(had
, ACMDM_FORMAT_SUGGEST
, (LPARAM
)&adfg
, 0L);
637 /***********************************************************************
638 * acmFormatTagDetailsA (MSACM32.@)
640 MMRESULT WINAPI
acmFormatTagDetailsA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
643 ACMFORMATTAGDETAILSW aftdw
;
646 memset(&aftdw
, 0, sizeof(aftdw
));
647 aftdw
.cbStruct
= sizeof(aftdw
);
648 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
649 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
651 mmr
= acmFormatTagDetailsW(had
, &aftdw
, fdwDetails
);
652 if (mmr
== MMSYSERR_NOERROR
) {
653 paftda
->dwFormatTag
= aftdw
.dwFormatTag
;
654 paftda
->dwFormatTagIndex
= aftdw
.dwFormatTagIndex
;
655 paftda
->cbFormatSize
= aftdw
.cbFormatSize
;
656 paftda
->fdwSupport
= aftdw
.fdwSupport
;
657 paftda
->cStandardFormats
= aftdw
.cStandardFormats
;
658 WideCharToMultiByte( CP_ACP
, 0, aftdw
.szFormatTag
, -1, paftda
->szFormatTag
,
659 sizeof(paftda
->szFormatTag
), NULL
, NULL
);
664 /***********************************************************************
665 * acmFormatTagDetailsW (MSACM32.@)
667 MMRESULT WINAPI
acmFormatTagDetailsW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
670 PWINE_ACMDRIVERID padid
;
671 MMRESULT mmr
= ACMERR_NOTPOSSIBLE
;
673 TRACE("(%p, %p, %d)\n", had
, paftd
, fdwDetails
);
675 if (fdwDetails
& ~(ACM_FORMATTAGDETAILSF_FORMATTAG
|ACM_FORMATTAGDETAILSF_INDEX
|
676 ACM_FORMATTAGDETAILSF_LARGESTSIZE
))
677 return MMSYSERR_INVALFLAG
;
679 switch (fdwDetails
) {
680 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
682 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
683 /* should check for codec only */
684 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
685 MSACM_FindFormatTagInCache(padid
, paftd
->dwFormatTag
, NULL
) &&
686 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
687 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
688 acmDriverClose(had
, 0);
689 if (mmr
== MMSYSERR_NOERROR
) break;
693 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
695 if (pad
&& MSACM_FindFormatTagInCache(pad
->obj
.pACMDriverID
, paftd
->dwFormatTag
, NULL
))
696 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
700 case ACM_FORMATTAGDETAILSF_INDEX
:
702 PWINE_ACMDRIVER pad
= MSACM_GetDriver(had
);
704 if (pad
&& paftd
->dwFormatTagIndex
< pad
->obj
.pACMDriverID
->cFormatTags
)
705 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
709 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
711 ACMFORMATTAGDETAILSW tmp
;
712 DWORD ft
= paftd
->dwFormatTag
;
714 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
715 /* should check for codec only */
716 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
717 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == 0) {
719 memset(&tmp
, 0, sizeof(tmp
));
720 tmp
.cbStruct
= sizeof(tmp
);
721 tmp
.dwFormatTag
= ft
;
723 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
724 (LPARAM
)&tmp
, fdwDetails
) == MMSYSERR_NOERROR
) {
725 if (mmr
== ACMERR_NOTPOSSIBLE
||
726 paftd
->cbFormatSize
< tmp
.cbFormatSize
) {
728 mmr
= MMSYSERR_NOERROR
;
731 acmDriverClose(had
, 0);
735 mmr
= MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
, (LPARAM
)paftd
, fdwDetails
);
740 WARN("Unsupported fdwDetails=%08x\n", fdwDetails
);
741 mmr
= MMSYSERR_ERROR
;
744 if (mmr
== MMSYSERR_NOERROR
&&
745 paftd
->dwFormatTag
== WAVE_FORMAT_PCM
&& paftd
->szFormatTag
[0] == 0)
746 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
747 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
752 struct MSACM_FormatTagEnumWtoA_Instance
{
753 PACMFORMATTAGDETAILSA paftda
;
754 DWORD_PTR dwInstance
;
755 ACMFORMATTAGENUMCBA fnCallback
;
758 static BOOL CALLBACK
MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid
,
759 PACMFORMATTAGDETAILSW paftdw
,
760 DWORD_PTR dwInstance
,
763 struct MSACM_FormatTagEnumWtoA_Instance
* paftei
;
765 paftei
= (struct MSACM_FormatTagEnumWtoA_Instance
*)dwInstance
;
767 paftei
->paftda
->dwFormatTagIndex
= paftdw
->dwFormatTagIndex
;
768 paftei
->paftda
->dwFormatTag
= paftdw
->dwFormatTag
;
769 paftei
->paftda
->cbFormatSize
= paftdw
->cbFormatSize
;
770 paftei
->paftda
->fdwSupport
= paftdw
->fdwSupport
;
771 paftei
->paftda
->cStandardFormats
= paftdw
->cStandardFormats
;
772 WideCharToMultiByte( CP_ACP
, 0, paftdw
->szFormatTag
, -1, paftei
->paftda
->szFormatTag
,
773 sizeof(paftei
->paftda
->szFormatTag
), NULL
, NULL
);
775 return (paftei
->fnCallback
)(hadid
, paftei
->paftda
,
776 paftei
->dwInstance
, fdwSupport
);
779 /***********************************************************************
780 * acmFormatTagEnumA (MSACM32.@)
782 MMRESULT WINAPI
acmFormatTagEnumA(HACMDRIVER had
, PACMFORMATTAGDETAILSA paftda
,
783 ACMFORMATTAGENUMCBA fnCallback
,
784 DWORD_PTR dwInstance
, DWORD fdwEnum
)
786 ACMFORMATTAGDETAILSW aftdw
;
787 struct MSACM_FormatTagEnumWtoA_Instance aftei
;
790 return MMSYSERR_INVALPARAM
;
792 if (paftda
->cbStruct
< sizeof(*paftda
))
793 return MMSYSERR_INVALPARAM
;
796 return MMSYSERR_INVALFLAG
;
798 memset(&aftdw
, 0, sizeof(aftdw
));
799 aftdw
.cbStruct
= sizeof(aftdw
);
800 aftdw
.dwFormatTagIndex
= paftda
->dwFormatTagIndex
;
801 aftdw
.dwFormatTag
= paftda
->dwFormatTag
;
803 aftei
.paftda
= paftda
;
804 aftei
.dwInstance
= dwInstance
;
805 aftei
.fnCallback
= fnCallback
;
807 return acmFormatTagEnumW(had
, &aftdw
, MSACM_FormatTagEnumCallbackWtoA
,
808 (DWORD_PTR
)&aftei
, fdwEnum
);
811 /***********************************************************************
812 * acmFormatTagEnumW (MSACM32.@)
814 MMRESULT WINAPI
acmFormatTagEnumW(HACMDRIVER had
, PACMFORMATTAGDETAILSW paftd
,
815 ACMFORMATTAGENUMCBW fnCallback
,
816 DWORD_PTR dwInstance
, DWORD fdwEnum
)
818 PWINE_ACMDRIVERID padid
;
820 BOOL bPcmDone
= FALSE
;
822 TRACE("(%p, %p, %p, %ld, %d)\n",
823 had
, paftd
, fnCallback
, dwInstance
, fdwEnum
);
826 return MMSYSERR_INVALPARAM
;
828 if (paftd
->cbStruct
< sizeof(*paftd
))
829 return MMSYSERR_INVALPARAM
;
832 return MMSYSERR_INVALFLAG
;
834 /* (WS) MSDN info page says that if had != 0, then we should find
835 * the specific driver to get its tags from. Therefore I'm removing
836 * the FIXME call and adding a search block below. It also seems
837 * that the lack of this functionality was the responsible for
838 * codecs to be multiply and incorrectly listed.
841 /* if (had) FIXME("had != NULL, not supported\n"); */
845 if (acmDriverID((HACMOBJ
)had
, (HACMDRIVERID
*)&padid
, 0) != MMSYSERR_NOERROR
)
846 return MMSYSERR_INVALHANDLE
;
848 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
849 paftd
->dwFormatTagIndex
= i
;
850 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
851 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
852 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
853 if (paftd
->szFormatTag
[0] == 0)
854 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
855 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
856 /* (WS) I'm preserving this PCM hack since it seems to be
857 * correct. Please notice this block was borrowed from
860 if (bPcmDone
) continue;
863 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
))
864 return MMSYSERR_NOERROR
;
870 /* if had==0 then search for the first suitable driver */
872 for (padid
= MSACM_pFirstACMDriverID
; padid
; padid
= padid
->pNextACMDriverID
) {
873 /* should check for codec only */
874 if (!(padid
->fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_DISABLED
) &&
875 acmDriverOpen(&had
, (HACMDRIVERID
)padid
, 0) == MMSYSERR_NOERROR
) {
876 for (i
= 0; i
< padid
->cFormatTags
; i
++) {
877 paftd
->dwFormatTagIndex
= i
;
878 if (MSACM_Message(had
, ACMDM_FORMATTAG_DETAILS
,
879 (LPARAM
)paftd
, ACM_FORMATTAGDETAILSF_INDEX
) == MMSYSERR_NOERROR
) {
880 if (paftd
->dwFormatTag
== WAVE_FORMAT_PCM
) {
881 if (paftd
->szFormatTag
[0] == 0)
882 MultiByteToWideChar( CP_ACP
, 0, "PCM", -1, paftd
->szFormatTag
,
883 sizeof(paftd
->szFormatTag
)/sizeof(WCHAR
) );
884 /* FIXME (EPP): I'm not sure this is the correct
885 * algorithm (should make more sense to apply the same
886 * for all already loaded formats, but this will do
889 if (bPcmDone
) continue;
892 if (!(fnCallback
)((HACMDRIVERID
)padid
, paftd
, dwInstance
, padid
->fdwSupport
)) {
893 acmDriverClose(had
, 0);
894 return MMSYSERR_NOERROR
;
898 acmDriverClose(had
, 0);
902 return MMSYSERR_NOERROR
;