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"
36 static BOOL CALLBACK
FormatTagEnumProc(HACMDRIVERID hadid
,
37 PACMFORMATTAGDETAILSA paftd
,
44 if (winetest_interactive
)
45 trace(" Format 0x%04x: %s\n", paftd
->dwFormatTag
, paftd
->szFormatTag
);
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
);
52 if (rc
== MMSYSERR_NOERROR
)
54 ACMFORMATDETAILSA fd
= {0};
55 WAVEFORMATEX
*pwfx
, dst
;
56 ACMFORMATTAGDETAILSA aftd_pcm
= {0};
57 DWORD dwSize
, dwSizeMax
;
60 fd
.cbStruct
= sizeof(fd
);
61 if (paftd
->cbFormatSize
< sizeof(WAVEFORMATEX
))
62 pwfx
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WAVEFORMATEX
));
64 pwfx
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, paftd
->cbFormatSize
);
66 fd
.cbwfx
= paftd
->cbFormatSize
;
67 fd
.dwFormatTag
= paftd
->dwFormatTag
;
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
);
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
;
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
);
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
;
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
);
107 /* test acmFormatSuggest */
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
);
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
);
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
);
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
);
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
);
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
);
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
);
152 if (paftd
->dwFormatTag
!= WAVE_FORMAT_PCM
)
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
);
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
);
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
);
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
);
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
);
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
);
191 for (i
= 0; i
< paftd
->cStandardFormats
; i
++)
193 fd
.dwFormatIndex
= i
;
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
);
203 /* Windows will write cbSize (and other data) even if the
204 * given cbwfx is not large enough */
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
);
220 fd
.dwFormatIndex
= paftd
->cStandardFormats
;
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
);
227 HeapFree(GetProcessHeap(), 0, pwfx
);
232 static BOOL CALLBACK
FormatEnumProc(HACMDRIVERID hadid
,
233 LPACMFORMATDETAILSA pafd
,
234 DWORD_PTR dwInstance
,
239 WAVEFORMATEX
*dst
, *dstMax
;
240 DWORD dwSize
, dwSizeMax
;
243 acmMetrics((HACMOBJ
)hadid
, ACM_METRIC_DRIVER_SUPPORT
, &fdwSupport
);
245 if (winetest_interactive
)
246 trace(" 0x%04x, %s\n", pafd
->dwFormatTag
, pafd
->szFormat
);
248 acmDriverOpen(&had
, hadid
, 0);
249 dwSize
= pafd
->cbwfx
;
250 dst
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
);
252 /* test acmFormatSuggest with valid src format */
253 if (pafd
->dwFormatTag
== WAVE_FORMAT_PCM
)
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
)
262 if (fdwSupport
& ACMDRIVERDETAILS_SUPPORTF_CODEC
) /* supports different conversions */
263 ok(dst
->wFormatTag
!= WAVE_FORMAT_PCM
, "expected different format\n");
265 ok(dst
->wFormatTag
== WAVE_FORMAT_PCM
,
266 "expected %d, got %d\n", WAVE_FORMAT_PCM
, dst
->wFormatTag
);
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
);
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
);
295 HeapFree(GetProcessHeap(), 0, dstMax
);
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
);
306 todo_wine_if(rc
!= ACMERR_NOTPOSSIBLE
)
307 ok(rc
== ACMERR_NOTPOSSIBLE
,
308 "acmFormatSuggest(): rc = %08x, should be %08x\n",
309 rc
, ACMERR_NOTPOSSIBLE
);
311 HeapFree(GetProcessHeap(), 0, dst
);
312 acmDriverClose(had
, 0);
317 static BOOL CALLBACK
DriverEnumProc(HACMDRIVERID hadid
,
318 DWORD_PTR dwInstance
,
322 ACMDRIVERDETAILSA dd
;
325 DWORD dwDriverPriority
;
326 DWORD dwDriverSupport
;
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");
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
);
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
);
354 /* MSDN says this should fail but it doesn't in practice */
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
);
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
);
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
);
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
);
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
);
386 /* cbStruct should contain size of returned data (at most sizeof(dd))
387 TODO: should it be *exactly* sizeof(dd), as tested here?
389 if (rc
== MMSYSERR_NOERROR
) {
390 static const struct {
391 const char *shortname
;
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
},
404 ok(dd
.cbStruct
== sizeof(dd
),
405 "acmDriverDetailsA(): cbStruct = %08x\n", dd
.cbStruct
);
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",
414 dd
.wPid
, iter
->pid_alt
);
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",
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
508 if (rc
== MMSYSERR_NOERROR
) {
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
);
519 rc
= acmDriverID((HACMOBJ
)1, &hid
, 0);
520 ok(rc
== MMSYSERR_INVALHANDLE
,
521 "acmDriverID(): rc = %08x, should be %08x\n",
522 rc
, MMSYSERR_INVALHANDLE
);
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
);
531 rc
= acmDriverID((HACMOBJ
)had
, &hid
, 1);
532 ok(rc
== MMSYSERR_INVALFLAG
,
533 "acmDriverID(): rc = %08x, should be %08x\n",
534 rc
, MMSYSERR_INVALFLAG
);
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
);
542 "acmDriverID() returned ID %p doesn't equal %p\n",
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
);
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
);
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
);
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
;
571 ACMFORMATTAGDETAILSA aftd
;
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
);
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
);
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
);
592 pwfx
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
);
594 if (dwSize
>= sizeof(WAVEFORMATEX
))
595 pwfx
->cbSize
= LOWORD(dwSize
) - sizeof(WAVEFORMATEX
);
596 pwfx
->wFormatTag
= WAVE_FORMAT_UNKNOWN
;
598 fd
.cbStruct
= sizeof(fd
);
601 fd
.dwFormatTag
= WAVE_FORMAT_UNKNOWN
;
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
);
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
);
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
);
625 /* try bad pwfx structure size */
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
);
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
);
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
);
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
);
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
);
658 aftd
.cbStruct
= sizeof(aftd
);
659 aftd
.dwFormatTag
= WAVE_FORMAT_UNKNOWN
;
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
);
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
);
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
);
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
);
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
);
692 fd
.cbStruct
= sizeof(fd
);
694 ZeroMemory(fd
.pwfx
, dwSize
);
696 fd
.dwFormatTag
= WAVE_FORMAT_UNKNOWN
;
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
);
704 HeapFree(GetProcessHeap(), 0, pwfx
);
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
);
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
);
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
);
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
);
735 static const char * get_metric(UINT 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";
777 static void check_count(UINT uMetric
)
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
);
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
);
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
);
800 /* try valid parameters */
801 rc
= acmMetrics(NULL
, uMetric
, &dwMetric
);
802 ok(rc
== MMSYSERR_NOERROR
, "acmMetrics() failed: rc = 0x%08x\n", rc
);
804 if (rc
== MMSYSERR_NOERROR
&& winetest_interactive
)
805 trace("%s: %u\n", get_metric(uMetric
), dwMetric
);
808 static void driver_tests(void)
811 DWORD dwACMVersion
= acmGetVersion();
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)" : "");
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
);
833 if (winetest_interactive
)
834 trace("enabled drivers:\n");
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
);
842 static void test_prepareheader(void)
845 ADPCMWAVEFORMAT
*src
;
849 BYTE buf
[sizeof(WAVEFORMATEX
) + 32], pcm
[2048], input
[512];
852 src
= (ADPCMWAVEFORMAT
*)buf
;
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;
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;
879 dst
.wFormatTag
= WAVE_FORMAT_PCM
;
880 dst
.nSamplesPerSec
= 22050;
881 dst
.wBitsPerSample
= 8;
883 dst
.nBlockAlign
= dst
.wBitsPerSample
* dst
.nChannels
/ 8;
884 dst
.nAvgBytesPerSec
= dst
.nSamplesPerSec
* dst
.nBlockAlign
;
886 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)src
, &dst
, NULL
, 0, 0, 0);
887 ok(mr
== MMSYSERR_NOERROR
, "open failed: 0x%x\n", mr
);
889 memset(input
, 0, sizeof(input
));
890 memset(&hdr
, 0, sizeof(hdr
));
891 hdr
.cbStruct
= sizeof(hdr
);
893 hdr
.cbSrcLength
= sizeof(input
);
895 hdr
.cbDstLength
= sizeof(pcm
);
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
);
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
);
905 memset(&hdr
, 0, sizeof(hdr
));
906 hdr
.cbStruct
= sizeof(hdr
);
908 hdr
.cbSrcLength
= 0; /* invalid source length */
910 hdr
.cbDstLength
= sizeof(pcm
);
912 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
913 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
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
);
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
);
923 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
924 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
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
);
930 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
931 ok(mr
== MMSYSERR_NOERROR
, "prepare failed: 0x%x\n", mr
);
933 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
934 ok(mr
== MMSYSERR_NOERROR
, "unprepare failed: 0x%x\n", mr
);
936 memset(&hdr
, 0, sizeof(hdr
));
937 hdr
.cbStruct
= sizeof(hdr
);
939 hdr
.cbSrcLength
= sizeof(input
);
941 hdr
.cbDstLength
= sizeof(pcm
);
942 hdr
.fdwStatus
= ACMSTREAMHEADER_STATUSF_DONE
;
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
);
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
);
956 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
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
);
962 /* The 2 next tests are related to Lost Horizon (bug 24723) */
963 memset(&hdr
, 0, sizeof(hdr
));
964 hdr
.cbStruct
= sizeof(hdr
);
966 hdr
.cbSrcLength
= sizeof(input
);
968 hdr
.cbDstLength
= -4;
970 mr
= acmStreamPrepareHeader(has
, &hdr
, 0);
971 if (sizeof(void *) == 4) /* 64 bit fails on this test */
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
);
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
);
984 ok(hdr
.cbDstLengthUsed
== 1010, "expected 1010, got %d\n", hdr
.cbDstLengthUsed
);
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
);
992 ok(mr
== MMSYSERR_INVALPARAM
, "expected 0x0b, got 0x%x\n", mr
);
994 memset(&hdr
, 0, sizeof(hdr
));
995 hdr
.cbStruct
= sizeof(hdr
);
997 hdr
.cbSrcLength
= 24;
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
);
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
);
1011 mr
= acmStreamUnprepareHeader(has
, &hdr
, 0);
1012 ok(mr
== ACMERR_UNPREPARED
, "expected 0x202, got 0x%x\n", mr
);
1014 /* Less output space than required */
1015 memset(&hdr
, 0, sizeof(hdr
));
1016 hdr
.cbStruct
= sizeof(hdr
);
1018 hdr
.cbSrcLength
= sizeof(input
);
1020 hdr
.cbDstLength
= 32;
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
);
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
);
1033 ok(hdr
.cbSrcLengthUsed
== hdr
.cbSrcLength
, "expected %d, got %d\n", hdr
.cbSrcLength
, hdr
.cbSrcLengthUsed
);
1035 ok(hdr
.cbDstLengthUsed
== hdr
.cbDstLength
, "expected %d, got %d\n", hdr
.cbDstLength
, hdr
.cbDstLengthUsed
);
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
);
1041 mr
= acmStreamClose(has
, 0);
1042 ok(mr
== MMSYSERR_NOERROR
, "close failed: 0x%x\n", mr
);
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};
1047 struct stream_output
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
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
},
1101 static void test_convert(void)
1104 ACMSTREAMHEADER hdr
= {0};
1109 for (i
= 0; i
< ARRAY_SIZE(expected_output
); i
++)
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
);
1114 memset(&hdr
, 0, sizeof(hdr
));
1115 hdr
.cbStruct
= sizeof(hdr
);
1116 hdr
.pbSrc
= (BYTE
*)input
;
1117 hdr
.cbSrcLength
= sizeof(input
);
1119 hdr
.cbDstLength
= sizeof(output
);
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
);
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
);
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
);
1138 mmr
= acmStreamClose(has
, 0);
1139 ok(mmr
== MMSYSERR_NOERROR
, "#%d: close failed: 0x%x\n", i
, mmr
);
1143 static void test_acmFormatSuggest(void)
1145 WAVEFORMATEX src
, dst
;
1150 acmMetrics(NULL
, ACM_METRIC_MAX_SIZE_FORMAT
, &sizeMax
);
1152 /* Test a valid PCM format */
1153 src
.wFormatTag
= WAVE_FORMAT_PCM
;
1155 src
.nSamplesPerSec
= 8000;
1156 src
.nAvgBytesPerSec
= 16000;
1157 src
.nBlockAlign
= 2;
1158 src
.wBitsPerSample
= 16;
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
);
1171 /* All parameters from destination are valid */
1172 suggest
= ACM_FORMATSUGGESTF_NCHANNELS
1173 | ACM_FORMATSUGGESTF_NSAMPLESPERSEC
1174 | ACM_FORMATSUGGESTF_WBITSPERSAMPLE
1175 | ACM_FORMATSUGGESTF_WFORMATTAG
;
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
);
1186 /* Test an invalid PCM format */
1187 ZeroMemory(&dst
, sizeof(dst
));
1188 src
.nSamplesPerSec
= 0xdeadbeef;
1190 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeMax
, suggest
);
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
);
1196 src
.nSamplesPerSec
= 8000;
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
);
1203 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeMax
, suggest
);
1205 ok(rc
== MMSYSERR_NODRIVER
, "failed with error 0x%x\n", rc
);
1207 /* Test converting between two known but incompatible formats */
1208 src
.wFormatTag
= WAVE_FORMAT_ALAW
;
1210 src
.nSamplesPerSec
= 8000;
1211 src
.nAvgBytesPerSec
= 8000;
1212 src
.nBlockAlign
= 1;
1213 src
.wBitsPerSample
= 8;
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
);
1220 rc
= acmFormatSuggest(NULL
, &src
, &dst
, sizeof(IMAADPCMWAVEFORMAT
), suggest
);
1222 ok(rc
== MMSYSERR_NODRIVER
, "failed with error 0x%x\n", rc
);
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
);
1230 /* Invalid source and destination */
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
);
1240 static void test_acmFormatTagDetails(void)
1242 ACMFORMATTAGDETAILSW aftd
= {0};
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
);
1252 static void test_acmFormatChoose(void)
1254 ACMFORMATCHOOSEW afc
= {0};
1259 acmMetrics(NULL
, ACM_METRIC_MAX_SIZE_FORMAT
, &sizeMax
);
1260 pwfx
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeMax
);
1262 afc
.cbStruct
= sizeof(afc
);
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
);
1272 rc
= acmFormatChooseW(&afc
);
1273 ok(rc
== MMSYSERR_INVALPARAM
, "expected 0xb, got 0x%x\n", rc
);
1276 HeapFree(GetProcessHeap(), 0, pwfx
);
1279 static void test_mp3(void)
1281 MPEGLAYER3WAVEFORMAT src
;
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;
1294 src
.wID
= MPEGLAYER3_ID_MPEG
;
1296 src
.nBlockSize
= 576;
1297 src
.nFramesPerBlock
= 1;
1298 src
.nCodecDelay
= 0;
1301 dst
.wFormatTag
= WAVE_FORMAT_PCM
;
1302 dst
.nSamplesPerSec
= 11025;
1303 dst
.wBitsPerSample
= 16;
1305 dst
.nBlockAlign
= dst
.wBitsPerSample
* dst
.nChannels
/ 8;
1306 dst
.nAvgBytesPerSec
= dst
.nSamplesPerSec
* dst
.nBlockAlign
;
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);
1314 src
.wfx
.cbSize
= MPEGLAYER3_WFX_EXTRA_BYTES
;
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);
1321 src
.wID
= MPEGLAYER3_ID_MPEG
;
1324 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
1325 ok(mr
== MMSYSERR_NOERROR
|| broken(mr
== ACMERR_NOTPOSSIBLE
) /* Win 2008 */,
1326 "failed with error 0x%x\n", mr
);
1327 if (mr
== MMSYSERR_NOERROR
)
1329 mr
= acmStreamClose(has
, 0);
1330 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
1332 src
.nBlockSize
= 576;
1333 src
.wfx
.nAvgBytesPerSec
= 0;
1335 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
1336 ok(mr
== MMSYSERR_NOERROR
|| broken(mr
== ACMERR_NOTPOSSIBLE
) /* Win 2008 */,
1337 "failed with error 0x%x\n", mr
);
1338 if (mr
== MMSYSERR_NOERROR
)
1340 /* causes a division by zero exception in XP, Vista,
1341 but throws ACMERR_NOTPOSSIBLE on others */
1342 if (0) acmStreamSize(has
, 4000, &output
, ACM_STREAMSIZEF_SOURCE
);
1343 mr
= acmStreamClose(has
, 0);
1344 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
1347 src
.wfx
.nAvgBytesPerSec
= 2000;
1349 mr
= acmStreamOpen(&has
, NULL
, (WAVEFORMATEX
*)&src
, &dst
, NULL
, 0, 0, 0);
1350 ok(mr
== MMSYSERR_NOERROR
|| broken(mr
== ACMERR_NOTPOSSIBLE
) /* Win 2008 */,
1351 "failed with error 0x%x\n", mr
);
1352 if (mr
== MMSYSERR_NOERROR
)
1354 mr
= acmStreamSize(has
, 4000, &output
, ACM_STREAMSIZEF_SOURCE
);
1355 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
1356 mr
= acmStreamClose(has
, 0);
1357 ok(mr
== MMSYSERR_NOERROR
, "failed with error 0x%x\n", mr
);
1365 int load
, free
, open
, close
, enable
, disable
, install
,
1366 remove
, details
, notify
, querycfg
, about
;
1370 int tag_details
, details
, suggest
;
1374 int open
, close
, size
, convert
, prepare
, unprepare
, reset
;
1379 static LRESULT CALLBACK
acm_driver_func(DWORD_PTR id
, HDRVR handle
, UINT msg
, LPARAM param1
, LPARAM param2
)
1383 /* Driver messages */
1385 driver_calls
.driver
.load
++;
1388 driver_calls
.driver
.free
++;
1391 driver_calls
.driver
.open
++;
1394 driver_calls
.driver
.close
++;
1397 driver_calls
.driver
.enable
++;
1400 driver_calls
.driver
.disable
++;
1402 case DRV_QUERYCONFIGURE
:
1403 driver_calls
.driver
.querycfg
++;
1406 driver_calls
.driver
.install
++;
1407 return DRVCNF_RESTART
;
1409 driver_calls
.driver
.remove
++;
1410 return DRVCNF_RESTART
;
1411 case ACMDM_DRIVER_ABOUT
:
1412 driver_calls
.driver
.about
++;
1413 return MMSYSERR_NOTSUPPORTED
;
1414 case ACMDM_DRIVER_DETAILS
:
1416 ACMDRIVERDETAILSA
*ptr
= (ACMDRIVERDETAILSA
*)param1
;
1418 /* copied from pcmconverter.c */
1419 ptr
->fccType
= ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
1420 ptr
->fccComp
= ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
;
1421 ptr
->wMid
= MM_MICROSOFT
;
1422 ptr
->wPid
= MM_MSFT_ACM_PCM
;
1423 ptr
->vdwACM
= 0x01000000;
1424 ptr
->vdwDriver
= 0x01000000;
1425 ptr
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CONVERTER
;
1426 ptr
->cFormatTags
= 1;
1427 ptr
->cFilterTags
= 0;
1429 strcpy(ptr
->szShortName
, "TEST-CODEC");
1430 strcpy(ptr
->szLongName
, "Wine Test Codec");
1431 strcpy(ptr
->szCopyright
, "Brought to you by the Wine team...");
1432 strcpy(ptr
->szLicensing
, "Refer to LICENSE file");
1433 ptr
->szFeatures
[0] = 0;
1435 driver_calls
.driver
.details
++;
1438 case ACMDM_DRIVER_NOTIFY
:
1439 driver_calls
.driver
.notify
++;
1440 return MMSYSERR_NOTSUPPORTED
;
1442 /* Format messages */
1443 case ACMDM_FORMATTAG_DETAILS
:
1444 driver_calls
.format
.tag_details
++;
1446 case ACMDM_FORMAT_DETAILS
:
1447 driver_calls
.format
.details
++;
1449 case ACMDM_FORMAT_SUGGEST
:
1450 driver_calls
.format
.suggest
++;
1453 /* Stream messages */
1454 case ACMDM_STREAM_OPEN
:
1455 driver_calls
.stream
.open
++;
1457 case ACMDM_STREAM_CLOSE
:
1458 driver_calls
.stream
.close
++;
1460 case ACMDM_STREAM_SIZE
:
1461 driver_calls
.stream
.size
++;
1463 case ACMDM_STREAM_CONVERT
:
1464 driver_calls
.stream
.convert
++;
1466 case ACMDM_STREAM_RESET
:
1467 driver_calls
.stream
.reset
++;
1468 return MMSYSERR_NOTSUPPORTED
;
1469 case ACMDM_STREAM_PREPARE
:
1470 driver_calls
.stream
.prepare
++;
1472 case ACMDM_STREAM_UNPREPARE
:
1473 driver_calls
.stream
.unprepare
++;
1477 driver_calls
.other
++;
1478 return DefDriverProc(id
, handle
, msg
, param1
, param2
);
1480 return MMSYSERR_NOERROR
;
1483 static void test_acmDriverAdd(void)
1489 ACMDRIVERDETAILSA drv_details
;
1492 /* Driver load steps:
1493 * - acmDriverAdd checks the passed parameters
1494 * - DRV_LOAD message is sent - required
1495 * - DRV_ENABLE message is sent - required
1496 * - DRV_OPEN message is sent - required
1497 * - DRV_DETAILS message is sent - required
1498 * - ACMDM_FORMATTAG_DETAILS message is sent - optional
1499 * - DRV_QUERYCONFIGURE message is sent - optional
1500 * - ACMDM_DRIVER_ABOUT message is sent - optional
1503 res
= acmDriverAddA(&drvid
, GetModuleHandleA(NULL
), (LPARAM
)acm_driver_func
, 0, ACM_DRIVERADDF_FUNCTION
);
1504 ok(res
== MMSYSERR_NOERROR
, "Expected 0, got %d\n", res
);
1506 ok(driver_calls
.driver
.open
== 1, "Expected 1, got %d\n", driver_calls
.driver
.open
);
1507 ok(driver_calls
.driver
.details
== 1, "Expected 1, got %d\n", driver_calls
.driver
.details
);
1509 memset(&acm
, 0, sizeof(acm
));
1510 res
= acmDriverDetailsA(drvid
, &acm
.drv_details
, 0);
1511 ok(res
== MMSYSERR_INVALPARAM
, "Expected 11, got %d\n", res
);
1513 acm
.drv_details
.cbStruct
= sizeof(acm
.drv_details
);
1514 res
= acmDriverDetailsA(drvid
, &acm
.drv_details
, 0);
1515 ok(res
== MMSYSERR_NOERROR
, "Expected 0, got %d\n", res
);
1517 ok(driver_calls
.driver
.open
== 1, "Expected 1, got %d\n", driver_calls
.driver
.open
);
1518 ok(driver_calls
.driver
.details
== 2, "Expected 2, got %d\n", driver_calls
.driver
.details
);
1520 ok(driver_calls
.driver
.close
== 0, "Expected 0, got %d\n", driver_calls
.driver
.close
);
1526 test_prepareheader();
1528 test_acmFormatSuggest();
1529 test_acmFormatTagDetails();
1530 test_acmFormatChoose();
1532 /* Test acmDriverAdd in the end as it may conflict
1533 * with other tests due to codec lookup order */
1534 test_acmDriverAdd();