Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / winmm / tests / mixer.c
blobac8656b8533b8569e7796b29bf82a953fbb71411
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #ifdef NONAMELESSSTRUCT
40 # define S1(x) (x).s1
41 #else
42 # define S1(x) (x)
43 #endif
45 #ifdef NONAMELESSUNION
46 # define U(x) (x).u
47 #else
48 # define U(x) (x)
49 #endif
51 static const char * line_flags(DWORD fdwLine)
53 static char flags[100];
54 BOOL first=TRUE;
55 flags[0]=0;
56 if (fdwLine&MIXERLINE_LINEF_ACTIVE) {
57 strcat(flags,"MIXERLINE_LINEF_ACTIVE");
58 first=FALSE;
60 if (fdwLine&MIXERLINE_LINEF_DISCONNECTED) {
61 if (!first)
62 strcat(flags, "|");
64 strcat(flags,"MIXERLINE_LINEF_DISCONNECTED");
65 first=FALSE;
68 if (fdwLine&MIXERLINE_LINEF_SOURCE) {
69 if (!first)
70 strcat(flags, "|");
72 strcat(flags,"MIXERLINE_LINEF_SOURCE");
75 return flags;
78 static const char * component_type(DWORD dwComponentType)
80 #define TYPE_TO_STR(x) case x: return #x
81 switch (dwComponentType) {
82 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_UNDEFINED);
83 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_DIGITAL);
84 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_LINE);
85 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_MONITOR);
86 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
87 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_HEADPHONES);
88 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_TELEPHONE);
89 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
90 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_VOICEIN);
91 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED);
92 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_DIGITAL);
93 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_LINE);
94 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE);
95 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER);
96 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC);
97 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE);
98 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER);
99 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
100 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY);
101 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_ANALOG);
103 #undef TYPE_TO_STR
104 return "UNKNOWN";
107 static const char * target_type(DWORD dwType)
109 #define TYPE_TO_STR(x) case x: return #x
110 switch (dwType) {
111 TYPE_TO_STR(MIXERLINE_TARGETTYPE_UNDEFINED);
112 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEOUT);
113 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEIN);
114 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIOUT);
115 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIIN);
116 TYPE_TO_STR(MIXERLINE_TARGETTYPE_AUX);
118 #undef TYPE_TO_STR
119 return "UNKNOWN";
122 static const char * control_type(DWORD dwControlType)
124 #define TYPE_TO_STR(x) case x: return #x
125 switch (dwControlType) {
126 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_CUSTOM);
127 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER);
128 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER);
129 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PEAKMETER);
130 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER);
131 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEAN);
132 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_ONOFF);
133 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUTE);
134 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MONO);
135 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_LOUDNESS);
136 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_STEREOENH);
137 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS_BOOST);
138 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BUTTON);
139 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_DECIBELS);
140 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNED);
141 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNED);
142 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PERCENT);
143 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SLIDER);
144 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PAN);
145 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN);
146 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_FADER);
147 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_VOLUME);
148 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS);
149 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_TREBLE);
150 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_EQUALIZER);
151 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SINGLESELECT);
152 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUX);
153 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT);
154 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MIXER);
155 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MICROTIME);
156 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MILLITIME);
158 #undef TYPE_TO_STR
159 return "UNKNOWN";
162 static const char * control_flags(DWORD fdwControl)
164 static char flags[100];
165 BOOL first=TRUE;
166 flags[0]=0;
167 if (fdwControl&MIXERCONTROL_CONTROLF_UNIFORM) {
168 strcat(flags,"MIXERCONTROL_CONTROLF_UNIFORM");
169 first=FALSE;
171 if (fdwControl&MIXERCONTROL_CONTROLF_MULTIPLE) {
172 if (!first)
173 strcat(flags, "|");
175 strcat(flags,"MIXERCONTROL_CONTROLF_MULTIPLE");
176 first=FALSE;
179 if (fdwControl&MIXERCONTROL_CONTROLF_DISABLED) {
180 if (!first)
181 strcat(flags, "|");
183 strcat(flags,"MIXERCONTROL_CONTROLF_DISABLED");
186 return flags;
189 static void mixer_test_controlA(HMIXER mix, LPMIXERCONTROLA control)
191 MMRESULT rc;
193 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
194 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
195 MIXERCONTROLDETAILS details;
196 MIXERCONTROLDETAILS_UNSIGNED value;
198 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
199 details.dwControlID = control->dwControlID;
200 details.cChannels = 1;
201 U(details).cMultipleItems = 0;
202 details.paDetails = &value;
203 details.cbDetails = sizeof(value);
205 /* read the current control value */
206 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
207 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
208 "MMSYSERR_NOERROR expected, got %s\n",
209 mmsys_error(rc));
210 if (rc==MMSYSERR_NOERROR) {
211 MIXERCONTROLDETAILS new_details;
212 MIXERCONTROLDETAILS_UNSIGNED new_value;
214 if (winetest_interactive)
215 trace(" Value=%ld\n",value.dwValue);
217 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
218 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
219 else
220 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
222 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
223 new_details.dwControlID = control->dwControlID;
224 new_details.cChannels = 1;
225 U(new_details).cMultipleItems = 0;
226 new_details.paDetails = &new_value;
227 new_details.cbDetails = sizeof(new_value);
229 /* change the control value by one step */
230 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
231 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
232 "MMSYSERR_NOERROR expected, got %s\n",
233 mmsys_error(rc));
234 if (rc==MMSYSERR_NOERROR) {
235 MIXERCONTROLDETAILS ret_details;
236 MIXERCONTROLDETAILS_UNSIGNED ret_value;
238 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
239 ret_details.dwControlID = control->dwControlID;
240 ret_details.cChannels = 1;
241 U(ret_details).cMultipleItems = 0;
242 ret_details.paDetails = &ret_value;
243 ret_details.cbDetails = sizeof(ret_value);
245 /* read back the new control value */
246 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
247 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
248 "MMSYSERR_NOERROR expected, got %s\n",
249 mmsys_error(rc));
250 if (rc==MMSYSERR_NOERROR) {
251 /* result may not match exactly because of rounding */
252 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
253 "Couldn't change value from %ld to %ld, returned %ld\n",
254 value.dwValue,new_value.dwValue,ret_value.dwValue);
256 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
257 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
258 details.dwControlID = control->dwControlID;
259 details.cChannels = 1;
260 U(details).cMultipleItems = 0;
261 details.paDetails = &value;
262 details.cbDetails = sizeof(value);
264 /* restore original value */
265 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
266 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
267 "MMSYSERR_NOERROR expected, got %s\n",
268 mmsys_error(rc));
273 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
274 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
275 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
276 MIXERCONTROLDETAILS details;
277 MIXERCONTROLDETAILS_BOOLEAN value;
279 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
280 details.dwControlID = control->dwControlID;
281 details.cChannels = 1;
282 U(details).cMultipleItems = 0;
283 details.paDetails = &value;
284 details.cbDetails = sizeof(value);
286 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
287 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
288 "MMSYSERR_NOERROR expected, got %s\n",
289 mmsys_error(rc));
290 if (rc==MMSYSERR_NOERROR) {
291 MIXERCONTROLDETAILS new_details;
292 MIXERCONTROLDETAILS_BOOLEAN new_value;
294 if (winetest_interactive)
295 trace(" Value=%ld\n",value.fValue);
297 if (value.fValue == FALSE)
298 new_value.fValue = TRUE;
299 else
300 new_value.fValue = FALSE;
302 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
303 new_details.dwControlID = control->dwControlID;
304 new_details.cChannels = 1;
305 U(new_details).cMultipleItems = 0;
306 new_details.paDetails = &new_value;
307 new_details.cbDetails = sizeof(new_value);
309 /* change the control value by one step */
310 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
311 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
312 "MMSYSERR_NOERROR expected, got %s\n",
313 mmsys_error(rc));
314 if (rc==MMSYSERR_NOERROR) {
315 MIXERCONTROLDETAILS ret_details;
316 MIXERCONTROLDETAILS_BOOLEAN ret_value;
318 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
319 ret_details.dwControlID = control->dwControlID;
320 ret_details.cChannels = 1;
321 U(ret_details).cMultipleItems = 0;
322 ret_details.paDetails = &ret_value;
323 ret_details.cbDetails = sizeof(ret_value);
325 /* read back the new control value */
326 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
327 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
328 "MMSYSERR_NOERROR expected, got %s\n",
329 mmsys_error(rc));
330 if (rc==MMSYSERR_NOERROR) {
331 /* result may not match exactly because of rounding */
332 ok(ret_value.fValue==new_value.fValue,
333 "Couldn't change value from %ld to %ld, returned %ld\n",
334 value.fValue,new_value.fValue,ret_value.fValue);
336 if (ret_value.fValue==new_value.fValue) {
337 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
338 details.dwControlID = control->dwControlID;
339 details.cChannels = 1;
340 U(details).cMultipleItems = 0;
341 details.paDetails = &value;
342 details.cbDetails = sizeof(value);
344 /* restore original value */
345 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
346 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
347 "MMSYSERR_NOERROR expected, got %s\n",
348 mmsys_error(rc));
353 } else {
354 /* FIXME */
358 void mixer_test_deviceA(int device)
360 MIXERCAPSA capsA;
361 HMIXER mix;
362 MMRESULT rc;
363 DWORD d,s,ns,nc;
365 rc=mixerGetDevCapsA(device,0,sizeof(capsA));
366 ok(rc==MMSYSERR_INVALPARAM,
367 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
368 mmsys_error(rc));
370 rc=mixerGetDevCapsA(device,&capsA,4);
371 ok(rc==MMSYSERR_NOERROR,
372 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
373 mmsys_error(rc));
375 rc=mixerGetDevCapsA(device,&capsA,sizeof(capsA));
376 ok(rc==MMSYSERR_NOERROR,
377 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
378 mmsys_error(rc));
380 if (winetest_interactive) {
381 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%ld\n", device,
382 capsA.szPname, capsA.vDriverVersion >> 8,
383 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid,
384 capsA.cDestinations);
385 } else {
386 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
387 capsA.szPname, capsA.vDriverVersion >> 8,
388 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
391 rc=mixerOpen(&mix, device, 0, 0, 0);
392 ok(rc==MMSYSERR_NOERROR,
393 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",mmsys_error(rc));
394 if (rc==MMSYSERR_NOERROR) {
395 for (d=0;d<capsA.cDestinations;d++) {
396 MIXERLINEA mixerlineA;
397 mixerlineA.cbStruct = 0;
398 mixerlineA.dwDestination=d;
399 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
400 MIXER_GETLINEINFOF_DESTINATION);
401 ok(rc==MMSYSERR_INVALPARAM,
402 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
403 "MMSYSERR_INVALPARAM expected, got %s\n",
404 mmsys_error(rc));
406 mixerlineA.cbStruct = sizeof(mixerlineA);
407 mixerlineA.dwDestination=capsA.cDestinations;
408 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
409 MIXER_GETLINEINFOF_DESTINATION);
410 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
411 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
412 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
413 mmsys_error(rc));
415 mixerlineA.cbStruct = sizeof(mixerlineA);
416 mixerlineA.dwDestination=d;
417 rc=mixerGetLineInfoA((HMIXEROBJ)mix,0,
418 MIXER_GETLINEINFOF_DESTINATION);
419 ok(rc==MMSYSERR_INVALPARAM,
420 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
421 "MMSYSERR_INVALPARAM expected, got %s\n",
422 mmsys_error(rc));
424 mixerlineA.cbStruct = sizeof(mixerlineA);
425 mixerlineA.dwDestination=d;
426 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,-1);
427 ok(rc==MMSYSERR_INVALFLAG,
428 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
429 mmsys_error(rc));
431 mixerlineA.cbStruct = sizeof(mixerlineA);
432 mixerlineA.dwDestination=d;
433 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
434 MIXER_GETLINEINFOF_DESTINATION);
435 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
436 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
437 "MMSYSERR_NOERROR expected, got %s\n",
438 mmsys_error(rc));
439 if (rc==MMSYSERR_NODRIVER)
440 trace(" No Driver\n");
441 else if (rc==MMSYSERR_NOERROR && winetest_interactive) {
442 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
443 d,mixerlineA.szShortName, mixerlineA.szName,
444 mixerlineA.dwDestination,mixerlineA.dwSource);
445 trace(" LineID=%08lx Channels=%ld "
446 "Connections=%ld Controls=%ld \n",
447 mixerlineA.dwLineID,mixerlineA.cChannels,
448 mixerlineA.cConnections,mixerlineA.cControls);
449 trace(" State=0x%08lx(%s)\n",
450 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
451 trace(" ComponentType=%s\n",
452 component_type(mixerlineA.dwComponentType));
453 trace(" Type=%s\n",
454 target_type(mixerlineA.Target.dwType));
455 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
456 mixerlineA.Target.dwDeviceID,
457 mixerlineA.Target.szPname,
458 mixerlineA.Target.vDriverVersion >> 8,
459 mixerlineA.Target.vDriverVersion & 0xff,
460 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
462 ns=mixerlineA.cConnections;
463 for(s=0;s<ns;s++) {
464 mixerlineA.cbStruct = sizeof(mixerlineA);
465 mixerlineA.dwDestination=d;
466 mixerlineA.dwSource=s;
467 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
468 MIXER_GETLINEINFOF_SOURCE);
469 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
470 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
471 "MMSYSERR_NOERROR expected, got %s\n",
472 mmsys_error(rc));
473 if (rc==MMSYSERR_NODRIVER)
474 trace(" No Driver\n");
475 else if (rc==MMSYSERR_NOERROR) {
476 LPMIXERCONTROLA array;
477 MIXERLINECONTROLSA controls;
478 if (winetest_interactive) {
479 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
480 s,mixerlineA.szShortName, mixerlineA.szName,
481 mixerlineA.dwDestination,mixerlineA.dwSource);
482 trace(" LineID=%08lx Channels=%ld "
483 "Connections=%ld Controls=%ld \n",
484 mixerlineA.dwLineID,mixerlineA.cChannels,
485 mixerlineA.cConnections,mixerlineA.cControls);
486 trace(" State=0x%08lx(%s)\n",
487 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
488 trace(" ComponentType=%s\n",
489 component_type(mixerlineA.dwComponentType));
490 trace(" Type=%s\n",
491 target_type(mixerlineA.Target.dwType));
492 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
493 mixerlineA.Target.dwDeviceID,
494 mixerlineA.Target.szPname,
495 mixerlineA.Target.vDriverVersion >> 8,
496 mixerlineA.Target.vDriverVersion & 0xff,
497 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
499 if (mixerlineA.cControls) {
500 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
501 mixerlineA.cControls*sizeof(MIXERCONTROLA));
502 if (array) {
503 rc=mixerGetLineControlsA((HMIXEROBJ)mix,0,
504 MIXER_GETLINECONTROLSF_ALL);
505 ok(rc==MMSYSERR_INVALPARAM,
506 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
507 "MMSYSERR_INVALPARAM expected, got %s\n",
508 mmsys_error(rc));
510 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,-1);
511 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
512 "mixerGetLineControlsA(-1): "
513 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
514 mmsys_error(rc));
516 controls.cbStruct = sizeof(MIXERLINECONTROLSA);
517 controls.cControls = mixerlineA.cControls;
518 controls.dwLineID = mixerlineA.dwLineID;
519 controls.pamxctrl = array;
520 controls.cbmxctrl = sizeof(MIXERCONTROLA);
522 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
523 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
525 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,
526 MIXER_GETLINECONTROLSF_ALL);
527 ok(rc==MMSYSERR_NOERROR,
528 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
529 "MMSYSERR_NOERROR expected, got %s\n",
530 mmsys_error(rc));
531 if (rc==MMSYSERR_NOERROR) {
532 for(nc=0;nc<mixerlineA.cControls;nc++) {
533 if (winetest_interactive) {
534 trace(" %ld: \"%s\" (%s) ControlID=%ld\n", nc,
535 array[nc].szShortName,
536 array[nc].szName, array[nc].dwControlID);
537 trace(" ControlType=%s\n",
538 control_type(array[nc].dwControlType));
539 trace(" Control=0x%08lx(%s)\n",
540 array[nc].fdwControl,
541 control_flags(array[nc].fdwControl));
542 trace(" Items=%ld Min=%ld Max=%ld Step=%ld\n",
543 array[nc].cMultipleItems,
544 S1(array[nc].Bounds).dwMinimum,
545 S1(array[nc].Bounds).dwMaximum,
546 array[nc].Metrics.cSteps);
549 mixer_test_controlA(mix, &array[nc]);
553 HeapFree(GetProcessHeap(),0,array);
559 rc=mixerClose(mix);
560 ok(rc==MMSYSERR_NOERROR,
561 "mixerClose: MMSYSERR_BADDEVICEID expected, got %s\n",
562 mmsys_error(rc));
566 static void mixer_test_controlW(HMIXER mix, LPMIXERCONTROLW control)
568 MMRESULT rc;
570 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
571 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
572 MIXERCONTROLDETAILS details;
573 MIXERCONTROLDETAILS_UNSIGNED value;
575 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
576 details.dwControlID = control->dwControlID;
577 details.cChannels = 1;
578 U(details).cMultipleItems = 0;
579 details.paDetails = &value;
580 details.cbDetails = sizeof(value);
582 /* read the current control value */
583 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
584 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
585 "MMSYSERR_NOERROR expected, got %s\n",
586 mmsys_error(rc));
587 if (rc==MMSYSERR_NOERROR) {
588 MIXERCONTROLDETAILS new_details;
589 MIXERCONTROLDETAILS_UNSIGNED new_value;
591 if (winetest_interactive)
592 trace(" Value=%ld\n",value.dwValue);
594 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
595 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
596 else
597 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
599 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
600 new_details.dwControlID = control->dwControlID;
601 new_details.cChannels = 1;
602 U(new_details).cMultipleItems = 0;
603 new_details.paDetails = &new_value;
604 new_details.cbDetails = sizeof(new_value);
606 /* change the control value by one step */
607 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
608 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
609 "MMSYSERR_NOERROR expected, got %s\n",
610 mmsys_error(rc));
611 if (rc==MMSYSERR_NOERROR) {
612 MIXERCONTROLDETAILS ret_details;
613 MIXERCONTROLDETAILS_UNSIGNED ret_value;
615 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
616 ret_details.dwControlID = control->dwControlID;
617 ret_details.cChannels = 1;
618 U(ret_details).cMultipleItems = 0;
619 ret_details.paDetails = &ret_value;
620 ret_details.cbDetails = sizeof(ret_value);
622 /* read back the new control value */
623 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
624 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
625 "MMSYSERR_NOERROR expected, got %s\n",
626 mmsys_error(rc));
627 if (rc==MMSYSERR_NOERROR) {
628 /* result may not match exactly because of rounding */
629 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
630 "Couldn't change value from %ld to %ld, returned %ld\n",
631 value.dwValue,new_value.dwValue,ret_value.dwValue);
633 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
634 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
635 details.dwControlID = control->dwControlID;
636 details.cChannels = 1;
637 U(details).cMultipleItems = 0;
638 details.paDetails = &value;
639 details.cbDetails = sizeof(value);
641 /* restore original value */
642 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
643 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
644 "MMSYSERR_NOERROR expected, got %s\n",
645 mmsys_error(rc));
650 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
651 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
652 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
653 MIXERCONTROLDETAILS details;
654 MIXERCONTROLDETAILS_BOOLEAN value;
656 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
657 details.dwControlID = control->dwControlID;
658 details.cChannels = 1;
659 U(details).cMultipleItems = 0;
660 details.paDetails = &value;
661 details.cbDetails = sizeof(value);
663 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
664 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
665 "MMSYSERR_NOERROR expected, got %s\n",
666 mmsys_error(rc));
667 if (rc==MMSYSERR_NOERROR) {
668 MIXERCONTROLDETAILS new_details;
669 MIXERCONTROLDETAILS_BOOLEAN new_value;
671 if (winetest_interactive)
672 trace(" Value=%ld\n",value.fValue);
674 if (value.fValue == FALSE)
675 new_value.fValue = TRUE;
676 else
677 new_value.fValue = FALSE;
679 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
680 new_details.dwControlID = control->dwControlID;
681 new_details.cChannels = 1;
682 U(new_details).cMultipleItems = 0;
683 new_details.paDetails = &new_value;
684 new_details.cbDetails = sizeof(new_value);
686 /* change the control value by one step */
687 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
688 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
689 "MMSYSERR_NOERROR expected, got %s\n",
690 mmsys_error(rc));
691 if (rc==MMSYSERR_NOERROR) {
692 MIXERCONTROLDETAILS ret_details;
693 MIXERCONTROLDETAILS_BOOLEAN ret_value;
695 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
696 ret_details.dwControlID = control->dwControlID;
697 ret_details.cChannels = 1;
698 U(ret_details).cMultipleItems = 0;
699 ret_details.paDetails = &ret_value;
700 ret_details.cbDetails = sizeof(ret_value);
702 /* read back the new control value */
703 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
704 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
705 "MMSYSERR_NOERROR expected, got %s\n",
706 mmsys_error(rc));
707 if (rc==MMSYSERR_NOERROR) {
708 /* result may not match exactly because of rounding */
709 ok(ret_value.fValue==new_value.fValue,
710 "Couldn't change value from %ld to %ld, returned %ld\n",
711 value.fValue,new_value.fValue,ret_value.fValue);
713 if (ret_value.fValue==new_value.fValue) {
714 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
715 details.dwControlID = control->dwControlID;
716 details.cChannels = 1;
717 U(details).cMultipleItems = 0;
718 details.paDetails = &value;
719 details.cbDetails = sizeof(value);
721 /* restore original value */
722 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
723 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
724 "MMSYSERR_NOERROR expected, got %s\n",
725 mmsys_error(rc));
730 } else {
731 /* FIXME */
735 void mixer_test_deviceW(int device)
737 MIXERCAPSW capsW;
738 HMIXER mix;
739 MMRESULT rc;
740 DWORD d,s,ns,nc;
741 char szShortName[MIXER_SHORT_NAME_CHARS];
742 char szName[MIXER_LONG_NAME_CHARS];
743 char szPname[MAXPNAMELEN];
745 rc=mixerGetDevCapsW(device,0,sizeof(capsW));
746 ok(rc==MMSYSERR_INVALPARAM,
747 "mixerGetDevCapsW: MMSYSERR_INVALPARAM expected, got %s\n",
748 mmsys_error(rc));
750 rc=mixerGetDevCapsW(device,&capsW,4);
751 ok(rc==MMSYSERR_NOERROR,
752 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
753 mmsys_error(rc));
755 rc=mixerGetDevCapsW(device,&capsW,sizeof(capsW));
756 ok(rc==MMSYSERR_NOERROR,
757 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
758 mmsys_error(rc));
760 WideCharToMultiByte(CP_ACP,0,capsW.szPname, MAXPNAMELEN,szPname,
761 MAXPNAMELEN,NULL,NULL);
762 if (winetest_interactive) {
763 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%ld\n", device,
764 szPname, capsW.vDriverVersion >> 8,
765 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid,
766 capsW.cDestinations);
767 } else {
768 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
769 szPname, capsW.vDriverVersion >> 8,
770 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid);
772 rc=mixerOpen(&mix, device, 0, 0, 0);
773 ok(rc==MMSYSERR_NOERROR,
774 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",mmsys_error(rc));
775 if (rc==MMSYSERR_NOERROR) {
776 for (d=0;d<capsW.cDestinations;d++) {
777 MIXERLINEW mixerlineW;
778 mixerlineW.cbStruct = 0;
779 mixerlineW.dwDestination=d;
780 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
781 MIXER_GETLINEINFOF_DESTINATION);
782 ok(rc==MMSYSERR_INVALPARAM,
783 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
784 "MMSYSERR_INVALPARAM expected, got %s\n",
785 mmsys_error(rc));
787 mixerlineW.cbStruct = sizeof(mixerlineW);
788 mixerlineW.dwDestination=capsW.cDestinations;
789 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
790 MIXER_GETLINEINFOF_DESTINATION);
791 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
792 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
793 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
794 mmsys_error(rc));
796 mixerlineW.cbStruct = sizeof(mixerlineW);
797 mixerlineW.dwDestination=d;
798 rc=mixerGetLineInfoW((HMIXEROBJ)mix,0,
799 MIXER_GETLINEINFOF_DESTINATION);
800 ok(rc==MMSYSERR_INVALPARAM,
801 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
802 "MMSYSERR_INVALPARAM expected, got %s\n",
803 mmsys_error(rc));
805 mixerlineW.cbStruct = sizeof(mixerlineW);
806 mixerlineW.dwDestination=d;
807 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,-1);
808 ok(rc==MMSYSERR_INVALFLAG,
809 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
810 mmsys_error(rc));
812 mixerlineW.cbStruct = sizeof(mixerlineW);
813 mixerlineW.dwDestination=d;
814 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
815 MIXER_GETLINEINFOF_DESTINATION);
816 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
817 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
818 "MMSYSERR_NOERROR expected, got %s\n",
819 mmsys_error(rc));
820 if (rc==MMSYSERR_NODRIVER)
821 trace(" No Driver\n");
822 else if (rc==MMSYSERR_NOERROR && winetest_interactive) {
823 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
824 MIXER_SHORT_NAME_CHARS,szShortName,
825 MIXER_SHORT_NAME_CHARS,NULL,NULL);
826 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
827 MIXER_LONG_NAME_CHARS,szName,
828 MIXER_LONG_NAME_CHARS,NULL,NULL);
829 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
830 MAXPNAMELEN,szPname,
831 MAXPNAMELEN,NULL, NULL);
832 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
833 d,szShortName,szName,
834 mixerlineW.dwDestination,mixerlineW.dwSource);
835 trace(" LineID=%08lx Channels=%ld "
836 "Connections=%ld Controls=%ld \n",
837 mixerlineW.dwLineID,mixerlineW.cChannels,
838 mixerlineW.cConnections,mixerlineW.cControls);
839 trace(" State=0x%08lx(%s)\n",
840 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
841 trace(" ComponentType=%s\n",
842 component_type(mixerlineW.dwComponentType));
843 trace(" Type=%s\n",
844 target_type(mixerlineW.Target.dwType));
845 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
846 mixerlineW.Target.dwDeviceID,szPname,
847 mixerlineW.Target.vDriverVersion >> 8,
848 mixerlineW.Target.vDriverVersion & 0xff,
849 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
851 ns=mixerlineW.cConnections;
852 for(s=0;s<ns;s++) {
853 mixerlineW.cbStruct = sizeof(mixerlineW);
854 mixerlineW.dwDestination=d;
855 mixerlineW.dwSource=s;
856 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
857 MIXER_GETLINEINFOF_SOURCE);
858 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
859 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
860 "MMSYSERR_NOERROR expected, got %s\n",
861 mmsys_error(rc));
862 if (rc==MMSYSERR_NODRIVER)
863 trace(" No Driver\n");
864 else if (rc==MMSYSERR_NOERROR) {
865 LPMIXERCONTROLW array;
866 MIXERLINECONTROLSW controls;
867 if (winetest_interactive) {
868 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
869 MIXER_SHORT_NAME_CHARS,szShortName,
870 MIXER_SHORT_NAME_CHARS,NULL,NULL);
871 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
872 MIXER_LONG_NAME_CHARS,szName,
873 MIXER_LONG_NAME_CHARS,NULL,NULL);
874 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
875 MAXPNAMELEN,szPname,
876 MAXPNAMELEN,NULL, NULL);
877 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
878 s,szShortName,szName,
879 mixerlineW.dwDestination,mixerlineW.dwSource);
880 trace(" LineID=%08lx Channels=%ld "
881 "Connections=%ld Controls=%ld \n",
882 mixerlineW.dwLineID,mixerlineW.cChannels,
883 mixerlineW.cConnections,mixerlineW.cControls);
884 trace(" State=0x%08lx(%s)\n",
885 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
886 trace(" ComponentType=%s\n",
887 component_type(mixerlineW.dwComponentType));
888 trace(" Type=%s\n",
889 target_type(mixerlineW.Target.dwType));
890 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
891 mixerlineW.Target.dwDeviceID,szPname,
892 mixerlineW.Target.vDriverVersion >> 8,
893 mixerlineW.Target.vDriverVersion & 0xff,
894 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
896 if (mixerlineW.cControls) {
897 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
898 mixerlineW.cControls*sizeof(MIXERCONTROLW));
899 if (array) {
900 rc=mixerGetLineControlsW((HMIXEROBJ)mix,0,
901 MIXER_GETLINECONTROLSF_ALL);
902 ok(rc==MMSYSERR_INVALPARAM,
903 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
904 "MMSYSERR_INVALPARAM expected, got %s\n",
905 mmsys_error(rc));
906 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
907 -1);
908 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
909 "mixerGetLineControlsA(-1): "
910 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
911 mmsys_error(rc));
913 controls.cbStruct = sizeof(MIXERLINECONTROLSW);
914 controls.cControls = mixerlineW.cControls;
915 controls.dwLineID = mixerlineW.dwLineID;
916 controls.pamxctrl = array;
917 controls.cbmxctrl = sizeof(MIXERCONTROLW);
919 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
920 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
922 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
923 MIXER_GETLINECONTROLSF_ALL);
924 ok(rc==MMSYSERR_NOERROR,
925 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
926 "MMSYSERR_NOERROR expected, got %s\n",
927 mmsys_error(rc));
928 if (rc==MMSYSERR_NOERROR) {
929 for(nc=0;nc<mixerlineW.cControls;nc++) {
930 if (winetest_interactive) {
931 WideCharToMultiByte(CP_ACP,0,array[nc].szShortName,
932 MIXER_SHORT_NAME_CHARS,szShortName,
933 MIXER_SHORT_NAME_CHARS,NULL,NULL);
934 WideCharToMultiByte(CP_ACP,0,array[nc].szName,
935 MIXER_LONG_NAME_CHARS,szName,
936 MIXER_LONG_NAME_CHARS,NULL,NULL);
937 trace(" %ld: \"%s\" (%s) ControlID=%ld\n", nc,
938 szShortName, szName, array[nc].dwControlID);
939 trace(" ControlType=%s\n",
940 control_type(array[nc].dwControlType));
941 trace(" Control=0x%08lx(%s)\n",
942 array[nc].fdwControl,
943 control_flags(array[nc].fdwControl));
944 trace(" Items=%ld Min=%ld Max=%ld Step=%ld\n",
945 array[nc].cMultipleItems,
946 S1(array[nc].Bounds).dwMinimum,
947 S1(array[nc].Bounds).dwMaximum,
948 array[nc].Metrics.cSteps);
950 mixer_test_controlW(mix, &array[nc]);
954 HeapFree(GetProcessHeap(),0,array);
960 rc=mixerClose(mix);
961 ok(rc==MMSYSERR_NOERROR,
962 "mixerClose: MMSYSERR_BADDEVICEID expected, got %s\n",
963 mmsys_error(rc));
967 void mixer_testsA()
969 MIXERCAPSA capsA;
970 HMIXER mix;
971 MMRESULT rc;
972 UINT ndev, d;
974 trace("--- Testing ASCII functions ---\n");
976 ndev=mixerGetNumDevs();
977 trace("found %d Mixer devices\n",ndev);
979 rc=mixerGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
980 ok(rc==MMSYSERR_BADDEVICEID,
981 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
982 mmsys_error(rc));
984 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
985 ok(rc==MMSYSERR_BADDEVICEID,
986 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
987 mmsys_error(rc));
989 for (d=0;d<ndev;d++)
990 mixer_test_deviceA(d);
993 void mixer_testsW()
995 MIXERCAPSW capsW;
996 HMIXER mix;
997 MMRESULT rc;
998 UINT ndev, d;
1000 trace("--- Testing WCHAR functions ---\n");
1002 ndev=mixerGetNumDevs();
1003 trace("found %d Mixer devices\n",ndev);
1005 rc=mixerGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
1006 ok(rc==MMSYSERR_BADDEVICEID||rc==MMSYSERR_NOTSUPPORTED,
1007 "mixerGetDevCapsW: MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1008 "expected, got %s\n", mmsys_error(rc));
1009 if (rc==MMSYSERR_NOTSUPPORTED)
1010 return;
1012 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
1013 ok(rc==MMSYSERR_BADDEVICEID,
1014 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1015 mmsys_error(rc));
1017 for (d=0;d<ndev;d++)
1018 mixer_test_deviceW(d);
1021 START_TEST(mixer)
1023 mixer_testsA();
1024 mixer_testsW();