winmm: Avoid testing linecontrols if can't get line info.
[wine/wine64.git] / dlls / winmm / tests / mixer.c
blob2352be31f34ce8aaa161ccf90328cf42ed626f65
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) {
199 MIXERCONTROLDETAILS new_details;
200 MIXERCONTROLDETAILS_UNSIGNED new_value;
202 if (winetest_interactive)
203 trace(" Value=%d\n",value.dwValue);
205 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
206 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
207 else
208 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
210 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
211 new_details.dwControlID = control->dwControlID;
212 new_details.cChannels = 1;
213 U(new_details).cMultipleItems = 0;
214 new_details.paDetails = &new_value;
215 new_details.cbDetails = sizeof(new_value);
217 /* change the control value by one step */
218 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
219 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
220 "MMSYSERR_NOERROR expected, got %s\n",
221 mmsys_error(rc));
222 if (rc==MMSYSERR_NOERROR) {
223 MIXERCONTROLDETAILS ret_details;
224 MIXERCONTROLDETAILS_UNSIGNED ret_value;
226 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
227 ret_details.dwControlID = control->dwControlID;
228 ret_details.cChannels = 1;
229 U(ret_details).cMultipleItems = 0;
230 ret_details.paDetails = &ret_value;
231 ret_details.cbDetails = sizeof(ret_value);
233 /* read back the new control value */
234 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
235 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
236 "MMSYSERR_NOERROR expected, got %s\n",
237 mmsys_error(rc));
238 if (rc==MMSYSERR_NOERROR) {
239 /* result may not match exactly because of rounding */
240 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
241 "Couldn't change value from %d to %d, returned %d\n",
242 value.dwValue,new_value.dwValue,ret_value.dwValue);
244 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
245 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
246 details.dwControlID = control->dwControlID;
247 details.cChannels = 1;
248 U(details).cMultipleItems = 0;
249 details.paDetails = &value;
250 details.cbDetails = sizeof(value);
252 /* restore original value */
253 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
254 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
255 "MMSYSERR_NOERROR expected, got %s\n",
256 mmsys_error(rc));
261 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
262 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
263 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
264 MIXERCONTROLDETAILS details;
265 MIXERCONTROLDETAILS_BOOLEAN value;
267 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
268 details.dwControlID = control->dwControlID;
269 details.cChannels = 1;
270 U(details).cMultipleItems = 0;
271 details.paDetails = &value;
272 details.cbDetails = sizeof(value);
274 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
275 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
276 "MMSYSERR_NOERROR expected, got %s\n",
277 mmsys_error(rc));
278 if (rc==MMSYSERR_NOERROR) {
279 MIXERCONTROLDETAILS new_details;
280 MIXERCONTROLDETAILS_BOOLEAN new_value;
282 if (winetest_interactive)
283 trace(" Value=%d\n",value.fValue);
285 if (value.fValue == FALSE)
286 new_value.fValue = TRUE;
287 else
288 new_value.fValue = FALSE;
290 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
291 new_details.dwControlID = control->dwControlID;
292 new_details.cChannels = 1;
293 U(new_details).cMultipleItems = 0;
294 new_details.paDetails = &new_value;
295 new_details.cbDetails = sizeof(new_value);
297 /* change the control value by one step */
298 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
299 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
300 "MMSYSERR_NOERROR expected, got %s\n",
301 mmsys_error(rc));
302 if (rc==MMSYSERR_NOERROR) {
303 MIXERCONTROLDETAILS ret_details;
304 MIXERCONTROLDETAILS_BOOLEAN ret_value;
306 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
307 ret_details.dwControlID = control->dwControlID;
308 ret_details.cChannels = 1;
309 U(ret_details).cMultipleItems = 0;
310 ret_details.paDetails = &ret_value;
311 ret_details.cbDetails = sizeof(ret_value);
313 /* read back the new control value */
314 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
315 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
316 "MMSYSERR_NOERROR expected, got %s\n",
317 mmsys_error(rc));
318 if (rc==MMSYSERR_NOERROR) {
319 /* result may not match exactly because of rounding */
320 ok(ret_value.fValue==new_value.fValue,
321 "Couldn't change value from %d to %d, returned %d\n",
322 value.fValue,new_value.fValue,ret_value.fValue);
324 if (ret_value.fValue==new_value.fValue) {
325 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
326 details.dwControlID = control->dwControlID;
327 details.cChannels = 1;
328 U(details).cMultipleItems = 0;
329 details.paDetails = &value;
330 details.cbDetails = sizeof(value);
332 /* restore original value */
333 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
334 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
335 "MMSYSERR_NOERROR expected, got %s\n",
336 mmsys_error(rc));
341 } else {
342 /* FIXME */
346 static void mixer_test_deviceA(int device)
348 MIXERCAPSA capsA;
349 HMIXER mix;
350 MMRESULT rc;
351 DWORD d,s,ns,nc;
353 rc=mixerGetDevCapsA(device,0,sizeof(capsA));
354 ok(rc==MMSYSERR_INVALPARAM,
355 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
356 mmsys_error(rc));
358 rc=mixerGetDevCapsA(device,&capsA,4);
359 ok(rc==MMSYSERR_NOERROR,
360 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
361 mmsys_error(rc));
363 rc=mixerGetDevCapsA(device,&capsA,sizeof(capsA));
364 ok(rc==MMSYSERR_NOERROR,
365 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
366 mmsys_error(rc));
368 if (winetest_interactive) {
369 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device,
370 capsA.szPname, capsA.vDriverVersion >> 8,
371 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid,
372 capsA.cDestinations);
373 } else {
374 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
375 capsA.szPname, capsA.vDriverVersion >> 8,
376 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
379 rc=mixerOpen(&mix, device, 0, 0, 0);
380 ok(rc==MMSYSERR_NOERROR,
381 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc));
382 if (rc==MMSYSERR_NOERROR) {
383 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_FUNCTION);
384 ok(rc==MMSYSERR_INVALFLAG,
385 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n", mmsys_error(rc));
387 /* Shouldn't open without a valid HWND */
388 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_WINDOW);
389 ok(rc==MMSYSERR_INVALPARAM,
390 "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n", mmsys_error(rc));
393 for (d=0;d<capsA.cDestinations;d++) {
394 MIXERLINEA mixerlineA;
395 mixerlineA.cbStruct = 0;
396 mixerlineA.dwDestination=d;
397 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
398 MIXER_GETLINEINFOF_DESTINATION);
399 ok(rc==MMSYSERR_INVALPARAM,
400 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
401 "MMSYSERR_INVALPARAM expected, got %s\n",
402 mmsys_error(rc));
404 mixerlineA.cbStruct = sizeof(mixerlineA);
405 mixerlineA.dwDestination=capsA.cDestinations;
406 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
407 MIXER_GETLINEINFOF_DESTINATION);
408 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
409 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
410 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
411 mmsys_error(rc));
413 mixerlineA.cbStruct = sizeof(mixerlineA);
414 mixerlineA.dwDestination=d;
415 rc=mixerGetLineInfoA((HMIXEROBJ)mix,0,
416 MIXER_GETLINEINFOF_DESTINATION);
417 ok(rc==MMSYSERR_INVALPARAM,
418 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
419 "MMSYSERR_INVALPARAM expected, got %s\n",
420 mmsys_error(rc));
422 mixerlineA.cbStruct = sizeof(mixerlineA);
423 mixerlineA.dwDestination=d;
424 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,-1);
425 ok(rc==MMSYSERR_INVALFLAG,
426 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
427 mmsys_error(rc));
429 mixerlineA.cbStruct = sizeof(mixerlineA);
430 mixerlineA.dwDestination=d;
431 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
432 MIXER_GETLINEINFOF_DESTINATION);
433 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
434 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
435 "MMSYSERR_NOERROR expected, got %s\n",
436 mmsys_error(rc));
437 if (rc==MMSYSERR_NODRIVER)
438 trace(" No Driver\n");
439 else if (rc==MMSYSERR_NOERROR) {
440 if (winetest_interactive) {
441 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
442 d,mixerlineA.szShortName, mixerlineA.szName,
443 mixerlineA.dwDestination,mixerlineA.dwSource);
444 trace(" LineID=%08x Channels=%d "
445 "Connections=%d Controls=%d\n",
446 mixerlineA.dwLineID,mixerlineA.cChannels,
447 mixerlineA.cConnections,mixerlineA.cControls);
448 trace(" State=0x%08x(%s)\n",
449 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
450 trace(" ComponentType=%s\n",
451 component_type(mixerlineA.dwComponentType));
452 trace(" Type=%s\n",
453 target_type(mixerlineA.Target.dwType));
454 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
455 mixerlineA.Target.dwDeviceID,
456 mixerlineA.Target.szPname,
457 mixerlineA.Target.vDriverVersion >> 8,
458 mixerlineA.Target.vDriverVersion & 0xff,
459 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
461 ns=mixerlineA.cConnections;
462 for(s=0;s<ns;s++) {
463 mixerlineA.cbStruct = sizeof(mixerlineA);
464 mixerlineA.dwDestination=d;
465 mixerlineA.dwSource=s;
466 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
467 MIXER_GETLINEINFOF_SOURCE);
468 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
469 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
470 "MMSYSERR_NOERROR expected, got %s\n",
471 mmsys_error(rc));
472 if (rc==MMSYSERR_NODRIVER)
473 trace(" No Driver\n");
474 else if (rc==MMSYSERR_NOERROR) {
475 LPMIXERCONTROLA array;
476 MIXERLINECONTROLSA controls;
477 if (winetest_interactive) {
478 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
479 s,mixerlineA.szShortName, mixerlineA.szName,
480 mixerlineA.dwDestination,mixerlineA.dwSource);
481 trace(" LineID=%08x Channels=%d "
482 "Connections=%d Controls=%d\n",
483 mixerlineA.dwLineID,mixerlineA.cChannels,
484 mixerlineA.cConnections,mixerlineA.cControls);
485 trace(" State=0x%08x(%s)\n",
486 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
487 trace(" ComponentType=%s\n",
488 component_type(mixerlineA.dwComponentType));
489 trace(" Type=%s\n",
490 target_type(mixerlineA.Target.dwType));
491 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
492 mixerlineA.Target.dwDeviceID,
493 mixerlineA.Target.szPname,
494 mixerlineA.Target.vDriverVersion >> 8,
495 mixerlineA.Target.vDriverVersion & 0xff,
496 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
498 if (mixerlineA.cControls) {
499 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
500 mixerlineA.cControls*sizeof(MIXERCONTROLA));
501 if (array) {
502 rc=mixerGetLineControlsA((HMIXEROBJ)mix,0,
503 MIXER_GETLINECONTROLSF_ALL);
504 ok(rc==MMSYSERR_INVALPARAM,
505 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
506 "MMSYSERR_INVALPARAM expected, got %s\n",
507 mmsys_error(rc));
509 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,-1);
510 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
511 "mixerGetLineControlsA(-1): "
512 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
513 mmsys_error(rc));
515 controls.cbStruct = sizeof(MIXERLINECONTROLSA);
516 controls.cControls = mixerlineA.cControls;
517 controls.dwLineID = mixerlineA.dwLineID;
518 controls.pamxctrl = array;
519 controls.cbmxctrl = sizeof(MIXERCONTROLA);
521 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
522 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
524 rc=mixerGetLineControlsA((HMIXEROBJ)mix,&controls,
525 MIXER_GETLINECONTROLSF_ALL);
526 ok(rc==MMSYSERR_NOERROR,
527 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
528 "MMSYSERR_NOERROR expected, got %s\n",
529 mmsys_error(rc));
530 if (rc==MMSYSERR_NOERROR) {
531 for(nc=0;nc<mixerlineA.cControls;nc++) {
532 if (winetest_interactive) {
533 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc,
534 array[nc].szShortName,
535 array[nc].szName, array[nc].dwControlID);
536 trace(" ControlType=%s\n",
537 control_type(array[nc].dwControlType));
538 trace(" Control=0x%08x(%s)\n",
539 array[nc].fdwControl,
540 control_flags(array[nc].fdwControl));
541 trace(" Items=%d Min=%d Max=%d Step=%d\n",
542 array[nc].cMultipleItems,
543 S1(array[nc].Bounds).dwMinimum,
544 S1(array[nc].Bounds).dwMaximum,
545 array[nc].Metrics.cSteps);
548 mixer_test_controlA(mix, &array[nc]);
552 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=%d\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 %d to %d, returned %d\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=%d\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 %d to %d, returned %d\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 static 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=%d\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);
774 rc=mixerOpen(&mix, device, 0, 0, 0);
775 ok(rc==MMSYSERR_NOERROR,
776 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",mmsys_error(rc));
777 if (rc==MMSYSERR_NOERROR) {
778 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_FUNCTION);
779 ok(rc==MMSYSERR_INVALFLAG,
780 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n", mmsys_error(rc));
782 /* Shouldn't open without a valid HWND */
783 rc=mixerOpen(&mix, device, 0, 0, CALLBACK_WINDOW);
784 ok(rc==MMSYSERR_INVALPARAM,
785 "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n", mmsys_error(rc));
787 for (d=0;d<capsW.cDestinations;d++) {
788 MIXERLINEW mixerlineW;
789 mixerlineW.cbStruct = 0;
790 mixerlineW.dwDestination=d;
791 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
792 MIXER_GETLINEINFOF_DESTINATION);
793 ok(rc==MMSYSERR_INVALPARAM,
794 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
795 "MMSYSERR_INVALPARAM expected, got %s\n",
796 mmsys_error(rc));
798 mixerlineW.cbStruct = sizeof(mixerlineW);
799 mixerlineW.dwDestination=capsW.cDestinations;
800 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
801 MIXER_GETLINEINFOF_DESTINATION);
802 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
803 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
804 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
805 mmsys_error(rc));
807 mixerlineW.cbStruct = sizeof(mixerlineW);
808 mixerlineW.dwDestination=d;
809 rc=mixerGetLineInfoW((HMIXEROBJ)mix,0,
810 MIXER_GETLINEINFOF_DESTINATION);
811 ok(rc==MMSYSERR_INVALPARAM,
812 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
813 "MMSYSERR_INVALPARAM expected, got %s\n",
814 mmsys_error(rc));
816 mixerlineW.cbStruct = sizeof(mixerlineW);
817 mixerlineW.dwDestination=d;
818 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,-1);
819 ok(rc==MMSYSERR_INVALFLAG,
820 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
821 mmsys_error(rc));
823 mixerlineW.cbStruct = sizeof(mixerlineW);
824 mixerlineW.dwDestination=d;
825 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
826 MIXER_GETLINEINFOF_DESTINATION);
827 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
828 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
829 "MMSYSERR_NOERROR expected, got %s\n",
830 mmsys_error(rc));
831 if (rc==MMSYSERR_NODRIVER)
832 trace(" No Driver\n");
833 else if (rc==MMSYSERR_NOERROR && winetest_interactive) {
834 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
835 MIXER_SHORT_NAME_CHARS,szShortName,
836 MIXER_SHORT_NAME_CHARS,NULL,NULL);
837 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
838 MIXER_LONG_NAME_CHARS,szName,
839 MIXER_LONG_NAME_CHARS,NULL,NULL);
840 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
841 MAXPNAMELEN,szPname,
842 MAXPNAMELEN,NULL, NULL);
843 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
844 d,szShortName,szName,
845 mixerlineW.dwDestination,mixerlineW.dwSource);
846 trace(" LineID=%08x Channels=%d "
847 "Connections=%d Controls=%d\n",
848 mixerlineW.dwLineID,mixerlineW.cChannels,
849 mixerlineW.cConnections,mixerlineW.cControls);
850 trace(" State=0x%08x(%s)\n",
851 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
852 trace(" ComponentType=%s\n",
853 component_type(mixerlineW.dwComponentType));
854 trace(" Type=%s\n",
855 target_type(mixerlineW.Target.dwType));
856 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
857 mixerlineW.Target.dwDeviceID,szPname,
858 mixerlineW.Target.vDriverVersion >> 8,
859 mixerlineW.Target.vDriverVersion & 0xff,
860 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
862 ns=mixerlineW.cConnections;
863 for(s=0;s<ns;s++) {
864 mixerlineW.cbStruct = sizeof(mixerlineW);
865 mixerlineW.dwDestination=d;
866 mixerlineW.dwSource=s;
867 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
868 MIXER_GETLINEINFOF_SOURCE);
869 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
870 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
871 "MMSYSERR_NOERROR expected, got %s\n",
872 mmsys_error(rc));
873 if (rc==MMSYSERR_NODRIVER)
874 trace(" No Driver\n");
875 else if (rc==MMSYSERR_NOERROR) {
876 LPMIXERCONTROLW array;
877 MIXERLINECONTROLSW controls;
878 if (winetest_interactive) {
879 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
880 MIXER_SHORT_NAME_CHARS,szShortName,
881 MIXER_SHORT_NAME_CHARS,NULL,NULL);
882 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
883 MIXER_LONG_NAME_CHARS,szName,
884 MIXER_LONG_NAME_CHARS,NULL,NULL);
885 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
886 MAXPNAMELEN,szPname,
887 MAXPNAMELEN,NULL, NULL);
888 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
889 s,szShortName,szName,
890 mixerlineW.dwDestination,mixerlineW.dwSource);
891 trace(" LineID=%08x Channels=%d "
892 "Connections=%d Controls=%d\n",
893 mixerlineW.dwLineID,mixerlineW.cChannels,
894 mixerlineW.cConnections,mixerlineW.cControls);
895 trace(" State=0x%08x(%s)\n",
896 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
897 trace(" ComponentType=%s\n",
898 component_type(mixerlineW.dwComponentType));
899 trace(" Type=%s\n",
900 target_type(mixerlineW.Target.dwType));
901 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
902 mixerlineW.Target.dwDeviceID,szPname,
903 mixerlineW.Target.vDriverVersion >> 8,
904 mixerlineW.Target.vDriverVersion & 0xff,
905 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
907 if (mixerlineW.cControls) {
908 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
909 mixerlineW.cControls*sizeof(MIXERCONTROLW));
910 if (array) {
911 rc=mixerGetLineControlsW((HMIXEROBJ)mix,0,
912 MIXER_GETLINECONTROLSF_ALL);
913 ok(rc==MMSYSERR_INVALPARAM,
914 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
915 "MMSYSERR_INVALPARAM expected, got %s\n",
916 mmsys_error(rc));
917 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
918 -1);
919 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
920 "mixerGetLineControlsA(-1): "
921 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
922 mmsys_error(rc));
924 controls.cbStruct = sizeof(MIXERLINECONTROLSW);
925 controls.cControls = mixerlineW.cControls;
926 controls.dwLineID = mixerlineW.dwLineID;
927 controls.pamxctrl = array;
928 controls.cbmxctrl = sizeof(MIXERCONTROLW);
930 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
931 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
933 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
934 MIXER_GETLINECONTROLSF_ALL);
935 ok(rc==MMSYSERR_NOERROR,
936 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
937 "MMSYSERR_NOERROR expected, got %s\n",
938 mmsys_error(rc));
939 if (rc==MMSYSERR_NOERROR) {
940 for(nc=0;nc<mixerlineW.cControls;nc++) {
941 if (winetest_interactive) {
942 WideCharToMultiByte(CP_ACP,0,array[nc].szShortName,
943 MIXER_SHORT_NAME_CHARS,szShortName,
944 MIXER_SHORT_NAME_CHARS,NULL,NULL);
945 WideCharToMultiByte(CP_ACP,0,array[nc].szName,
946 MIXER_LONG_NAME_CHARS,szName,
947 MIXER_LONG_NAME_CHARS,NULL,NULL);
948 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc,
949 szShortName, szName, array[nc].dwControlID);
950 trace(" ControlType=%s\n",
951 control_type(array[nc].dwControlType));
952 trace(" Control=0x%08x(%s)\n",
953 array[nc].fdwControl,
954 control_flags(array[nc].fdwControl));
955 trace(" Items=%d Min=%d Max=%d Step=%d\n",
956 array[nc].cMultipleItems,
957 S1(array[nc].Bounds).dwMinimum,
958 S1(array[nc].Bounds).dwMaximum,
959 array[nc].Metrics.cSteps);
961 mixer_test_controlW(mix, &array[nc]);
965 HeapFree(GetProcessHeap(),0,array);
971 rc=mixerClose(mix);
972 ok(rc==MMSYSERR_NOERROR,
973 "mixerClose: MMSYSERR_BADDEVICEID expected, got %s\n",
974 mmsys_error(rc));
978 static void mixer_testsA(void)
980 MIXERCAPSA capsA;
981 HMIXER mix;
982 MMRESULT rc;
983 UINT ndev, d;
985 trace("--- Testing ASCII functions ---\n");
987 ndev=mixerGetNumDevs();
988 trace("found %d Mixer devices\n",ndev);
990 rc=mixerGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
991 ok(rc==MMSYSERR_BADDEVICEID,
992 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
993 mmsys_error(rc));
995 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
996 ok(rc==MMSYSERR_BADDEVICEID,
997 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
998 mmsys_error(rc));
1000 for (d=0;d<ndev;d++)
1001 mixer_test_deviceA(d);
1004 static void mixer_testsW(void)
1006 MIXERCAPSW capsW;
1007 HMIXER mix;
1008 MMRESULT rc;
1009 UINT ndev, d;
1011 trace("--- Testing WCHAR functions ---\n");
1013 ndev=mixerGetNumDevs();
1014 trace("found %d Mixer devices\n",ndev);
1016 rc=mixerGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
1017 ok(rc==MMSYSERR_BADDEVICEID||rc==MMSYSERR_NOTSUPPORTED,
1018 "mixerGetDevCapsW: MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1019 "expected, got %s\n", mmsys_error(rc));
1020 if (rc==MMSYSERR_NOTSUPPORTED)
1021 return;
1023 rc=mixerOpen(&mix, ndev+1, 0, 0, 0);
1024 ok(rc==MMSYSERR_BADDEVICEID,
1025 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1026 mmsys_error(rc));
1028 for (d=0;d<ndev;d++)
1029 mixer_test_deviceW(d);
1032 START_TEST(mixer)
1034 mixer_testsA();
1035 mixer_testsW();