push b25f14be0dd3305724e1f1ef337bfe2a9ff59832
[wine/hacks.git] / dlls / winmm / tests / mixer.c
blob25711b7e78795c3193d5b9711f12e68c0ab0e8f6
1 /*
2 * Test mixer
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
22 * To Do:
23 * add interactive tests
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
31 #include "wine/test.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "mmsystem.h"
37 #include "winmm_test.h"
39 static const char * line_flags(DWORD fdwLine)
41 static char flags[100];
42 BOOL first=TRUE;
43 flags[0]=0;
44 if (fdwLine&MIXERLINE_LINEF_ACTIVE) {
45 strcat(flags,"MIXERLINE_LINEF_ACTIVE");
46 first=FALSE;
48 if (fdwLine&MIXERLINE_LINEF_DISCONNECTED) {
49 if (!first)
50 strcat(flags, "|");
52 strcat(flags,"MIXERLINE_LINEF_DISCONNECTED");
53 first=FALSE;
56 if (fdwLine&MIXERLINE_LINEF_SOURCE) {
57 if (!first)
58 strcat(flags, "|");
60 strcat(flags,"MIXERLINE_LINEF_SOURCE");
63 return flags;
66 static const char * component_type(DWORD dwComponentType)
68 #define TYPE_TO_STR(x) case x: return #x
69 switch (dwComponentType) {
70 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_UNDEFINED);
71 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_DIGITAL);
72 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_LINE);
73 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_MONITOR);
74 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
75 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_HEADPHONES);
76 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_TELEPHONE);
77 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
78 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_VOICEIN);
79 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED);
80 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_DIGITAL);
81 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_LINE);
82 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE);
83 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER);
84 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC);
85 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE);
86 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER);
87 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
88 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY);
89 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_ANALOG);
91 #undef TYPE_TO_STR
92 return "UNKNOWN";
95 static const char * target_type(DWORD dwType)
97 #define TYPE_TO_STR(x) case x: return #x
98 switch (dwType) {
99 TYPE_TO_STR(MIXERLINE_TARGETTYPE_UNDEFINED);
100 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEOUT);
101 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEIN);
102 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIOUT);
103 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIIN);
104 TYPE_TO_STR(MIXERLINE_TARGETTYPE_AUX);
106 #undef TYPE_TO_STR
107 return "UNKNOWN";
110 static const char * control_type(DWORD dwControlType)
112 #define TYPE_TO_STR(x) case x: return #x
113 switch (dwControlType) {
114 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_CUSTOM);
115 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER);
116 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER);
117 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PEAKMETER);
118 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER);
119 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEAN);
120 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_ONOFF);
121 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUTE);
122 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MONO);
123 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_LOUDNESS);
124 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_STEREOENH);
125 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS_BOOST);
126 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BUTTON);
127 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_DECIBELS);
128 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNED);
129 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNED);
130 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PERCENT);
131 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SLIDER);
132 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PAN);
133 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN);
134 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_FADER);
135 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_VOLUME);
136 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS);
137 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_TREBLE);
138 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_EQUALIZER);
139 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SINGLESELECT);
140 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUX);
141 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT);
142 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MIXER);
143 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MICROTIME);
144 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MILLITIME);
146 #undef TYPE_TO_STR
147 return "UNKNOWN";
150 static const char * control_flags(DWORD fdwControl)
152 static char flags[100];
153 BOOL first=TRUE;
154 flags[0]=0;
155 if (fdwControl&MIXERCONTROL_CONTROLF_UNIFORM) {
156 strcat(flags,"MIXERCONTROL_CONTROLF_UNIFORM");
157 first=FALSE;
159 if (fdwControl&MIXERCONTROL_CONTROLF_MULTIPLE) {
160 if (!first)
161 strcat(flags, "|");
163 strcat(flags,"MIXERCONTROL_CONTROLF_MULTIPLE");
164 first=FALSE;
167 if (fdwControl&MIXERCONTROL_CONTROLF_DISABLED) {
168 if (!first)
169 strcat(flags, "|");
171 strcat(flags,"MIXERCONTROL_CONTROLF_DISABLED");
174 return flags;
177 static void mixer_test_controlA(HMIXER mix, LPMIXERCONTROLA control)
179 MMRESULT rc;
181 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
182 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
183 MIXERCONTROLDETAILS details;
184 MIXERCONTROLDETAILS_UNSIGNED value;
186 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
187 details.dwControlID = control->dwControlID;
188 details.cChannels = 1;
189 U(details).cMultipleItems = 0;
190 details.paDetails = &value;
191 details.cbDetails = sizeof(value);
193 /* read the current control value */
194 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
195 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
196 "MMSYSERR_NOERROR expected, got %s\n",
197 mmsys_error(rc));
198 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
199 MIXERCONTROLDETAILS new_details;
200 MIXERCONTROLDETAILS_UNSIGNED new_value;
202 trace(" Value=%d\n",value.dwValue);
204 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
205 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
206 else
207 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
209 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
210 new_details.dwControlID = control->dwControlID;
211 new_details.cChannels = 1;
212 U(new_details).cMultipleItems = 0;
213 new_details.paDetails = &new_value;
214 new_details.cbDetails = sizeof(new_value);
216 /* change the control value by one step */
217 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
218 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
219 "MMSYSERR_NOERROR expected, got %s\n",
220 mmsys_error(rc));
221 if (rc==MMSYSERR_NOERROR) {
222 MIXERCONTROLDETAILS ret_details;
223 MIXERCONTROLDETAILS_UNSIGNED ret_value;
225 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
226 ret_details.dwControlID = control->dwControlID;
227 ret_details.cChannels = 1;
228 U(ret_details).cMultipleItems = 0;
229 ret_details.paDetails = &ret_value;
230 ret_details.cbDetails = sizeof(ret_value);
232 /* read back the new control value */
233 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
234 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
235 "MMSYSERR_NOERROR expected, got %s\n",
236 mmsys_error(rc));
237 if (rc==MMSYSERR_NOERROR) {
238 /* result may not match exactly because of rounding */
239 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
240 "Couldn't change value from %d to %d, returned %d\n",
241 value.dwValue,new_value.dwValue,ret_value.dwValue);
243 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
244 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
245 details.dwControlID = control->dwControlID;
246 details.cChannels = 1;
247 U(details).cMultipleItems = 0;
248 details.paDetails = &value;
249 details.cbDetails = sizeof(value);
251 /* restore original value */
252 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
253 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
254 "MMSYSERR_NOERROR expected, got %s\n",
255 mmsys_error(rc));
260 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
261 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
262 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
263 MIXERCONTROLDETAILS details;
264 MIXERCONTROLDETAILS_BOOLEAN value;
266 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
267 details.dwControlID = control->dwControlID;
268 details.cChannels = 1;
269 U(details).cMultipleItems = 0;
270 details.paDetails = &value;
271 details.cbDetails = sizeof(value);
273 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
274 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
275 "MMSYSERR_NOERROR expected, got %s\n",
276 mmsys_error(rc));
277 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
278 MIXERCONTROLDETAILS new_details;
279 MIXERCONTROLDETAILS_BOOLEAN new_value;
281 trace(" Value=%d\n",value.fValue);
283 if (value.fValue == FALSE)
284 new_value.fValue = TRUE;
285 else
286 new_value.fValue = FALSE;
288 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
289 new_details.dwControlID = control->dwControlID;
290 new_details.cChannels = 1;
291 U(new_details).cMultipleItems = 0;
292 new_details.paDetails = &new_value;
293 new_details.cbDetails = sizeof(new_value);
295 /* change the control value by one step */
296 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
297 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
298 "MMSYSERR_NOERROR expected, got %s\n",
299 mmsys_error(rc));
300 if (rc==MMSYSERR_NOERROR) {
301 MIXERCONTROLDETAILS ret_details;
302 MIXERCONTROLDETAILS_BOOLEAN ret_value;
304 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
305 ret_details.dwControlID = control->dwControlID;
306 ret_details.cChannels = 1;
307 U(ret_details).cMultipleItems = 0;
308 ret_details.paDetails = &ret_value;
309 ret_details.cbDetails = sizeof(ret_value);
311 /* read back the new control value */
312 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
313 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
314 "MMSYSERR_NOERROR expected, got %s\n",
315 mmsys_error(rc));
316 if (rc==MMSYSERR_NOERROR) {
317 /* result may not match exactly because of rounding */
318 ok(ret_value.fValue==new_value.fValue,
319 "Couldn't change value from %d to %d, returned %d\n",
320 value.fValue,new_value.fValue,ret_value.fValue);
322 if (ret_value.fValue==new_value.fValue) {
323 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
324 details.dwControlID = control->dwControlID;
325 details.cChannels = 1;
326 U(details).cMultipleItems = 0;
327 details.paDetails = &value;
328 details.cbDetails = sizeof(value);
330 /* restore original value */
331 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
332 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
333 "MMSYSERR_NOERROR expected, got %s\n",
334 mmsys_error(rc));
339 } else {
340 /* FIXME */
344 static void mixer_test_deviceA(int device)
346 MIXERCAPSA capsA;
347 HMIXER mix;
348 MMRESULT rc;
349 DWORD d,s,ns,nc;
351 rc=mixerGetDevCapsA(device,0,sizeof(capsA));
352 ok(rc==MMSYSERR_INVALPARAM,
353 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
354 mmsys_error(rc));
356 rc=mixerGetDevCapsA(device,&capsA,4);
357 ok(rc==MMSYSERR_NOERROR,
358 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
359 mmsys_error(rc));
361 rc=mixerGetDevCapsA(device,&capsA,sizeof(capsA));
362 ok(rc==MMSYSERR_NOERROR,
363 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
364 mmsys_error(rc));
366 if (winetest_interactive) {
367 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device,
368 capsA.szPname, capsA.vDriverVersion >> 8,
369 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid,
370 capsA.cDestinations);
371 } else {
372 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
373 capsA.szPname, capsA.vDriverVersion >> 8,
374 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
377 rc=mixerOpen(&mix, device, 0, 0, 0);
378 ok(rc==MMSYSERR_NOERROR,
379 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc));
380 if (rc==MMSYSERR_NOERROR) {
381 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_FUNCTION);
382 ok(rc==MMSYSERR_INVALFLAG,
383 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n", mmsys_error(rc));
385 for (d=0;d<capsA.cDestinations;d++) {
386 MIXERLINEA mixerlineA;
387 mixerlineA.cbStruct = 0;
388 mixerlineA.dwDestination=d;
389 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
390 MIXER_GETLINEINFOF_DESTINATION);
391 ok(rc==MMSYSERR_INVALPARAM,
392 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
393 "MMSYSERR_INVALPARAM expected, got %s\n",
394 mmsys_error(rc));
396 mixerlineA.cbStruct = sizeof(mixerlineA);
397 mixerlineA.dwDestination=capsA.cDestinations;
398 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
399 MIXER_GETLINEINFOF_DESTINATION);
400 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
401 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
402 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
403 mmsys_error(rc));
405 mixerlineA.cbStruct = sizeof(mixerlineA);
406 mixerlineA.dwDestination=d;
407 rc=mixerGetLineInfoA((HMIXEROBJ)mix,0,
408 MIXER_GETLINEINFOF_DESTINATION);
409 ok(rc==MMSYSERR_INVALPARAM,
410 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
411 "MMSYSERR_INVALPARAM expected, got %s\n",
412 mmsys_error(rc));
414 mixerlineA.cbStruct = sizeof(mixerlineA);
415 mixerlineA.dwDestination=d;
416 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,-1);
417 ok(rc==MMSYSERR_INVALFLAG,
418 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
419 mmsys_error(rc));
421 mixerlineA.cbStruct = sizeof(mixerlineA);
422 mixerlineA.dwDestination=d;
423 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
424 MIXER_GETLINEINFOF_DESTINATION);
425 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
426 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
427 "MMSYSERR_NOERROR expected, got %s\n",
428 mmsys_error(rc));
429 if (rc==MMSYSERR_NODRIVER)
430 trace(" No Driver\n");
431 else if (rc==MMSYSERR_NOERROR) {
432 if (winetest_interactive) {
433 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
434 d,mixerlineA.szShortName, mixerlineA.szName,
435 mixerlineA.dwDestination,mixerlineA.dwSource);
436 trace(" LineID=%08x Channels=%d "
437 "Connections=%d Controls=%d\n",
438 mixerlineA.dwLineID,mixerlineA.cChannels,
439 mixerlineA.cConnections,mixerlineA.cControls);
440 trace(" State=0x%08x(%s)\n",
441 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
442 trace(" ComponentType=%s\n",
443 component_type(mixerlineA.dwComponentType));
444 trace(" Type=%s\n",
445 target_type(mixerlineA.Target.dwType));
446 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
447 mixerlineA.Target.dwDeviceID,
448 mixerlineA.Target.szPname,
449 mixerlineA.Target.vDriverVersion >> 8,
450 mixerlineA.Target.vDriverVersion & 0xff,
451 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
453 ns=mixerlineA.cConnections;
454 for(s=0;s<ns;s++) {
455 mixerlineA.cbStruct = sizeof(mixerlineA);
456 mixerlineA.dwDestination=d;
457 mixerlineA.dwSource=s;
458 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
459 MIXER_GETLINEINFOF_SOURCE);
460 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
461 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
462 "MMSYSERR_NOERROR expected, got %s\n",
463 mmsys_error(rc));
464 if (rc==MMSYSERR_NODRIVER)
465 trace(" No Driver\n");
466 else if (rc==MMSYSERR_NOERROR) {
467 LPMIXERCONTROLA array;
468 MIXERLINECONTROLSA controls;
469 if (winetest_interactive) {
470 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
471 s,mixerlineA.szShortName, mixerlineA.szName,
472 mixerlineA.dwDestination,mixerlineA.dwSource);
473 trace(" LineID=%08x Channels=%d "
474 "Connections=%d Controls=%d\n",
475 mixerlineA.dwLineID,mixerlineA.cChannels,
476 mixerlineA.cConnections,mixerlineA.cControls);
477 trace(" State=0x%08x(%s)\n",
478 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
479 trace(" ComponentType=%s\n",
480 component_type(mixerlineA.dwComponentType));
481 trace(" Type=%s\n",
482 target_type(mixerlineA.Target.dwType));
483 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
484 mixerlineA.Target.dwDeviceID,
485 mixerlineA.Target.szPname,
486 mixerlineA.Target.vDriverVersion >> 8,
487 mixerlineA.Target.vDriverVersion & 0xff,
488 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
490 if (mixerlineA.cControls) {
491 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
492 mixerlineA.cControls*sizeof(MIXERCONTROLA));
493 if (array) {
494 memset(&controls, 0, sizeof(controls));
496 rc=mixerGetLineControlsA((HMIXEROBJ)mix,0,
497 MIXER_GETLINECONTROLSF_ALL);
498 ok(rc==MMSYSERR_INVALPARAM,
499 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
500 "MMSYSERR_INVALPARAM expected, got %s\n",
501 mmsys_error(rc));
503 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,-1);
504 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
505 "mixerGetLineControlsA(-1): "
506 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
507 mmsys_error(rc));
509 controls.cbStruct = sizeof(MIXERLINECONTROLSA);
510 controls.cControls = mixerlineA.cControls;
511 controls.dwLineID = mixerlineA.dwLineID;
512 controls.pamxctrl = array;
513 controls.cbmxctrl = sizeof(MIXERCONTROLA);
515 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
516 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
518 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,
519 MIXER_GETLINECONTROLSF_ALL);
520 ok(rc==MMSYSERR_NOERROR,
521 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
522 "MMSYSERR_NOERROR expected, got %s\n",
523 mmsys_error(rc));
524 if (rc==MMSYSERR_NOERROR) {
525 for(nc=0;nc<mixerlineA.cControls;nc++) {
526 if (winetest_interactive) {
527 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc,
528 array[nc].szShortName,
529 array[nc].szName, array[nc].dwControlID);
530 trace(" ControlType=%s\n",
531 control_type(array[nc].dwControlType));
532 trace(" Control=0x%08x(%s)\n",
533 array[nc].fdwControl,
534 control_flags(array[nc].fdwControl));
535 trace(" Items=%d Min=%d Max=%d Step=%d\n",
536 array[nc].cMultipleItems,
537 S1(array[nc].Bounds).dwMinimum,
538 S1(array[nc].Bounds).dwMaximum,
539 array[nc].Metrics.cSteps);
542 mixer_test_controlA(mix, &array[nc]);
546 HeapFree(GetProcessHeap(),0,array);
553 rc=mixerClose(mix);
554 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALHANDLE,
555 "mixerClose: MMSYSERR_NOERROR or MMSYSERR_INVALHANDLE expected, got %s\n",
556 mmsys_error(rc));
560 static void mixer_test_controlW(HMIXER mix, LPMIXERCONTROLW control)
562 MMRESULT rc;
564 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
565 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
566 MIXERCONTROLDETAILS details;
567 MIXERCONTROLDETAILS_UNSIGNED value;
569 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
570 details.dwControlID = control->dwControlID;
571 details.cChannels = 1;
572 U(details).cMultipleItems = 0;
573 details.paDetails = &value;
574 details.cbDetails = sizeof(value);
576 /* read the current control value */
577 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
578 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
579 "MMSYSERR_NOERROR expected, got %s\n",
580 mmsys_error(rc));
581 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
582 MIXERCONTROLDETAILS new_details;
583 MIXERCONTROLDETAILS_UNSIGNED new_value;
585 trace(" Value=%d\n",value.dwValue);
587 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
588 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
589 else
590 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
592 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
593 new_details.dwControlID = control->dwControlID;
594 new_details.cChannels = 1;
595 U(new_details).cMultipleItems = 0;
596 new_details.paDetails = &new_value;
597 new_details.cbDetails = sizeof(new_value);
599 /* change the control value by one step */
600 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
601 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
602 "MMSYSERR_NOERROR expected, got %s\n",
603 mmsys_error(rc));
604 if (rc==MMSYSERR_NOERROR) {
605 MIXERCONTROLDETAILS ret_details;
606 MIXERCONTROLDETAILS_UNSIGNED ret_value;
608 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
609 ret_details.dwControlID = control->dwControlID;
610 ret_details.cChannels = 1;
611 U(ret_details).cMultipleItems = 0;
612 ret_details.paDetails = &ret_value;
613 ret_details.cbDetails = sizeof(ret_value);
615 /* read back the new control value */
616 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
617 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
618 "MMSYSERR_NOERROR expected, got %s\n",
619 mmsys_error(rc));
620 if (rc==MMSYSERR_NOERROR) {
621 /* result may not match exactly because of rounding */
622 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
623 "Couldn't change value from %d to %d, returned %d\n",
624 value.dwValue,new_value.dwValue,ret_value.dwValue);
626 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
627 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
628 details.dwControlID = control->dwControlID;
629 details.cChannels = 1;
630 U(details).cMultipleItems = 0;
631 details.paDetails = &value;
632 details.cbDetails = sizeof(value);
634 /* restore original value */
635 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
636 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
637 "MMSYSERR_NOERROR expected, got %s\n",
638 mmsys_error(rc));
643 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
644 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
645 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
646 MIXERCONTROLDETAILS details;
647 MIXERCONTROLDETAILS_BOOLEAN value;
649 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
650 details.dwControlID = control->dwControlID;
651 details.cChannels = 1;
652 U(details).cMultipleItems = 0;
653 details.paDetails = &value;
654 details.cbDetails = sizeof(value);
656 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
657 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
658 "MMSYSERR_NOERROR expected, got %s\n",
659 mmsys_error(rc));
660 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
661 MIXERCONTROLDETAILS new_details;
662 MIXERCONTROLDETAILS_BOOLEAN new_value;
664 trace(" Value=%d\n",value.fValue);
666 if (value.fValue == FALSE)
667 new_value.fValue = TRUE;
668 else
669 new_value.fValue = FALSE;
671 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
672 new_details.dwControlID = control->dwControlID;
673 new_details.cChannels = 1;
674 U(new_details).cMultipleItems = 0;
675 new_details.paDetails = &new_value;
676 new_details.cbDetails = sizeof(new_value);
678 /* change the control value by one step */
679 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
680 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
681 "MMSYSERR_NOERROR expected, got %s\n",
682 mmsys_error(rc));
683 if (rc==MMSYSERR_NOERROR) {
684 MIXERCONTROLDETAILS ret_details;
685 MIXERCONTROLDETAILS_BOOLEAN ret_value;
687 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
688 ret_details.dwControlID = control->dwControlID;
689 ret_details.cChannels = 1;
690 U(ret_details).cMultipleItems = 0;
691 ret_details.paDetails = &ret_value;
692 ret_details.cbDetails = sizeof(ret_value);
694 /* read back the new control value */
695 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
696 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
697 "MMSYSERR_NOERROR expected, got %s\n",
698 mmsys_error(rc));
699 if (rc==MMSYSERR_NOERROR) {
700 /* result may not match exactly because of rounding */
701 ok(ret_value.fValue==new_value.fValue,
702 "Couldn't change value from %d to %d, returned %d\n",
703 value.fValue,new_value.fValue,ret_value.fValue);
705 if (ret_value.fValue==new_value.fValue) {
706 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
707 details.dwControlID = control->dwControlID;
708 details.cChannels = 1;
709 U(details).cMultipleItems = 0;
710 details.paDetails = &value;
711 details.cbDetails = sizeof(value);
713 /* restore original value */
714 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
715 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
716 "MMSYSERR_NOERROR expected, got %s\n",
717 mmsys_error(rc));
722 } else {
723 /* FIXME */
727 static void mixer_test_deviceW(int device)
729 MIXERCAPSW capsW;
730 HMIXER mix;
731 MMRESULT rc;
732 DWORD d,s,ns,nc;
733 char szShortName[MIXER_SHORT_NAME_CHARS];
734 char szName[MIXER_LONG_NAME_CHARS];
735 char szPname[MAXPNAMELEN];
737 rc=mixerGetDevCapsW(device,0,sizeof(capsW));
738 ok(rc==MMSYSERR_INVALPARAM,
739 "mixerGetDevCapsW: MMSYSERR_INVALPARAM expected, got %s\n",
740 mmsys_error(rc));
742 rc=mixerGetDevCapsW(device,&capsW,4);
743 ok(rc==MMSYSERR_NOERROR ||
744 rc==MMSYSERR_INVALPARAM, /* Vista and W2K8 */
745 "mixerGetDevCapsW: MMSYSERR_NOERROR or MMSYSERR_INVALPARAM expected, got %s\n",
746 mmsys_error(rc));
748 rc=mixerGetDevCapsW(device,&capsW,sizeof(capsW));
749 ok(rc==MMSYSERR_NOERROR,
750 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
751 mmsys_error(rc));
753 WideCharToMultiByte(CP_ACP,0,capsW.szPname, MAXPNAMELEN,szPname,
754 MAXPNAMELEN,NULL,NULL);
755 if (winetest_interactive) {
756 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device,
757 szPname, capsW.vDriverVersion >> 8,
758 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid,
759 capsW.cDestinations);
760 } else {
761 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
762 szPname, capsW.vDriverVersion >> 8,
763 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid);
767 rc=mixerOpen(&mix, device, 0, 0, 0);
768 ok(rc==MMSYSERR_NOERROR,
769 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",mmsys_error(rc));
770 if (rc==MMSYSERR_NOERROR) {
771 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_FUNCTION);
772 ok(rc==MMSYSERR_INVALFLAG,
773 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n", mmsys_error(rc));
775 for (d=0;d<capsW.cDestinations;d++) {
776 MIXERLINEW mixerlineW;
777 mixerlineW.cbStruct = 0;
778 mixerlineW.dwDestination=d;
779 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
780 MIXER_GETLINEINFOF_DESTINATION);
781 ok(rc==MMSYSERR_INVALPARAM,
782 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
783 "MMSYSERR_INVALPARAM expected, got %s\n",
784 mmsys_error(rc));
786 mixerlineW.cbStruct = sizeof(mixerlineW);
787 mixerlineW.dwDestination=capsW.cDestinations;
788 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
789 MIXER_GETLINEINFOF_DESTINATION);
790 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
791 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
792 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
793 mmsys_error(rc));
795 mixerlineW.cbStruct = sizeof(mixerlineW);
796 mixerlineW.dwDestination=d;
797 rc=mixerGetLineInfoW((HMIXEROBJ)mix,0,
798 MIXER_GETLINEINFOF_DESTINATION);
799 ok(rc==MMSYSERR_INVALPARAM,
800 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
801 "MMSYSERR_INVALPARAM expected, got %s\n",
802 mmsys_error(rc));
804 mixerlineW.cbStruct = sizeof(mixerlineW);
805 mixerlineW.dwDestination=d;
806 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,-1);
807 ok(rc==MMSYSERR_INVALFLAG,
808 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
809 mmsys_error(rc));
811 mixerlineW.cbStruct = sizeof(mixerlineW);
812 mixerlineW.dwDestination=d;
813 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
814 MIXER_GETLINEINFOF_DESTINATION);
815 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
816 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
817 "MMSYSERR_NOERROR expected, got %s\n",
818 mmsys_error(rc));
819 if (rc==MMSYSERR_NODRIVER)
820 trace(" No Driver\n");
821 else if (rc==MMSYSERR_NOERROR && winetest_interactive) {
822 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
823 MIXER_SHORT_NAME_CHARS,szShortName,
824 MIXER_SHORT_NAME_CHARS,NULL,NULL);
825 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
826 MIXER_LONG_NAME_CHARS,szName,
827 MIXER_LONG_NAME_CHARS,NULL,NULL);
828 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
829 MAXPNAMELEN,szPname,
830 MAXPNAMELEN,NULL, NULL);
831 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
832 d,szShortName,szName,
833 mixerlineW.dwDestination,mixerlineW.dwSource);
834 trace(" LineID=%08x Channels=%d "
835 "Connections=%d Controls=%d\n",
836 mixerlineW.dwLineID,mixerlineW.cChannels,
837 mixerlineW.cConnections,mixerlineW.cControls);
838 trace(" State=0x%08x(%s)\n",
839 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
840 trace(" ComponentType=%s\n",
841 component_type(mixerlineW.dwComponentType));
842 trace(" Type=%s\n",
843 target_type(mixerlineW.Target.dwType));
844 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
845 mixerlineW.Target.dwDeviceID,szPname,
846 mixerlineW.Target.vDriverVersion >> 8,
847 mixerlineW.Target.vDriverVersion & 0xff,
848 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
850 ns=mixerlineW.cConnections;
851 for(s=0;s<ns;s++) {
852 mixerlineW.cbStruct = sizeof(mixerlineW);
853 mixerlineW.dwDestination=d;
854 mixerlineW.dwSource=s;
855 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
856 MIXER_GETLINEINFOF_SOURCE);
857 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
858 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
859 "MMSYSERR_NOERROR expected, got %s\n",
860 mmsys_error(rc));
861 if (rc==MMSYSERR_NODRIVER)
862 trace(" No Driver\n");
863 else if (rc==MMSYSERR_NOERROR) {
864 LPMIXERCONTROLW array;
865 MIXERLINECONTROLSW controls;
866 if (winetest_interactive) {
867 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
868 MIXER_SHORT_NAME_CHARS,szShortName,
869 MIXER_SHORT_NAME_CHARS,NULL,NULL);
870 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
871 MIXER_LONG_NAME_CHARS,szName,
872 MIXER_LONG_NAME_CHARS,NULL,NULL);
873 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
874 MAXPNAMELEN,szPname,
875 MAXPNAMELEN,NULL, NULL);
876 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
877 s,szShortName,szName,
878 mixerlineW.dwDestination,mixerlineW.dwSource);
879 trace(" LineID=%08x Channels=%d "
880 "Connections=%d Controls=%d\n",
881 mixerlineW.dwLineID,mixerlineW.cChannels,
882 mixerlineW.cConnections,mixerlineW.cControls);
883 trace(" State=0x%08x(%s)\n",
884 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
885 trace(" ComponentType=%s\n",
886 component_type(mixerlineW.dwComponentType));
887 trace(" Type=%s\n",
888 target_type(mixerlineW.Target.dwType));
889 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
890 mixerlineW.Target.dwDeviceID,szPname,
891 mixerlineW.Target.vDriverVersion >> 8,
892 mixerlineW.Target.vDriverVersion & 0xff,
893 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
895 if (mixerlineW.cControls) {
896 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
897 mixerlineW.cControls*sizeof(MIXERCONTROLW));
898 if (array) {
899 rc=mixerGetLineControlsW((HMIXEROBJ)mix,0,
900 MIXER_GETLINECONTROLSF_ALL);
901 ok(rc==MMSYSERR_INVALPARAM,
902 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
903 "MMSYSERR_INVALPARAM expected, got %s\n",
904 mmsys_error(rc));
905 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
906 -1);
907 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
908 "mixerGetLineControlsA(-1): "
909 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
910 mmsys_error(rc));
912 controls.cbStruct = sizeof(MIXERLINECONTROLSW);
913 controls.cControls = mixerlineW.cControls;
914 controls.dwLineID = mixerlineW.dwLineID;
915 controls.pamxctrl = array;
916 controls.cbmxctrl = sizeof(MIXERCONTROLW);
918 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
919 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
921 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
922 MIXER_GETLINECONTROLSF_ALL);
923 ok(rc==MMSYSERR_NOERROR,
924 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
925 "MMSYSERR_NOERROR expected, got %s\n",
926 mmsys_error(rc));
927 if (rc==MMSYSERR_NOERROR) {
928 for(nc=0;nc<mixerlineW.cControls;nc++) {
929 if (winetest_interactive) {
930 WideCharToMultiByte(CP_ACP,0,array[nc].szShortName,
931 MIXER_SHORT_NAME_CHARS,szShortName,
932 MIXER_SHORT_NAME_CHARS,NULL,NULL);
933 WideCharToMultiByte(CP_ACP,0,array[nc].szName,
934 MIXER_LONG_NAME_CHARS,szName,
935 MIXER_LONG_NAME_CHARS,NULL,NULL);
936 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc,
937 szShortName, szName, array[nc].dwControlID);
938 trace(" ControlType=%s\n",
939 control_type(array[nc].dwControlType));
940 trace(" Control=0x%08x(%s)\n",
941 array[nc].fdwControl,
942 control_flags(array[nc].fdwControl));
943 trace(" Items=%d Min=%d Max=%d Step=%d\n",
944 array[nc].cMultipleItems,
945 S1(array[nc].Bounds).dwMinimum,
946 S1(array[nc].Bounds).dwMaximum,
947 array[nc].Metrics.cSteps);
949 mixer_test_controlW(mix, &array[nc]);
953 HeapFree(GetProcessHeap(),0,array);
959 rc=mixerClose(mix);
960 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALHANDLE,
961 "mixerClose: MMSYSERR_NOERROR or MMSYSERR_INVALHANDLE expected, got %s\n",
962 mmsys_error(rc));
966 static void mixer_testsA(void)
968 MIXERCAPSA capsA;
969 HMIXER mix;
970 MMRESULT rc;
971 UINT ndev, d;
973 trace("--- Testing ASCII functions ---\n");
975 ndev=mixerGetNumDevs();
976 trace("found %d Mixer devices\n",ndev);
978 rc=mixerGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
979 ok(rc==MMSYSERR_BADDEVICEID,
980 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
981 mmsys_error(rc));
983 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
984 ok(rc==MMSYSERR_BADDEVICEID,
985 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
986 mmsys_error(rc));
988 for (d=0;d<ndev;d++)
989 mixer_test_deviceA(d);
992 static void mixer_testsW(void)
994 MIXERCAPSW capsW;
995 HMIXER mix;
996 MMRESULT rc;
997 UINT ndev, d;
999 trace("--- Testing WCHAR functions ---\n");
1001 ndev=mixerGetNumDevs();
1002 trace("found %d Mixer devices\n",ndev);
1004 rc=mixerGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
1005 ok(rc==MMSYSERR_BADDEVICEID||rc==MMSYSERR_NOTSUPPORTED,
1006 "mixerGetDevCapsW: MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1007 "expected, got %s\n", mmsys_error(rc));
1008 if (rc==MMSYSERR_NOTSUPPORTED)
1009 return;
1011 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
1012 ok(rc==MMSYSERR_BADDEVICEID,
1013 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1014 mmsys_error(rc));
1016 for (d=0;d<ndev;d++)
1017 mixer_test_deviceW(d);
1020 START_TEST(mixer)
1022 mixer_testsA();
1023 mixer_testsW();