1 /* 2 * Unit tests for msacm functions 3 * 4 * Copyright (c) 2004 Robert Reif 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <math.h> 25 26 #include "wine/test.h" 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winnls.h" 30 #include "mmsystem.h" 31 #define NOBITMAP 32 #include "mmreg.h" 33 #include "msacm.h" 34 #include "wine/msacmdrv.h" 35 36 static BOOL CALLBACK FormatTagEnumProc(HACMDRIVERID hadid, 37 PACMFORMATTAGDETAILSA paftd, 38 DWORD_PTR dwInstance, 39 DWORD fdwSupport) 40 { 41 MMRESULT rc; 42 HACMDRIVER had; 43 44 if (winetest_interactive) 45 trace(" Format 0x%04x: %s\n", paftd->dwFormatTag, paftd->szFormatTag); 46 47 rc = acmDriverOpen(&had, hadid, 0); 48 ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NODRIVER, 49 "acmDriverOpen(): rc = %08x, should be %08x\n", 50 rc, MMSYSERR_NOERROR); 51 52 if (rc == MMSYSERR_NOERROR) 53 { 54 ACMFORMATDETAILSA fd = {0}; 55 WAVEFORMATEX *pwfx, dst; 56 ACMFORMATTAGDETAILSA aftd_pcm = {0}; 57 DWORD dwSize, dwSizeMax; 58 DWORD i; 59 60 fd.cbStruct = sizeof(fd); 61 if (paftd->cbFormatSize < sizeof(WAVEFORMATEX)) 62 pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEFORMATEX)); 63 else 64 pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, paftd->cbFormatSize); 65 fd.pwfx = pwfx; 66 fd.cbwfx = paftd->cbFormatSize; 67 fd.dwFormatTag = paftd->dwFormatTag; 68 69 /* try bad pwfx */ 70 fd.pwfx = NULL; 71 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_FORMAT); 72 ok(rc == MMSYSERR_INVALPARAM, 73 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 74 rc, MMSYSERR_INVALPARAM); 75 fd.pwfx = pwfx; 76 77 /* try bad wFormatTag */ 78 fd.pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN; 79 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_FORMAT); 80 ok(rc == MMSYSERR_INVALPARAM, 81 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 82 rc, MMSYSERR_INVALPARAM); 83 fd.pwfx->wFormatTag = paftd->dwFormatTag; 84 85 /* try bad fdwSupport */ 86 fd.fdwSupport = 0xdeadbeef; 87 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_FORMAT); 88 ok(rc == MMSYSERR_INVALPARAM, 89 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 90 rc, MMSYSERR_INVALPARAM); 91 fd.fdwSupport = 0; 92 93 /* try bad pwfx structure size */ 94 fd.cbwfx = sizeof(PCMWAVEFORMAT)-1; 95 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_FORMAT); 96 ok(rc == MMSYSERR_INVALPARAM, 97 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 98 rc, MMSYSERR_INVALPARAM); 99 fd.cbwfx = paftd->cbFormatSize; 100 101 /* test bad parameters (all zero) */ 102 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_FORMAT); 103 ok(rc == ACMERR_NOTPOSSIBLE, 104 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 105 rc, ACMERR_NOTPOSSIBLE); 106 107 /* test acmFormatSuggest */ 108 109 /* if we don't specify a format, we must give at least the driver's maximum size for any format */ 110 acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); 111 rc = acmFormatSuggest(had, pwfx, &dst, dwSize-1, 0); 112 ok(rc == MMSYSERR_INVALPARAM, 113 "acmFormatSuggest(): rc = %08x, should be %08x\n", 114 rc, MMSYSERR_INVALPARAM); 115 116 rc = acmFormatSuggest(had, pwfx, &dst, dwSize, 0); 117 ok(rc == ACMERR_NOTPOSSIBLE, 118 "acmFormatSuggest(): rc = %08x, should be %08x\n", 119 rc, ACMERR_NOTPOSSIBLE); 120 121 /* if we do specify a format, we must give at least the driver's maximum size for that format */ 122 aftd_pcm.cbStruct = sizeof(aftd_pcm); 123 aftd_pcm.dwFormatTag = WAVE_FORMAT_PCM; 124 rc = acmFormatTagDetailsA(had, &aftd_pcm, ACM_FORMATTAGDETAILSF_LARGESTSIZE); 125 ok(rc == MMSYSERR_NOERROR, "returned %08x\n", rc); 126 127 dst.wFormatTag = WAVE_FORMAT_PCM; 128 rc = acmFormatSuggest(had, pwfx, &dst, aftd_pcm.cbFormatSize-1, ACM_FORMATSUGGESTF_WFORMATTAG); 129 ok(rc == MMSYSERR_INVALPARAM, 130 "acmFormatSuggest(): rc = %08x, should be %08x\n", 131 rc, MMSYSERR_INVALPARAM); 132 133 rc = acmFormatSuggest(had, pwfx, &dst, aftd_pcm.cbFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG); 134 ok(rc == ACMERR_NOTPOSSIBLE, 135 "acmFormatSuggest(): rc = %08x, should be %08x\n", 136 rc, ACMERR_NOTPOSSIBLE); 137 138 /* test nonexistent format */ 139 dst.wFormatTag = 0xbeef; 140 rc = acmFormatSuggest(had, pwfx, &dst, 0, ACM_FORMATSUGGESTF_WFORMATTAG); 141 ok(rc == ACMERR_NOTPOSSIBLE || rc == MMSYSERR_INVALPARAM, 142 "acmFormatSuggest(): rc = %08x, should be %08x\n", 143 rc, ACMERR_NOTPOSSIBLE); 144 145 /* if the driver is NULL, we must give at least the maximum size for any driver */ 146 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &dwSizeMax); 147 rc = acmFormatSuggest(NULL, pwfx, &dst, dwSizeMax-1, 0); 148 ok(rc == MMSYSERR_INVALPARAM, 149 "acmFormatSuggest(): rc = %08x, should be %08x\n", 150 rc, MMSYSERR_INVALPARAM); 151 152 if (paftd->dwFormatTag != WAVE_FORMAT_PCM) 153 { 154 rc = acmFormatSuggest(NULL, pwfx, &dst, dwSizeMax, 0); 155 ok(rc == ACMERR_NOTPOSSIBLE, 156 "acmFormatSuggest(): rc = %08x, should be %08x\n", 157 rc, ACMERR_NOTPOSSIBLE); 158 } 159 160 /* if we specify a dst format, we must give the maximum size for that format */ 161 dst.wFormatTag = WAVE_FORMAT_PCM; 162 rc = acmFormatSuggest(NULL, pwfx, &dst, aftd_pcm.cbFormatSize-1, ACM_FORMATSUGGESTF_WFORMATTAG); 163 ok(rc == MMSYSERR_INVALPARAM || broken (rc == ACMERR_NOTPOSSIBLE), /* WinXP */ 164 "acmFormatSuggest(): rc = %08x, should be %08x\n", 165 rc, MMSYSERR_INVALPARAM); 166 167 rc = acmFormatSuggest(NULL, pwfx, &dst, aftd_pcm.cbFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG); 168 ok(rc == ACMERR_NOTPOSSIBLE, 169 "acmFormatSuggest(): rc = %08x, should be %08x\n", 170 rc, ACMERR_NOTPOSSIBLE); 171 172 dst.wFormatTag = paftd->dwFormatTag; 173 rc = acmFormatSuggest(NULL, pwfx, &dst, paftd->cbFormatSize-1, ACM_FORMATSUGGESTF_WFORMATTAG); 174 ok(rc == MMSYSERR_INVALPARAM || broken (rc == ACMERR_NOTPOSSIBLE), /* WinXP */ 175 "acmFormatSuggest(): rc = %08x, should be %08x\n", 176 rc, MMSYSERR_INVALPARAM); 177 178 rc = acmFormatSuggest(NULL, pwfx, &dst, paftd->cbFormatSize, ACM_FORMATSUGGESTF_WFORMATTAG); 179 ok(rc == ACMERR_NOTPOSSIBLE, 180 "acmFormatSuggest(): rc = %08x, should be %08x\n", 181 rc, ACMERR_NOTPOSSIBLE); 182 183 /* test nonexistent format */ 184 dst.wFormatTag = 0xbeef; 185 rc = acmFormatSuggest(NULL, pwfx, &dst, 0, ACM_FORMATSUGGESTF_WFORMATTAG); 186 ok(rc == ACMERR_NOTPOSSIBLE || rc == MMSYSERR_INVALPARAM, 187 "acmFormatSuggest(): rc = %08x, should be %08x\n", 188 rc, ACMERR_NOTPOSSIBLE); 189 190 /* test index */ 191 for (i = 0; i < paftd->cStandardFormats; i++) 192 { 193 fd.dwFormatIndex = i; 194 195 fd.fdwSupport = 0; 196 fd.cbwfx = paftd->cbFormatSize; 197 fd.pwfx->cbSize = 0xbeef; 198 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 199 ok(rc == MMSYSERR_NOERROR, 200 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 201 rc, MMSYSERR_NOERROR); 202 203 /* Windows will write cbSize (and other data) even if the 204 * given cbwfx is not large enough */ 205 fd.fdwSupport = 0; 206 fd.cbwfx = sizeof(PCMWAVEFORMAT); 207 fd.pwfx->cbSize = 0xbeef; 208 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 209 todo_wine_if(rc != MMSYSERR_NOERROR) /* remove when fixed */ 210 ok(rc == MMSYSERR_NOERROR, 211 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 212 rc, MMSYSERR_NOERROR); 213 if (paftd->dwFormatTag != WAVE_FORMAT_PCM) 214 todo_wine_if(fd.pwfx->cbSize != paftd->cbFormatSize - sizeof(WAVEFORMATEX)) /* remove when fixed */ 215 ok(fd.pwfx->cbSize == paftd->cbFormatSize - sizeof(WAVEFORMATEX), 216 "got %d\n", fd.pwfx->cbSize); 217 } 218 219 /* one more */ 220 fd.dwFormatIndex = paftd->cStandardFormats; 221 fd.fdwSupport = 0; 222 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 223 ok(rc == MMSYSERR_INVALPARAM, 224 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 225 rc, MMSYSERR_INVALPARAM); 226 227 HeapFree(GetProcessHeap(), 0, pwfx); 228 } 229 return TRUE; 230 } 231 232 static BOOL CALLBACK FormatEnumProc(HACMDRIVERID hadid, 233 LPACMFORMATDETAILSA pafd, 234 DWORD_PTR dwInstance, 235 DWORD fd) 236 { 237 MMRESULT rc; 238 HACMDRIVER had; 239 WAVEFORMATEX *dst, *dstMax; 240 DWORD dwSize, dwSizeMax; 241 DWORD fdwSupport; 242 243 acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, &fdwSupport); 244 245 if (winetest_interactive) 246 trace(" 0x%04x, %s\n", pafd->dwFormatTag, pafd->szFormat); 247 248 acmDriverOpen(&had, hadid, 0); 249 dwSize = pafd->cbwfx; 250 dst = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 251 252 /* test acmFormatSuggest with valid src format */ 253 if (pafd->dwFormatTag == WAVE_FORMAT_PCM) 254 { 255 rc = acmFormatSuggest(had, pafd->pwfx, dst, dwSize, 0); 256 /* this fails on some decode-only drivers */ 257 ok(rc == MMSYSERR_NOERROR || rc == ACMERR_NOTPOSSIBLE, 258 "acmFormatSuggest(): rc = %08x, should be %08x\n", 259 rc, MMSYSERR_NOERROR); 260 if (rc == MMSYSERR_NOERROR) 261 { 262 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) /* supports different conversions */ 263 ok(dst->wFormatTag != WAVE_FORMAT_PCM, "expected different format\n"); 264 else 265 ok(dst->wFormatTag == WAVE_FORMAT_PCM, 266 "expected %d, got %d\n", WAVE_FORMAT_PCM, dst->wFormatTag); 267 } 268 } 269 else 270 { 271 rc = acmFormatSuggest(had, pafd->pwfx, dst, dwSize, 0); 272 ok(rc == MMSYSERR_NOERROR, 273 "acmFormatSuggest(): rc = %08x, should be %08x\n", 274 rc, MMSYSERR_NOERROR); 275 ok(dst->wFormatTag == WAVE_FORMAT_PCM, 276 "expected %d, got %d\n", WAVE_FORMAT_PCM, dst->wFormatTag); 277 ok(dst->nChannels == pafd->pwfx->nChannels, 278 "expected %d, got %d\n", pafd->pwfx->nChannels, dst->nChannels); 279 if (pafd->dwFormatTag != 0x42) /* codec 0x0042 returns a different sample rate */ 280 ok(dst->nSamplesPerSec == pafd->pwfx->nSamplesPerSec, 281 "expected %d, got %d\n", pafd->pwfx->nSamplesPerSec, dst->nSamplesPerSec); 282 ok(dst->wBitsPerSample == 16, 283 "expected %d, got %d\n", 16, dst->wBitsPerSample); 284 ok(dst->nBlockAlign == 2*pafd->pwfx->nChannels, 285 "expected %d, got %d\n", 2*pafd->pwfx->nChannels, dst->nBlockAlign); 286 287 /* test with NULL driver */ 288 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &dwSizeMax); 289 dstMax = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSizeMax); 290 rc = acmFormatSuggest(NULL, pafd->pwfx, dstMax, dwSizeMax, 0); 291 ok(rc == MMSYSERR_NOERROR, 292 "acmFormatSuggest(): rc = %08x, should be %08x\n", 293 rc, MMSYSERR_NOERROR); 294 295 HeapFree(GetProcessHeap(), 0, dstMax); 296 } 297 298 ZeroMemory(dst, dwSize); 299 dst->wFormatTag = pafd->pwfx->wFormatTag; 300 rc = acmFormatSuggest(had, pafd->pwfx, dst, dwSize, ACM_FORMATSUGGESTF_WFORMATTAG); 301 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) /* supports same conversions */ 302 ok(rc == MMSYSERR_NOERROR, 303 "acmFormatSuggest(): rc = %08x, should be %08x\n", 304 rc, MMSYSERR_NOERROR); 305 else 306 todo_wine_if(rc != ACMERR_NOTPOSSIBLE) 307 ok(rc == ACMERR_NOTPOSSIBLE, 308 "acmFormatSuggest(): rc = %08x, should be %08x\n", 309 rc, ACMERR_NOTPOSSIBLE); 310 311 HeapFree(GetProcessHeap(), 0, dst); 312 acmDriverClose(had, 0); 313 314 return TRUE; 315 } 316 317 static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid, 318 DWORD_PTR dwInstance, 319 DWORD fdwSupport) 320 { 321 MMRESULT rc; 322 ACMDRIVERDETAILSA dd; 323 HACMDRIVER had; 324 325 DWORD dwDriverPriority; 326 DWORD dwDriverSupport; 327 328 if (winetest_interactive) { 329 trace("id: %p\n", hadid); 330 trace(" Supports:\n"); 331 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_ASYNC) 332 trace(" async conversions\n"); 333 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) 334 trace(" different format conversions\n"); 335 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CONVERTER) 336 trace(" same format conversions\n"); 337 if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_FILTER) 338 trace(" filtering\n"); 339 } 340 341 /* try an invalid pointer */ 342 rc = acmDriverDetailsA(hadid, 0, 0); 343 ok(rc == MMSYSERR_INVALPARAM, 344 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 345 rc, MMSYSERR_INVALPARAM); 346 347 /* try an invalid structure size */ 348 ZeroMemory(&dd, sizeof(dd)); 349 rc = acmDriverDetailsA(hadid, &dd, 0); 350 ok(rc == MMSYSERR_INVALPARAM, 351 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 352 rc, MMSYSERR_INVALPARAM); 353 354 /* MSDN says this should fail but it doesn't in practice */ 355 dd.cbStruct = 4; 356 rc = acmDriverDetailsA(hadid, &dd, 0); 357 ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, 358 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 359 rc, MMSYSERR_NOERROR); 360 361 /* try an invalid handle */ 362 dd.cbStruct = sizeof(dd); 363 rc = acmDriverDetailsA((HACMDRIVERID)1, &dd, 0); 364 ok(rc == MMSYSERR_INVALHANDLE, 365 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 366 rc, MMSYSERR_INVALHANDLE); 367 368 /* try an invalid handle and pointer */ 369 rc = acmDriverDetailsA((HACMDRIVERID)1, 0, 0); 370 ok(rc == MMSYSERR_INVALPARAM, 371 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 372 rc, MMSYSERR_INVALPARAM); 373 374 /* try invalid details */ 375 rc = acmDriverDetailsA(hadid, &dd, -1); 376 ok(rc == MMSYSERR_INVALFLAG, 377 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 378 rc, MMSYSERR_INVALFLAG); 379 380 /* try valid parameters */ 381 rc = acmDriverDetailsA(hadid, &dd, 0); 382 ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED, 383 "acmDriverDetailsA(): rc = %08x, should be %08x\n", 384 rc, MMSYSERR_NOERROR); 385 386 /* cbStruct should contain size of returned data (at most sizeof(dd)) 387 TODO: should it be *exactly* sizeof(dd), as tested here? 388 */ 389 if (rc == MMSYSERR_NOERROR) { 390 static const struct { 391 const char *shortname; 392 WORD mid; 393 WORD pid; 394 WORD pid_alt; 395 } *iter, expected_ids[] = { 396 { "Microsoft IMA ADPCM", MM_MICROSOFT, MM_MSFT_ACM_IMAADPCM }, 397 { "MS-ADPCM", MM_MICROSOFT, MM_MSFT_ACM_MSADPCM }, 398 { "Microsoft CCITT G.711", MM_MICROSOFT, MM_MSFT_ACM_G711}, 399 { "MPEG Layer-3 Codec", MM_FRAUNHOFER_IIS, MM_FHGIIS_MPEGLAYER3_DECODE, MM_FHGIIS_MPEGLAYER3_PROFESSIONAL }, 400 { "MS-PCM", MM_MICROSOFT, MM_MSFT_ACM_PCM }, 401 { 0 } 402 }; 403 404 ok(dd.cbStruct == sizeof(dd), 405 "acmDriverDetailsA(): cbStruct = %08x\n", dd.cbStruct); 406 407 for (iter = expected_ids; iter->shortname; ++iter) { 408 if (!strcmp(iter->shortname, dd.szShortName)) { 409 /* try alternative product id on mismatch */ 410 if (iter->pid_alt && iter->pid != dd.wPid) 411 ok(iter->mid == dd.wMid && iter->pid_alt == dd.wPid, 412 "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n", 413 dd.wMid, iter->mid, 414 dd.wPid, iter->pid_alt); 415 else 416 ok(iter->mid == dd.wMid && iter->pid == dd.wPid, 417 "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n", 418 dd.wMid, iter->mid, 419 dd.wPid, iter->pid); 420 } 421 } 422 } 423 424 if (rc == MMSYSERR_NOERROR && winetest_interactive) { 425 trace(" Short name: %s\n", dd.szShortName); 426 trace(" Long name: %s\n", dd.szLongName); 427 trace(" Copyright: %s\n", dd.szCopyright); 428 trace(" Licensing: %s\n", dd.szLicensing); 429 trace(" Features: %s\n", dd.szFeatures); 430 trace(" Supports %u formats\n", dd.cFormatTags); 431 trace(" Supports %u filter formats\n", dd.cFilterTags); 432 trace(" Mid: 0x%x\n", dd.wMid); 433 trace(" Pid: 0x%x\n", dd.wPid); 434 } 435 436 /* try bad pointer */ 437 rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, 0); 438 ok(rc == MMSYSERR_INVALPARAM, 439 "acmMetrics(): rc = %08x, should be %08x\n", 440 rc, MMSYSERR_INVALPARAM); 441 442 /* try bad handle */ 443 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, &dwDriverPriority); 444 ok(rc == MMSYSERR_INVALHANDLE, 445 "acmMetrics(): rc = %08x, should be %08x\n", 446 rc, MMSYSERR_INVALHANDLE); 447 448 /* try bad pointer and handle */ 449 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_PRIORITY, 0); 450 ok(rc == MMSYSERR_INVALHANDLE, 451 "acmMetrics(): rc = %08x, should be %08x\n", 452 rc, MMSYSERR_INVALHANDLE); 453 454 /* try valid parameters */ 455 rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_PRIORITY, &dwDriverSupport); 456 ok(rc == MMSYSERR_NOERROR, 457 "acmMetrics(): rc = %08x, should be %08x\n", 458 rc, MMSYSERR_NOERROR); 459 460 /* try bad pointer */ 461 rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, 0); 462 ok(rc == MMSYSERR_INVALPARAM, 463 "acmMetrics(): rc = %08x, should be %08x\n", 464 rc, MMSYSERR_INVALPARAM); 465 466 /* try bad handle */ 467 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); 468 ok(rc == MMSYSERR_INVALHANDLE, 469 "acmMetrics(): rc = %08x, should be %08x\n", 470 rc, MMSYSERR_INVALHANDLE); 471 472 /* try bad pointer and handle */ 473 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_DRIVER_SUPPORT, 0); 474 ok(rc == MMSYSERR_INVALHANDLE, 475 "acmMetrics(): rc = %08x, should be %08x\n", 476 rc, MMSYSERR_INVALHANDLE); 477 478 /* try valid parameters */ 479 rc = acmMetrics((HACMOBJ)hadid, ACM_METRIC_DRIVER_SUPPORT, &dwDriverSupport); 480 ok(rc == MMSYSERR_NOERROR, 481 "acmMetrics(): rc = %08x, should be %08x\n", 482 rc, MMSYSERR_NOERROR); 483 484 /* try invalid pointer */ 485 rc = acmDriverOpen(0, hadid, 0); 486 ok(rc == MMSYSERR_INVALPARAM, 487 "acmDriverOpen(): rc = %08x, should be %08x\n", 488 rc, MMSYSERR_INVALPARAM); 489 490 /* try invalid handle */ 491 rc = acmDriverOpen(&had, (HACMDRIVERID)1, 0); 492 ok(rc == MMSYSERR_INVALHANDLE, 493 "acmDriverOpen(): rc = %08x, should be %08x\n", 494 rc, MMSYSERR_INVALHANDLE); 495 496 /* try invalid open */ 497 rc = acmDriverOpen(&had, hadid, -1); 498 ok(rc == MMSYSERR_INVALFLAG, 499 "acmDriverOpen(): rc = %08x, should be %08x\n", 500 rc, MMSYSERR_INVALFLAG); 501 502 /* try valid parameters */ 503 rc = acmDriverOpen(&had, hadid, 0); 504 ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NODRIVER, 505 "acmDriverOpen(): rc = %08x, should be %08x\n", 506 rc, MMSYSERR_NOERROR); 507 508 if (rc == MMSYSERR_NOERROR) { 509 DWORD dwSize; 510 HACMDRIVERID hid; 511 512 /* try bad pointer */ 513 rc = acmDriverID((HACMOBJ)had, 0, 0); 514 ok(rc == MMSYSERR_INVALPARAM, 515 "acmDriverID(): rc = %08x, should be %08x\n", 516 rc, MMSYSERR_INVALPARAM); 517 518 /* try bad handle */ 519 rc = acmDriverID((HACMOBJ)1, &hid, 0); 520 ok(rc == MMSYSERR_INVALHANDLE, 521 "acmDriverID(): rc = %08x, should be %08x\n", 522 rc, MMSYSERR_INVALHANDLE); 523 524 /* try bad handle and pointer */ 525 rc = acmDriverID((HACMOBJ)1, 0, 0); 526 ok(rc == MMSYSERR_INVALHANDLE, 527 "acmDriverID(): rc = %08x, should be %08x\n", 528 rc, MMSYSERR_INVALHANDLE); 529 530 /* try bad flag */ 531 rc = acmDriverID((HACMOBJ)had, &hid, 1); 532 ok(rc == MMSYSERR_INVALFLAG, 533 "acmDriverID(): rc = %08x, should be %08x\n", 534 rc, MMSYSERR_INVALFLAG); 535 536 /* try valid parameters */ 537 rc = acmDriverID((HACMOBJ)had, &hid, 0); 538 ok(rc == MMSYSERR_NOERROR, 539 "acmDriverID(): rc = %08x, should be %08x\n", 540 rc, MMSYSERR_NOERROR); 541 ok(hid == hadid, 542 "acmDriverID() returned ID %p doesn't equal %p\n", 543 hid, hadid); 544 545 /* try bad pointer */ 546 rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, 0); 547 ok(rc == MMSYSERR_INVALPARAM, 548 "acmMetrics(): rc = %08x, should be %08x\n", 549 rc, MMSYSERR_INVALPARAM); 550 551 /* try bad handle */ 552 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); 553 ok(rc == MMSYSERR_INVALHANDLE, 554 "acmMetrics(): rc = %08x, should be %08x\n", 555 rc, MMSYSERR_INVALHANDLE); 556 557 /* try bad pointer and handle */ 558 rc = acmMetrics((HACMOBJ)1, ACM_METRIC_MAX_SIZE_FORMAT, 0); 559 ok(rc == MMSYSERR_INVALHANDLE, 560 "acmMetrics(): rc = %08x, should be %08x\n", 561 rc, MMSYSERR_INVALHANDLE); 562 563 /* try valid parameters */ 564 rc = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize); 565 ok(rc == MMSYSERR_NOERROR, 566 "acmMetrics(): rc = %08x, should be %08x\n", 567 rc, MMSYSERR_NOERROR); 568 if (rc == MMSYSERR_NOERROR) { 569 ACMFORMATDETAILSA fd; 570 WAVEFORMATEX * pwfx; 571 ACMFORMATTAGDETAILSA aftd; 572 573 /* try bad pointer */ 574 rc = acmFormatEnumA(had, 0, FormatEnumProc, 0, 0); 575 ok(rc == MMSYSERR_INVALPARAM, 576 "acmFormatEnumA(): rc = %08x, should be %08x\n", 577 rc, MMSYSERR_INVALPARAM); 578 579 /* try bad structure size */ 580 ZeroMemory(&fd, sizeof(fd)); 581 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 582 ok(rc == MMSYSERR_INVALPARAM, 583 "acmFormatEnumA(): rc = %08x, should be %08x\n", 584 rc, MMSYSERR_INVALPARAM); 585 586 fd.cbStruct = sizeof(fd) - 1; 587 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 588 ok(rc == MMSYSERR_INVALPARAM, 589 "acmFormatEnumA(): rc = %08x, should be %08x\n", 590 rc, MMSYSERR_INVALPARAM); 591 592 pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 593 594 if (dwSize >= sizeof(WAVEFORMATEX)) 595 pwfx->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX); 596 pwfx->wFormatTag = WAVE_FORMAT_UNKNOWN; 597 598 fd.cbStruct = sizeof(fd); 599 fd.pwfx = pwfx; 600 fd.cbwfx = dwSize; 601 fd.dwFormatTag = WAVE_FORMAT_UNKNOWN; 602 603 /* try bad callback */ 604 rc = acmFormatEnumA(had, &fd, NULL, 0, 0); 605 ok(rc == MMSYSERR_INVALPARAM, 606 "acmFormatEnumA(): rc = %08x, should be %08x\n", 607 rc, MMSYSERR_INVALPARAM); 608 609 /* try bad pwfx */ 610 fd.pwfx = NULL; 611 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 612 ok(rc == MMSYSERR_INVALPARAM, 613 "acmFormatEnumA(): rc = %08x, should be %08x\n", 614 rc, MMSYSERR_INVALPARAM); 615 fd.pwfx = pwfx; 616 617 /* fdwSupport must be zero */ 618 fd.fdwSupport = 0xdeadbeef; 619 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 620 ok(rc == MMSYSERR_INVALPARAM, 621 "acmFormatEnumA(): rc = %08x, should be %08x\n", 622 rc, MMSYSERR_INVALPARAM); 623 fd.fdwSupport = 0; 624 625 /* try bad pwfx structure size */ 626 fd.cbwfx = dwSize-1; 627 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 628 ok(rc == MMSYSERR_INVALPARAM, 629 "acmFormatEnumA(): rc = %08x, should be %08x\n", 630 rc, MMSYSERR_INVALPARAM); 631 fd.cbwfx = dwSize; 632 633 /* try valid parameters */ 634 rc = acmFormatEnumA(had, &fd, FormatEnumProc, 0, 0); 635 ok(rc == MMSYSERR_NOERROR, 636 "acmFormatEnumA(): rc = %08x, should be %08x\n", 637 rc, MMSYSERR_NOERROR); 638 639 /* try bad pointer */ 640 rc = acmFormatTagEnumA(had, 0, FormatTagEnumProc, 0, 0); 641 ok(rc == MMSYSERR_INVALPARAM, 642 "acmFormatTagEnumA(): rc = %08x, should be %08x\n", 643 rc, MMSYSERR_INVALPARAM); 644 645 /* try bad structure size */ 646 ZeroMemory(&aftd, sizeof(aftd)); 647 rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); 648 ok(rc == MMSYSERR_INVALPARAM, 649 "acmFormatTagEnumA(): rc = %08x, should be %08x\n", 650 rc, MMSYSERR_INVALPARAM); 651 652 aftd.cbStruct = sizeof(aftd) - 1; 653 rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); 654 ok(rc == MMSYSERR_INVALPARAM, 655 "acmFormatTagEnumA(): rc = %08x, should be %08x\n", 656 rc, MMSYSERR_INVALPARAM); 657 658 aftd.cbStruct = sizeof(aftd); 659 aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN; 660 661 /* try bad flag */ 662 rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 1); 663 ok(rc == MMSYSERR_INVALFLAG, 664 "acmFormatTagEnumA(): rc = %08x, should be %08x\n", 665 rc, MMSYSERR_INVALFLAG); 666 667 /* try valid parameters */ 668 rc = acmFormatTagEnumA(had, &aftd, FormatTagEnumProc, 0, 0); 669 ok(rc == MMSYSERR_NOERROR, 670 "acmFormatTagEnumA(): rc = %08x, should be %08x\n", 671 rc, MMSYSERR_NOERROR); 672 673 /* try bad pointer */ 674 rc = acmFormatDetailsA(had, NULL, ACM_FORMATDETAILSF_INDEX); 675 ok(rc == MMSYSERR_INVALPARAM, 676 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 677 rc, MMSYSERR_INVALPARAM); 678 679 /* try bad structure size */ 680 ZeroMemory(&fd, sizeof(fd)); 681 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 682 ok(rc == MMSYSERR_INVALPARAM, 683 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 684 rc, MMSYSERR_INVALPARAM); 685 686 fd.cbStruct = sizeof(fd) - 1; 687 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 688 ok(rc == MMSYSERR_INVALPARAM, 689 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 690 rc, MMSYSERR_INVALPARAM); 691 692 fd.cbStruct = sizeof(fd); 693 fd.pwfx = pwfx; 694 ZeroMemory(fd.pwfx, dwSize); 695 fd.cbwfx = dwSize; 696 fd.dwFormatTag = WAVE_FORMAT_UNKNOWN; 697 698 /* try WAVE_FORMAT_UNKNOWN */ 699 rc = acmFormatDetailsA(had, &fd, ACM_FORMATDETAILSF_INDEX); 700 ok(rc == MMSYSERR_INVALPARAM, 701 "acmFormatDetailsA(): rc = %08x, should be %08x\n", 702 rc, MMSYSERR_INVALPARAM); 703 704 HeapFree(GetProcessHeap(), 0, pwfx); 705 706 /* try invalid handle */ 707 rc = acmDriverClose((HACMDRIVER)1, 0); 708 ok(rc == MMSYSERR_INVALHANDLE, 709 "acmDriverClose(): rc = %08x, should be %08x\n", 710 rc, MMSYSERR_INVALHANDLE); 711 712 /* try invalid flag */ 713 rc = acmDriverClose(had, 1); 714 ok(rc == MMSYSERR_INVALFLAG, 715 "acmDriverClose(): rc = %08x, should be %08x\n", 716 rc, MMSYSERR_INVALFLAG); 717 718 /* try valid parameters */ 719 rc = acmDriverClose(had, 0); 720 ok(rc == MMSYSERR_NOERROR, 721 "acmDriverClose(): rc = %08x, should be %08x\n", 722 rc, MMSYSERR_NOERROR); 723 724 /* try closing again */ 725 rc = acmDriverClose(had, 0); 726 ok(rc == MMSYSERR_INVALHANDLE, 727 "acmDriverClose(): rc = %08x, should be %08x\n", 728 rc, MMSYSERR_INVALHANDLE); 729 } 730 } 731 732 return TRUE; 733 } 734 735 static const char * get_metric(UINT uMetric) 736 { 737 switch (uMetric) { 738 case ACM_METRIC_COUNT_CODECS: 739 return "ACM_METRIC_COUNT_CODECS"; 740 case ACM_METRIC_COUNT_CONVERTERS: 741 return "ACM_METRIC_COUNT_CONVERTERS"; 742 case ACM_METRIC_COUNT_DISABLED: 743 return "ACM_METRIC_COUNT_DISABLED"; 744 case ACM_METRIC_COUNT_DRIVERS: 745 return "ACM_METRIC_COUNT_DRIVERS"; 746 case ACM_METRIC_COUNT_FILTERS: 747 return "ACM_METRIC_COUNT_FILTERS"; 748 case ACM_METRIC_COUNT_HARDWARE: 749 return "ACM_METRIC_COUNT_HARDWARE"; 750 case ACM_METRIC_COUNT_LOCAL_CODECS: 751 return "ACM_METRIC_COUNT_LOCAL_CODECS"; 752 case ACM_METRIC_COUNT_LOCAL_CONVERTERS: 753 return "ACM_METRIC_COUNT_LOCAL_CONVERTERS"; 754 case ACM_METRIC_COUNT_LOCAL_DISABLED: 755 return "ACM_METRIC_COUNT_LOCAL_DISABLED"; 756 case ACM_METRIC_COUNT_LOCAL_DRIVERS: 757 return "ACM_METRIC_COUNT_LOCAL_DRIVERS"; 758 case ACM_METRIC_COUNT_LOCAL_FILTERS: 759 return "ACM_METRIC_COUNT_LOCAL_FILTERS"; 760 case ACM_METRIC_DRIVER_PRIORITY: 761 return "ACM_METRIC_DRIVER_PRIORITY"; 762 case ACM_METRIC_DRIVER_SUPPORT: 763 return "ACM_METRIC_DRIVER_SUPPORT"; 764 case ACM_METRIC_HARDWARE_WAVE_INPUT: 765 return "ACM_METRIC_HARDWARE_WAVE_INPUT"; 766 case ACM_METRIC_HARDWARE_WAVE_OUTPUT: 767 return "ACM_METRIC_HARDWARE_WAVE_OUTPUT"; 768 case ACM_METRIC_MAX_SIZE_FILTER: 769 return "ACM_METRIC_MAX_SIZE_FILTER"; 770 case ACM_METRIC_MAX_SIZE_FORMAT: 771 return "ACM_METRIC_MAX_SIZE_FORMAT"; 772 } 773 774 return "UNKNOWN"; 775 } 776 777 static void check_count(UINT uMetric) 778 { 779 DWORD dwMetric; 780 MMRESULT rc; 781 782 /* try invalid result pointer */ 783 rc = acmMetrics(NULL, uMetric, 0); 784 ok(rc == MMSYSERR_INVALPARAM, 785 "acmMetrics(NULL, %s, 0): rc = 0x%08x, should be 0x%08x\n", 786 get_metric(uMetric), rc, MMSYSERR_INVALPARAM); 787 788 /* try invalid handle */ 789 rc = acmMetrics((HACMOBJ)1, uMetric, &dwMetric); 790 ok(rc == MMSYSERR_INVALHANDLE, 791 "acmMetrics(1, %s, %p): rc = 0x%08x, should be 0x%08x\n", 792 get_metric(uMetric), &dwMetric, rc, MMSYSERR_INVALHANDLE); 793 794 /* try invalid result pointer and handle */ 795 rc = acmMetrics((HACMOBJ)1, uMetric, 0); 796 ok(rc == MMSYSERR_INVALHANDLE, 797 "acmMetrics(1, %s, 0): rc = 0x%08x, should be 0x%08x\n", 798 get_metric(uMetric), rc, MMSYSERR_INVALHANDLE); 799 800 /* try valid parameters */ 801 rc = acmMetrics(NULL, uMetric, &dwMetric); 802 ok(rc == MMSYSERR_NOERROR, "acmMetrics() failed: rc = 0x%08x\n", rc); 803 804 if (rc == MMSYSERR_NOERROR && winetest_interactive) 805 trace("%s: %u\n", get_metric(uMetric), dwMetric); 806 } 807 808 static void driver_tests(void) 809 { 810 MMRESULT rc; 811 DWORD dwACMVersion = acmGetVersion(); 812 813 if (winetest_interactive) { 814 trace("ACM version = %u.%02u build %u%s\n", 815 HIWORD(dwACMVersion) >> 8, 816 HIWORD(dwACMVersion) & 0xff, 817 LOWORD(dwACMVersion), 818 LOWORD(dwACMVersion) == 0 ? " (Retail)" : ""); 819 } 820 821 check_count(ACM_METRIC_COUNT_CODECS); 822 check_count(ACM_METRIC_COUNT_CONVERTERS); 823 check_count(ACM_METRIC_COUNT_DISABLED); 824 check_count(ACM_METRIC_COUNT_DRIVERS); 825 check_count(ACM_METRIC_COUNT_FILTERS); 826 check_count(ACM_METRIC_COUNT_HARDWARE); 827 check_count(ACM_METRIC_COUNT_LOCAL_CODECS); 828 check_count(ACM_METRIC_COUNT_LOCAL_CONVERTERS); 829 check_count(ACM_METRIC_COUNT_LOCAL_DISABLED); 830 check_count(ACM_METRIC_COUNT_LOCAL_DRIVERS); 831 check_count(ACM_METRIC_COUNT_LOCAL_FILTERS); 832 833 if (winetest_interactive) 834 trace("enabled drivers:\n"); 835 836 rc = acmDriverEnum(DriverEnumProc, 0, 0); 837 ok(rc == MMSYSERR_NOERROR, 838 "acmDriverEnum() failed, rc=%08x, should be 0x%08x\n", 839 rc, MMSYSERR_NOERROR); 840 } 841 842 static void test_prepareheader(void) 843 { 844 HACMSTREAM has; 845 ADPCMWAVEFORMAT *src; 846 WAVEFORMATEX dst; 847 MMRESULT mr; 848 ACMSTREAMHEADER hdr; 849 BYTE buf[sizeof(WAVEFORMATEX) + 32], pcm[2048], input[512]; 850 ADPCMCOEFSET *coef; 851 852 src = (ADPCMWAVEFORMAT*)buf; 853 coef = src->aCoef; 854 src->wfx.cbSize = 32; 855 src->wfx.wFormatTag = WAVE_FORMAT_ADPCM; 856 src->wfx.nSamplesPerSec = 22050; 857 src->wfx.wBitsPerSample = 4; 858 src->wfx.nChannels = 1; 859 src->wfx.nBlockAlign = 512; 860 src->wfx.nAvgBytesPerSec = 11025; 861 src->wSamplesPerBlock = 0x3f4; 862 src->wNumCoef = 7; 863 coef[0].iCoef1 = 0x0100; 864 coef[0].iCoef2 = 0x0000; 865 coef[1].iCoef1 = 0x0200; 866 coef[1].iCoef2 = 0xff00; 867 coef[2].iCoef1 = 0x0000; 868 coef[2].iCoef2 = 0x0000; 869 coef[3].iCoef1 = 0x00c0; 870 coef[3].iCoef2 = 0x0040; 871 coef[4].iCoef1 = 0x00f0; 872 coef[4].iCoef2 = 0x0000; 873 coef[5].iCoef1 = 0x01cc; 874 coef[5].iCoef2 = 0xff30; 875 coef[6].iCoef1 = 0x0188; 876 coef[6].iCoef2 = 0xff18; 877 878 dst.cbSize = 0; 879 dst.wFormatTag = WAVE_FORMAT_PCM; 880 dst.nSamplesPerSec = 22050; 881 dst.wBitsPerSample = 8; 882 dst.nChannels = 1; 883 dst.nBlockAlign = dst.wBitsPerSample * dst.nChannels / 8; 884 dst.nAvgBytesPerSec = dst.nSamplesPerSec * dst.nBlockAlign; 885 886 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)src, &dst, NULL, 0, 0, 0); 887 ok(mr == MMSYSERR_NOERROR, "open failed: 0x%x\n", mr); 888 889 memset(input, 0, sizeof(input)); 890 memset(&hdr, 0, sizeof(hdr)); 891 hdr.cbStruct = sizeof(hdr); 892 hdr.pbSrc = input; 893 hdr.cbSrcLength = sizeof(input); 894 hdr.pbDst = pcm; 895 hdr.cbDstLength = sizeof(pcm); 896 897 mr = acmStreamPrepareHeader(has, &hdr, 0); 898 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 899 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); 900 901 mr = acmStreamUnprepareHeader(has, &hdr, 0); 902 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 903 ok(hdr.fdwStatus == 0, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); 904 905 memset(&hdr, 0, sizeof(hdr)); 906 hdr.cbStruct = sizeof(hdr); 907 hdr.pbSrc = input; 908 hdr.cbSrcLength = 0; /* invalid source length */ 909 hdr.pbDst = pcm; 910 hdr.cbDstLength = sizeof(pcm); 911 912 mr = acmStreamPrepareHeader(has, &hdr, 0); 913 ok(mr == MMSYSERR_INVALPARAM, "expected 0x0b, got 0x%x\n", mr); 914 915 hdr.cbSrcLength = src->wfx.nBlockAlign - 1; /* less than block align */ 916 mr = acmStreamPrepareHeader(has, &hdr, 0); 917 ok(mr == ACMERR_NOTPOSSIBLE, "expected 0x200, got 0x%x\n", mr); 918 919 hdr.cbSrcLength = src->wfx.nBlockAlign + 1; /* more than block align */ 920 mr = acmStreamPrepareHeader(has, &hdr, 0); 921 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 922 923 mr = acmStreamUnprepareHeader(has, &hdr, 0); 924 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 925 926 hdr.cbSrcLength = src->wfx.nBlockAlign; 927 mr = acmStreamPrepareHeader(has, &hdr, 1); /* invalid use of reserved parameter */ 928 ok(mr == MMSYSERR_INVALFLAG, "expected 0x0a, got 0x%x\n", mr); 929 930 mr = acmStreamPrepareHeader(has, &hdr, 0); 931 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 932 933 mr = acmStreamUnprepareHeader(has, &hdr, 0); 934 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 935 936 memset(&hdr, 0, sizeof(hdr)); 937 hdr.cbStruct = sizeof(hdr); 938 hdr.pbSrc = input; 939 hdr.cbSrcLength = sizeof(input); 940 hdr.pbDst = pcm; 941 hdr.cbDstLength = sizeof(pcm); 942 hdr.fdwStatus = ACMSTREAMHEADER_STATUSF_DONE; 943 944 mr = acmStreamPrepareHeader(has, &hdr, 0); 945 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 946 ok(hdr.fdwStatus == (ACMSTREAMHEADER_STATUSF_PREPARED | ACMSTREAMHEADER_STATUSF_DONE), "header wasn't prepared: 0x%x\n", hdr.fdwStatus); 947 948 hdr.cbSrcLengthUsed = 12345; 949 hdr.cbDstLengthUsed = 12345; 950 hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; 951 mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); 952 ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); 953 ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); 954 ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); 955 todo_wine 956 ok(hdr.cbDstLengthUsed == 1010, "expected 1010, got %d\n", hdr.cbDstLengthUsed); 957 958 mr = acmStreamUnprepareHeader(has, &hdr, 0); 959 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 960 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); 961 962 /* The 2 next tests are related to Lost Horizon (bug 24723) */ 963 memset(&hdr, 0, sizeof(hdr)); 964 hdr.cbStruct = sizeof(hdr); 965 hdr.pbSrc = input; 966 hdr.cbSrcLength = sizeof(input); 967 hdr.pbDst = pcm; 968 hdr.cbDstLength = -4; 969 970 mr = acmStreamPrepareHeader(has, &hdr, 0); 971 if (sizeof(void *) == 4) /* 64 bit fails on this test */ 972 { 973 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 974 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); 975 976 hdr.cbSrcLengthUsed = 12345; 977 hdr.cbDstLengthUsed = 12345; 978 hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; 979 mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); 980 ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); 981 ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); 982 ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); 983 todo_wine 984 ok(hdr.cbDstLengthUsed == 1010, "expected 1010, got %d\n", hdr.cbDstLengthUsed); 985 986 mr = acmStreamUnprepareHeader(has, &hdr, 0); 987 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 988 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); 989 } 990 else 991 todo_wine 992 ok(mr == MMSYSERR_INVALPARAM, "expected 0x0b, got 0x%x\n", mr); 993 994 memset(&hdr, 0, sizeof(hdr)); 995 hdr.cbStruct = sizeof(hdr); 996 hdr.pbSrc = input; 997 hdr.cbSrcLength = 24; 998 hdr.pbDst = pcm; 999 hdr.cbDstLength = -4; 1000 mr = acmStreamPrepareHeader(has, &hdr, 0); 1001 ok(mr == ACMERR_NOTPOSSIBLE, "expected 0x200, got 0x%x\n", mr); 1002 ok(hdr.fdwStatus == 0, "expected 0, got 0x%x\n", hdr.fdwStatus); 1003 1004 hdr.cbSrcLengthUsed = 12345; 1005 hdr.cbDstLengthUsed = 12345; 1006 mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); 1007 ok(mr == ACMERR_UNPREPARED, "expected 0x202, got 0x%x\n", mr); 1008 ok(hdr.cbSrcLengthUsed == 12345, "expected 12345, got %d\n", hdr.cbSrcLengthUsed); 1009 ok(hdr.cbDstLengthUsed == 12345, "expected 12345, got %d\n", hdr.cbDstLengthUsed); 1010 1011 mr = acmStreamUnprepareHeader(has, &hdr, 0); 1012 ok(mr == ACMERR_UNPREPARED, "expected 0x202, got 0x%x\n", mr); 1013 1014 /* Less output space than required */ 1015 memset(&hdr, 0, sizeof(hdr)); 1016 hdr.cbStruct = sizeof(hdr); 1017 hdr.pbSrc = input; 1018 hdr.cbSrcLength = sizeof(input); 1019 hdr.pbDst = pcm; 1020 hdr.cbDstLength = 32; 1021 1022 mr = acmStreamPrepareHeader(has, &hdr, 0); 1023 ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); 1024 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); 1025 1026 hdr.cbSrcLengthUsed = 12345; 1027 hdr.cbDstLengthUsed = 12345; 1028 hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; 1029 mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); 1030 ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); 1031 ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); 1032 todo_wine 1033 ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); 1034 todo_wine 1035 ok(hdr.cbDstLengthUsed == hdr.cbDstLength, "expected %d, got %d\n", hdr.cbDstLength, hdr.cbDstLengthUsed); 1036 1037 mr = acmStreamUnprepareHeader(has, &hdr, 0); 1038 ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); 1039 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); 1040 1041 mr = acmStreamClose(has, 0); 1042 ok(mr == MMSYSERR_NOERROR, "close failed: 0x%x\n", mr); 1043 } 1044 1045 static const BYTE input[64] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}; 1046 1047 struct stream_output 1048 { 1049 WAVEFORMATEX src; 1050 WAVEFORMATEX dst; 1051 BYTE output[256]; 1052 DWORD dst_used; 1053 BOOL todo; 1054 }; 1055 1056 static const struct stream_output expected_output[] = { 1057 /* #0: Identical conversion */ 1058 {{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}, 64, FALSE}, 1059 1060 /* #1: 1 -> 2 channels */ 1061 {{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63}, 128, FALSE}, 1062 1063 /* #2: 2 -> 1 channels: all of the audio underflows due to addition */ 1064 {{WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 32, FALSE}, 1065 1066 /* #3: 2 -> 2 channels */ 1067 {{WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {WAVE_FORMAT_PCM, 2, 8000, 16000, 2, 8}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}, 64, FALSE}, 1068 1069 /* #4: 8 -> 16 bits per sample */ 1070 {{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {0,128,0,129,0,130,0,131,0,132,0,133,0,134,0,135,0,136,0,137,0,138,0,139,0,140,0,141,0,142,0,143,0,144,0,145,0,146,0,147,0,148,0,149,0,150,0,151,0,152,0,153,0,154,0,155,0,156,0,157,0,158,0,159,0,160,0,161,0,162,0,163,0,164,0,165,0,166,0,167,0,168,0,169,0,170,0,171,0,172,0,173,0,174,0,175,0,176,0,177,0,178,0,179,0,180,0,181,0,182,0,183,0,184,0,185,0,186,0,187,0,188,0,189,0,190,0,191}, 128, FALSE}, 1071 1072 /* #5: 16 -> 8 bits per sample */ 1073 {{WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191}, 32, FALSE}, 1074 1075 /* #6: 16 bits per sample, 2 -> 1 channels */ 1076 {{WAVE_FORMAT_PCM, 2, 8000, 32000, 4, 16}, {WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16}, {2,4,10,12,18,20,26,28,34,36,42,44,50,52,58,60,66,68,74,76,82,84,90,92,98,100,106,108,114,116,122,124}, 32, FALSE}, 1077 1078 /* #7: 8000 -> 11025 sample rate */ 1079 /* FIXME: upsampling is slightly off on wine - the algorithm is wrong whenever error > (srcrate + dstrate) / 2 */ 1080 {{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {0,1,1,2,3,4,4,5,6,7,7,8,9,9,10,11,12,12,13,14,15,15,16,17,17,18,19,20,20,21,22,22,23,24,25,25,26,27,28,28,29,30,30,31,32,33,33,34,35,36,36,37,38,38,39,40,41,41,42,43,44,44,45,46,46,47,48,49,49,50,51,52,52,53,54,54,55,56,57,57,58,59,60,60,61,62,62,63}, 88, TRUE}, 1081 1082 /* #8: 8000 -> 22050 sample rate */ 1083 {{WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {0,0,1,1,1,2,2,3,3,3,4,4,4,5,5,5,6,6,7,7,7,8,8,8,9,9,9,10,10,11,11,11,12,12,12,13,13,13,14,14,15,15,15,16,16,16,17,17,17,18,18,19,19,19,20,20,20,21,21,21,22,22,22,23,23,24,24,24,25,25,25,26,26,26,27,27,28,28,28,29,29,29,30,30,30,31,31,32,32,32,33,33,33,34,34,34,35,35,36,36,36,37,37,37,38,38,38,39,39,40,40,40,41,41,41,42,42,42,43,43,44,44,44,45,45,45,46,46,46,47,47,48,48,48,49,49,49,50,50,50,51,51,52,52,52,53,53,53,54,54,54,55,55,56,56,56,57,57,57,58,58,58,59,59,60,60,60,61,61,61,62,62,62,63,63,63}, 176, TRUE}, 1084 1085 /* #9: 11025 -> 22050 sample rate */ 1086 {{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63}, 128, FALSE}, 1087 1088 /* #10: 22050 -> 11025 sample rate */ 1089 {{WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63}, 32, FALSE}, 1090 1091 /* #11: 11025 -> 8000 sample rate */ 1092 {{WAVE_FORMAT_PCM, 1, 11025, 11025, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {0,2,3,4,6,7,8,10,11,13,14,15,17,18,19,21,22,24,25,26,28,29,31,32,33,35,36,37,39,40,42,43,44,46,47,48,50,51,53,54,55,57,58,59,61,62}, 46, FALSE}, 1093 1094 /* #12: 22050 -> 8000 sample rate */ 1095 {{WAVE_FORMAT_PCM, 1, 22050, 22050, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {1,4,6,9,12,15,17,20,23,26,28,31,34,37,39,42,45,48,50,53,56,59,62}, 23, FALSE}, 1096 1097 /* #13: 44100 -> 8000 sample rate */ 1098 {{WAVE_FORMAT_PCM, 1, 44100, 44100, 1, 8}, {WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8}, {2,8,13,19,24,30,35,41,46,52,57,63}, 12, FALSE}, 1099 }; 1100 1101 static void test_convert(void) 1102 { 1103 HACMSTREAM has; 1104 ACMSTREAMHEADER hdr = {0}; 1105 BYTE output[256]; 1106 MMRESULT mmr; 1107 unsigned i; 1108 1109 for (i = 0; i < sizeof(expected_output)/sizeof(struct stream_output); i++) 1110 { 1111 mmr = acmStreamOpen(&has, NULL, (WAVEFORMATEX *)&expected_output[i].src, (WAVEFORMATEX *)&expected_output[i].dst, NULL, 0, 0, 0); 1112 ok(mmr == MMSYSERR_NOERROR, "#%d: open failed: 0x%x\n", i, mmr); 1113 1114 memset(&hdr, 0, sizeof(hdr)); 1115 hdr.cbStruct = sizeof(hdr); 1116 hdr.pbSrc = (BYTE *)input; 1117 hdr.cbSrcLength = sizeof(input); 1118 hdr.pbDst = output; 1119 hdr.cbDstLength = sizeof(output); 1120 1121 mmr = acmStreamPrepareHeader(has, &hdr, 0); 1122 ok(mmr == MMSYSERR_NOERROR, "#%d: prepare failed: 0x%x\n", i, mmr); 1123 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "#%d: header wasn't prepared: 0x%x\n", i, hdr.fdwStatus); 1124 1125 memset(&output, 0, sizeof(output)); 1126 mmr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); 1127 ok(mmr == MMSYSERR_NOERROR, "#%d: convert failed: 0x%x\n", i, mmr); 1128 ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "#%d: conversion was not done: 0x%x\n", i, hdr.fdwStatus); 1129 ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "#%d: expected %d, got %d\n", i, hdr.cbSrcLength, hdr.cbSrcLengthUsed); 1130 ok(hdr.cbDstLengthUsed == expected_output[i].dst_used, "#%d: expected %d, got %d\n", i, expected_output[i].dst_used, hdr.cbDstLengthUsed); 1131 todo_wine_if(expected_output[i].todo) 1132 ok(!memcmp(expected_output[i].output, output, hdr.cbDstLengthUsed), "#%d: output does not match\n", i); 1133 1134 mmr = acmStreamUnprepareHeader(has, &hdr, 0); 1135 ok(mmr == MMSYSERR_NOERROR, "#%d: unprepare failed: 0x%x\n", i, mmr); 1136 ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "#%d: header wasn't unprepared: 0x%x\n", i, hdr.fdwStatus); 1137 1138 mmr = acmStreamClose(has, 0); 1139 ok(mmr == MMSYSERR_NOERROR, "#%d: close failed: 0x%x\n", i, mmr); 1140 } 1141 } 1142 1143 static void test_acmFormatSuggest(void) 1144 { 1145 WAVEFORMATEX src, dst; 1146 DWORD suggest; 1147 MMRESULT rc; 1148 DWORD sizeMax; 1149 1150 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &sizeMax); 1151 1152 /* Test a valid PCM format */ 1153 src.wFormatTag = WAVE_FORMAT_PCM; 1154 src.nChannels = 1; 1155 src.nSamplesPerSec = 8000; 1156 src.nAvgBytesPerSec = 16000; 1157 src.nBlockAlign = 2; 1158 src.wBitsPerSample = 16; 1159 src.cbSize = 0; 1160 suggest = 0; 1161 memset(&dst, 0, sizeof(dst)); 1162 rc = acmFormatSuggest(NULL, &src, &dst, sizeof(PCMWAVEFORMAT), suggest); 1163 ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); 1164 ok(src.wFormatTag == dst.wFormatTag, "expected %d, got %d\n", src.wFormatTag, dst.wFormatTag); 1165 ok(src.nChannels == dst.nChannels, "expected %d, got %d\n", src.nChannels, dst.nChannels); 1166 ok(src.nSamplesPerSec == dst.nSamplesPerSec, "expected %d, got %d\n", src.nSamplesPerSec, dst.nSamplesPerSec); 1167 ok(src.nAvgBytesPerSec == dst.nAvgBytesPerSec, "expected %d, got %d\n", src.nAvgBytesPerSec, dst.nAvgBytesPerSec); 1168 ok(src.nBlockAlign == dst.nBlockAlign, "expected %d, got %d\n", src.nBlockAlign, dst.nBlockAlign); 1169 ok(src.wBitsPerSample == dst.wBitsPerSample, "expected %d, got %d\n", src.wBitsPerSample, dst.wBitsPerSample); 1170 1171 /* All parameters from destination are valid */ 1172 suggest = ACM_FORMATSUGGESTF_NCHANNELS 1173 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC 1174 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE 1175 | ACM_FORMATSUGGESTF_WFORMATTAG; 1176 dst = src; 1177 rc = acmFormatSuggest(NULL, &src, &dst, sizeof(PCMWAVEFORMAT), suggest); 1178 ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); 1179 ok(src.wFormatTag == dst.wFormatTag, "expected %d, got %d\n", src.wFormatTag, dst.wFormatTag); 1180 ok(src.nChannels == dst.nChannels, "expected %d, got %d\n", src.nChannels, dst.nChannels); 1181 ok(src.nSamplesPerSec == dst.nSamplesPerSec, "expected %d, got %d\n", src.nSamplesPerSec, dst.nSamplesPerSec); 1182 ok(src.nAvgBytesPerSec == dst.nAvgBytesPerSec, "expected %d, got %d\n", src.nAvgBytesPerSec, dst.nAvgBytesPerSec); 1183 ok(src.nBlockAlign == dst.nBlockAlign, "expected %d, got %d\n", src.nBlockAlign, dst.nBlockAlign); 1184 ok(src.wBitsPerSample == dst.wBitsPerSample, "expected %d, got %d\n", src.wBitsPerSample, dst.wBitsPerSample); 1185 1186 /* Test an invalid PCM format */ 1187 ZeroMemory(&dst, sizeof(dst)); 1188 src.nSamplesPerSec = 0xdeadbeef; 1189 suggest = 0; 1190 rc = acmFormatSuggest(NULL, &src, &dst, sizeMax, suggest); 1191 todo_wine { 1192 ok(rc == MMSYSERR_NOERROR, "failed with error 0x%x\n", rc); 1193 ok(dst.wFormatTag == WAVE_FORMAT_PCM, "expected %d, got %d\n", WAVE_FORMAT_PCM, dst.wFormatTag); 1194 ok(dst.nSamplesPerSec == 0xdeadbeef, "expected %d, got %d\n", 0xdeadbeef, dst.nSamplesPerSec); 1195 } 1196 src.nSamplesPerSec = 8000; 1197 1198 /* Test a nonexistent format */ 1199 src.wFormatTag = 0xbeef; 1200 rc = acmFormatSuggest(NULL, &src, &dst, sizeMax-1, suggest); 1201 ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); 1202 1203 rc = acmFormatSuggest(NULL, &src, &dst, sizeMax, suggest); 1204 todo_wine 1205 ok(rc == MMSYSERR_NODRIVER, "failed with error 0x%x\n", rc); 1206 1207 /* Test converting between two known but incompatible formats */ 1208 src.wFormatTag = WAVE_FORMAT_ALAW; 1209 src.nChannels = 1; 1210 src.nSamplesPerSec = 8000; 1211 src.nAvgBytesPerSec = 8000; 1212 src.nBlockAlign = 1; 1213 src.wBitsPerSample = 8; 1214 src.cbSize = 0; 1215 suggest = ACM_FORMATSUGGESTF_WFORMATTAG; 1216 dst.wFormatTag = WAVE_FORMAT_IMA_ADPCM; 1217 rc = acmFormatSuggest(NULL, &src, &dst, sizeof(IMAADPCMWAVEFORMAT)-1, suggest); 1218 ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); 1219 1220 rc = acmFormatSuggest(NULL, &src, &dst, sizeof(IMAADPCMWAVEFORMAT), suggest); 1221 todo_wine 1222 ok(rc == MMSYSERR_NODRIVER, "failed with error 0x%x\n", rc); 1223 1224 /* Invalid suggest flags */ 1225 src.wFormatTag = WAVE_FORMAT_PCM; 1226 suggest = 0xFFFFFFFF; 1227 rc = acmFormatSuggest(NULL, &src, &dst, sizeof(dst), suggest); 1228 ok(rc == MMSYSERR_INVALFLAG, "failed with error 0x%x\n", rc); 1229 1230 /* Invalid source and destination */ 1231 suggest = 0; 1232 rc = acmFormatSuggest(NULL, NULL, &dst, sizeof(dst), suggest); 1233 ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); 1234 rc = acmFormatSuggest(NULL, &src, NULL, sizeof(dst), suggest); 1235 ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); 1236 rc = acmFormatSuggest(NULL, NULL, NULL, sizeof(dst), suggest); 1237 ok(rc == MMSYSERR_INVALPARAM, "failed with error 0x%x\n", rc); 1238 } 1239 1240 static void test_acmFormatTagDetails(void) 1241 { 1242 ACMFORMATTAGDETAILSW aftd = {0}; 1243 MMRESULT rc; 1244 1245 aftd.cbStruct = sizeof(aftd); 1246 aftd.dwFormatTag = WAVE_FORMAT_MPEGLAYER3; 1247 rc = acmFormatTagDetailsW(NULL, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG); 1248 if (rc == MMSYSERR_NOERROR) 1249 ok(aftd.cbFormatSize == sizeof(MPEGLAYER3WAVEFORMAT), "got %d\n", aftd.cbFormatSize); 1250 } 1251 1252 static void test_acmFormatChoose(void) 1253 { 1254 ACMFORMATCHOOSEW afc = {0}; 1255 WAVEFORMATEX *pwfx; 1256 DWORD sizeMax; 1257 MMRESULT rc; 1258 1259 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &sizeMax); 1260 pwfx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeMax); 1261 1262 afc.cbStruct = sizeof(afc); 1263 afc.pwfx = pwfx; 1264 1265 /* test invalid struct size */ 1266 afc.cbStruct = sizeof(afc)-1; 1267 rc = acmFormatChooseW(&afc); 1268 ok(rc == MMSYSERR_INVALPARAM, "expected 0xb, got 0x%x\n", rc); 1269 afc.cbStruct = sizeof(afc); 1270 1271 afc.pwfx = NULL; 1272 rc = acmFormatChooseW(&afc); 1273 ok(rc == MMSYSERR_INVALPARAM, "expected 0xb, got 0x%x\n", rc); 1274 afc.pwfx = pwfx; 1275 1276 HeapFree(GetProcessHeap(), 0, pwfx); 1277 } 1278 1279 static void test_mp3(void) 1280 { 1281 MPEGLAYER3WAVEFORMAT src; 1282 WAVEFORMATEX dst; 1283 HACMSTREAM has; 1284 DWORD output; 1285 MMRESULT mr; 1286 1287 src.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; 1288 src.wfx.nSamplesPerSec = 11025; 1289 src.wfx.wBitsPerSample = 0; 1290 src.wfx.nChannels = 1; 1291 src.wfx.nBlockAlign = 576; 1292 src.wfx.nAvgBytesPerSec = 2000; 1293 1294 src.wID = MPEGLAYER3_ID_MPEG; 1295 src.fdwFlags = 0; 1296 src.nBlockSize = 576; 1297 src.nFramesPerBlock = 1; 1298 src.nCodecDelay = 0; 1299 1300 dst.cbSize = 0; 1301 dst.wFormatTag = WAVE_FORMAT_PCM; 1302 dst.nSamplesPerSec = 11025; 1303 dst.wBitsPerSample = 16; 1304 dst.nChannels = 1; 1305 dst.nBlockAlign = dst.wBitsPerSample * dst.nChannels / 8; 1306 dst.nAvgBytesPerSec = dst.nSamplesPerSec * dst.nBlockAlign; 1307 1308 src.wfx.cbSize = 0; 1309 1310 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)&src, &dst, NULL, 0, 0, 0); 1311 ok(mr == ACMERR_NOTPOSSIBLE, "expected error ACMERR_NOTPOSSIBLE, got 0x%x\n", mr); 1312 if (mr == MMSYSERR_NOERROR) acmStreamClose(has, 0); 1313 1314 src.wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES; 1315 src.wID = 0; 1316 1317 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)&src, &dst, NULL, 0, 0, 0); 1318 ok(mr == ACMERR_NOTPOSSIBLE, "expected error ACMERR_NOTPOSSIBLE, got 0x%x\n", mr); 1319 if (mr == MMSYSERR_NOERROR) acmStreamClose(has, 0); 1320 1321 src.wID = MPEGLAYER3_ID_MPEG; 1322 src.nBlockSize = 0; 1323 1324 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)&src, &dst, NULL, 0, 0, 0); 1325 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1326 mr = acmStreamClose(has, 0); 1327 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1328 1329 src.nBlockSize = 576; 1330 src.wfx.nAvgBytesPerSec = 0; 1331 1332 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)&src, &dst, NULL, 0, 0, 0); 1333 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1334 /* causes a division by zero exception */ 1335 if (0) acmStreamSize(has, 4000, &output, ACM_STREAMSIZEF_SOURCE); 1336 mr = acmStreamClose(has, 0); 1337 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1338 1339 src.wfx.nAvgBytesPerSec = 2000; 1340 1341 mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)&src, &dst, NULL, 0, 0, 0); 1342 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1343 mr = acmStreamSize(has, 4000, &output, ACM_STREAMSIZEF_SOURCE); 1344 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1345 mr = acmStreamClose(has, 0); 1346 ok(mr == MMSYSERR_NOERROR, "failed with error 0x%x\n", mr); 1347 } 1348 1349 static struct 1350 { 1351 struct 1352 { 1353 int load, free, open, close, enable, disable, install, 1354 remove, details, notify, querycfg, about; 1355 } driver; 1356 struct 1357 { 1358 int tag_details, details, suggest; 1359 } format; 1360 struct 1361 { 1362 int open, close, size, convert, prepare, unprepare, reset; 1363 } stream; 1364 int other; 1365 } driver_calls; 1366 1367 static LRESULT CALLBACK acm_driver_func(DWORD_PTR id, HDRVR handle, UINT msg, LPARAM param1, LPARAM param2) 1368 { 1369 switch (msg) 1370 { 1371 /* Driver messages */ 1372 case DRV_LOAD: 1373 driver_calls.driver.load++; 1374 return 1; 1375 case DRV_FREE: 1376 driver_calls.driver.free++; 1377 return 1; 1378 case DRV_OPEN: 1379 driver_calls.driver.open++; 1380 return 1; 1381 case DRV_CLOSE: 1382 driver_calls.driver.close++; 1383 return 1; 1384 case DRV_ENABLE: 1385 driver_calls.driver.enable++; 1386 return 1; 1387 case DRV_DISABLE: 1388 driver_calls.driver.disable++; 1389 return 1; 1390 case DRV_QUERYCONFIGURE: 1391 driver_calls.driver.querycfg++; 1392 return 1; 1393 case DRV_INSTALL: 1394 driver_calls.driver.install++; 1395 return DRVCNF_RESTART; 1396 case DRV_REMOVE: 1397 driver_calls.driver.remove++; 1398 return DRVCNF_RESTART; 1399 case ACMDM_DRIVER_ABOUT: 1400 driver_calls.driver.about++; 1401 return MMSYSERR_NOTSUPPORTED; 1402 case ACMDM_DRIVER_DETAILS: 1403 { 1404 ACMDRIVERDETAILSA *ptr = (ACMDRIVERDETAILSA *)param1; 1405 1406 /* copied from pcmconverter.c */ 1407 ptr->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; 1408 ptr->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; 1409 ptr->wMid = MM_MICROSOFT; 1410 ptr->wPid = MM_MSFT_ACM_PCM; 1411 ptr->vdwACM = 0x01000000; 1412 ptr->vdwDriver = 0x01000000; 1413 ptr->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CONVERTER; 1414 ptr->cFormatTags = 1; 1415 ptr->cFilterTags = 0; 1416 ptr->hicon = NULL; 1417 strcpy(ptr->szShortName, "TEST-CODEC"); 1418 strcpy(ptr->szLongName, "Wine Test Codec"); 1419 strcpy(ptr->szCopyright, "Brought to you by the Wine team..."); 1420 strcpy(ptr->szLicensing, "Refer to LICENSE file"); 1421 ptr->szFeatures[0] = 0; 1422 1423 driver_calls.driver.details++; 1424 break; 1425 } 1426 case ACMDM_DRIVER_NOTIFY: 1427 driver_calls.driver.notify++; 1428 return MMSYSERR_NOTSUPPORTED; 1429 1430 /* Format messages */ 1431 case ACMDM_FORMATTAG_DETAILS: 1432 driver_calls.format.tag_details++; 1433 break; 1434 case ACMDM_FORMAT_DETAILS: 1435 driver_calls.format.details++; 1436 break; 1437 case ACMDM_FORMAT_SUGGEST: 1438 driver_calls.format.suggest++; 1439 break; 1440 1441 /* Stream messages */ 1442 case ACMDM_STREAM_OPEN: 1443 driver_calls.stream.open++; 1444 break; 1445 case ACMDM_STREAM_CLOSE: 1446 driver_calls.stream.close++; 1447 break; 1448 case ACMDM_STREAM_SIZE: 1449 driver_calls.stream.size++; 1450 break; 1451 case ACMDM_STREAM_CONVERT: 1452 driver_calls.stream.convert++; 1453 break; 1454 case ACMDM_STREAM_RESET: 1455 driver_calls.stream.reset++; 1456 return MMSYSERR_NOTSUPPORTED; 1457 case ACMDM_STREAM_PREPARE: 1458 driver_calls.stream.prepare++; 1459 break; 1460 case ACMDM_STREAM_UNPREPARE: 1461 driver_calls.stream.unprepare++; 1462 break; 1463 1464 default: 1465 driver_calls.other++; 1466 return DefDriverProc(id, handle, msg, param1, param2); 1467 } 1468 return MMSYSERR_NOERROR; 1469 } 1470 1471 static void test_acmDriverAdd(void) 1472 { 1473 MMRESULT res; 1474 HACMDRIVERID drvid; 1475 union 1476 { 1477 ACMDRIVERDETAILSA drv_details; 1478 } acm; 1479 1480 /* Driver load steps: 1481 * - acmDriverAdd checks the passed parameters 1482 * - DRV_LOAD message is sent - required 1483 * - DRV_ENABLE message is sent - required 1484 * - DRV_OPEN message is sent - required 1485 * - DRV_DETAILS message is sent - required 1486 * - ACMDM_FORMATTAG_DETAILS message is sent - optional 1487 * - DRV_QUERYCONFIGURE message is sent - optional 1488 * - ACMDM_DRIVER_ABOUT message is sent - optional 1489 */ 1490 1491 res = acmDriverAddA(&drvid, GetModuleHandleA(NULL), (LPARAM)acm_driver_func, 0, ACM_DRIVERADDF_FUNCTION); 1492 ok(res == MMSYSERR_NOERROR, "Expected 0, got %d\n", res); 1493 todo_wine 1494 ok(driver_calls.driver.open == 1, "Expected 1, got %d\n", driver_calls.driver.open); 1495 ok(driver_calls.driver.details == 1, "Expected 1, got %d\n", driver_calls.driver.details); 1496 1497 memset(&acm, 0, sizeof(acm)); 1498 res = acmDriverDetailsA(drvid, &acm.drv_details, 0); 1499 ok(res == MMSYSERR_INVALPARAM, "Expected 11, got %d\n", res); 1500 1501 acm.drv_details.cbStruct = sizeof(acm.drv_details); 1502 res = acmDriverDetailsA(drvid, &acm.drv_details, 0); 1503 ok(res == MMSYSERR_NOERROR, "Expected 0, got %d\n", res); 1504 todo_wine 1505 ok(driver_calls.driver.open == 1, "Expected 1, got %d\n", driver_calls.driver.open); 1506 ok(driver_calls.driver.details == 2, "Expected 2, got %d\n", driver_calls.driver.details); 1507 todo_wine 1508 ok(driver_calls.driver.close == 0, "Expected 0, got %d\n", driver_calls.driver.close); 1509 } 1510 1511 START_TEST(msacm) 1512 { 1513 driver_tests(); 1514 test_prepareheader(); 1515 test_convert(); 1516 test_acmFormatSuggest(); 1517 test_acmFormatTagDetails(); 1518 test_acmFormatChoose(); 1519 test_mp3(); 1520 /* Test acmDriverAdd in the end as it may conflict 1521 * with other tests due to codec lookup order */ 1522 test_acmDriverAdd(); 1523 } 1524