2 * Unit tests for msacm functions
4 * Copyright (c) 2004 Robert Reif
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.
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.
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
26 #include "wine/test.h"
35 static BOOL CALLBACK
FormatTagEnumProc(HACMDRIVERID hadid
,
36 PACMFORMATTAGDETAILSA paftd
,
40 if (winetest_interactive
)
41 trace(" Format 0x%04x: %s\n", paftd
->dwFormatTag
, paftd
->szFormatTag
);
46 static BOOL CALLBACK
FormatEnumProc(HACMDRIVERID hadid
,
47 LPACMFORMATDETAILSA pafd
,
51 if (winetest_interactive
)
52 trace(" 0x%04x, %s\n", pafd
->dwFormatTag
, pafd
->szFormat
);
57 static BOOL CALLBACK
DriverEnumProc(HACMDRIVERID hadid
,
65 DWORD dwDriverPriority
;
66 DWORD dwDriverSupport
;
68 if (winetest_interactive
) {
69 trace("id: %p\n", hadid
);
70 trace(" Supports:\n");
71 if (fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_ASYNC
)
72 trace(" async conversions\n");
73 if (fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_CODEC
)
74 trace(" different format conversions\n");
75 if (fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_CONVERTER
)
76 trace(" same format conversions\n");
77 if (fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_FILTER
)
78 trace(" filtering\n");
81 /* try an invalid pointer */
82 rc
= acmDriverDetailsA(hadid
, 0, 0);
83 ok(rc
== MMSYSERR_INVALPARAM
,
84 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
85 rc
, MMSYSERR_INVALPARAM
);
87 /* try an invalid structure size */
88 ZeroMemory(&dd
, sizeof(dd
));
89 rc
= acmDriverDetailsA(hadid
, &dd
, 0);
90 ok(rc
== MMSYSERR_INVALPARAM
,
91 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
92 rc
, MMSYSERR_INVALPARAM
);
94 /* MSDN says this should fail but it doesn't in practice */
96 rc
= acmDriverDetailsA(hadid
, &dd
, 0);
97 ok(rc
== MMSYSERR_NOERROR
|| rc
== MMSYSERR_NOTSUPPORTED
,
98 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
99 rc
, MMSYSERR_NOERROR
);
101 /* try an invalid handle */
102 dd
.cbStruct
= sizeof(dd
);
103 rc
= acmDriverDetailsA((HACMDRIVERID
)1, &dd
, 0);
104 ok(rc
== MMSYSERR_INVALHANDLE
,
105 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
106 rc
, MMSYSERR_INVALHANDLE
);
108 /* try an invalid handle and pointer */
109 rc
= acmDriverDetailsA((HACMDRIVERID
)1, 0, 0);
110 ok(rc
== MMSYSERR_INVALPARAM
,
111 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
112 rc
, MMSYSERR_INVALPARAM
);
114 /* try invalid details */
115 rc
= acmDriverDetailsA(hadid
, &dd
, -1);
116 ok(rc
== MMSYSERR_INVALFLAG
,
117 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
118 rc
, MMSYSERR_INVALFLAG
);
120 /* try valid parameters */
121 rc
= acmDriverDetailsA(hadid
, &dd
, 0);
122 ok(rc
== MMSYSERR_NOERROR
|| rc
== MMSYSERR_NOTSUPPORTED
,
123 "acmDriverDetailsA(): rc = %08x, should be %08x\n",
124 rc
, MMSYSERR_NOERROR
);
126 /* cbStruct should contain size of returned data (at most sizeof(dd))
127 TODO: should it be *exactly* sizeof(dd), as tested here?
129 if (rc
== MMSYSERR_NOERROR
) {
130 static const struct {
131 const char *shortname
;
135 } *iter
, expected_ids
[] = {
136 { "Microsoft IMA ADPCM", MM_MICROSOFT
, MM_MSFT_ACM_IMAADPCM
},
137 { "MS-ADPCM", MM_MICROSOFT
, MM_MSFT_ACM_MSADPCM
},
138 { "Microsoft CCITT G.711", MM_MICROSOFT
, MM_MSFT_ACM_G711
},
139 { "MPEG Layer-3 Codec", MM_FRAUNHOFER_IIS
, MM_FHGIIS_MPEGLAYER3_DECODE
, MM_FHGIIS_MPEGLAYER3_PROFESSIONAL
},
140 { "MS-PCM", MM_MICROSOFT
, MM_MSFT_ACM_PCM
},
144 ok(dd
.cbStruct
== sizeof(dd
),
145 "acmDriverDetailsA(): cbStruct = %08x\n", dd
.cbStruct
);
147 for (iter
= expected_ids
; iter
->shortname
; ++iter
) {
148 if (!strcmp(iter
->shortname
, dd
.szShortName
)) {
149 /* try alternative product id on mismatch */
150 if (iter
->pid_alt
&& iter
->pid
!= dd
.wPid
)
151 ok(iter
->mid
== dd
.wMid
&& iter
->pid_alt
== dd
.wPid
,
152 "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n",
154 dd
.wPid
, iter
->pid_alt
);
156 ok(iter
->mid
== dd
.wMid
&& iter
->pid
== dd
.wPid
,
157 "Got wrong manufacturer (0x%x vs 0x%x) or product (0x%x vs 0x%x)\n",
164 if (rc
== MMSYSERR_NOERROR
&& winetest_interactive
) {
165 trace(" Short name: %s\n", dd
.szShortName
);
166 trace(" Long name: %s\n", dd
.szLongName
);
167 trace(" Copyright: %s\n", dd
.szCopyright
);
168 trace(" Licensing: %s\n", dd
.szLicensing
);
169 trace(" Features: %s\n", dd
.szFeatures
);
170 trace(" Supports %u formats\n", dd
.cFormatTags
);
171 trace(" Supports %u filter formats\n", dd
.cFilterTags
);
172 trace(" Mid: 0x%x\n", dd
.wMid
);
173 trace(" Pid: 0x%x\n", dd
.wPid
);
176 /* try bad pointer */
177 rc
= acmMetrics((HACMOBJ
)hadid
, ACM_METRIC_DRIVER_PRIORITY
, 0);
178 ok(rc
== MMSYSERR_INVALPARAM
,
179 "acmMetrics(): rc = %08x, should be %08x\n",
180 rc
, MMSYSERR_INVALPARAM
);
183 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_DRIVER_PRIORITY
, &dwDriverPriority
);
184 ok(rc
== MMSYSERR_INVALHANDLE
,
185 "acmMetrics(): rc = %08x, should be %08x\n",
186 rc
, MMSYSERR_INVALHANDLE
);
188 /* try bad pointer and handle */
189 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_DRIVER_PRIORITY
, 0);
190 ok(rc
== MMSYSERR_INVALHANDLE
,
191 "acmMetrics(): rc = %08x, should be %08x\n",
192 rc
, MMSYSERR_INVALHANDLE
);
194 /* try valid parameters */
195 rc
= acmMetrics((HACMOBJ
)hadid
, ACM_METRIC_DRIVER_PRIORITY
, &dwDriverSupport
);
196 ok(rc
== MMSYSERR_NOERROR
,
197 "acmMetrics(): rc = %08x, should be %08x\n",
198 rc
, MMSYSERR_NOERROR
);
200 /* try bad pointer */
201 rc
= acmMetrics((HACMOBJ
)hadid
, ACM_METRIC_DRIVER_SUPPORT
, 0);
202 ok(rc
== MMSYSERR_INVALPARAM
,
203 "acmMetrics(): rc = %08x, should be %08x\n",
204 rc
, MMSYSERR_INVALPARAM
);
207 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_DRIVER_SUPPORT
, &dwDriverSupport
);
208 ok(rc
== MMSYSERR_INVALHANDLE
,
209 "acmMetrics(): rc = %08x, should be %08x\n",
210 rc
, MMSYSERR_INVALHANDLE
);
212 /* try bad pointer and handle */
213 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_DRIVER_SUPPORT
, 0);
214 ok(rc
== MMSYSERR_INVALHANDLE
,
215 "acmMetrics(): rc = %08x, should be %08x\n",
216 rc
, MMSYSERR_INVALHANDLE
);
218 /* try valid parameters */
219 rc
= acmMetrics((HACMOBJ
)hadid
, ACM_METRIC_DRIVER_SUPPORT
, &dwDriverSupport
);
220 ok(rc
== MMSYSERR_NOERROR
,
221 "acmMetrics(): rc = %08x, should be %08x\n",
222 rc
, MMSYSERR_NOERROR
);
224 /* try invalid pointer */
225 rc
= acmDriverOpen(0, hadid
, 0);
226 ok(rc
== MMSYSERR_INVALPARAM
,
227 "acmDriverOpen(): rc = %08x, should be %08x\n",
228 rc
, MMSYSERR_INVALPARAM
);
230 /* try invalid handle */
231 rc
= acmDriverOpen(&had
, (HACMDRIVERID
)1, 0);
232 ok(rc
== MMSYSERR_INVALHANDLE
,
233 "acmDriverOpen(): rc = %08x, should be %08x\n",
234 rc
, MMSYSERR_INVALHANDLE
);
236 /* try invalid open */
237 rc
= acmDriverOpen(&had
, hadid
, -1);
238 ok(rc
== MMSYSERR_INVALFLAG
,
239 "acmDriverOpen(): rc = %08x, should be %08x\n",
240 rc
, MMSYSERR_INVALFLAG
);
242 /* try valid parameters */
243 rc
= acmDriverOpen(&had
, hadid
, 0);
244 ok(rc
== MMSYSERR_NOERROR
|| rc
== MMSYSERR_NODRIVER
,
245 "acmDriverOpen(): rc = %08x, should be %08x\n",
246 rc
, MMSYSERR_NOERROR
);
248 if (rc
== MMSYSERR_NOERROR
) {
252 /* try bad pointer */
253 rc
= acmDriverID((HACMOBJ
)had
, 0, 0);
254 ok(rc
== MMSYSERR_INVALPARAM
,
255 "acmDriverID(): rc = %08x, should be %08x\n",
256 rc
, MMSYSERR_INVALPARAM
);
259 rc
= acmDriverID((HACMOBJ
)1, &hid
, 0);
260 ok(rc
== MMSYSERR_INVALHANDLE
,
261 "acmDriverID(): rc = %08x, should be %08x\n",
262 rc
, MMSYSERR_INVALHANDLE
);
264 /* try bad handle and pointer */
265 rc
= acmDriverID((HACMOBJ
)1, 0, 0);
266 ok(rc
== MMSYSERR_INVALHANDLE
,
267 "acmDriverID(): rc = %08x, should be %08x\n",
268 rc
, MMSYSERR_INVALHANDLE
);
271 rc
= acmDriverID((HACMOBJ
)had
, &hid
, 1);
272 ok(rc
== MMSYSERR_INVALFLAG
,
273 "acmDriverID(): rc = %08x, should be %08x\n",
274 rc
, MMSYSERR_INVALFLAG
);
276 /* try valid parameters */
277 rc
= acmDriverID((HACMOBJ
)had
, &hid
, 0);
278 ok(rc
== MMSYSERR_NOERROR
,
279 "acmDriverID(): rc = %08x, should be %08x\n",
280 rc
, MMSYSERR_NOERROR
);
282 "acmDriverID() returned ID %p doesn't equal %p\n",
285 /* try bad pointer */
286 rc
= acmMetrics((HACMOBJ
)had
, ACM_METRIC_MAX_SIZE_FORMAT
, 0);
287 ok(rc
== MMSYSERR_INVALPARAM
,
288 "acmMetrics(): rc = %08x, should be %08x\n",
289 rc
, MMSYSERR_INVALPARAM
);
292 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_MAX_SIZE_FORMAT
, &dwSize
);
293 ok(rc
== MMSYSERR_INVALHANDLE
,
294 "acmMetrics(): rc = %08x, should be %08x\n",
295 rc
, MMSYSERR_INVALHANDLE
);
297 /* try bad pointer and handle */
298 rc
= acmMetrics((HACMOBJ
)1, ACM_METRIC_MAX_SIZE_FORMAT
, 0);
299 ok(rc
== MMSYSERR_INVALHANDLE
,
300 "acmMetrics(): rc = %08x, should be %08x\n",
301 rc
, MMSYSERR_INVALHANDLE
);
303 /* try valid parameters */
304 rc
= acmMetrics((HACMOBJ
)had
, ACM_METRIC_MAX_SIZE_FORMAT
, &dwSize
);
305 ok(rc
== MMSYSERR_NOERROR
,
306 "acmMetrics(): rc = %08x, should be %08x\n",
307 rc
, MMSYSERR_NOERROR
);
308 if (rc
== MMSYSERR_NOERROR
) {
309 ACMFORMATDETAILSA fd
;
311 ACMFORMATTAGDETAILSA aftd
;
313 /* try bad pointer */
314 rc
= acmFormatEnumA(had
, 0, FormatEnumProc
, 0, 0);
315 ok(rc
== MMSYSERR_INVALPARAM
,
316 "acmFormatEnumA(): rc = %08x, should be %08x\n",
317 rc
, MMSYSERR_INVALPARAM
);
319 /* try bad structure size */
320 ZeroMemory(&fd
, sizeof(fd
));
321 rc
= acmFormatEnumA(had
, &fd
, FormatEnumProc
, 0, 0);
322 ok(rc
== MMSYSERR_INVALPARAM
,
323 "acmFormatEnumA(): rc = %08x, should be %08x\n",
324 rc
, MMSYSERR_INVALPARAM
);
326 fd
.cbStruct
= sizeof(fd
) - 1;
327 rc
= acmFormatEnumA(had
, &fd
, FormatEnumProc
, 0, 0);
328 ok(rc
== MMSYSERR_INVALPARAM
,
329 "acmFormatEnumA(): rc = %08x, should be %08x\n",
330 rc
, MMSYSERR_INVALPARAM
);
332 if (dwSize
< sizeof(WAVEFORMATEX
))
333 dwSize
= sizeof(WAVEFORMATEX
);
335 pwfx
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
);
337 pwfx
->cbSize
= LOWORD(dwSize
) - sizeof(WAVEFORMATEX
);
338 pwfx
->wFormatTag
= WAVE_FORMAT_UNKNOWN
;
340 fd
.cbStruct
= sizeof(fd
);
343 fd
.dwFormatTag
= WAVE_FORMAT_UNKNOWN
;
345 /* try valid parameters */
346 rc
= acmFormatEnumA(had
, &fd
, FormatEnumProc
, 0, 0);
347 ok(rc
== MMSYSERR_NOERROR
,
348 "acmFormatEnumA(): rc = %08x, should be %08x\n",
349 rc
, MMSYSERR_NOERROR
);
351 /* try bad pointer */
352 rc
= acmFormatTagEnumA(had
, 0, FormatTagEnumProc
, 0, 0);
353 ok(rc
== MMSYSERR_INVALPARAM
,
354 "acmFormatTagEnumA(): rc = %08x, should be %08x\n",
355 rc
, MMSYSERR_INVALPARAM
);
357 /* try bad structure size */
358 ZeroMemory(&aftd
, sizeof(aftd
));
359 rc
= acmFormatTagEnumA(had
, &aftd
, FormatTagEnumProc
, 0, 0);
360 ok(rc
== MMSYSERR_INVALPARAM
,
361 "acmFormatTagEnumA(): rc = %08x, should be %08x\n",
362 rc
, MMSYSERR_INVALPARAM
);
364 aftd
.cbStruct
= sizeof(aftd
) - 1;
365 rc
= acmFormatTagEnumA(had
, &aftd
, FormatTagEnumProc
, 0, 0);
366 ok(rc
== MMSYSERR_INVALPARAM
,
367 "acmFormatTagEnumA(): rc = %08x, should be %08x\n",
368 rc
, MMSYSERR_INVALPARAM
);
370 aftd
.cbStruct
= sizeof(aftd
);
371 aftd
.dwFormatTag
= WAVE_FORMAT_UNKNOWN
;
374 rc
= acmFormatTagEnumA(had
, &aftd
, FormatTagEnumProc
, 0, 1);
375 ok(rc
== MMSYSERR_INVALFLAG
,
376 "acmFormatTagEnumA(): rc = %08x, should be %08x\n",
377 rc
, MMSYSERR_INVALFLAG
);
379 /* try valid parameters */
380 rc
= acmFormatTagEnumA(had
, &aftd
, FormatTagEnumProc
, 0, 0);
381 ok(rc
== MMSYSERR_NOERROR
,
382 "acmFormatTagEnumA(): rc = %08x, should be %08x\n",
383 rc
, MMSYSERR_NOERROR
);
385 HeapFree(GetProcessHeap(), 0, pwfx
);
387 /* try invalid handle */
388 rc
= acmDriverClose((HACMDRIVER
)1, 0);
389 ok(rc
== MMSYSERR_INVALHANDLE
,
390 "acmDriverClose(): rc = %08x, should be %08x\n",
391 rc
, MMSYSERR_INVALHANDLE
);
393 /* try invalid flag */
394 rc
= acmDriverClose(had
, 1);
395 ok(rc
== MMSYSERR_INVALFLAG
,
396 "acmDriverClose(): rc = %08x, should be %08x\n",
397 rc
, MMSYSERR_INVALFLAG
);
399 /* try valid parameters */
400 rc
= acmDriverClose(had
, 0);
401 ok(rc
== MMSYSERR_NOERROR
,
402 "acmDriverClose(): rc = %08x, should be %08x\n",
403 rc
, MMSYSERR_NOERROR
);
405 /* try closing again */
406 rc
= acmDriverClose(had
, 0);
407 ok(rc
== MMSYSERR_INVALHANDLE
,
408 "acmDriverClose(): rc = %08x, should be %08x\n",
409 rc
, MMSYSERR_INVALHANDLE
);
416 static const char * get_metric(UINT uMetric
)
419 case ACM_METRIC_COUNT_CODECS
:
420 return "ACM_METRIC_COUNT_CODECS";
421 case ACM_METRIC_COUNT_CONVERTERS
:
422 return "ACM_METRIC_COUNT_CONVERTERS";
423 case ACM_METRIC_COUNT_DISABLED
:
424 return "ACM_METRIC_COUNT_DISABLED";
425 case ACM_METRIC_COUNT_DRIVERS
:
426 return "ACM_METRIC_COUNT_DRIVERS";
427 case ACM_METRIC_COUNT_FILTERS
:
428 return "ACM_METRIC_COUNT_FILTERS";
429 case ACM_METRIC_COUNT_HARDWARE
:
430 return "ACM_METRIC_COUNT_HARDWARE";
431 case ACM_METRIC_COUNT_LOCAL_CODECS
:
432 return "ACM_METRIC_COUNT_LOCAL_CODECS";
433 case ACM_METRIC_COUNT_LOCAL_CONVERTERS
:
434 return "ACM_METRIC_COUNT_LOCAL_CONVERTERS";
435 case ACM_METRIC_COUNT_LOCAL_DISABLED
:
436 return "ACM_METRIC_COUNT_LOCAL_DISABLED";
437 case ACM_METRIC_COUNT_LOCAL_DRIVERS
:
438 return "ACM_METRIC_COUNT_LOCAL_DRIVERS";
439 case ACM_METRIC_COUNT_LOCAL_FILTERS
:
440 return "ACM_METRIC_COUNT_LOCAL_FILTERS";
441 case ACM_METRIC_DRIVER_PRIORITY
:
442 return "ACM_METRIC_DRIVER_PRIORITY";
443 case ACM_METRIC_DRIVER_SUPPORT
:
444 return "ACM_METRIC_DRIVER_SUPPORT";
445 case ACM_METRIC_HARDWARE_WAVE_INPUT
:
446 return "ACM_METRIC_HARDWARE_WAVE_INPUT";
447 case ACM_METRIC_HARDWARE_WAVE_OUTPUT
:
448 return "ACM_METRIC_HARDWARE_WAVE_OUTPUT";
449 case ACM_METRIC_MAX_SIZE_FILTER
:
450 return "ACM_METRIC_MAX_SIZE_FILTER";
451 case ACM_METRIC_MAX_SIZE_FORMAT
:
452 return "ACM_METRIC_MAX_SIZE_FORMAT";
458 static void check_count(UINT uMetric
)
463 /* try invalid result pointer */
464 rc
= acmMetrics(NULL
, uMetric
, 0);
465 ok(rc
== MMSYSERR_INVALPARAM
,
466 "acmMetrics(NULL, %s, 0): rc = 0x%08x, should be 0x%08x\n",
467 get_metric(uMetric
), rc
, MMSYSERR_INVALPARAM
);
469 /* try invalid handle */
470 rc
= acmMetrics((HACMOBJ
)1, uMetric
, &dwMetric
);
471 ok(rc
== MMSYSERR_INVALHANDLE
,
472 "acmMetrics(1, %s, %p): rc = 0x%08x, should be 0x%08x\n",
473 get_metric(uMetric
), &dwMetric
, rc
, MMSYSERR_INVALHANDLE
);
475 /* try invalid result pointer and handle */
476 rc
= acmMetrics((HACMOBJ
)1, uMetric
, 0);
477 ok(rc
== MMSYSERR_INVALHANDLE
,
478 "acmMetrics(1, %s, 0): rc = 0x%08x, should be 0x%08x\n",
479 get_metric(uMetric
), rc
, MMSYSERR_INVALHANDLE
);
481 /* try valid parameters */
482 rc
= acmMetrics(NULL
, uMetric
, &dwMetric
);
483 ok(rc
== MMSYSERR_NOERROR
, "acmMetrics() failed: rc = 0x%08x\n", rc
);
485 if (rc
== MMSYSERR_NOERROR
&& winetest_interactive
)
486 trace("%s: %u\n", get_metric(uMetric
), dwMetric
);
489 static void driver_tests(void)
492 DWORD dwACMVersion
= acmGetVersion();
494 if (winetest_interactive
) {
495 trace("ACM version = %u.%02u build %u%s\n",
496 HIWORD(dwACMVersion
) >> 8,
497 HIWORD(dwACMVersion
) & 0xff,
498 LOWORD(dwACMVersion
),
499 LOWORD(dwACMVersion
) == 0 ? " (Retail)" : "");
502 check_count(ACM_METRIC_COUNT_CODECS
);
503 check_count(ACM_METRIC_COUNT_CONVERTERS
);
504 check_count(ACM_METRIC_COUNT_DISABLED
);
505 check_count(ACM_METRIC_COUNT_DRIVERS
);
506 check_count(ACM_METRIC_COUNT_FILTERS
);
507 check_count(ACM_METRIC_COUNT_HARDWARE
);
508 check_count(ACM_METRIC_COUNT_LOCAL_CODECS
);
509 check_count(ACM_METRIC_COUNT_LOCAL_CONVERTERS
);
510 check_count(ACM_METRIC_COUNT_LOCAL_DISABLED
);
511 check_count(ACM_METRIC_COUNT_LOCAL_DRIVERS
);
512 check_count(ACM_METRIC_COUNT_LOCAL_FILTERS
);
514 if (winetest_interactive
)
515 trace("enabled drivers:\n");
517 rc
= acmDriverEnum(DriverEnumProc
, 0, 0);
518 ok(rc
== MMSYSERR_NOERROR
,
519 "acmDriverEnum() failed, rc=%08x, should be 0x%08x\n",
520 rc
, MMSYSERR_NOERROR
);
523 static void test_prepareheader(void)
526 ADPCMWAVEFORMAT
*src
;
530 BYTE buf
[sizeof(WAVEFORMATEX
) + 32], pcm
[2048], input
[512];
533 src
= (ADPCMWAVEFORMAT
*)buf
;
535 src
->wfx
.cbSize
= 32;
536 src
->wfx
.wFormatTag
= WAVE_FORMAT_ADPCM
;
537 src
->wfx
.nSamplesPerSec
= 22050;
538 src
->wfx
.wBitsPerSample
= 4;
539 src
->wfx
.nChannels
= 1;
540 src
->wfx
.nBlockAlign
= 512;
541 src
->wfx
.nAvgBytesPerSec
= 11025;
542 src
->wSamplesPerBlock
= 0x3f4;
544 coef
[0].iCoef1
= 0x0100;
545 coef
[0].iCoef2
= 0x0000;
546 coef
[1].iCoef1
= 0x0200;
547 coef
[1].iCoef2
= 0xff00;
548 coef
[2].iCoef1
= 0x0000;
549 coef
[2].iCoef2
= 0x0000;
550 coef
[3].iCoef1
= 0x00c0;
551 coef
[3].iCoef2
= 0x0040;
552 coef
[4].iCoef1
= 0x00f0;
553 coef
[4].iCoef2
= 0x0000;
554 coef
[5].iCoef1
= 0x01cc;
555 coef
[5].iCoef2
= 0xff30;
556 coef
[6].iCoef1
= 0x0188;
557 coef
[6].iCoef2
= 0xff18;
560 dst
.wFormatTag
= WAVE_FORMAT_PCM
;
561 dst
.nSamplesPerSec
= 22050;
562 dst
.wBitsPerSample
= 8;
564 dst
.nBlockAlign
= dst
.wBitsPerSample
* dst
.nChannels
/ 8;
565 dst
.nAvgBytesPerSec
= dst
.nSamplesPerSec
* dst
.nBlockAlign
;
567 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)src
, &dst
, NULL
, 0, 0, 0);
568 ok(mr
== MMSYSERR_NOERROR
, "open failed: 0x%x\n", mr
);
570 memset(input
, 0, sizeof(input
));
571 memset(&hdr
, 0, sizeof(hdr
));
572 hdr
.cbStruct
= sizeof(hdr
);
574 hdr
.cbSrcLength
= sizeof(input
);
576 hdr
.cbDstLength
= sizeof(pcm
);
578 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
579 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
580 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_PREPARED
, "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
582 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
583 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
584 ok(hdr
.fdwStatus
== 0, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
586 memset(&hdr
, 0, sizeof(hdr
));
587 hdr
.cbStruct
= sizeof(hdr
);
589 hdr
.cbSrcLength
= 0; /* invalid source length */
591 hdr
.cbDstLength
= sizeof(pcm
);
593 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
594 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
596 hdr
.cbSrcLength
= src
->wfx
.nBlockAlign
- 1; /* less than block align */
597 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
598 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected 0x200, got 0x%x\n", mr
);
600 hdr
.cbSrcLength
= src
->wfx
.nBlockAlign
+ 1; /* more than block align */
601 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
602 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
604 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
605 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
607 hdr
.cbSrcLength
= src
->wfx
.nBlockAlign
;
608 mr
= acmStreamPrepareHeader(has
, &hdr
, 1); /* invalid use of reserved parameter */
609 ok(mr
== MMSYSERR_INVALFLAG
, "expected 0x0a, got 0x%x\n", mr
);
611 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
612 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
614 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
615 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
617 memset(&hdr
, 0, sizeof(hdr
));
618 hdr
.cbStruct
= sizeof(hdr
);
620 hdr
.cbSrcLength
= sizeof(input
);
622 hdr
.cbDstLength
= sizeof(pcm
);
623 hdr
.fdwStatus
= ACMSTREAMHEADER_STATUSF_DONE
;
625 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
626 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
627 ok(hdr
.fdwStatus
== (ACMSTREAMHEADER_STATUSF_PREPARED
| ACMSTREAMHEADER_STATUSF_DONE
), "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
629 hdr
.cbSrcLengthUsed
= 12345;
630 hdr
.cbDstLengthUsed
= 12345;
631 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
632 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
633 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
634 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
635 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
637 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
639 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
640 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
641 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
643 /* The 2 next tests are related to Lost Horizon (bug 24723) */
644 memset(&hdr
, 0, sizeof(hdr
));
645 hdr
.cbStruct
= sizeof(hdr
);
647 hdr
.cbSrcLength
= sizeof(input
);
649 hdr
.cbDstLength
= -4;
651 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
652 if (sizeof(void *) == 4) /* 64 bit fails on this test */
654 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
655 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_PREPARED
, "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
657 hdr
.cbSrcLengthUsed
= 12345;
658 hdr
.cbDstLengthUsed
= 12345;
659 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
660 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
661 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
662 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
663 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
665 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
667 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
668 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
669 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
673 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
675 memset(&hdr
, 0, sizeof(hdr
));
676 hdr
.cbStruct
= sizeof(hdr
);
678 hdr
.cbSrcLength
= 24;
680 hdr
.cbDstLength
= -4;
681 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
682 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected 0x200, got 0x%x\n", mr
);
683 ok(hdr
.fdwStatus
== 0, "expected 0, got 0x%x\n", hdr
.fdwStatus
);
685 hdr
.cbSrcLengthUsed
= 12345;
686 hdr
.cbDstLengthUsed
= 12345;
687 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
688 ok(mr
== ACMERR_UNPREPARED
, "expected 0x202, got 0x%x\n", mr
);
689 ok(hdr
.cbSrcLengthUsed
== 12345, "expected 12345, got %d\n", hdr
.cbSrcLengthUsed
);
690 ok(hdr
.cbDstLengthUsed
== 12345, "expected 12345, got %d\n", hdr
.cbDstLengthUsed
);
692 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
693 ok(mr
== ACMERR_UNPREPARED
, "expected 0x202, got 0x%x\n", mr
);
695 /* Less output space than required */
696 memset(&hdr
, 0, sizeof(hdr
));
697 hdr
.cbStruct
= sizeof(hdr
);
699 hdr
.cbSrcLength
= sizeof(input
);
701 hdr
.cbDstLength
= 32;
703 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
704 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
705 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_PREPARED
, "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
707 hdr
.cbSrcLengthUsed
= 12345;
708 hdr
.cbDstLengthUsed
= 12345;
709 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
710 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
711 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
712 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
714 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
716 ok(hdr
.cbDstLengthUsed
== hdr
.cbDstLength
, "expected %d, got %d\n", hdr
.cbDstLength
, hdr
.cbDstLengthUsed
);
718 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
719 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
720 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
722 mr
= acmStreamClose(has
, 0);
723 ok(mr
== MMSYSERR_NOERROR
, "close failed: 0x%x\n", mr
);
726 static void test_acmFormatSuggest(void)
728 WAVEFORMATEX src
, dst
;
732 /* Test a valid PCM format */
733 src
.wFormatTag
= WAVE_FORMAT_PCM
;
735 src
.nSamplesPerSec
= 8000;
736 src
.nAvgBytesPerSec
= 16000;
738 src
.wBitsPerSample
= 16;
741 memset(&dst
, 0, sizeof(dst
));
742 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
743 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
745 ok(src
.wFormatTag
== dst
.wFormatTag
, "expected %d, got %d\n", src
.wFormatTag
, dst
.wFormatTag
);
746 ok(src
.nChannels
== dst
.nChannels
, "expected %d, got %d\n", src
.nChannels
, dst
.nChannels
);
747 ok(src
.nSamplesPerSec
== dst
.nSamplesPerSec
, "expected %d, got %d\n", src
.nSamplesPerSec
, dst
.nSamplesPerSec
);
749 ok(src
.nAvgBytesPerSec
== dst
.nAvgBytesPerSec
, "expected %d, got %d\n", src
.nAvgBytesPerSec
, dst
.nAvgBytesPerSec
);
751 ok(src
.nBlockAlign
== dst
.nBlockAlign
, "expected %d, got %d\n", src
.nBlockAlign
, dst
.nBlockAlign
);
753 ok(src
.wBitsPerSample
== dst
.wBitsPerSample
, "expected %d, got %d\n", src
.wBitsPerSample
, dst
.wBitsPerSample
);
755 /* All parameters from destination are valid */
756 suggest
= ACM_FORMATSUGGESTF_NCHANNELS
757 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC
758 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE
759 | ACM_FORMATSUGGESTF_WFORMATTAG
;
761 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
762 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
763 ok(src
.wFormatTag
== dst
.wFormatTag
, "expected %d, got %d\n", src
.wFormatTag
, dst
.wFormatTag
);
764 ok(src
.nChannels
== dst
.nChannels
, "expected %d, got %d\n", src
.nChannels
, dst
.nChannels
);
765 ok(src
.nSamplesPerSec
== dst
.nSamplesPerSec
, "expected %d, got %d\n", src
.nSamplesPerSec
, dst
.nSamplesPerSec
);
766 ok(src
.nAvgBytesPerSec
== dst
.nAvgBytesPerSec
, "expected %d, got %d\n", src
.nAvgBytesPerSec
, dst
.nAvgBytesPerSec
);
767 ok(src
.nBlockAlign
== dst
.nBlockAlign
, "expected %d, got %d\n", src
.nBlockAlign
, dst
.nBlockAlign
);
768 ok(src
.wBitsPerSample
== dst
.wBitsPerSample
, "expected %d, got %d\n", src
.wBitsPerSample
, dst
.wBitsPerSample
);
770 /* Test for WAVE_FORMAT_MSRT24 used in Monster Truck Madness 2 */
771 src
.wFormatTag
= WAVE_FORMAT_MSRT24
;
773 src
.nSamplesPerSec
= 8000;
774 src
.nAvgBytesPerSec
= 16000;
776 src
.wBitsPerSample
= 16;
779 suggest
= ACM_FORMATSUGGESTF_NCHANNELS
780 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC
781 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE
782 | ACM_FORMATSUGGESTF_WFORMATTAG
;
783 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
784 ok(rc
== ACMERR_NOTPOSSIBLE
, "failed with error 0x%x\n", rc
);
785 memset(&dst
, 0, sizeof(dst
));
787 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
789 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
791 /* Invalid struct size */
792 src
.wFormatTag
= WAVE_FORMAT_PCM
;
793 rc
= acmFormatSuggest(NULL
, &src
, &dst
, 0, suggest
);
795 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
796 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) / 2, suggest
);
798 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
799 /* cbSize is the last parameter and not required for PCM */
800 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - 1, suggest
);
801 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
802 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
), suggest
);
803 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
804 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
) - 1, suggest
);
806 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
807 /* cbSize is required for others */
808 src
.wFormatTag
= WAVE_FORMAT_ADPCM
;
809 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
), suggest
);
811 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
812 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - 1, suggest
);
814 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
816 /* Invalid suggest flags */
817 src
.wFormatTag
= WAVE_FORMAT_PCM
;
818 suggest
= 0xFFFFFFFF;
819 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
820 ok(rc
== MMSYSERR_INVALFLAG
, "failed with error 0x%x\n", rc
);
822 /* Invalid source and destination */
824 rc
= acmFormatSuggest(NULL
, NULL
, &dst
, sizeof(dst
), suggest
);
825 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
826 rc
= acmFormatSuggest(NULL
, &src
, NULL
, sizeof(dst
), suggest
);
827 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
828 rc
= acmFormatSuggest(NULL
, NULL
, NULL
, sizeof(dst
), suggest
);
829 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
834 MPEGLAYER3WAVEFORMAT src
;
840 src
.wfx
.wFormatTag
= WAVE_FORMAT_MPEGLAYER3
;
841 src
.wfx
.nSamplesPerSec
= 11025;
842 src
.wfx
.wBitsPerSample
= 0;
843 src
.wfx
.nChannels
= 1;
844 src
.wfx
.nBlockAlign
= 576;
845 src
.wfx
.nAvgBytesPerSec
= 2000;
847 src
.wID
= MPEGLAYER3_ID_MPEG
;
849 src
.nBlockSize
= 576;
850 src
.nFramesPerBlock
= 1;
854 dst
.wFormatTag
= WAVE_FORMAT_PCM
;
855 dst
.nSamplesPerSec
= 11025;
856 dst
.wBitsPerSample
= 16;
858 dst
.nBlockAlign
= dst
.wBitsPerSample
* dst
.nChannels
/ 8;
859 dst
.nAvgBytesPerSec
= dst
.nSamplesPerSec
* dst
.nBlockAlign
;
863 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
864 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected error ACMERR_NOTPOSSIBLE, got 0x%x\n", mr
);
865 if (mr
== MMSYSERR_NOERROR
) acmStreamClose(has
, 0);
867 src
.wfx
.cbSize
= MPEGLAYER3_WFX_EXTRA_BYTES
;
870 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
871 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected error ACMERR_NOTPOSSIBLE, got 0x%x\n", mr
);
872 if (mr
== MMSYSERR_NOERROR
) acmStreamClose(has
, 0);
874 src
.wID
= MPEGLAYER3_ID_MPEG
;
877 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
878 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
879 mr
= acmStreamClose(has
, 0);
880 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
882 src
.nBlockSize
= 576;
883 src
.wfx
.nAvgBytesPerSec
= 0;
885 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
886 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
887 /* causes a division by zero exception */
888 if (0) acmStreamSize(has
, 4000, &output
, ACM_STREAMSIZEF_SOURCE
);
889 mr
= acmStreamClose(has
, 0);
890 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
892 src
.wfx
.nAvgBytesPerSec
= 2000;
894 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
895 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
896 mr
= acmStreamSize(has
, 4000, &output
, ACM_STREAMSIZEF_SOURCE
);
897 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
898 mr
= acmStreamClose(has
, 0);
899 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
905 test_prepareheader();
906 test_acmFormatSuggest();