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(HMIXEROBJ mix
, MIXERCONTROLA
*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
.cbDetails
= sizeof(value
);
202 /* test NULL paDetails */
203 details
.paDetails
= NULL
;
204 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
205 ok(rc
==MMSYSERR_INVALPARAM
,
206 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
209 /* read the current control value */
210 details
.paDetails
= &value
;
211 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
212 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
213 "MMSYSERR_NOERROR expected, got %s\n",
215 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
216 MIXERCONTROLDETAILS new_details
;
217 MIXERCONTROLDETAILS_UNSIGNED new_value
;
219 trace(" Value=%d\n",value
.dwValue
);
221 if (value
.dwValue
+ control
->Metrics
.cSteps
< S1(control
->Bounds
).dwMaximum
)
222 new_value
.dwValue
= value
.dwValue
+ control
->Metrics
.cSteps
;
224 new_value
.dwValue
= value
.dwValue
- control
->Metrics
.cSteps
;
226 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
227 new_details
.dwControlID
= control
->dwControlID
;
228 new_details
.cChannels
= 1;
229 U(new_details
).cMultipleItems
= 0;
230 new_details
.paDetails
= &new_value
;
231 new_details
.cbDetails
= sizeof(new_value
);
233 /* change the control value by one step */
234 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
235 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
236 "MMSYSERR_NOERROR expected, got %s\n",
238 if (rc
==MMSYSERR_NOERROR
) {
239 MIXERCONTROLDETAILS ret_details
;
240 MIXERCONTROLDETAILS_UNSIGNED ret_value
;
242 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
243 ret_details
.dwControlID
= control
->dwControlID
;
244 ret_details
.cChannels
= 1;
245 U(ret_details
).cMultipleItems
= 0;
246 ret_details
.paDetails
= &ret_value
;
247 ret_details
.cbDetails
= sizeof(ret_value
);
249 /* read back the new control value */
250 rc
= mixerGetControlDetailsA(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
251 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
252 "MMSYSERR_NOERROR expected, got %s\n",
254 if (rc
==MMSYSERR_NOERROR
) {
255 /* result may not match exactly because of rounding */
256 ok(abs(ret_value
.dwValue
-new_value
.dwValue
)<=1,
257 "Couldn't change value from %d to %d, returned %d\n",
258 value
.dwValue
,new_value
.dwValue
,ret_value
.dwValue
);
260 if (abs(ret_value
.dwValue
-new_value
.dwValue
)<=1) {
261 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
262 details
.dwControlID
= control
->dwControlID
;
263 details
.cChannels
= 1;
264 U(details
).cMultipleItems
= 0;
265 details
.paDetails
= &value
;
266 details
.cbDetails
= sizeof(value
);
268 /* restore original value */
269 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
270 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
271 "MMSYSERR_NOERROR expected, got %s\n",
277 } else if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUTE
) ||
278 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BOOLEAN
) ||
279 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BUTTON
)) {
280 MIXERCONTROLDETAILS details
;
281 MIXERCONTROLDETAILS_BOOLEAN value
;
283 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
284 details
.dwControlID
= control
->dwControlID
;
285 details
.cChannels
= 1;
286 U(details
).cMultipleItems
= 0;
287 details
.paDetails
= &value
;
288 details
.cbDetails
= sizeof(value
);
290 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
291 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
292 "MMSYSERR_NOERROR expected, got %s\n",
294 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
295 MIXERCONTROLDETAILS new_details
;
296 MIXERCONTROLDETAILS_BOOLEAN new_value
;
298 trace(" Value=%d\n",value
.fValue
);
300 if (value
.fValue
== FALSE
)
301 new_value
.fValue
= TRUE
;
303 new_value
.fValue
= FALSE
;
305 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
306 new_details
.dwControlID
= control
->dwControlID
;
307 new_details
.cChannels
= 1;
308 U(new_details
).cMultipleItems
= 0;
309 new_details
.paDetails
= &new_value
;
310 new_details
.cbDetails
= sizeof(new_value
);
312 /* change the control value by one step */
313 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
314 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
315 "MMSYSERR_NOERROR expected, got %s\n",
317 if (rc
==MMSYSERR_NOERROR
) {
318 MIXERCONTROLDETAILS ret_details
;
319 MIXERCONTROLDETAILS_BOOLEAN ret_value
;
321 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
322 ret_details
.dwControlID
= control
->dwControlID
;
323 ret_details
.cChannels
= 1;
324 U(ret_details
).cMultipleItems
= 0;
325 ret_details
.paDetails
= &ret_value
;
326 ret_details
.cbDetails
= sizeof(ret_value
);
328 /* read back the new control value */
329 rc
= mixerGetControlDetailsA(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
330 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
331 "MMSYSERR_NOERROR expected, got %s\n",
333 if (rc
==MMSYSERR_NOERROR
) {
334 /* result may not match exactly because of rounding */
335 ok(ret_value
.fValue
==new_value
.fValue
,
336 "Couldn't change value from %d to %d, returned %d\n",
337 value
.fValue
,new_value
.fValue
,ret_value
.fValue
);
339 if (ret_value
.fValue
==new_value
.fValue
) {
340 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
341 details
.dwControlID
= control
->dwControlID
;
342 details
.cChannels
= 1;
343 U(details
).cMultipleItems
= 0;
344 details
.paDetails
= &value
;
345 details
.cbDetails
= sizeof(value
);
347 /* restore original value */
348 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
349 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
350 "MMSYSERR_NOERROR expected, got %s\n",
361 static void mixer_test_deviceA(int device
)
368 rc
=mixerGetDevCapsA(device
,0,sizeof(capsA
));
369 ok(rc
==MMSYSERR_INVALPARAM
,
370 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
373 rc
=mixerGetDevCapsA(device
,&capsA
,4);
374 ok(rc
==MMSYSERR_NOERROR
,
375 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
378 rc
=mixerGetDevCapsA(device
,&capsA
,sizeof(capsA
));
379 ok(rc
==MMSYSERR_NOERROR
,
380 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
383 if (winetest_interactive
) {
384 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device
,
385 capsA
.szPname
, capsA
.vDriverVersion
>> 8,
386 capsA
.vDriverVersion
& 0xff,capsA
.wMid
,capsA
.wPid
,
387 capsA
.cDestinations
);
389 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device
,
390 capsA
.szPname
, capsA
.vDriverVersion
>> 8,
391 capsA
.vDriverVersion
& 0xff,capsA
.wMid
,capsA
.wPid
);
394 rc
= mixerOpen((HMIXER
*)&mix
, device
, 0, 0, 0);
395 ok(rc
==MMSYSERR_NOERROR
,
396 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc
));
397 if (rc
==MMSYSERR_NOERROR
) {
400 rc
=mixerGetDevCapsA((UINT_PTR
)mix
,&capsA2
,sizeof(capsA2
));
401 ok(rc
==MMSYSERR_NOERROR
,
402 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
404 ok(!strcmp(capsA2
.szPname
, capsA
.szPname
), "Got wrong device caps\n");
406 for (d
=0;d
<capsA
.cDestinations
;d
++) {
407 MIXERLINEA mixerlineA
;
408 mixerlineA
.cbStruct
= 0;
409 mixerlineA
.dwDestination
=d
;
410 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
411 ok(rc
==MMSYSERR_INVALPARAM
,
412 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
413 "MMSYSERR_INVALPARAM expected, got %s\n",
416 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
417 mixerlineA
.dwDestination
=capsA
.cDestinations
;
418 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
419 ok(rc
==MMSYSERR_INVALPARAM
||rc
==MIXERR_INVALLINE
,
420 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
421 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
424 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
425 mixerlineA
.dwDestination
=d
;
426 rc
= mixerGetLineInfoA(mix
, 0, MIXER_GETLINEINFOF_DESTINATION
);
427 ok(rc
==MMSYSERR_INVALPARAM
,
428 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
429 "MMSYSERR_INVALPARAM expected, got %s\n",
432 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
433 mixerlineA
.dwDestination
=d
;
434 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, -1);
435 ok(rc
==MMSYSERR_INVALFLAG
,
436 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
439 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
440 mixerlineA
.dwDestination
=d
;
441 mixerlineA
.dwUser
= (ULONG_PTR
)0xdeadbeef;
442 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
443 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
444 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
445 "MMSYSERR_NOERROR expected, got %s\n",
447 ok(mixerlineA
.dwUser
== 0, "dwUser was not reset\n");
448 if (rc
==MMSYSERR_NODRIVER
)
449 trace(" No Driver\n");
450 else if (rc
==MMSYSERR_NOERROR
) {
451 if (winetest_interactive
) {
452 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
453 d
,mixerlineA
.szShortName
, mixerlineA
.szName
,
454 mixerlineA
.dwDestination
,mixerlineA
.dwSource
);
455 trace(" LineID=%08x Channels=%d "
456 "Connections=%d Controls=%d\n",
457 mixerlineA
.dwLineID
,mixerlineA
.cChannels
,
458 mixerlineA
.cConnections
,mixerlineA
.cControls
);
459 trace(" State=0x%08x(%s)\n",
460 mixerlineA
.fdwLine
,line_flags(mixerlineA
.fdwLine
));
461 trace(" ComponentType=%s\n",
462 component_type(mixerlineA
.dwComponentType
));
464 target_type(mixerlineA
.Target
.dwType
));
465 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
466 mixerlineA
.Target
.dwDeviceID
,
467 mixerlineA
.Target
.szPname
,
468 mixerlineA
.Target
.vDriverVersion
>> 8,
469 mixerlineA
.Target
.vDriverVersion
& 0xff,
470 mixerlineA
.Target
.wMid
, mixerlineA
.Target
.wPid
);
472 ns
=mixerlineA
.cConnections
;
474 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
475 mixerlineA
.dwDestination
=d
;
476 mixerlineA
.dwSource
=s
;
477 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_SOURCE
);
478 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
479 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
480 "MMSYSERR_NOERROR expected, got %s\n",
482 if (rc
==MMSYSERR_NODRIVER
)
483 trace(" No Driver\n");
484 else if (rc
==MMSYSERR_NOERROR
) {
485 LPMIXERCONTROLA array
;
486 MIXERLINECONTROLSA controls
;
487 if (winetest_interactive
) {
488 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
489 s
,mixerlineA
.szShortName
, mixerlineA
.szName
,
490 mixerlineA
.dwDestination
,mixerlineA
.dwSource
);
491 trace(" LineID=%08x Channels=%d "
492 "Connections=%d Controls=%d\n",
493 mixerlineA
.dwLineID
,mixerlineA
.cChannels
,
494 mixerlineA
.cConnections
,mixerlineA
.cControls
);
495 trace(" State=0x%08x(%s)\n",
496 mixerlineA
.fdwLine
,line_flags(mixerlineA
.fdwLine
));
497 trace(" ComponentType=%s\n",
498 component_type(mixerlineA
.dwComponentType
));
500 target_type(mixerlineA
.Target
.dwType
));
501 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
502 mixerlineA
.Target
.dwDeviceID
,
503 mixerlineA
.Target
.szPname
,
504 mixerlineA
.Target
.vDriverVersion
>> 8,
505 mixerlineA
.Target
.vDriverVersion
& 0xff,
506 mixerlineA
.Target
.wMid
, mixerlineA
.Target
.wPid
);
508 if (mixerlineA
.cControls
) {
509 array
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
510 mixerlineA
.cControls
*sizeof(MIXERCONTROLA
));
512 memset(&controls
, 0, sizeof(controls
));
514 rc
= mixerGetLineControlsA(mix
, 0, MIXER_GETLINECONTROLSF_ALL
);
515 ok(rc
==MMSYSERR_INVALPARAM
,
516 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
517 "MMSYSERR_INVALPARAM expected, got %s\n",
520 rc
= mixerGetLineControlsA(mix
, &controls
, -1);
521 ok(rc
==MMSYSERR_INVALFLAG
||rc
==MMSYSERR_INVALPARAM
,
522 "mixerGetLineControlsA(-1): "
523 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
526 controls
.cbStruct
= sizeof(MIXERLINECONTROLSA
);
527 controls
.cControls
= mixerlineA
.cControls
;
528 controls
.dwLineID
= mixerlineA
.dwLineID
;
529 controls
.pamxctrl
= array
;
530 controls
.cbmxctrl
= sizeof(MIXERCONTROLA
);
532 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
533 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
535 rc
= mixerGetLineControlsA(mix
, &controls
, MIXER_GETLINECONTROLSF_ALL
);
536 ok(rc
==MMSYSERR_NOERROR
,
537 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
538 "MMSYSERR_NOERROR expected, got %s\n",
540 if (rc
==MMSYSERR_NOERROR
) {
541 for(nc
=0;nc
<mixerlineA
.cControls
;nc
++) {
542 if (winetest_interactive
) {
543 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc
,
544 array
[nc
].szShortName
,
545 array
[nc
].szName
, array
[nc
].dwControlID
);
546 trace(" ControlType=%s\n",
547 control_type(array
[nc
].dwControlType
));
548 trace(" Control=0x%08x(%s)\n",
549 array
[nc
].fdwControl
,
550 control_flags(array
[nc
].fdwControl
));
551 trace(" Items=%d Min=%d Max=%d Step=%d\n",
552 array
[nc
].cMultipleItems
,
553 S1(array
[nc
].Bounds
).dwMinimum
,
554 S1(array
[nc
].Bounds
).dwMaximum
,
555 array
[nc
].Metrics
.cSteps
);
558 mixer_test_controlA(mix
, &array
[nc
]);
562 HeapFree(GetProcessHeap(),0,array
);
569 test_mixerClose((HMIXER
)mix
);
573 static void mixer_test_controlW(HMIXEROBJ mix
, MIXERCONTROLW
*control
)
577 if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_VOLUME
) ||
578 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_UNSIGNED
)) {
579 MIXERCONTROLDETAILS details
;
580 MIXERCONTROLDETAILS_UNSIGNED value
;
582 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
583 details
.dwControlID
= control
->dwControlID
;
584 details
.cChannels
= 1;
585 U(details
).cMultipleItems
= 0;
586 details
.paDetails
= &value
;
587 details
.cbDetails
= sizeof(value
);
589 /* read the current control value */
590 rc
= mixerGetControlDetailsW(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
591 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
592 "MMSYSERR_NOERROR expected, got %s\n",
594 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
595 MIXERCONTROLDETAILS new_details
;
596 MIXERCONTROLDETAILS_UNSIGNED new_value
;
598 trace(" Value=%d\n",value
.dwValue
);
600 if (value
.dwValue
+ control
->Metrics
.cSteps
< S1(control
->Bounds
).dwMaximum
)
601 new_value
.dwValue
= value
.dwValue
+ control
->Metrics
.cSteps
;
603 new_value
.dwValue
= value
.dwValue
- control
->Metrics
.cSteps
;
605 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
606 new_details
.dwControlID
= control
->dwControlID
;
607 new_details
.cChannels
= 1;
608 U(new_details
).cMultipleItems
= 0;
609 new_details
.paDetails
= &new_value
;
610 new_details
.cbDetails
= sizeof(new_value
);
612 /* change the control value by one step */
613 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
614 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
615 "MMSYSERR_NOERROR expected, got %s\n",
617 if (rc
==MMSYSERR_NOERROR
) {
618 MIXERCONTROLDETAILS ret_details
;
619 MIXERCONTROLDETAILS_UNSIGNED ret_value
;
621 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
622 ret_details
.dwControlID
= control
->dwControlID
;
623 ret_details
.cChannels
= 1;
624 U(ret_details
).cMultipleItems
= 0;
625 ret_details
.paDetails
= &ret_value
;
626 ret_details
.cbDetails
= sizeof(ret_value
);
628 /* read back the new control value */
629 rc
= mixerGetControlDetailsW(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
630 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
631 "MMSYSERR_NOERROR expected, got %s\n",
633 if (rc
==MMSYSERR_NOERROR
) {
634 /* result may not match exactly because of rounding */
635 ok(abs(ret_value
.dwValue
-new_value
.dwValue
)<=1,
636 "Couldn't change value from %d to %d, returned %d\n",
637 value
.dwValue
,new_value
.dwValue
,ret_value
.dwValue
);
639 if (abs(ret_value
.dwValue
-new_value
.dwValue
)<=1) {
640 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
641 details
.dwControlID
= control
->dwControlID
;
642 details
.cChannels
= 1;
643 U(details
).cMultipleItems
= 0;
644 details
.paDetails
= &value
;
645 details
.cbDetails
= sizeof(value
);
647 /* restore original value */
648 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
649 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
650 "MMSYSERR_NOERROR expected, got %s\n",
656 } else if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUTE
) ||
657 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BOOLEAN
) ||
658 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BUTTON
)) {
659 MIXERCONTROLDETAILS details
;
660 MIXERCONTROLDETAILS_BOOLEAN value
;
662 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
663 details
.dwControlID
= control
->dwControlID
;
664 details
.cChannels
= 1;
665 U(details
).cMultipleItems
= 0;
666 details
.paDetails
= &value
;
667 details
.cbDetails
= sizeof(value
);
669 rc
= mixerGetControlDetailsW(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
670 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
671 "MMSYSERR_NOERROR expected, got %s\n",
673 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
674 MIXERCONTROLDETAILS new_details
;
675 MIXERCONTROLDETAILS_BOOLEAN new_value
;
677 trace(" Value=%d\n",value
.fValue
);
679 if (value
.fValue
== FALSE
)
680 new_value
.fValue
= TRUE
;
682 new_value
.fValue
= FALSE
;
684 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
685 new_details
.dwControlID
= control
->dwControlID
;
686 new_details
.cChannels
= 1;
687 U(new_details
).cMultipleItems
= 0;
688 new_details
.paDetails
= &new_value
;
689 new_details
.cbDetails
= sizeof(new_value
);
691 /* change the control value by one step */
692 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
693 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
694 "MMSYSERR_NOERROR expected, got %s\n",
696 if (rc
==MMSYSERR_NOERROR
) {
697 MIXERCONTROLDETAILS ret_details
;
698 MIXERCONTROLDETAILS_BOOLEAN ret_value
;
700 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
701 ret_details
.dwControlID
= control
->dwControlID
;
702 ret_details
.cChannels
= 1;
703 U(ret_details
).cMultipleItems
= 0;
704 ret_details
.paDetails
= &ret_value
;
705 ret_details
.cbDetails
= sizeof(ret_value
);
707 /* read back the new control value */
708 rc
= mixerGetControlDetailsW(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
709 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
710 "MMSYSERR_NOERROR expected, got %s\n",
712 if (rc
==MMSYSERR_NOERROR
) {
713 /* result may not match exactly because of rounding */
714 ok(ret_value
.fValue
==new_value
.fValue
,
715 "Couldn't change value from %d to %d, returned %d\n",
716 value
.fValue
,new_value
.fValue
,ret_value
.fValue
);
718 if (ret_value
.fValue
==new_value
.fValue
) {
719 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
720 details
.dwControlID
= control
->dwControlID
;
721 details
.cChannels
= 1;
722 U(details
).cMultipleItems
= 0;
723 details
.paDetails
= &value
;
724 details
.cbDetails
= sizeof(value
);
726 /* restore original value */
727 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
728 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
729 "MMSYSERR_NOERROR expected, got %s\n",
740 static void mixer_test_deviceW(int device
)
746 char szShortName
[MIXER_SHORT_NAME_CHARS
];
747 char szName
[MIXER_LONG_NAME_CHARS
];
748 char szPname
[MAXPNAMELEN
];
750 rc
=mixerGetDevCapsW(device
,0,sizeof(capsW
));
751 ok(rc
==MMSYSERR_INVALPARAM
,
752 "mixerGetDevCapsW: MMSYSERR_INVALPARAM expected, got %s\n",
755 rc
=mixerGetDevCapsW(device
,&capsW
,4);
756 ok(rc
==MMSYSERR_NOERROR
||
757 rc
==MMSYSERR_INVALPARAM
, /* Vista and W2K8 */
758 "mixerGetDevCapsW: MMSYSERR_NOERROR or MMSYSERR_INVALPARAM expected, got %s\n",
761 rc
=mixerGetDevCapsW(device
,&capsW
,sizeof(capsW
));
762 ok(rc
==MMSYSERR_NOERROR
,
763 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
766 WideCharToMultiByte(CP_ACP
,0,capsW
.szPname
, MAXPNAMELEN
,szPname
,
767 MAXPNAMELEN
,NULL
,NULL
);
768 if (winetest_interactive
) {
769 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%d\n", device
,
770 szPname
, capsW
.vDriverVersion
>> 8,
771 capsW
.vDriverVersion
& 0xff,capsW
.wMid
,capsW
.wPid
,
772 capsW
.cDestinations
);
774 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device
,
775 szPname
, capsW
.vDriverVersion
>> 8,
776 capsW
.vDriverVersion
& 0xff,capsW
.wMid
,capsW
.wPid
);
780 rc
= mixerOpen((HMIXER
*)&mix
, device
, 0, 0, 0);
781 ok(rc
==MMSYSERR_NOERROR
,
782 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc
));
783 if (rc
==MMSYSERR_NOERROR
) {
786 rc
=mixerGetDevCapsW((UINT_PTR
)mix
,&capsW2
,sizeof(capsW2
));
787 ok(rc
==MMSYSERR_NOERROR
,
788 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
790 ok(!lstrcmpW(capsW2
.szPname
, capsW
.szPname
), "Got wrong device caps\n");
792 for (d
=0;d
<capsW
.cDestinations
;d
++) {
793 MIXERLINEW mixerlineW
;
794 mixerlineW
.cbStruct
= 0;
795 mixerlineW
.dwDestination
=d
;
796 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
797 ok(rc
==MMSYSERR_INVALPARAM
,
798 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
799 "MMSYSERR_INVALPARAM expected, got %s\n",
802 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
803 mixerlineW
.dwDestination
=capsW
.cDestinations
;
804 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
805 ok(rc
==MMSYSERR_INVALPARAM
||rc
==MIXERR_INVALLINE
,
806 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
807 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
810 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
811 mixerlineW
.dwDestination
=d
;
812 rc
= mixerGetLineInfoW(mix
, 0, MIXER_GETLINEINFOF_DESTINATION
);
813 ok(rc
==MMSYSERR_INVALPARAM
,
814 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
815 "MMSYSERR_INVALPARAM expected, got %s\n",
818 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
819 mixerlineW
.dwDestination
=d
;
820 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, -1);
821 ok(rc
==MMSYSERR_INVALFLAG
,
822 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
825 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
826 mixerlineW
.dwDestination
=d
;
827 mixerlineW
.dwUser
= (ULONG_PTR
)0xdeadbeef;
828 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
829 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
830 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
831 "MMSYSERR_NOERROR expected, got %s\n",
833 ok(mixerlineW
.dwUser
== 0, "dwUser was not reset\n");
834 if (rc
==MMSYSERR_NODRIVER
)
835 trace(" No Driver\n");
836 else if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
837 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szShortName
,
838 MIXER_SHORT_NAME_CHARS
,szShortName
,
839 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
840 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szName
,
841 MIXER_LONG_NAME_CHARS
,szName
,
842 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
843 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.Target
.szPname
,
845 MAXPNAMELEN
,NULL
, NULL
);
846 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
847 d
,szShortName
,szName
,
848 mixerlineW
.dwDestination
,mixerlineW
.dwSource
);
849 trace(" LineID=%08x Channels=%d "
850 "Connections=%d Controls=%d\n",
851 mixerlineW
.dwLineID
,mixerlineW
.cChannels
,
852 mixerlineW
.cConnections
,mixerlineW
.cControls
);
853 trace(" State=0x%08x(%s)\n",
854 mixerlineW
.fdwLine
,line_flags(mixerlineW
.fdwLine
));
855 trace(" ComponentType=%s\n",
856 component_type(mixerlineW
.dwComponentType
));
858 target_type(mixerlineW
.Target
.dwType
));
859 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
860 mixerlineW
.Target
.dwDeviceID
,szPname
,
861 mixerlineW
.Target
.vDriverVersion
>> 8,
862 mixerlineW
.Target
.vDriverVersion
& 0xff,
863 mixerlineW
.Target
.wMid
, mixerlineW
.Target
.wPid
);
865 ns
=mixerlineW
.cConnections
;
867 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
868 mixerlineW
.dwDestination
=d
;
869 mixerlineW
.dwSource
=s
;
870 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_SOURCE
);
871 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
872 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
873 "MMSYSERR_NOERROR expected, got %s\n",
875 if (rc
==MMSYSERR_NODRIVER
)
876 trace(" No Driver\n");
877 else if (rc
==MMSYSERR_NOERROR
) {
878 LPMIXERCONTROLW array
;
879 MIXERLINECONTROLSW controls
;
880 if (winetest_interactive
) {
881 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szShortName
,
882 MIXER_SHORT_NAME_CHARS
,szShortName
,
883 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
884 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szName
,
885 MIXER_LONG_NAME_CHARS
,szName
,
886 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
887 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.Target
.szPname
,
889 MAXPNAMELEN
,NULL
, NULL
);
890 trace(" %d: \"%s\" (%s) Destination=%d Source=%d\n",
891 s
,szShortName
,szName
,
892 mixerlineW
.dwDestination
,mixerlineW
.dwSource
);
893 trace(" LineID=%08x Channels=%d "
894 "Connections=%d Controls=%d\n",
895 mixerlineW
.dwLineID
,mixerlineW
.cChannels
,
896 mixerlineW
.cConnections
,mixerlineW
.cControls
);
897 trace(" State=0x%08x(%s)\n",
898 mixerlineW
.fdwLine
,line_flags(mixerlineW
.fdwLine
));
899 trace(" ComponentType=%s\n",
900 component_type(mixerlineW
.dwComponentType
));
902 target_type(mixerlineW
.Target
.dwType
));
903 trace(" Device=%d (%s) %d.%d (%d:%d)\n",
904 mixerlineW
.Target
.dwDeviceID
,szPname
,
905 mixerlineW
.Target
.vDriverVersion
>> 8,
906 mixerlineW
.Target
.vDriverVersion
& 0xff,
907 mixerlineW
.Target
.wMid
, mixerlineW
.Target
.wPid
);
909 if (mixerlineW
.cControls
) {
910 array
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
911 mixerlineW
.cControls
*sizeof(MIXERCONTROLW
));
913 rc
= mixerGetLineControlsW(mix
, 0, MIXER_GETLINECONTROLSF_ALL
);
914 ok(rc
==MMSYSERR_INVALPARAM
,
915 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
916 "MMSYSERR_INVALPARAM expected, got %s\n",
918 rc
= mixerGetLineControlsW(mix
, &controls
, -1);
919 ok(rc
==MMSYSERR_INVALFLAG
||rc
==MMSYSERR_INVALPARAM
,
920 "mixerGetLineControlsW(-1): "
921 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
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(mix
, &controls
, MIXER_GETLINECONTROLSF_ALL
);
934 ok(rc
==MMSYSERR_NOERROR
,
935 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
936 "MMSYSERR_NOERROR expected, got %s\n",
938 if (rc
==MMSYSERR_NOERROR
) {
939 for(nc
=0;nc
<mixerlineW
.cControls
;nc
++) {
940 if (winetest_interactive
) {
941 WideCharToMultiByte(CP_ACP
,0,array
[nc
].szShortName
,
942 MIXER_SHORT_NAME_CHARS
,szShortName
,
943 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
944 WideCharToMultiByte(CP_ACP
,0,array
[nc
].szName
,
945 MIXER_LONG_NAME_CHARS
,szName
,
946 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
947 trace(" %d: \"%s\" (%s) ControlID=%d\n", nc
,
948 szShortName
, szName
, array
[nc
].dwControlID
);
949 trace(" ControlType=%s\n",
950 control_type(array
[nc
].dwControlType
));
951 trace(" Control=0x%08x(%s)\n",
952 array
[nc
].fdwControl
,
953 control_flags(array
[nc
].fdwControl
));
954 trace(" Items=%d Min=%d Max=%d Step=%d\n",
955 array
[nc
].cMultipleItems
,
956 S1(array
[nc
].Bounds
).dwMinimum
,
957 S1(array
[nc
].Bounds
).dwMaximum
,
958 array
[nc
].Metrics
.cSteps
);
960 mixer_test_controlW(mix
, &array
[nc
]);
964 HeapFree(GetProcessHeap(),0,array
);
970 test_mixerClose((HMIXER
)mix
);
974 static void mixer_testsA(void)
980 trace("--- Testing ASCII functions ---\n");
982 ndev
=mixerGetNumDevs();
983 trace("found %d Mixer devices\n",ndev
);
985 rc
=mixerGetDevCapsA(ndev
+1,&capsA
,sizeof(capsA
));
986 ok(rc
==MMSYSERR_BADDEVICEID
,
987 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
991 mixer_test_deviceA(d
);
994 static void mixer_testsW(void)
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
)
1012 for (d
=0;d
<ndev
;d
++)
1013 mixer_test_deviceW(d
);
1016 static void test_mixerOpen(void)
1023 ndev
= mixerGetNumDevs();
1025 /* Test mixerOpen with invalid device ID values. */
1026 rc
= mixerOpen(&mix
, ndev
+ 1, 0, 0, 0);
1027 ok(rc
== MMSYSERR_BADDEVICEID
,
1028 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1031 rc
= mixerOpen(&mix
, -1, 0, 0, 0);
1032 ok(rc
== MMSYSERR_BADDEVICEID
||
1033 rc
== MMSYSERR_INVALHANDLE
, /* NT4/W2K */
1034 "mixerOpen: MMSYSERR_BADDEVICEID or MMSYSERR_INVALHANDLE expected, got %s\n",
1037 for (d
= 0; d
< ndev
; d
++) {
1038 /* Test mixerOpen with valid device ID values and invalid parameters. */
1039 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_FUNCTION
);
1040 ok(rc
== MMSYSERR_INVALFLAG
1041 || rc
== MMSYSERR_NOTSUPPORTED
, /* 98/ME */
1042 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n",
1045 rc
= mixerOpen(&mix
, d
, 0xdeadbeef, 0, CALLBACK_WINDOW
);
1046 ok(rc
== MMSYSERR_INVALPARAM
||
1047 broken(rc
== MMSYSERR_NOERROR
/* 98 */),
1048 "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n",
1050 if (rc
== MMSYSERR_NOERROR
)
1051 test_mixerClose(mix
);
1053 /* Test mixerOpen with a NULL dwCallback and CALLBACK_WINDOW flag. */
1054 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_WINDOW
);
1055 ok(rc
== MMSYSERR_NOERROR
,
1056 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1058 if (rc
== MMSYSERR_NOERROR
)
1059 test_mixerClose(mix
);
1061 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_THREAD
);
1062 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1063 rc
== MMSYSERR_NOTSUPPORTED
, /* 98 */
1064 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1066 if (rc
== MMSYSERR_NOERROR
)
1067 test_mixerClose(mix
);
1069 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_EVENT
);
1070 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1071 rc
== MMSYSERR_NOTSUPPORTED
, /* 98 */
1072 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1074 if (rc
== MMSYSERR_NOERROR
)
1075 test_mixerClose(mix
);
1077 event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1079 /* NOTSUPPORTED is not broken, but it enables the todo_wine marker. */
1080 rc
= mixerOpen(&mix
, d
, (DWORD_PTR
)event
, 0, CALLBACK_EVENT
);
1082 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1083 broken(rc
== MMSYSERR_NOTSUPPORTED
), /* 98 */
1084 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1086 if (rc
== MMSYSERR_NOERROR
)
1087 test_mixerClose(mix
);
1089 /* Test mixerOpen with normal parameters. */
1090 rc
= mixerOpen(&mix
, d
, 0, 0, 0);
1091 ok(rc
== MMSYSERR_NOERROR
,
1092 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1095 if (rc
== MMSYSERR_NOERROR
)
1096 test_mixerClose(mix
);
1098 rc
= WaitForSingleObject(event
, 0);
1099 ok(rc
== WAIT_TIMEOUT
, "WaitEvent %d\n", rc
);