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
23 * add interactive tests
31 #include "wine/test.h"
37 #include "winmm_test.h"
39 static const char * line_flags(DWORD fdwLine)
41 static char flags[100];
44 if (fdwLine&MIXERLINE_LINEF_ACTIVE) {
45 strcat(flags,"MIXERLINE_LINEF_ACTIVE");
48 if (fdwLine&MIXERLINE_LINEF_DISCONNECTED) {
52 strcat(flags,"MIXERLINE_LINEF_DISCONNECTED");
56 if (fdwLine&MIXERLINE_LINEF_SOURCE) {
60 strcat(flags,"MIXERLINE_LINEF_SOURCE");
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);
95 static const char * target_type(DWORD dwType)
97 #define TYPE_TO_STR(x) case x: return #x
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);
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);
150 static const char * control_flags(DWORD fdwControl)
152 static char flags[100];
155 if (fdwControl&MIXERCONTROL_CONTROLF_UNIFORM) {
156 strcat(flags,"MIXERCONTROL_CONTROLF_UNIFORM");
159 if (fdwControl&MIXERCONTROL_CONTROLF_MULTIPLE) {
163 strcat(flags,"MIXERCONTROL_CONTROLF_MULTIPLE");
167 if (fdwControl&MIXERCONTROL_CONTROLF_DISABLED) {
171 strcat(flags,"MIXERCONTROL_CONTROLF_DISABLED");
177 static void test_mixerClose(HMIXER mix)
181 rc = mixerClose(mix);
182 ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_INVALHANDLE,
183 "mixerClose: MMSYSERR_NOERROR or MMSYSERR_INVALHANDLE expected, got %s\n",
187 static void mixer_test_controlA(HMIXER mix, LPMIXERCONTROLA control)
191 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
192 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
193 MIXERCONTROLDETAILS details;
194 MIXERCONTROLDETAILS_UNSIGNED value;
196 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
197 details.dwControlID = control->dwControlID;
198 details.cChannels = 1;
199 U(details).cMultipleItems = 0;
200 details.paDetails = &value;
201 details.cbDetails = sizeof(value);
203 /* read the current control value */
204 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
205 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
206 "MMSYSERR_NOERROR expected, got %s\n",
208 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
209 MIXERCONTROLDETAILS new_details;
210 MIXERCONTROLDETAILS_UNSIGNED new_value;
212 trace(" Value=%d\n",value.dwValue);
214 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
215 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
217 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
219 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
220 new_details.dwControlID = control->dwControlID;
221 new_details.cChannels = 1;
222 U(new_details).cMultipleItems = 0;
223 new_details.paDetails = &new_value;
224 new_details.cbDetails = sizeof(new_value);
226 /* change the control value by one step */
227 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
228 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
229 "MMSYSERR_NOERROR expected, got %s\n",
231 if (rc==MMSYSERR_NOERROR) {
232 MIXERCONTROLDETAILS ret_details;
233 MIXERCONTROLDETAILS_UNSIGNED ret_value;
235 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
236 ret_details.dwControlID = control->dwControlID;
237 ret_details.cChannels = 1;
238 U(ret_details).cMultipleItems = 0;
239 ret_details.paDetails = &ret_value;
240 ret_details.cbDetails = sizeof(ret_value);
242 /* read back the new control value */
243 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
244 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
245 "MMSYSERR_NOERROR expected, got %s\n",
247 if (rc==MMSYSERR_NOERROR) {
248 /* result may not match exactly because of rounding */
249 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
250 "Couldn't change value from %d to %d, returned %d\n",
251 value.dwValue,new_value.dwValue,ret_value.dwValue);
253 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
254 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
255 details.dwControlID = control->dwControlID;
256 details.cChannels = 1;
257 U(details).cMultipleItems = 0;
258 details.paDetails = &value;
259 details.cbDetails = sizeof(value);
261 /* restore original value */
262 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
263 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
264 "MMSYSERR_NOERROR expected, got %s\n",
270 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
271 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
272 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
273 MIXERCONTROLDETAILS details;
274 MIXERCONTROLDETAILS_BOOLEAN value;
276 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
277 details.dwControlID = control->dwControlID;
278 details.cChannels = 1;
279 U(details).cMultipleItems = 0;
280 details.paDetails = &value;
281 details.cbDetails = sizeof(value);
283 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
284 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
285 "MMSYSERR_NOERROR expected, got %s\n",
287 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
288 MIXERCONTROLDETAILS new_details;
289 MIXERCONTROLDETAILS_BOOLEAN new_value;
291 trace(" Value=%d\n",value.fValue);
293 if (value.fValue == FALSE)
294 new_value.fValue = TRUE;
296 new_value.fValue = FALSE;
298 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
299 new_details.dwControlID = control->dwControlID;
300 new_details.cChannels = 1;
301 U(new_details).cMultipleItems = 0;
302 new_details.paDetails = &new_value;
303 new_details.cbDetails = sizeof(new_value);
305 /* change the control value by one step */
306 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
307 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
308 "MMSYSERR_NOERROR expected, got %s\n",
310 if (rc==MMSYSERR_NOERROR) {
311 MIXERCONTROLDETAILS ret_details;
312 MIXERCONTROLDETAILS_BOOLEAN ret_value;
314 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
315 ret_details.dwControlID = control->dwControlID;
316 ret_details.cChannels = 1;
317 U(ret_details).cMultipleItems = 0;
318 ret_details.paDetails = &ret_value;
319 ret_details.cbDetails = sizeof(ret_value);
321 /* read back the new control value */
322 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
323 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
324 "MMSYSERR_NOERROR expected, got %s\n",
326 if (rc==MMSYSERR_NOERROR) {
327 /* result may not match exactly because of rounding */
328 ok(ret_value.fValue==new_value.fValue,
329 "Couldn't change value from %d to %d, returned %d\n",
330 value.fValue,new_value.fValue,ret_value.fValue);
332 if (ret_value.fValue==new_value.fValue) {
333 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
334 details.dwControlID = control->dwControlID;
335 details.cChannels = 1;
336 U(details).cMultipleItems = 0;
337 details.paDetails = &value;
338 details.cbDetails = sizeof(value);
340 /* restore original value */
341 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
342 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
343 "MMSYSERR_NOERROR expected, got %s\n",
354 static void mixer_test_deviceA(int device)
361 rc=mixerGetDevCapsA(device,0,sizeof(capsA));
362 ok(rc==MMSYSERR_INVALPARAM,
363 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
366 rc=mixerGetDevCapsA(device,&capsA,4);
367 ok(rc==MMSYSERR_NOERROR,
368 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
371 rc=mixerGetDevCapsA(device,&capsA,sizeof(capsA));
372 ok(rc==MMSYSERR_NOERROR,
373 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
376 if (winetest_interactive) {
377 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device,
378 capsA.szPname, capsA.vDriverVersion >> 8,
379 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid,
380 capsA.cDestinations);
382 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
383 capsA.szPname, capsA.vDriverVersion >> 8,
384 capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
387 rc=mixerOpen(&mix, device, 0, 0, 0);
388 ok(rc==MMSYSERR_NOERROR,
389 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc));
390 if (rc==MMSYSERR_NOERROR) {
391 for (d=0;d<capsA.cDestinations;d++) {
392 MIXERLINEA mixerlineA;
393 mixerlineA.cbStruct = 0;
394 mixerlineA.dwDestination=d;
395 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
396 MIXER_GETLINEINFOF_DESTINATION);
397 ok(rc==MMSYSERR_INVALPARAM,
398 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
399 "MMSYSERR_INVALPARAM expected, got %s\n",
402 mixerlineA.cbStruct = sizeof(mixerlineA);
403 mixerlineA.dwDestination=capsA.cDestinations;
404 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
405 MIXER_GETLINEINFOF_DESTINATION);
406 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
407 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
408 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
411 mixerlineA.cbStruct = sizeof(mixerlineA);
412 mixerlineA.dwDestination=d;
413 rc=mixerGetLineInfoA((HMIXEROBJ)mix,0,
414 MIXER_GETLINEINFOF_DESTINATION);
415 ok(rc==MMSYSERR_INVALPARAM,
416 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
417 "MMSYSERR_INVALPARAM expected, got %s\n",
420 mixerlineA.cbStruct = sizeof(mixerlineA);
421 mixerlineA.dwDestination=d;
422 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,-1);
423 ok(rc==MMSYSERR_INVALFLAG,
424 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
427 mixerlineA.cbStruct = sizeof(mixerlineA);
428 mixerlineA.dwDestination=d;
429 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
430 MIXER_GETLINEINFOF_DESTINATION);
431 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
432 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
433 "MMSYSERR_NOERROR expected, got %s\n",
435 if (rc==MMSYSERR_NODRIVER)
436 trace(" No Driver\n");
437 else if (rc==MMSYSERR_NOERROR) {
438 if (winetest_interactive) {
439 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
440 d,mixerlineA.szShortName, mixerlineA.szName,
441 mixerlineA.dwDestination,mixerlineA.dwSource);
442 trace(" LineID=%08x Channels=%d "
443 "Connections=%d Controls=%d\n",
444 mixerlineA.dwLineID,mixerlineA.cChannels,
445 mixerlineA.cConnections,mixerlineA.cControls);
446 trace(" State=0x%08x(%s)\n",
447 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
448 trace(" ComponentType=%s\n",
449 component_type(mixerlineA.dwComponentType));
451 target_type(mixerlineA.Target.dwType));
452 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
453 mixerlineA.Target.dwDeviceID,
454 mixerlineA.Target.szPname,
455 mixerlineA.Target.vDriverVersion >> 8,
456 mixerlineA.Target.vDriverVersion & 0xff,
457 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
459 ns=mixerlineA.cConnections;
461 mixerlineA.cbStruct = sizeof(mixerlineA);
462 mixerlineA.dwDestination=d;
463 mixerlineA.dwSource=s;
464 rc=mixerGetLineInfoA((HMIXEROBJ)mix,&mixerlineA,
465 MIXER_GETLINEINFOF_SOURCE);
466 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
467 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
468 "MMSYSERR_NOERROR expected, got %s\n",
470 if (rc==MMSYSERR_NODRIVER)
471 trace(" No Driver\n");
472 else if (rc==MMSYSERR_NOERROR) {
473 LPMIXERCONTROLA array;
474 MIXERLINECONTROLSA controls;
475 if (winetest_interactive) {
476 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
477 s,mixerlineA.szShortName, mixerlineA.szName,
478 mixerlineA.dwDestination,mixerlineA.dwSource);
479 trace(" LineID=%08x Channels=%d "
480 "Connections=%d Controls=%d\n",
481 mixerlineA.dwLineID,mixerlineA.cChannels,
482 mixerlineA.cConnections,mixerlineA.cControls);
483 trace(" State=0x%08x(%s)\n",
484 mixerlineA.fdwLine,line_flags(mixerlineA.fdwLine));
485 trace(" ComponentType=%s\n",
486 component_type(mixerlineA.dwComponentType));
488 target_type(mixerlineA.Target.dwType));
489 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
490 mixerlineA.Target.dwDeviceID,
491 mixerlineA.Target.szPname,
492 mixerlineA.Target.vDriverVersion >> 8,
493 mixerlineA.Target.vDriverVersion & 0xff,
494 mixerlineA.Target.wMid, mixerlineA.Target.wPid);
496 if (mixerlineA.cControls) {
497 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
498 mixerlineA.cControls*sizeof(MIXERCONTROLA));
500 memset(&controls, 0, sizeof(controls));
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",
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",
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",
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 test_mixerClose(mix);
563 static void mixer_test_controlW(HMIXER mix, LPMIXERCONTROLW control)
567 if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) ||
568 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) {
569 MIXERCONTROLDETAILS details;
570 MIXERCONTROLDETAILS_UNSIGNED value;
572 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
573 details.dwControlID = control->dwControlID;
574 details.cChannels = 1;
575 U(details).cMultipleItems = 0;
576 details.paDetails = &value;
577 details.cbDetails = sizeof(value);
579 /* read the current control value */
580 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
581 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
582 "MMSYSERR_NOERROR expected, got %s\n",
584 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
585 MIXERCONTROLDETAILS new_details;
586 MIXERCONTROLDETAILS_UNSIGNED new_value;
588 trace(" Value=%d\n",value.dwValue);
590 if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum)
591 new_value.dwValue = value.dwValue + control->Metrics.cSteps;
593 new_value.dwValue = value.dwValue - control->Metrics.cSteps;
595 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
596 new_details.dwControlID = control->dwControlID;
597 new_details.cChannels = 1;
598 U(new_details).cMultipleItems = 0;
599 new_details.paDetails = &new_value;
600 new_details.cbDetails = sizeof(new_value);
602 /* change the control value by one step */
603 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
604 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
605 "MMSYSERR_NOERROR expected, got %s\n",
607 if (rc==MMSYSERR_NOERROR) {
608 MIXERCONTROLDETAILS ret_details;
609 MIXERCONTROLDETAILS_UNSIGNED ret_value;
611 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
612 ret_details.dwControlID = control->dwControlID;
613 ret_details.cChannels = 1;
614 U(ret_details).cMultipleItems = 0;
615 ret_details.paDetails = &ret_value;
616 ret_details.cbDetails = sizeof(ret_value);
618 /* read back the new control value */
619 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
620 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
621 "MMSYSERR_NOERROR expected, got %s\n",
623 if (rc==MMSYSERR_NOERROR) {
624 /* result may not match exactly because of rounding */
625 ok(abs(ret_value.dwValue-new_value.dwValue)<=1,
626 "Couldn't change value from %d to %d, returned %d\n",
627 value.dwValue,new_value.dwValue,ret_value.dwValue);
629 if (abs(ret_value.dwValue-new_value.dwValue)<=1) {
630 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
631 details.dwControlID = control->dwControlID;
632 details.cChannels = 1;
633 U(details).cMultipleItems = 0;
634 details.paDetails = &value;
635 details.cbDetails = sizeof(value);
637 /* restore original value */
638 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
639 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
640 "MMSYSERR_NOERROR expected, got %s\n",
646 } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) ||
647 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) ||
648 (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) {
649 MIXERCONTROLDETAILS details;
650 MIXERCONTROLDETAILS_BOOLEAN value;
652 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
653 details.dwControlID = control->dwControlID;
654 details.cChannels = 1;
655 U(details).cMultipleItems = 0;
656 details.paDetails = &value;
657 details.cbDetails = sizeof(value);
659 rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE);
660 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
661 "MMSYSERR_NOERROR expected, got %s\n",
663 if (rc==MMSYSERR_NOERROR && winetest_interactive) {
664 MIXERCONTROLDETAILS new_details;
665 MIXERCONTROLDETAILS_BOOLEAN new_value;
667 trace(" Value=%d\n",value.fValue);
669 if (value.fValue == FALSE)
670 new_value.fValue = TRUE;
672 new_value.fValue = FALSE;
674 new_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
675 new_details.dwControlID = control->dwControlID;
676 new_details.cChannels = 1;
677 U(new_details).cMultipleItems = 0;
678 new_details.paDetails = &new_value;
679 new_details.cbDetails = sizeof(new_value);
681 /* change the control value by one step */
682 rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE);
683 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
684 "MMSYSERR_NOERROR expected, got %s\n",
686 if (rc==MMSYSERR_NOERROR) {
687 MIXERCONTROLDETAILS ret_details;
688 MIXERCONTROLDETAILS_BOOLEAN ret_value;
690 ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS);
691 ret_details.dwControlID = control->dwControlID;
692 ret_details.cChannels = 1;
693 U(ret_details).cMultipleItems = 0;
694 ret_details.paDetails = &ret_value;
695 ret_details.cbDetails = sizeof(ret_value);
697 /* read back the new control value */
698 rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE);
699 ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
700 "MMSYSERR_NOERROR expected, got %s\n",
702 if (rc==MMSYSERR_NOERROR) {
703 /* result may not match exactly because of rounding */
704 ok(ret_value.fValue==new_value.fValue,
705 "Couldn't change value from %d to %d, returned %d\n",
706 value.fValue,new_value.fValue,ret_value.fValue);
708 if (ret_value.fValue==new_value.fValue) {
709 details.cbStruct = sizeof(MIXERCONTROLDETAILS);
710 details.dwControlID = control->dwControlID;
711 details.cChannels = 1;
712 U(details).cMultipleItems = 0;
713 details.paDetails = &value;
714 details.cbDetails = sizeof(value);
716 /* restore original value */
717 rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE);
718 ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
719 "MMSYSERR_NOERROR expected, got %s\n",
730 static void mixer_test_deviceW(int device)
736 char szShortName[MIXER_SHORT_NAME_CHARS];
737 char szName[MIXER_LONG_NAME_CHARS];
738 char szPname[MAXPNAMELEN];
740 rc=mixerGetDevCapsW(device,0,sizeof(capsW));
741 ok(rc==MMSYSERR_INVALPARAM,
742 "mixerGetDevCapsW: MMSYSERR_INVALPARAM expected, got %s\n",
745 rc=mixerGetDevCapsW(device,&capsW,4);
746 ok(rc==MMSYSERR_NOERROR ||
747 rc==MMSYSERR_INVALPARAM, /* Vista and W2K8 */
748 "mixerGetDevCapsW: MMSYSERR_NOERROR or MMSYSERR_INVALPARAM expected, got %s\n",
751 rc=mixerGetDevCapsW(device,&capsW,sizeof(capsW));
752 ok(rc==MMSYSERR_NOERROR,
753 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
756 WideCharToMultiByte(CP_ACP,0,capsW.szPname, MAXPNAMELEN,szPname,
757 MAXPNAMELEN,NULL,NULL);
758 if (winetest_interactive) {
759 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device,
760 szPname, capsW.vDriverVersion >> 8,
761 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid,
762 capsW.cDestinations);
764 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device,
765 szPname, capsW.vDriverVersion >> 8,
766 capsW.vDriverVersion & 0xff,capsW.wMid,capsW.wPid);
770 rc=mixerOpen(&mix, device, 0, 0, 0);
771 ok(rc==MMSYSERR_NOERROR,
772 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc));
773 if (rc==MMSYSERR_NOERROR) {
774 for (d=0;d<capsW.cDestinations;d++) {
775 MIXERLINEW mixerlineW;
776 mixerlineW.cbStruct = 0;
777 mixerlineW.dwDestination=d;
778 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
779 MIXER_GETLINEINFOF_DESTINATION);
780 ok(rc==MMSYSERR_INVALPARAM,
781 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
782 "MMSYSERR_INVALPARAM expected, got %s\n",
785 mixerlineW.cbStruct = sizeof(mixerlineW);
786 mixerlineW.dwDestination=capsW.cDestinations;
787 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
788 MIXER_GETLINEINFOF_DESTINATION);
789 ok(rc==MMSYSERR_INVALPARAM||rc==MIXERR_INVALLINE,
790 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
791 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
794 mixerlineW.cbStruct = sizeof(mixerlineW);
795 mixerlineW.dwDestination=d;
796 rc=mixerGetLineInfoW((HMIXEROBJ)mix,0,
797 MIXER_GETLINEINFOF_DESTINATION);
798 ok(rc==MMSYSERR_INVALPARAM,
799 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
800 "MMSYSERR_INVALPARAM expected, got %s\n",
803 mixerlineW.cbStruct = sizeof(mixerlineW);
804 mixerlineW.dwDestination=d;
805 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,-1);
806 ok(rc==MMSYSERR_INVALFLAG,
807 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
810 mixerlineW.cbStruct = sizeof(mixerlineW);
811 mixerlineW.dwDestination=d;
812 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
813 MIXER_GETLINEINFOF_DESTINATION);
814 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
815 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
816 "MMSYSERR_NOERROR expected, got %s\n",
818 if (rc==MMSYSERR_NODRIVER)
819 trace(" No Driver\n");
820 else if (rc==MMSYSERR_NOERROR && winetest_interactive) {
821 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
822 MIXER_SHORT_NAME_CHARS,szShortName,
823 MIXER_SHORT_NAME_CHARS,NULL,NULL);
824 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
825 MIXER_LONG_NAME_CHARS,szName,
826 MIXER_LONG_NAME_CHARS,NULL,NULL);
827 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
829 MAXPNAMELEN,NULL, NULL);
830 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
831 d,szShortName,szName,
832 mixerlineW.dwDestination,mixerlineW.dwSource);
833 trace(" LineID=%08x Channels=%d "
834 "Connections=%d Controls=%d\n",
835 mixerlineW.dwLineID,mixerlineW.cChannels,
836 mixerlineW.cConnections,mixerlineW.cControls);
837 trace(" State=0x%08x(%s)\n",
838 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
839 trace(" ComponentType=%s\n",
840 component_type(mixerlineW.dwComponentType));
842 target_type(mixerlineW.Target.dwType));
843 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
844 mixerlineW.Target.dwDeviceID,szPname,
845 mixerlineW.Target.vDriverVersion >> 8,
846 mixerlineW.Target.vDriverVersion & 0xff,
847 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
849 ns=mixerlineW.cConnections;
851 mixerlineW.cbStruct = sizeof(mixerlineW);
852 mixerlineW.dwDestination=d;
853 mixerlineW.dwSource=s;
854 rc=mixerGetLineInfoW((HMIXEROBJ)mix,&mixerlineW,
855 MIXER_GETLINEINFOF_SOURCE);
856 ok(rc==MMSYSERR_NOERROR||rc==MMSYSERR_NODRIVER,
857 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
858 "MMSYSERR_NOERROR expected, got %s\n",
860 if (rc==MMSYSERR_NODRIVER)
861 trace(" No Driver\n");
862 else if (rc==MMSYSERR_NOERROR) {
863 LPMIXERCONTROLW array;
864 MIXERLINECONTROLSW controls;
865 if (winetest_interactive) {
866 WideCharToMultiByte(CP_ACP,0,mixerlineW.szShortName,
867 MIXER_SHORT_NAME_CHARS,szShortName,
868 MIXER_SHORT_NAME_CHARS,NULL,NULL);
869 WideCharToMultiByte(CP_ACP,0,mixerlineW.szName,
870 MIXER_LONG_NAME_CHARS,szName,
871 MIXER_LONG_NAME_CHARS,NULL,NULL);
872 WideCharToMultiByte(CP_ACP,0,mixerlineW.Target.szPname,
874 MAXPNAMELEN,NULL, NULL);
875 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
876 s,szShortName,szName,
877 mixerlineW.dwDestination,mixerlineW.dwSource);
878 trace(" LineID=%08x Channels=%d "
879 "Connections=%d Controls=%d\n",
880 mixerlineW.dwLineID,mixerlineW.cChannels,
881 mixerlineW.cConnections,mixerlineW.cControls);
882 trace(" State=0x%08x(%s)\n",
883 mixerlineW.fdwLine,line_flags(mixerlineW.fdwLine));
884 trace(" ComponentType=%s\n",
885 component_type(mixerlineW.dwComponentType));
887 target_type(mixerlineW.Target.dwType));
888 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
889 mixerlineW.Target.dwDeviceID,szPname,
890 mixerlineW.Target.vDriverVersion >> 8,
891 mixerlineW.Target.vDriverVersion & 0xff,
892 mixerlineW.Target.wMid, mixerlineW.Target.wPid);
894 if (mixerlineW.cControls) {
895 array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
896 mixerlineW.cControls*sizeof(MIXERCONTROLW));
898 rc=mixerGetLineControlsW((HMIXEROBJ)mix,0,
899 MIXER_GETLINECONTROLSF_ALL);
900 ok(rc==MMSYSERR_INVALPARAM,
901 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
902 "MMSYSERR_INVALPARAM expected, got %s\n",
904 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
906 ok(rc==MMSYSERR_INVALFLAG||rc==MMSYSERR_INVALPARAM,
907 "mixerGetLineControlsA(-1): "
908 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
911 controls.cbStruct = sizeof(MIXERLINECONTROLSW);
912 controls.cControls = mixerlineW.cControls;
913 controls.dwLineID = mixerlineW.dwLineID;
914 controls.pamxctrl = array;
915 controls.cbmxctrl = sizeof(MIXERCONTROLW);
917 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
918 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
920 rc=mixerGetLineControlsW((HMIXEROBJ)mix,&controls,
921 MIXER_GETLINECONTROLSF_ALL);
922 ok(rc==MMSYSERR_NOERROR,
923 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
924 "MMSYSERR_NOERROR expected, got %s\n",
926 if (rc==MMSYSERR_NOERROR) {
927 for(nc=0;nc<mixerlineW.cControls;nc++) {
928 if (winetest_interactive) {
929 WideCharToMultiByte(CP_ACP,0,array[nc].szShortName,
930 MIXER_SHORT_NAME_CHARS,szShortName,
931 MIXER_SHORT_NAME_CHARS,NULL,NULL);
932 WideCharToMultiByte(CP_ACP,0,array[nc].szName,
933 MIXER_LONG_NAME_CHARS,szName,
934 MIXER_LONG_NAME_CHARS,NULL,NULL);
935 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc,
936 szShortName, szName, array[nc].dwControlID);
937 trace(" ControlType=%s\n",
938 control_type(array[nc].dwControlType));
939 trace(" Control=0x%08x(%s)\n",
940 array[nc].fdwControl,
941 control_flags(array[nc].fdwControl));
942 trace(" Items=%d Min=%d Max=%d Step=%d\n",
943 array[nc].cMultipleItems,
944 S1(array[nc].Bounds).dwMinimum,
945 S1(array[nc].Bounds).dwMaximum,
946 array[nc].Metrics.cSteps);
948 mixer_test_controlW(mix, &array[nc]);
952 HeapFree(GetProcessHeap(),0,array);
958 test_mixerClose(mix);
962 static void mixer_testsA(void)
968 trace("--- Testing ASCII functions ---\n");
970 ndev=mixerGetNumDevs();
971 trace("found %d Mixer devices\n",ndev);
973 rc=mixerGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
974 ok(rc==MMSYSERR_BADDEVICEID,
975 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
979 mixer_test_deviceA(d);
982 static void mixer_testsW(void)
988 trace("--- Testing WCHAR functions ---\n");
990 ndev=mixerGetNumDevs();
991 trace("found %d Mixer devices\n",ndev);
993 rc=mixerGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
994 ok(rc==MMSYSERR_BADDEVICEID||rc==MMSYSERR_NOTSUPPORTED,
995 "mixerGetDevCapsW: MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
996 "expected, got %s\n", mmsys_error(rc));
997 if (rc==MMSYSERR_NOTSUPPORTED)
1000 for (d=0;d<ndev;d++)
1001 mixer_test_deviceW(d);
1004 static void test_mixerOpen(void)
1011 ndev = mixerGetNumDevs();
1013 /* Test mixerOpen with invalid device ID values. */
1014 rc = mixerOpen(&mix, ndev + 1, 0, 0, 0);
1015 ok(rc == MMSYSERR_BADDEVICEID,
1016 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1019 rc = mixerOpen(&mix, -1, 0, 0, 0);
1020 ok(rc == MMSYSERR_BADDEVICEID ||
1021 rc == MMSYSERR_INVALHANDLE, /* NT4/W2K */
1022 "mixerOpen: MMSYSERR_BADDEVICEID or MMSYSERR_INVALHANDLE expected, got %s\n",
1025 for (d = 0; d < ndev; d++) {
1026 /* Test mixerOpen with valid device ID values and invalid parameters. */
1027 rc = mixerOpen(&mix, d, 0, 0, CALLBACK_FUNCTION);
1028 ok(rc == MMSYSERR_INVALFLAG
1029 || rc == MMSYSERR_NOTSUPPORTED, /* 98/ME */
1030 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n",
1033 rc = mixerOpen(&mix, d, 0xdeadbeef, 0, CALLBACK_WINDOW);
1034 ok(rc == MMSYSERR_INVALPARAM ||
1035 broken(rc == MMSYSERR_NOERROR /* 98 */),
1036 "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n",
1038 if (rc == MMSYSERR_NOERROR)
1039 test_mixerClose(mix);
1041 /* Test mixerOpen with a NULL dwCallback and CALLBACK_WINDOW flag. */
1042 rc = mixerOpen(&mix, d, 0, 0, CALLBACK_WINDOW);
1043 ok(rc == MMSYSERR_NOERROR,
1044 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1046 if (rc == MMSYSERR_NOERROR)
1047 test_mixerClose(mix);
1049 rc = mixerOpen(&mix, d, 0, 0, CALLBACK_THREAD);
1050 ok(rc == MMSYSERR_NOERROR /* since w2k */ ||
1051 rc == MMSYSERR_NOTSUPPORTED, /* 98 */
1052 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1054 if (rc == MMSYSERR_NOERROR)
1055 test_mixerClose(mix);
1057 rc = mixerOpen(&mix, d, 0, 0, CALLBACK_EVENT);
1058 ok(rc == MMSYSERR_NOERROR /* since w2k */ ||
1059 rc == MMSYSERR_NOTSUPPORTED, /* 98 */
1060 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1062 if (rc == MMSYSERR_NOERROR)
1063 test_mixerClose(mix);
1065 event = CreateEvent(NULL, FALSE, FALSE, NULL);
1066 ok(event != NULL, "CreateEvent(): error=%d\n", GetLastError());
1068 /* NOTSUPPORTED is not broken, but it enables the todo_wine marker. */
1069 rc = mixerOpen(&mix, d, (DWORD_PTR)event, 0, CALLBACK_EVENT);
1071 ok(rc == MMSYSERR_NOERROR /* since w2k */ ||
1072 broken(rc == MMSYSERR_NOTSUPPORTED), /* 98 */
1073 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1075 if (rc == MMSYSERR_NOERROR)
1076 test_mixerClose(mix);
1078 /* Test mixerOpen with normal parameters. */
1079 rc = mixerOpen(&mix, d, 0, 0, 0);
1080 ok(rc == MMSYSERR_NOERROR,
1081 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1084 if (rc == MMSYSERR_NOERROR)
1085 test_mixerClose(mix);
1087 rc = WaitForSingleObject(event, 0);
1088 ok(rc == WAIT_TIMEOUT, "WaitEvent %d\n", rc);