1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 2 3 /* 4 * MSACM32 library 5 * 6 * Copyright 1998 Patrik Stridvall 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include <stdarg.h> 24 #include <string.h> 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winnls.h" 28 #include "winerror.h" 29 #include "mmsystem.h" 30 #define NOBITMAP 31 #include "mmreg.h" 32 #include "msacm.h" 33 #include "msacmdrv.h" 34 #include "wineacm.h" 35 #include "wine/debug.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(msacm); 38 39 /*********************************************************************** 40 * acmFilterChooseA (MSACM32.@) 41 */ 42 MMRESULT WINAPI acmFilterChooseA(PACMFILTERCHOOSEA pafltrc) 43 { 44 FIXME("(%p): stub\n", pafltrc); 45 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 46 return MMSYSERR_ERROR; 47 } 48 49 /*********************************************************************** 50 * acmFilterChooseW (MSACM32.@) 51 */ 52 MMRESULT WINAPI acmFilterChooseW(PACMFILTERCHOOSEW pafltrc) 53 { 54 FIXME("(%p): stub\n", pafltrc); 55 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 56 return MMSYSERR_ERROR; 57 } 58 59 /*********************************************************************** 60 * acmFilterDetailsA (MSACM32.@) 61 */ 62 MMRESULT WINAPI acmFilterDetailsA(HACMDRIVER had, PACMFILTERDETAILSA pafd, 63 DWORD fdwDetails) 64 { 65 ACMFILTERDETAILSW afdw; 66 MMRESULT mmr; 67 68 memset(&afdw, 0, sizeof(afdw)); 69 afdw.cbStruct = sizeof(afdw); 70 afdw.dwFilterIndex = pafd->dwFilterIndex; 71 afdw.dwFilterTag = pafd->dwFilterTag; 72 afdw.pwfltr = pafd->pwfltr; 73 afdw.cbwfltr = pafd->cbwfltr; 74 75 mmr = acmFilterDetailsW(had, &afdw, fdwDetails); 76 if (mmr == MMSYSERR_NOERROR) { 77 pafd->dwFilterTag = afdw.dwFilterTag; 78 pafd->fdwSupport = afdw.fdwSupport; 79 WideCharToMultiByte( CP_ACP, 0, afdw.szFilter, -1, pafd->szFilter, 80 sizeof(pafd->szFilter), NULL, NULL ); 81 } 82 return mmr; 83 } 84 85 /*********************************************************************** 86 * acmFilterDetailsW (MSACM32.@) 87 */ 88 MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 89 DWORD fdwDetails) 90 { 91 MMRESULT mmr; 92 ACMFILTERTAGDETAILSA aftd; 93 94 TRACE("(%p, %p, %d)\n", had, pafd, fdwDetails); 95 96 memset(&aftd, 0, sizeof(aftd)); 97 aftd.cbStruct = sizeof(aftd); 98 99 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; 100 101 switch (fdwDetails) { 102 case ACM_FILTERDETAILSF_FILTER: 103 if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) { 104 mmr = MMSYSERR_INVALPARAM; 105 break; 106 } 107 if (had == NULL) { 108 PWINE_ACMDRIVERID padid; 109 110 mmr = ACMERR_NOTPOSSIBLE; 111 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 112 /* should check for codec only */ 113 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 114 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 115 mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, 116 (LPARAM)pafd, (LPARAM)fdwDetails); 117 acmDriverClose(had, 0); 118 if (mmr == MMSYSERR_NOERROR) break; 119 } 120 } 121 } else { 122 mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails); 123 } 124 break; 125 case ACM_FILTERDETAILSF_INDEX: 126 /* should check pafd->dwFilterIndex < aftd->cStandardFilters */ 127 mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails); 128 break; 129 default: 130 WARN("Unknown fdwDetails %08x\n", fdwDetails); 131 mmr = MMSYSERR_INVALFLAG; 132 break; 133 } 134 135 TRACE("=> %d\n", mmr); 136 return mmr; 137 } 138 139 struct MSACM_FilterEnumWtoA_Instance { 140 PACMFILTERDETAILSA pafda; 141 DWORD_PTR dwInstance; 142 ACMFILTERENUMCBA fnCallback; 143 }; 144 145 static BOOL CALLBACK MSACM_FilterEnumCallbackWtoA(HACMDRIVERID hadid, 146 PACMFILTERDETAILSW pafdw, 147 DWORD_PTR dwInstance, 148 DWORD fdwSupport) 149 { 150 struct MSACM_FilterEnumWtoA_Instance* pafei; 151 152 pafei = (struct MSACM_FilterEnumWtoA_Instance*)dwInstance; 153 154 pafei->pafda->dwFilterIndex = pafdw->dwFilterIndex; 155 pafei->pafda->dwFilterTag = pafdw->dwFilterTag; 156 pafei->pafda->fdwSupport = pafdw->fdwSupport; 157 WideCharToMultiByte( CP_ACP, 0, pafdw->szFilter, -1, pafei->pafda->szFilter, 158 sizeof(pafei->pafda->szFilter), NULL, NULL ); 159 160 return (pafei->fnCallback)(hadid, pafei->pafda, 161 pafei->dwInstance, fdwSupport); 162 } 163 164 /*********************************************************************** 165 * acmFilterEnumA (MSACM32.@) 166 */ 167 MMRESULT WINAPI acmFilterEnumA(HACMDRIVER had, PACMFILTERDETAILSA pafda, 168 ACMFILTERENUMCBA fnCallback, 169 DWORD_PTR dwInstance, DWORD fdwEnum) 170 { 171 ACMFILTERDETAILSW afdw; 172 struct MSACM_FilterEnumWtoA_Instance afei; 173 174 memset(&afdw, 0, sizeof(afdw)); 175 afdw.cbStruct = sizeof(afdw); 176 afdw.dwFilterIndex = pafda->dwFilterIndex; 177 afdw.dwFilterTag = pafda->dwFilterTag; 178 afdw.pwfltr = pafda->pwfltr; 179 afdw.cbwfltr = pafda->cbwfltr; 180 181 afei.pafda = pafda; 182 afei.dwInstance = dwInstance; 183 afei.fnCallback = fnCallback; 184 185 return acmFilterEnumW(had, &afdw, MSACM_FilterEnumCallbackWtoA, 186 (DWORD_PTR)&afei, fdwEnum); 187 } 188 189 static BOOL MSACM_FilterEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had, 190 PACMFILTERDETAILSW pafd, 191 ACMFILTERENUMCBW fnCallback, 192 DWORD_PTR dwInstance, DWORD fdwEnum) 193 { 194 ACMFILTERTAGDETAILSW aftd; 195 unsigned int i, j; 196 197 for (i = 0; i < padid->cFilterTags; i++) { 198 memset(&aftd, 0, sizeof(aftd)); 199 aftd.cbStruct = sizeof(aftd); 200 aftd.dwFilterTagIndex = i; 201 if (acmFilterTagDetailsW(had, &aftd, ACM_FILTERTAGDETAILSF_INDEX) != MMSYSERR_NOERROR) 202 continue; 203 204 if ((fdwEnum & ACM_FILTERENUMF_DWFILTERTAG) && 205 aftd.dwFilterTag != pafd->pwfltr->dwFilterTag) 206 continue; 207 208 for (j = 0; j < aftd.cStandardFilters; j++) { 209 pafd->dwFilterIndex = j; 210 pafd->dwFilterTag = aftd.dwFilterTag; 211 if (acmFilterDetailsW(had, pafd, ACM_FILTERDETAILSF_INDEX) != MMSYSERR_NOERROR) 212 continue; 213 214 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport)) 215 return FALSE; 216 } 217 } 218 return TRUE; 219 } 220 221 /*********************************************************************** 222 * acmFilterEnumW (MSACM32.@) 223 */ 224 MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 225 ACMFILTERENUMCBW fnCallback, 226 DWORD_PTR dwInstance, DWORD fdwEnum) 227 { 228 PWINE_ACMDRIVERID padid; 229 BOOL ret; 230 231 TRACE("(%p, %p, %p, %ld, %d)\n", 232 had, pafd, fnCallback, dwInstance, fdwEnum); 233 234 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM; 235 236 if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG)) 237 FIXME("Unsupported fdwEnum values\n"); 238 239 if (had) { 240 HACMDRIVERID hadid; 241 242 if (acmDriverID((HACMOBJ)had, &hadid, 0) != MMSYSERR_NOERROR) 243 return MMSYSERR_INVALHANDLE; 244 MSACM_FilterEnumHelper(MSACM_GetDriverID(hadid), had, pafd, 245 fnCallback, dwInstance, fdwEnum); 246 return MMSYSERR_NOERROR; 247 } 248 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 249 /* should check for codec only */ 250 if ((padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || 251 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR) 252 continue; 253 ret = MSACM_FilterEnumHelper(padid, had, pafd, 254 fnCallback, dwInstance, fdwEnum); 255 acmDriverClose(had, 0); 256 if (!ret) break; 257 } 258 return MMSYSERR_NOERROR; 259 } 260 261 /*********************************************************************** 262 * acmFilterTagDetailsA (MSACM32.@) 263 */ 264 MMRESULT WINAPI acmFilterTagDetailsA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda, 265 DWORD fdwDetails) 266 { 267 ACMFILTERTAGDETAILSW aftdw; 268 MMRESULT mmr; 269 270 memset(&aftdw, 0, sizeof(aftdw)); 271 aftdw.cbStruct = sizeof(aftdw); 272 aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex; 273 aftdw.dwFilterTag = paftda->dwFilterTag; 274 275 mmr = acmFilterTagDetailsW(had, &aftdw, fdwDetails); 276 if (mmr == MMSYSERR_NOERROR) { 277 paftda->dwFilterTag = aftdw.dwFilterTag; 278 paftda->dwFilterTagIndex = aftdw.dwFilterTagIndex; 279 paftda->cbFilterSize = aftdw.cbFilterSize; 280 paftda->fdwSupport = aftdw.fdwSupport; 281 paftda->cStandardFilters = aftdw.cStandardFilters; 282 WideCharToMultiByte( CP_ACP, 0, aftdw.szFilterTag, -1, paftda->szFilterTag, 283 sizeof(paftda->szFilterTag), NULL, NULL ); 284 } 285 return mmr; 286 } 287 288 /*********************************************************************** 289 * acmFilterTagDetailsW (MSACM32.@) 290 */ 291 MMRESULT WINAPI acmFilterTagDetailsW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, 292 DWORD fdwDetails) 293 { 294 PWINE_ACMDRIVERID padid; 295 MMRESULT mmr; 296 297 TRACE("(%p, %p, %d)\n", had, paftd, fdwDetails); 298 299 if (fdwDetails & ~(ACM_FILTERTAGDETAILSF_FILTERTAG|ACM_FILTERTAGDETAILSF_INDEX| 300 ACM_FILTERTAGDETAILSF_LARGESTSIZE)) 301 return MMSYSERR_INVALFLAG; 302 303 switch (fdwDetails) { 304 case ACM_FILTERTAGDETAILSF_FILTERTAG: 305 if (had == NULL) { 306 mmr = ACMERR_NOTPOSSIBLE; 307 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 308 /* should check for codec only */ 309 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 310 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 311 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails); 312 acmDriverClose(had, 0); 313 if (mmr == MMSYSERR_NOERROR) break; 314 } 315 } 316 } else { 317 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails); 318 } 319 break; 320 321 case ACM_FILTERTAGDETAILSF_INDEX: 322 /* FIXME should check paftd->dwFilterTagIndex < add.cFilterTags */ 323 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails); 324 break; 325 326 case ACM_FILTERTAGDETAILSF_LARGESTSIZE: 327 if (had == NULL) { 328 ACMFILTERTAGDETAILSW tmp; 329 DWORD ft = paftd->dwFilterTag; 330 331 mmr = ACMERR_NOTPOSSIBLE; 332 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 333 /* should check for codec only */ 334 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 335 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { 336 337 memset(&tmp, 0, sizeof(tmp)); 338 tmp.cbStruct = sizeof(tmp); 339 tmp.dwFilterTag = ft; 340 341 if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, 342 (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) { 343 if (mmr == ACMERR_NOTPOSSIBLE || 344 paftd->cbFilterSize < tmp.cbFilterSize) { 345 *paftd = tmp; 346 mmr = MMSYSERR_NOERROR; 347 } 348 } 349 acmDriverClose(had, 0); 350 } 351 } 352 } else { 353 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails); 354 } 355 break; 356 357 default: 358 WARN("Unsupported fdwDetails=%08x\n", fdwDetails); 359 mmr = MMSYSERR_ERROR; 360 } 361 362 if (mmr == MMSYSERR_NOERROR && 363 paftd->dwFilterTag == WAVE_FORMAT_PCM && paftd->szFilterTag[0] == 0) 364 MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFilterTag, 365 sizeof(paftd->szFilterTag)/sizeof(WCHAR) ); 366 367 return mmr; 368 } 369 370 struct MSACM_FilterTagEnumWtoA_Instance { 371 PACMFILTERTAGDETAILSA paftda; 372 DWORD_PTR dwInstance; 373 ACMFILTERTAGENUMCBA fnCallback; 374 }; 375 376 static BOOL CALLBACK MSACM_FilterTagEnumCallbackWtoA(HACMDRIVERID hadid, 377 PACMFILTERTAGDETAILSW paftdw, 378 DWORD_PTR dwInstance, 379 DWORD fdwSupport) 380 { 381 struct MSACM_FilterTagEnumWtoA_Instance* paftei; 382 383 paftei = (struct MSACM_FilterTagEnumWtoA_Instance*)dwInstance; 384 385 paftei->paftda->dwFilterTagIndex = paftdw->dwFilterTagIndex; 386 paftei->paftda->dwFilterTag = paftdw->dwFilterTag; 387 paftei->paftda->cbFilterSize = paftdw->cbFilterSize; 388 paftei->paftda->fdwSupport = paftdw->fdwSupport; 389 paftei->paftda->cStandardFilters = paftdw->cStandardFilters; 390 WideCharToMultiByte( CP_ACP, 0, paftdw->szFilterTag, -1, paftei->paftda->szFilterTag, 391 sizeof(paftei->paftda->szFilterTag), NULL, NULL ); 392 393 return (paftei->fnCallback)(hadid, paftei->paftda, 394 paftei->dwInstance, fdwSupport); 395 } 396 397 /*********************************************************************** 398 * acmFilterTagEnumA (MSACM32.@) 399 */ 400 MMRESULT WINAPI acmFilterTagEnumA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda, 401 ACMFILTERTAGENUMCBA fnCallback, 402 DWORD_PTR dwInstance, DWORD fdwEnum) 403 { 404 ACMFILTERTAGDETAILSW aftdw; 405 struct MSACM_FilterTagEnumWtoA_Instance aftei; 406 407 memset(&aftdw, 0, sizeof(aftdw)); 408 aftdw.cbStruct = sizeof(aftdw); 409 aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex; 410 aftdw.dwFilterTag = paftda->dwFilterTag; 411 412 aftei.paftda = paftda; 413 aftei.dwInstance = dwInstance; 414 aftei.fnCallback = fnCallback; 415 416 return acmFilterTagEnumW(had, &aftdw, MSACM_FilterTagEnumCallbackWtoA, 417 (DWORD_PTR)&aftei, fdwEnum); 418 } 419 420 /*********************************************************************** 421 * acmFilterTagEnumW (MSACM32.@) 422 */ 423 MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, 424 ACMFILTERTAGENUMCBW fnCallback, 425 DWORD_PTR dwInstance, DWORD fdwEnum) 426 { 427 PWINE_ACMDRIVERID padid; 428 unsigned int i; 429 430 TRACE("(%p, %p, %p, %ld, %d)\n", 431 had, paftd, fnCallback, dwInstance, fdwEnum); 432 433 if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM; 434 435 if (had) FIXME("had != NULL, not supported\n"); 436 437 for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { 438 /* should check for codec only */ 439 if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && 440 acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) { 441 442 for (i = 0; i < padid->cFilterTags; i++) { 443 paftd->dwFilterTagIndex = i; 444 if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) { 445 if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, padid->fdwSupport)) { 446 padid = NULL; 447 break; 448 } 449 } 450 } 451 acmDriverClose(had, 0); 452 } 453 } 454 return MMSYSERR_NOERROR; 455 } 456