1 /* 2 * MSACM32 library 3 * 4 * Copyright 1998 Patrik Stridvall 5 * 2000 Eric Pouech 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <string.h> 24 #include "windef.h" 25 #include "winbase.h" 26 #include "winnls.h" 27 #include "winerror.h" 28 #include "wingdi.h" 29 #include "winuser.h" 30 #include "wine/unicode.h" 31 #include "wine/debug.h" 32 #include "mmsystem.h" 33 #include "mmreg.h" 34 #include "msacm.h" 35 #include "msacmdrv.h" 36 #include "wineacm.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(msacm); 39 40 struct MSACM_FillFormatData { 41 HWND hWnd; 42 #define WINE_ACMFF_TAG 0 43 #define WINE_ACMFF_FORMAT 1 44 #define WINE_ACMFF_WFX 2 45 int mode; 46 WCHAR szFormatTag[ACMFORMATTAGDETAILS_FORMATTAG_CHARS]; 47 PACMFORMATCHOOSEW afc; 48 DWORD ret; 49 }; 50 51 static BOOL CALLBACK MSACM_FillFormatTagsCB(HACMDRIVERID hadid, 52 PACMFORMATTAGDETAILSW paftd, 53 DWORD_PTR dwInstance, 54 DWORD fdwSupport) 55 { 56 struct MSACM_FillFormatData* affd = (struct MSACM_FillFormatData*)dwInstance; 57 58 switch (affd->mode) { 59 case WINE_ACMFF_TAG: 60 if (paftd->cStandardFormats > 0) 61 { 62 if (SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 63 CB_FINDSTRINGEXACT, -1, 64 (LPARAM)paftd->szFormatTag) == CB_ERR) 65 { 66 int index = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 67 CB_ADDSTRING, 0, (LPARAM)paftd->szFormatTag); 68 if (((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) && 69 (paftd->dwFormatTag == affd->afc->pwfx->wFormatTag)) || 70 (!(affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) && 71 (paftd->dwFormatTag == WAVE_FORMAT_PCM))) 72 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 73 CB_SETCURSEL, index, 0); 74 } 75 } 76 break; 77 case WINE_ACMFF_FORMAT: 78 if (strcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) { 79 HACMDRIVER had; 80 81 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) { 82 ACMFORMATDETAILSW afd = {0}; 83 unsigned int i, len; 84 MMRESULT mmr; 85 WCHAR buffer[ACMFORMATDETAILS_FORMAT_CHARS+16]; 86 87 afd.cbStruct = sizeof(afd); 88 afd.dwFormatTag = paftd->dwFormatTag; 89 afd.pwfx = HeapAlloc(MSACM_hHeap, 0, paftd->cbFormatSize); 90 if (!afd.pwfx) return FALSE; 91 afd.pwfx->wFormatTag = paftd->dwFormatTag; 92 if (paftd->dwFormatTag != WAVE_FORMAT_PCM) 93 afd.pwfx->cbSize = paftd->cbFormatSize - sizeof(WAVEFORMATEX); 94 afd.cbwfx = paftd->cbFormatSize; 95 96 for (i = 0; i < paftd->cStandardFormats; i++) { 97 static const WCHAR fmtW[] = {'%','d',' ','K','o','/','s','\0'}; 98 int j, index; 99 100 afd.dwFormatIndex = i; 101 afd.fdwSupport = 0; 102 mmr = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX); 103 if (mmr == MMSYSERR_NOERROR) { 104 lstrcpynW(buffer, afd.szFormat, ACMFORMATTAGDETAILS_FORMATTAG_CHARS + 1); 105 len = strlenW(buffer); 106 for (j = len; j < ACMFORMATTAGDETAILS_FORMATTAG_CHARS; j++) 107 buffer[j] = ' '; 108 wsprintfW(buffer + ACMFORMATTAGDETAILS_FORMATTAG_CHARS, 109 fmtW, (afd.pwfx->nAvgBytesPerSec + 512) / 1024); 110 index = SendDlgItemMessageW(affd->hWnd, 111 IDD_ACMFORMATCHOOSE_CMB_FORMAT, 112 CB_ADDSTRING, 0, (LPARAM)buffer); 113 if ((affd->afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT) && 114 affd->afc->cbwfx >= paftd->cbFormatSize && 115 !memcmp(afd.pwfx, affd->afc->pwfx, paftd->cbFormatSize)) 116 SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, 117 CB_SETCURSEL, index, 0); 118 } 119 } 120 acmDriverClose(had, 0); 121 HeapFree(MSACM_hHeap, 0, afd.pwfx); 122 } 123 } 124 break; 125 case WINE_ACMFF_WFX: 126 if (strcmpW(affd->szFormatTag, paftd->szFormatTag) == 0) { 127 HACMDRIVER had; 128 129 if (acmDriverOpen(&had, hadid, 0) == MMSYSERR_NOERROR) { 130 ACMFORMATDETAILSW afd = {0}; 131 132 afd.cbStruct = sizeof(afd); 133 afd.dwFormatTag = paftd->dwFormatTag; 134 afd.pwfx = affd->afc->pwfx; 135 afd.cbwfx = affd->afc->cbwfx; 136 137 afd.dwFormatIndex = SendDlgItemMessageW(affd->hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, 138 CB_GETCURSEL, 0, 0); 139 affd->ret = acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_INDEX); 140 acmDriverClose(had, 0); 141 return TRUE; 142 } 143 } 144 break; 145 default: 146 FIXME("Unknown mode (%d)\n", affd->mode); 147 break; 148 } 149 return TRUE; 150 } 151 152 static BOOL MSACM_FillFormatTags(HWND hWnd, PACMFORMATCHOOSEW afc) 153 { 154 ACMFORMATTAGDETAILSW aftd; 155 struct MSACM_FillFormatData affd; 156 157 memset(&aftd, 0, sizeof(aftd)); 158 aftd.cbStruct = sizeof(aftd); 159 160 affd.hWnd = hWnd; 161 affd.mode = WINE_ACMFF_TAG; 162 affd.afc = afc; 163 164 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0); 165 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_GETCURSEL, 0, 0) == CB_ERR) 166 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, CB_SETCURSEL, 0, 0); 167 return TRUE; 168 } 169 170 static BOOL MSACM_FillFormat(HWND hWnd, PACMFORMATCHOOSEW afc) 171 { 172 ACMFORMATTAGDETAILSW aftd; 173 struct MSACM_FillFormatData affd; 174 175 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_RESETCONTENT, 0, 0); 176 177 memset(&aftd, 0, sizeof(aftd)); 178 aftd.cbStruct = sizeof(aftd); 179 180 affd.hWnd = hWnd; 181 affd.mode = WINE_ACMFF_FORMAT; 182 affd.afc = afc; 183 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 184 CB_GETLBTEXT, 185 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 186 CB_GETCURSEL, 0, 0), 187 (LPARAM)affd.szFormatTag); 188 189 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0); 190 if (SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_GETCURSEL, 0, 0) == CB_ERR) 191 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMAT, CB_SETCURSEL, 0, 0); 192 return TRUE; 193 } 194 195 static MMRESULT MSACM_GetWFX(HWND hWnd, PACMFORMATCHOOSEW afc) 196 { 197 ACMFORMATTAGDETAILSW aftd; 198 struct MSACM_FillFormatData affd; 199 200 memset(&aftd, 0, sizeof(aftd)); 201 aftd.cbStruct = sizeof(aftd); 202 203 affd.hWnd = hWnd; 204 affd.mode = WINE_ACMFF_WFX; 205 affd.afc = afc; 206 affd.ret = MMSYSERR_NOERROR; 207 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 208 CB_GETLBTEXT, 209 SendDlgItemMessageW(hWnd, IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, 210 CB_GETCURSEL, 0, 0), 211 (LPARAM)affd.szFormatTag); 212 213 acmFormatTagEnumW(NULL, &aftd, MSACM_FillFormatTagsCB, (DWORD_PTR)&affd, 0); 214 return affd.ret; 215 } 216 217 static const WCHAR fmt_prop[] = {'a','c','m','p','r','o','p','\0'}; 218 219 static INT_PTR CALLBACK FormatChooseDlgProc(HWND hWnd, UINT msg, 220 WPARAM wParam, LPARAM lParam) 221 { 222 PACMFORMATCHOOSEW afc = (PACMFORMATCHOOSEW)GetPropW(hWnd, fmt_prop); 223 224 TRACE("hwnd=%p msg=%i 0x%08lx 0x%08lx\n", hWnd, msg, wParam, lParam); 225 226 switch (msg) { 227 case WM_INITDIALOG: 228 afc = (PACMFORMATCHOOSEW)lParam; 229 SetPropW(hWnd, fmt_prop, (HANDLE)afc); 230 MSACM_FillFormatTags(hWnd, afc); 231 MSACM_FillFormat(hWnd, afc); 232 if ((afc->fdwStyle & ~(ACMFORMATCHOOSE_STYLEF_CONTEXTHELP| 233 ACMFORMATCHOOSE_STYLEF_SHOWHELP| 234 ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT| 235 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE| 236 ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE)) != 0) 237 FIXME("Unsupported style %08x\n", afc->fdwStyle); 238 if (!(afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP)) 239 ShowWindow(GetDlgItem(hWnd, IDD_ACMFORMATCHOOSE_BTN_HELP), SW_HIDE); 240 return TRUE; 241 242 case WM_COMMAND: 243 switch (LOWORD(wParam)) { 244 case IDOK: 245 EndDialog(hWnd, MSACM_GetWFX(hWnd, afc)); 246 return TRUE; 247 case IDCANCEL: 248 EndDialog(hWnd, ACMERR_CANCELED); 249 return TRUE; 250 case IDD_ACMFORMATCHOOSE_CMB_FORMATTAG: 251 switch (HIWORD(wParam)) { 252 case CBN_SELCHANGE: 253 MSACM_FillFormat(hWnd, afc); 254 break; 255 default: 256 TRACE("Dropped dlgNotif (fmtTag): 0x%08x 0x%08lx\n", 257 HIWORD(wParam), lParam); 258 break; 259 } 260 break; 261 case IDD_ACMFORMATCHOOSE_BTN_HELP: 262 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_SHOWHELP) 263 SendMessageW(afc->hwndOwner, 264 RegisterWindowMessageW(ACMHELPMSGSTRINGW), 0L, 0L); 265 break; 266 267 default: 268 TRACE("Dropped dlgCmd: ctl=%d ntf=0x%04x 0x%08lx\n", 269 LOWORD(wParam), HIWORD(wParam), lParam); 270 break; 271 } 272 break; 273 case WM_CONTEXTMENU: 274 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP) 275 SendMessageW(afc->hwndOwner, 276 RegisterWindowMessageW(ACMHELPMSGCONTEXTMENUW), 277 wParam, lParam); 278 break; 279 #if defined(WM_CONTEXTHELP) 280 case WM_CONTEXTHELP: 281 if (afc->fdwStyle & ACMFORMATCHOOSE_STYLEF_CONTEXTHELP) 282 SendMessageW(afc->hwndOwner, 283 RegisterWindowMessageW(ACMHELPMSGCONTEXTHELPW), 284 wParam, lParam); 285 break; 286 #endif 287 default: 288 TRACE("Dropped dlgMsg: hwnd=%p msg=%i 0x%08lx 0x%08lx\n", 289 hWnd, msg, wParam, lParam ); 290 break; 291 } 292 return FALSE; 293 } 294 295 /*********************************************************************** 296 * acmFormatChooseA (MSACM32.@) 297 */ 298 MMRESULT WINAPI acmFormatChooseA(PACMFORMATCHOOSEA pafmtc) 299 { 300 ACMFORMATCHOOSEW afcw; 301 MMRESULT ret; 302 LPWSTR title = NULL; 303 LPWSTR name = NULL; 304 LPWSTR templ = NULL; 305 DWORD sz; 306 307 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEA)) 308 return MMSYSERR_INVALPARAM; 309 310 afcw.cbStruct = sizeof(afcw); 311 afcw.fdwStyle = pafmtc->fdwStyle; 312 afcw.hwndOwner = pafmtc->hwndOwner; 313 afcw.pwfx = pafmtc->pwfx; 314 afcw.cbwfx = pafmtc->cbwfx; 315 if (pafmtc->pszTitle) 316 { 317 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, NULL, 0); 318 if (!(title = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 319 { 320 ret = MMSYSERR_NOMEM; 321 goto done; 322 } 323 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTitle, -1, title, sz); 324 } 325 afcw.pszTitle = title; 326 if (pafmtc->pszName) 327 { 328 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, NULL, 0); 329 if (!(name = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 330 { 331 ret = MMSYSERR_NOMEM; 332 goto done; 333 } 334 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszName, -1, name, sz); 335 } 336 afcw.pszName = name; 337 afcw.cchName = pafmtc->cchName; 338 afcw.fdwEnum = pafmtc->fdwEnum; 339 afcw.pwfxEnum = pafmtc->pwfxEnum; 340 afcw.hInstance = pafmtc->hInstance; 341 if (pafmtc->pszTemplateName) 342 { 343 sz = MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, NULL, 0); 344 if (!(templ = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 345 { 346 ret = MMSYSERR_NOMEM; 347 goto done; 348 } 349 MultiByteToWideChar(CP_ACP, 0, pafmtc->pszTemplateName, -1, templ, sz); 350 } 351 afcw.pszTemplateName = templ; 352 /* FIXME: hook procs not supported yet */ 353 if (pafmtc->pfnHook) 354 { 355 FIXME("Unsupported hook procs\n"); 356 ret = MMSYSERR_NOTSUPPORTED; 357 goto done; 358 } 359 ret = acmFormatChooseW(&afcw); 360 if (ret == MMSYSERR_NOERROR) 361 { 362 WideCharToMultiByte(CP_ACP, 0, afcw.szFormatTag, -1, pafmtc->szFormatTag, sizeof(pafmtc->szFormatTag), 363 NULL, NULL); 364 WideCharToMultiByte(CP_ACP, 0, afcw.szFormat, -1, pafmtc->szFormat, sizeof(pafmtc->szFormat), 365 NULL, NULL); 366 if (pafmtc->pszName) 367 WideCharToMultiByte(CP_ACP, 0, afcw.pszName, -1, pafmtc->pszName, pafmtc->cchName, NULL, NULL); 368 } 369 done: 370 HeapFree(GetProcessHeap(), 0, title); 371 HeapFree(GetProcessHeap(), 0, name); 372 HeapFree(GetProcessHeap(), 0, templ); 373 return ret; 374 } 375 376 /*********************************************************************** 377 * acmFormatChooseW (MSACM32.@) 378 */ 379 MMRESULT WINAPI acmFormatChooseW(PACMFORMATCHOOSEW pafmtc) 380 { 381 if (pafmtc->cbStruct < sizeof(ACMFORMATCHOOSEW)) 382 return MMSYSERR_INVALPARAM; 383 384 if (!pafmtc->pwfx) 385 return MMSYSERR_INVALPARAM; 386 387 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATEHANDLE) 388 return DialogBoxIndirectParamW(MSACM_hInstance32, (LPCDLGTEMPLATEW)pafmtc->hInstance, 389 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc); 390 391 if (pafmtc->fdwStyle & ACMFORMATCHOOSE_STYLEF_ENABLETEMPLATE) 392 return DialogBoxParamW(pafmtc->hInstance, pafmtc->pszTemplateName, 393 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc); 394 395 return DialogBoxParamW(MSACM_hInstance32, MAKEINTRESOURCEW(DLG_ACMFORMATCHOOSE_ID), 396 pafmtc->hwndOwner, FormatChooseDlgProc, (LPARAM)pafmtc); 397 } 398 399 /*********************************************************************** 400 * acmFormatDetailsA (MSACM32.@) 401 */ 402 MMRESULT WINAPI acmFormatDetailsA(HACMDRIVER had, PACMFORMATDETAILSA pafd, 403 DWORD fdwDetails) 404 { 405 ACMFORMATDETAILSW afdw; 406 MMRESULT mmr; 407 408 if (!pafd) 409 return MMSYSERR_INVALPARAM; 410 411 memset(&afdw, 0, sizeof(afdw)); 412 afdw.cbStruct = sizeof(afdw); 413 afdw.dwFormatIndex = pafd->dwFormatIndex; 414 afdw.dwFormatTag = pafd->dwFormatTag; 415 afdw.fdwSupport = pafd->fdwSupport; 416 afdw.pwfx = pafd->pwfx; 417 afdw.cbwfx = pafd->cbwfx; 418 419 mmr = acmFormatDetailsW(had, &afdw, fdwDetails); 420 if (mmr == MMSYSERR_NOERROR) { 421 pafd->dwFormatTag = afdw.dwFormatTag; 422 pafd->fdwSupport = afdw.fdwSupport; 423 WideCharToMultiByte( CP_ACP, 0, afdw.szFormat, -1, 424 pafd->szFormat, sizeof(pafd->szFormat), NULL, NULL ); 425 } 426 return mmr; 427 } 428 429 /*********************************************************************** 430 * acmFormatDetailsW (MSACM32.@) 431 */ 432 MMRESULT WINAPI acmFormatDetailsW(HACMDRIVER had, PACMFORMATDETAILSW pafd, DWORD fdwDetails) 433 { 434 MMRESULT mmr; 435 static const WCHAR fmt1[] = {'%','d',' ','H','z',0}; 436 static const WCHAR fmt2[] = {';',' ','%','d',' ','b','i','t','s',0}; 437 ACMFORMATTAGDETAILSW aftd = {0}; 438 439 TRACE("(%p, %p, %d)\n", had, pafd, fdwDetails); 440 441 if (!pafd) 442 return MMSYSERR_INVALPARAM; 443 444 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; 445 446 if (!pafd->pwfx) 447 return MMSYSERR_INVALPARAM; 448 449 if (pafd->cbwfx < sizeof(PCMWAVEFORMAT)) 450 return MMSYSERR_INVALPARAM; 451 452 if (pafd->fdwSupport) 453 return MMSYSERR_INVALPARAM; 454 455 if (pafd->dwFormatTag == WAVE_FORMAT_UNKNOWN) 456 return MMSYSERR_INVALPARAM; 457 458 switch (fdwDetails) { 459 case ACM_FORMATDETAILSF_FORMAT: 460 if (pafd->dwFormatTag != pafd->pwfx->wFormatTag) { 461 mmr = MMSYSERR_INVALPARAM; 462 break; 463 } 464 if (had == NULL) { 465 PWINE_ACMDRIVERID padid; 466 467 mmr = ACMERR_NOTPOSSIBLE; 468 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 469 /* should check for codec only */ 470 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 471 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 472 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); 473 acmDriverClose(had, 0); 474 if (mmr == MMSYSERR_NOERROR) break; 475 } 476 } 477 } else { 478 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); 479 } 480 break; 481 case ACM_FORMATDETAILSF_INDEX: 482 aftd.cbStruct = sizeof(aftd); 483 aftd.dwFormatTag = pafd->dwFormatTag; 484 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG); 485 if (mmr != MMSYSERR_NOERROR) 486 break; 487 if (pafd->dwFormatIndex >= aftd.cStandardFormats) 488 { 489 mmr = MMSYSERR_INVALPARAM; 490 break; 491 } 492 mmr = MSACM_Message(had, ACMDM_FORMAT_DETAILS, (LPARAM)pafd, fdwDetails); 493 break; 494 default: 495 WARN("Unknown fdwDetails %08x\n", fdwDetails); 496 mmr = MMSYSERR_INVALFLAG; 497 break; 498 } 499 500 if (mmr == MMSYSERR_NOERROR && pafd->szFormat[0] == 0) { 501 wsprintfW(pafd->szFormat, fmt1, pafd->pwfx->nSamplesPerSec); 502 if (pafd->pwfx->wBitsPerSample) { 503 wsprintfW(pafd->szFormat + lstrlenW(pafd->szFormat), fmt2, 504 pafd->pwfx->wBitsPerSample); 505 } 506 MultiByteToWideChar( CP_ACP, 0, (pafd->pwfx->nChannels == 1) ? "; Mono" : "; Stereo", -1, 507 pafd->szFormat + strlenW(pafd->szFormat), 508 sizeof(pafd->szFormat)/sizeof(WCHAR) - strlenW(pafd->szFormat) ); 509 } 510 511 TRACE("=> %d\n", mmr); 512 return mmr; 513 } 514 515 struct MSACM_FormatEnumWtoA_Instance { 516 PACMFORMATDETAILSA pafda; 517 DWORD_PTR dwInstance; 518 ACMFORMATENUMCBA fnCallback; 519 }; 520 521 static BOOL CALLBACK MSACM_FormatEnumCallbackWtoA(HACMDRIVERID hadid, 522 PACMFORMATDETAILSW pafdw, 523 DWORD_PTR dwInstance, 524 DWORD fdwSupport) 525 { 526 struct MSACM_FormatEnumWtoA_Instance* pafei; 527 528 pafei = (struct MSACM_FormatEnumWtoA_Instance*)dwInstance; 529 530 pafei->pafda->dwFormatIndex = pafdw->dwFormatIndex; 531 pafei->pafda->dwFormatTag = pafdw->dwFormatTag; 532 pafei->pafda->fdwSupport = pafdw->fdwSupport; 533 WideCharToMultiByte( CP_ACP, 0, pafdw->szFormat, -1, 534 pafei->pafda->szFormat, sizeof(pafei->pafda->szFormat), NULL, NULL ); 535 536 return (pafei->fnCallback)(hadid, pafei->pafda, 537 pafei->dwInstance, fdwSupport); 538 } 539 540 /*********************************************************************** 541 * acmFormatEnumA (MSACM32.@) 542 */ 543 MMRESULT WINAPI acmFormatEnumA(HACMDRIVER had, PACMFORMATDETAILSA pafda, 544 ACMFORMATENUMCBA fnCallback, 545 DWORD_PTR dwInstance, DWORD fdwEnum) 546 { 547 ACMFORMATDETAILSW afdw; 548 struct MSACM_FormatEnumWtoA_Instance afei; 549 550 if (!pafda) 551 return MMSYSERR_INVALPARAM; 552 553 if (!fnCallback) 554 return MMSYSERR_INVALPARAM; 555 556 if (pafda->cbStruct < sizeof(*pafda)) 557 return MMSYSERR_INVALPARAM; 558 559 memset(&afdw, 0, sizeof(afdw)); 560 afdw.cbStruct = sizeof(afdw); 561 afdw.dwFormatIndex = pafda->dwFormatIndex; 562 afdw.dwFormatTag = pafda->dwFormatTag; 563 afdw.fdwSupport = pafda->fdwSupport; 564 afdw.pwfx = pafda->pwfx; 565 afdw.cbwfx = pafda->cbwfx; 566 567 afei.pafda = pafda; 568 afei.dwInstance = dwInstance; 569 afei.fnCallback = fnCallback; 570 571 return acmFormatEnumW(had, &afdw, MSACM_FormatEnumCallbackWtoA, 572 (DWORD_PTR)&afei, fdwEnum); 573 } 574 575 /*********************************************************************** 576 * acmFormatEnumW (MSACM32.@) 577 */ 578 static BOOL MSACM_FormatEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had, 579 PACMFORMATDETAILSW pafd, PWAVEFORMATEX pwfxRef, 580 ACMFORMATENUMCBW fnCallback, 581 DWORD_PTR dwInstance, DWORD fdwEnum) 582 { 583 ACMFORMATTAGDETAILSW aftd; 584 unsigned int i, j; 585 586 if (fdwEnum & ACM_FORMATENUMF_SUGGEST) { 587 HDRVR hdrvr; 588 ACMDRVFORMATSUGGEST adfs; 589 pafd->dwFormatIndex = 0; 590 memset(&aftd, 0, sizeof(aftd)); 591 aftd.cbStruct = sizeof(aftd); 592 memset(&adfs, 0, sizeof(adfs)); 593 adfs.cbStruct = sizeof(adfs); 594 595 for (i = 0; i < padid->cFormatTags; i++) { 596 aftd.dwFormatTag = i; 597 pafd->dwFormatTag = aftd.dwFormatTag; 598 pafd->pwfx->wFormatTag = pafd->dwFormatTag; 599 600 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR) 601 continue; 602 603 adfs.cbwfxSrc = aftd.cbFormatSize; 604 adfs.cbwfxDst = aftd.cbFormatSize; 605 adfs.pwfxSrc = pwfxRef; 606 adfs.pwfxDst = pafd->pwfx; 607 pafd->fdwSupport = padid->fdwSupport; 608 609 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && 610 aftd.dwFormatTag != pwfxRef->wFormatTag) 611 continue; 612 613 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) && 614 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE)) 615 continue; 616 617 hdrvr = OpenDriver(padid->pszFileName,0,0); 618 SendDriverMessage(hdrvr,ACMDM_FORMAT_SUGGEST,(LPARAM)&adfs,(fdwEnum & 0x000000FFL)); 619 620 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_FORMAT) != MMSYSERR_NOERROR) 621 continue; 622 623 pafd->cbwfx = sizeof(*(pafd->pwfx)); 624 625 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport)) 626 return FALSE; 627 } 628 } else { 629 for (i = 0; i < padid->cFormatTags; i++) { 630 memset(&aftd, 0, sizeof(aftd)); 631 aftd.cbStruct = sizeof(aftd); 632 aftd.dwFormatTagIndex = i; 633 if (acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_INDEX) != MMSYSERR_NOERROR) 634 continue; 635 636 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && aftd.dwFormatTag != pwfxRef->wFormatTag) 637 continue; 638 639 for (j = 0; j < aftd.cStandardFormats; j++) { 640 pafd->dwFormatIndex = j; 641 pafd->dwFormatTag = aftd.dwFormatTag; 642 pafd->fdwSupport = 0; 643 if (acmFormatDetailsW(had, pafd, ACM_FORMATDETAILSF_INDEX) != MMSYSERR_NOERROR) 644 continue; 645 646 if ((fdwEnum & ACM_FORMATENUMF_NCHANNELS) && 647 pafd->pwfx->nChannels != pwfxRef->nChannels) 648 continue; 649 if ((fdwEnum & ACM_FORMATENUMF_NSAMPLESPERSEC) && 650 pafd->pwfx->nSamplesPerSec != pwfxRef->nSamplesPerSec) 651 continue; 652 if ((fdwEnum & ACM_FORMATENUMF_WBITSPERSAMPLE) && 653 pafd->pwfx->wBitsPerSample != pwfxRef->wBitsPerSample) 654 continue; 655 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) && 656 !(pafd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_HARDWARE)) 657 continue; 658 659 /* more checks to be done on fdwEnum */ 660 661 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport)) 662 return FALSE; 663 } 664 /* the "formats" used by the filters are also reported */ 665 } 666 } 667 return TRUE; 668 } 669 670 /**********************************************************************/ 671 672 MMRESULT WINAPI acmFormatEnumW(HACMDRIVER had, PACMFORMATDETAILSW pafd, 673 ACMFORMATENUMCBW fnCallback, 674 DWORD_PTR dwInstance, DWORD fdwEnum) 675 { 676 PWINE_ACMDRIVERID padid; 677 WAVEFORMATEX wfxRef; 678 BOOL ret; 679 DWORD cbwfxMax; 680 MMRESULT mmr; 681 682 TRACE("(%p, %p, %p, %ld, %d)\n", 683 had, pafd, fnCallback, dwInstance, fdwEnum); 684 685 if (!pafd) 686 return MMSYSERR_INVALPARAM; 687 688 if (!fnCallback) 689 return MMSYSERR_INVALPARAM; 690 691 if (pafd->cbStruct < sizeof(*pafd)) 692 return MMSYSERR_INVALPARAM; 693 694 if (pafd->fdwSupport) 695 return MMSYSERR_INVALPARAM; 696 697 if (!pafd->pwfx) 698 return MMSYSERR_INVALPARAM; 699 700 if (fdwEnum & (ACM_FORMATENUMF_WFORMATTAG|ACM_FORMATENUMF_NCHANNELS| 701 ACM_FORMATENUMF_NSAMPLESPERSEC|ACM_FORMATENUMF_WBITSPERSAMPLE| 702 ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_SUGGEST)) 703 wfxRef = *pafd->pwfx; 704 705 if ((fdwEnum & ACM_FORMATENUMF_HARDWARE) && 706 !(fdwEnum & (ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT))) 707 return MMSYSERR_INVALPARAM; 708 709 if ((fdwEnum & ACM_FORMATENUMF_WFORMATTAG) && 710 (pafd->dwFormatTag != pafd->pwfx->wFormatTag)) 711 return MMSYSERR_INVALPARAM; 712 713 if (fdwEnum & (ACM_FORMATENUMF_CONVERT|ACM_FORMATENUMF_INPUT|ACM_FORMATENUMF_OUTPUT)) 714 FIXME("Unsupported fdwEnum values %08x\n", fdwEnum); 715 716 mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &cbwfxMax); 717 if (mmr != MMSYSERR_NOERROR) 718 return mmr; 719 if (pafd->cbwfx < cbwfxMax) 720 return MMSYSERR_INVALPARAM; 721 722 if (had) { 723 HACMDRIVERID hadid; 724 725 if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR) 726 return MMSYSERR_INVALHANDLE; 727 MSACM_FormatEnumHelper(MSACM_GetDriverID(hadid), had, pafd, &wfxRef, 728 fnCallback, dwInstance, fdwEnum); 729 return MMSYSERR_NOERROR; 730 } 731 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 732 /* should check for codec only */ 733 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || 734 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR) 735 continue; 736 ret = MSACM_FormatEnumHelper(padid, had, pafd, &wfxRef, 737 fnCallback, dwInstance, fdwEnum); 738 acmDriverClose(had, 0); 739 if (!ret) break; 740 } 741 return MMSYSERR_NOERROR; 742 } 743 744 /*********************************************************************** 745 * acmFormatSuggest (MSACM32.@) 746 */ 747 MMRESULT WINAPI acmFormatSuggest(HACMDRIVER had, PWAVEFORMATEX pwfxSrc, 748 PWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest) 749 { 750 ACMFORMATTAGDETAILSW aftd = {0}; 751 ACMDRVFORMATSUGGEST adfg; 752 MMRESULT mmr; 753 754 TRACE("(%p, %p, %p, %d, %d)\n", 755 had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest); 756 757 if (!pwfxSrc || !pwfxDst) 758 return MMSYSERR_INVALPARAM; 759 760 if (fdwSuggest & ~(ACM_FORMATSUGGESTF_NCHANNELS|ACM_FORMATSUGGESTF_NSAMPLESPERSEC| 761 ACM_FORMATSUGGESTF_WBITSPERSAMPLE|ACM_FORMATSUGGESTF_WFORMATTAG)) 762 return MMSYSERR_INVALFLAG; 763 764 /* if we were given PCM, try to convert to PCM */ 765 if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && !had && 766 !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) 767 { 768 ACMFORMATDETAILSW afd = {0}; 769 afd.cbStruct = sizeof(afd); 770 afd.dwFormatTag = WAVE_FORMAT_PCM; 771 afd.pwfx = pwfxSrc; 772 afd.cbwfx = sizeof(PCMWAVEFORMAT); 773 if (!acmFormatDetailsW(had, &afd, ACM_FORMATDETAILSF_FORMAT)) 774 { 775 memcpy(pwfxDst, pwfxSrc, sizeof(PCMWAVEFORMAT)); 776 return MMSYSERR_NOERROR; 777 } 778 } 779 780 aftd.cbStruct = sizeof(aftd); 781 if (fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) 782 aftd.dwFormatTag = pwfxDst->wFormatTag; 783 mmr = acmFormatTagDetailsW(had, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE); 784 if ((fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) && mmr == ACMERR_NOTPOSSIBLE) 785 return ACMERR_NOTPOSSIBLE; 786 787 if (cbwfxDst < aftd.cbFormatSize) 788 return MMSYSERR_INVALPARAM; 789 790 adfg.cbStruct = sizeof(adfg); 791 adfg.fdwSuggest = fdwSuggest; 792 adfg.pwfxSrc = pwfxSrc; 793 adfg.cbwfxSrc = (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) ? 794 sizeof(WAVEFORMATEX) : (sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); 795 adfg.pwfxDst = pwfxDst; 796 adfg.cbwfxDst = cbwfxDst; 797 798 if (had == NULL) { 799 PWINE_ACMDRIVERID padid; 800 801 /* MS doc says: ACM finds the best suggestion. 802 * Well, first found will be the "best" 803 */ 804 mmr = ACMERR_NOTPOSSIBLE; 805 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 806 /* should check for codec only */ 807 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || 808 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR) 809 continue; 810 811 if (MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L) == MMSYSERR_NOERROR) { 812 mmr = MMSYSERR_NOERROR; 813 break; 814 } 815 acmDriverClose(had, 0); 816 } 817 } else { 818 mmr = MSACM_Message(had, ACMDM_FORMAT_SUGGEST, (LPARAM)&adfg, 0L); 819 } 820 return mmr; 821 } 822 823 /*********************************************************************** 824 * acmFormatTagDetailsA (MSACM32.@) 825 */ 826 MMRESULT WINAPI acmFormatTagDetailsA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda, 827 DWORD fdwDetails) 828 { 829 ACMFORMATTAGDETAILSW aftdw; 830 MMRESULT mmr; 831 832 memset(&aftdw, 0, sizeof(aftdw)); 833 aftdw.cbStruct = sizeof(aftdw); 834 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex; 835 aftdw.dwFormatTag = paftda->dwFormatTag; 836 837 mmr = acmFormatTagDetailsW(had, &aftdw, fdwDetails); 838 if (mmr == MMSYSERR_NOERROR) { 839 paftda->dwFormatTag = aftdw.dwFormatTag; 840 paftda->dwFormatTagIndex = aftdw.dwFormatTagIndex; 841 paftda->cbFormatSize = aftdw.cbFormatSize; 842 paftda->fdwSupport = aftdw.fdwSupport; 843 paftda->cStandardFormats = aftdw.cStandardFormats; 844 WideCharToMultiByte( CP_ACP, 0, aftdw.szFormatTag, -1, paftda->szFormatTag, 845 sizeof(paftda->szFormatTag), NULL, NULL ); 846 } 847 return mmr; 848 } 849 850 /*********************************************************************** 851 * acmFormatTagDetailsW (MSACM32.@) 852 */ 853 MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, 854 DWORD fdwDetails) 855 { 856 PWINE_ACMDRIVERID padid; 857 MMRESULT mmr = ACMERR_NOTPOSSIBLE; 858 859 TRACE("(%p, %p, %d)\n", had, paftd, fdwDetails); 860 861 if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX| 862 ACM_FORMATTAGDETAILSF_LARGESTSIZE)) 863 return MMSYSERR_INVALFLAG; 864 865 switch (fdwDetails) { 866 case ACM_FORMATTAGDETAILSF_FORMATTAG: 867 if (had == NULL) { 868 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 869 /* should check for codec only */ 870 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 871 MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) && 872 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 873 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); 874 acmDriverClose(had, 0); 875 if (mmr == MMSYSERR_NOERROR) break; 876 } 877 } 878 } else { 879 PWINE_ACMDRIVER pad = MSACM_GetDriver(had); 880 881 if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL)) 882 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); 883 } 884 break; 885 886 case ACM_FORMATTAGDETAILSF_INDEX: 887 if (had != NULL) { 888 PWINE_ACMDRIVER pad = MSACM_GetDriver(had); 889 890 if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags) 891 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); 892 } 893 break; 894 895 case ACM_FORMATTAGDETAILSF_LARGESTSIZE: 896 if (had == NULL) { 897 ACMFORMATTAGDETAILSW tmp; 898 DWORD ft = paftd->dwFormatTag; 899 900 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 901 /* should check for codec only */ 902 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 903 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 904 905 memset(&tmp, 0, sizeof(tmp)); 906 tmp.cbStruct = sizeof(tmp); 907 tmp.dwFormatTag = ft; 908 909 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, 910 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) { 911 if (mmr == ACMERR_NOTPOSSIBLE || 912 paftd->cbFormatSize < tmp.cbFormatSize) { 913 *paftd = tmp; 914 mmr = MMSYSERR_NOERROR; 915 } 916 } 917 acmDriverClose(had, 0); 918 } 919 } 920 } else { 921 mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); 922 } 923 break; 924 925 default: 926 WARN("Unsupported fdwDetails=%08x\n", fdwDetails); 927 mmr = MMSYSERR_ERROR; 928 } 929 930 if (mmr == MMSYSERR_NOERROR && 931 paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0) 932 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, 933 sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); 934 935 return mmr; 936 } 937 938 struct MSACM_FormatTagEnumWtoA_Instance { 939 PACMFORMATTAGDETAILSA paftda; 940 DWORD_PTR dwInstance; 941 ACMFORMATTAGENUMCBA fnCallback; 942 }; 943 944 static BOOL CALLBACK MSACM_FormatTagEnumCallbackWtoA(HACMDRIVERID hadid, 945 PACMFORMATTAGDETAILSW paftdw, 946 DWORD_PTR dwInstance, 947 DWORD fdwSupport) 948 { 949 struct MSACM_FormatTagEnumWtoA_Instance* paftei; 950 951 paftei = (struct MSACM_FormatTagEnumWtoA_Instance*)dwInstance; 952 953 paftei->paftda->dwFormatTagIndex = paftdw->dwFormatTagIndex; 954 paftei->paftda->dwFormatTag = paftdw->dwFormatTag; 955 paftei->paftda->cbFormatSize = paftdw->cbFormatSize; 956 paftei->paftda->fdwSupport = paftdw->fdwSupport; 957 paftei->paftda->cStandardFormats = paftdw->cStandardFormats; 958 WideCharToMultiByte( CP_ACP, 0, paftdw->szFormatTag, -1, paftei->paftda->szFormatTag, 959 sizeof(paftei->paftda->szFormatTag), NULL, NULL ); 960 961 return (paftei->fnCallback)(hadid, paftei->paftda, 962 paftei->dwInstance, fdwSupport); 963 } 964 965 /*********************************************************************** 966 * acmFormatTagEnumA (MSACM32.@) 967 */ 968 MMRESULT WINAPI acmFormatTagEnumA(HACMDRIVER had, PACMFORMATTAGDETAILSA paftda, 969 ACMFORMATTAGENUMCBA fnCallback, 970 DWORD_PTR dwInstance, DWORD fdwEnum) 971 { 972 ACMFORMATTAGDETAILSW aftdw; 973 struct MSACM_FormatTagEnumWtoA_Instance aftei; 974 975 if (!paftda) 976 return MMSYSERR_INVALPARAM; 977 978 if (paftda->cbStruct < sizeof(*paftda)) 979 return MMSYSERR_INVALPARAM; 980 981 if (fdwEnum != 0) 982 return MMSYSERR_INVALFLAG; 983 984 memset(&aftdw, 0, sizeof(aftdw)); 985 aftdw.cbStruct = sizeof(aftdw); 986 aftdw.dwFormatTagIndex = paftda->dwFormatTagIndex; 987 aftdw.dwFormatTag = paftda->dwFormatTag; 988 989 aftei.paftda = paftda; 990 aftei.dwInstance = dwInstance; 991 aftei.fnCallback = fnCallback; 992 993 return acmFormatTagEnumW(had, &aftdw, MSACM_FormatTagEnumCallbackWtoA, 994 (DWORD_PTR)&aftei, fdwEnum); 995 } 996 997 /*********************************************************************** 998 * acmFormatTagEnumW (MSACM32.@) 999 */ 1000 MMRESULT WINAPI acmFormatTagEnumW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, 1001 ACMFORMATTAGENUMCBW fnCallback, 1002 DWORD_PTR dwInstance, DWORD fdwEnum) 1003 { 1004 PWINE_ACMDRIVERID padid; 1005 unsigned int i; 1006 BOOL bPcmDone = FALSE; 1007 1008 TRACE("(%p, %p, %p, %ld, %d)\n", 1009 had, paftd, fnCallback, dwInstance, fdwEnum); 1010 1011 if (!paftd) 1012 return MMSYSERR_INVALPARAM; 1013 1014 if (paftd->cbStruct < sizeof(*paftd)) 1015 return MMSYSERR_INVALPARAM; 1016 1017 if (fdwEnum != 0) 1018 return MMSYSERR_INVALFLAG; 1019 1020 /* (WS) MSDN info page says that if had != 0, then we should find 1021 * the specific driver to get its tags from. Therefore I'm removing 1022 * the FIXME call and adding a search block below. It also seems 1023 * that the lack of this functionality was the responsible for 1024 * codecs to be multiply and incorrectly listed. 1025 */ 1026 1027 /* if (had) FIXME("had != NULL, not supported\n"); */ 1028 1029 if (had) { 1030 if (acmDriverID((HACMOBJ)had, (HACMDRIVERID *)&padid, 0) != MMSYSERR_NOERROR) 1031 return MMSYSERR_INVALHANDLE; 1032 1033 for (i = 0; i < padid->cFormatTags; i++) { 1034 paftd->dwFormatTagIndex = i; 1035 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, 1036 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { 1037 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) { 1038 if (paftd->szFormatTag[0] == 0) 1039 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, 1040 sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); 1041 /* (WS) I'm preserving this PCM hack since it seems to be 1042 * correct. Please notice this block was borrowed from 1043 * below. 1044 */ 1045 if (bPcmDone) continue; 1046 bPcmDone = TRUE; 1047 } 1048 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) 1049 return MMSYSERR_NOERROR; 1050 } 1051 } 1052 } 1053 /* if had==0 then search for the first suitable driver */ 1054 else { 1055 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 1056 /* should check for codec only */ 1057 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 1058 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) { 1059 for (i = 0; i < padid->cFormatTags; i++) { 1060 paftd->dwFormatTagIndex = i; 1061 if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, 1062 (LPARAM)paftd, ACM_FORMATTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { 1063 if (paftd->dwFormatTag == WAVE_FORMAT_PCM) { 1064 if (paftd->szFormatTag[0] == 0) 1065 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, 1066 sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); 1067 /* FIXME (EPP): I'm not sure this is the correct 1068 * algorithm (should make more sense to apply the same 1069 * for all already loaded formats, but this will do 1070 * for now 1071 */ 1072 if (bPcmDone) continue; 1073 bPcmDone = TRUE; 1074 } 1075 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) { 1076 acmDriverClose(had, 0); 1077 return MMSYSERR_NOERROR; 1078 } 1079 } 1080 } 1081 acmDriverClose(had, 0); 1082 } 1083 } 1084 } 1085 return MMSYSERR_NOERROR; 1086 } 1087