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);
595 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
597 hdr
.cbSrcLength
= src
->wfx
.nBlockAlign
- 1; /* less than block align */
598 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
600 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected 0x200, got 0x%x\n", mr
);
602 hdr
.cbSrcLength
= src
->wfx
.nBlockAlign
;
603 mr
= acmStreamPrepareHeader(has
, &hdr
, 1); /* invalid use of reserved parameter */
605 ok(mr
== MMSYSERR_INVALFLAG
, "expected 0x0a, got 0x%x\n", mr
);
607 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
608 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
610 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
611 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
613 memset(&hdr
, 0, sizeof(hdr
));
614 hdr
.cbStruct
= sizeof(hdr
);
616 hdr
.cbSrcLength
= sizeof(input
);
618 hdr
.cbDstLength
= sizeof(pcm
);
619 hdr
.fdwStatus
= ACMSTREAMHEADER_STATUSF_DONE
;
621 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
622 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
623 ok(hdr
.fdwStatus
== (ACMSTREAMHEADER_STATUSF_PREPARED
| ACMSTREAMHEADER_STATUSF_DONE
), "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
625 hdr
.cbSrcLengthUsed
= 12345;
626 hdr
.cbDstLengthUsed
= 12345;
627 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
628 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
629 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
630 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
631 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
633 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
635 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
636 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
637 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
639 /* The 2 next tests are related to Lost Horizon (bug 24723) */
640 memset(&hdr
, 0, sizeof(hdr
));
641 hdr
.cbStruct
= sizeof(hdr
);
643 hdr
.cbSrcLength
= sizeof(input
);
645 hdr
.cbDstLength
= -4;
647 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
648 if (sizeof(void *) == 4) /* 64 bit fails on this test */
650 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
651 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_PREPARED
, "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
653 hdr
.cbSrcLengthUsed
= 12345;
654 hdr
.cbDstLengthUsed
= 12345;
655 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
656 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
657 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
658 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
659 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
661 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
663 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
664 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
665 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
669 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
671 memset(&hdr
, 0, sizeof(hdr
));
672 hdr
.cbStruct
= sizeof(hdr
);
674 hdr
.cbSrcLength
= 24;
676 hdr
.cbDstLength
= -4;
677 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
679 ok(mr
== ACMERR_NOTPOSSIBLE
, "expected 0x200, got 0x%x\n", mr
);
680 ok(hdr
.fdwStatus
== 0, "expected 0, got 0x%x\n", hdr
.fdwStatus
);
682 hdr
.cbSrcLengthUsed
= 12345;
683 hdr
.cbDstLengthUsed
= 12345;
684 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
685 ok(mr
== ACMERR_UNPREPARED
, "expected 0x202, got 0x%x\n", mr
);
686 ok(hdr
.cbSrcLengthUsed
== 12345, "expected 12345, got %d\n", hdr
.cbSrcLengthUsed
);
687 ok(hdr
.cbDstLengthUsed
== 12345, "expected 12345, got %d\n", hdr
.cbDstLengthUsed
);
689 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
690 ok(mr
== ACMERR_UNPREPARED
, "expected 0x202, got 0x%x\n", mr
);
692 /* Less output space than required */
693 memset(&hdr
, 0, sizeof(hdr
));
694 hdr
.cbStruct
= sizeof(hdr
);
696 hdr
.cbSrcLength
= sizeof(input
);
698 hdr
.cbDstLength
= 32;
700 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
701 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
702 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_PREPARED
, "header wasn't prepared: 0x%x\n", hdr
.fdwStatus
);
704 hdr
.cbSrcLengthUsed
= 12345;
705 hdr
.cbDstLengthUsed
= 12345;
706 hdr
.fdwStatus
&= ~ACMSTREAMHEADER_STATUSF_DONE
;
707 mr
= acmStreamConvert(has
, &hdr
, ACM_STREAMCONVERTF_BLOCKALIGN
);
708 ok(mr
== MMSYSERR_NOERROR
, "convert failed: 0x%x\n", mr
);
709 ok(hdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_DONE
, "conversion was not done: 0x%x\n", hdr
.fdwStatus
);
711 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
713 ok(hdr
.cbDstLengthUsed
== hdr
.cbDstLength
, "expected %d, got %d\n", hdr
.cbDstLength
, hdr
.cbDstLengthUsed
);
715 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
716 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
717 ok(hdr
.fdwStatus
== ACMSTREAMHEADER_STATUSF_DONE
, "header wasn't unprepared: 0x%x\n", hdr
.fdwStatus
);
719 mr
= acmStreamClose(has
, 0);
720 ok(mr
== MMSYSERR_NOERROR
, "close failed: 0x%x\n", mr
);
723 static void test_acmFormatSuggest(void)
725 WAVEFORMATEX src
, dst
;
729 /* Test a valid PCM format */
730 src
.wFormatTag
= WAVE_FORMAT_PCM
;
732 src
.nSamplesPerSec
= 8000;
733 src
.nAvgBytesPerSec
= 16000;
735 src
.wBitsPerSample
= 16;
738 memset(&dst
, 0, sizeof(dst
));
739 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
740 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
742 ok(src
.wFormatTag
== dst
.wFormatTag
, "expected %d, got %d\n", src
.wFormatTag
, dst
.wFormatTag
);
743 ok(src
.nChannels
== dst
.nChannels
, "expected %d, got %d\n", src
.nChannels
, dst
.nChannels
);
744 ok(src
.nSamplesPerSec
== dst
.nSamplesPerSec
, "expected %d, got %d\n", src
.nSamplesPerSec
, dst
.nSamplesPerSec
);
746 ok(src
.nAvgBytesPerSec
== dst
.nAvgBytesPerSec
, "expected %d, got %d\n", src
.nAvgBytesPerSec
, dst
.nAvgBytesPerSec
);
748 ok(src
.nBlockAlign
== dst
.nBlockAlign
, "expected %d, got %d\n", src
.nBlockAlign
, dst
.nBlockAlign
);
750 ok(src
.wBitsPerSample
== dst
.wBitsPerSample
, "expected %d, got %d\n", src
.wBitsPerSample
, dst
.wBitsPerSample
);
752 /* All parameters from destination are valid */
753 suggest
= ACM_FORMATSUGGESTF_NCHANNELS
754 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC
755 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE
756 | ACM_FORMATSUGGESTF_WFORMATTAG
;
758 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
759 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
760 ok(src
.wFormatTag
== dst
.wFormatTag
, "expected %d, got %d\n", src
.wFormatTag
, dst
.wFormatTag
);
761 ok(src
.nChannels
== dst
.nChannels
, "expected %d, got %d\n", src
.nChannels
, dst
.nChannels
);
762 ok(src
.nSamplesPerSec
== dst
.nSamplesPerSec
, "expected %d, got %d\n", src
.nSamplesPerSec
, dst
.nSamplesPerSec
);
763 ok(src
.nAvgBytesPerSec
== dst
.nAvgBytesPerSec
, "expected %d, got %d\n", src
.nAvgBytesPerSec
, dst
.nAvgBytesPerSec
);
764 ok(src
.nBlockAlign
== dst
.nBlockAlign
, "expected %d, got %d\n", src
.nBlockAlign
, dst
.nBlockAlign
);
765 ok(src
.wBitsPerSample
== dst
.wBitsPerSample
, "expected %d, got %d\n", src
.wBitsPerSample
, dst
.wBitsPerSample
);
767 /* Test for WAVE_FORMAT_MSRT24 used in Monster Truck Madness 2 */
768 src
.wFormatTag
= WAVE_FORMAT_MSRT24
;
770 src
.nSamplesPerSec
= 8000;
771 src
.nAvgBytesPerSec
= 16000;
773 src
.wBitsPerSample
= 16;
776 suggest
= ACM_FORMATSUGGESTF_NCHANNELS
777 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC
778 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE
779 | ACM_FORMATSUGGESTF_WFORMATTAG
;
780 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
781 ok(rc
== ACMERR_NOTPOSSIBLE
, "failed with error 0x%x\n", rc
);
782 memset(&dst
, 0, sizeof(dst
));
784 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
786 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
788 /* Invalid struct size */
789 src
.wFormatTag
= WAVE_FORMAT_PCM
;
790 rc
= acmFormatSuggest(NULL
, &src
, &dst
, 0, suggest
);
792 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
793 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) / 2, suggest
);
795 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
796 /* cbSize is the last parameter and not required for PCM */
797 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - 1, suggest
);
798 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
799 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
), suggest
);
800 ok(rc
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", rc
);
801 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
) - 1, suggest
);
803 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
804 /* cbSize is required for others */
805 src
.wFormatTag
= WAVE_FORMAT_ADPCM
;
806 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - sizeof(dst
.cbSize
), suggest
);
808 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
809 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
) - 1, suggest
);
811 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
813 /* Invalid suggest flags */
814 src
.wFormatTag
= WAVE_FORMAT_PCM
;
815 suggest
= 0xFFFFFFFF;
816 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(dst
), suggest
);
817 ok(rc
== MMSYSERR_INVALFLAG
, "failed with error 0x%x\n", rc
);
819 /* Invalid source and destination */
821 rc
= acmFormatSuggest(NULL
, NULL
, &dst
, sizeof(dst
), suggest
);
822 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
823 rc
= acmFormatSuggest(NULL
, &src
, NULL
, sizeof(dst
), suggest
);
824 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
825 rc
= acmFormatSuggest(NULL
, NULL
, NULL
, sizeof(dst
), suggest
);
826 ok(rc
== MMSYSERR_INVALPARAM
, "failed with error 0x%x\n", rc
);
832 test_prepareheader();
833 test_acmFormatSuggest();