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 BOOL
compare_uint(unsigned int x
, unsigned int y
, unsigned int max_diff
)
41 unsigned int diff
= x
> y
? x
- y
: y
- x
;
42 return diff
<= max_diff
;
45 static const char * line_flags(DWORD fdwLine
)
47 static char flags
[100];
50 if (fdwLine
&MIXERLINE_LINEF_ACTIVE
) {
51 strcat(flags
,"MIXERLINE_LINEF_ACTIVE");
54 if (fdwLine
&MIXERLINE_LINEF_DISCONNECTED
) {
58 strcat(flags
,"MIXERLINE_LINEF_DISCONNECTED");
62 if (fdwLine
&MIXERLINE_LINEF_SOURCE
) {
66 strcat(flags
,"MIXERLINE_LINEF_SOURCE");
72 static const char * component_type(DWORD dwComponentType
)
74 #define TYPE_TO_STR(x) case x: return #x
75 switch (dwComponentType
) {
76 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_UNDEFINED
);
77 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_DIGITAL
);
78 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_LINE
);
79 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_MONITOR
);
80 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
);
81 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_HEADPHONES
);
82 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_TELEPHONE
);
83 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_WAVEIN
);
84 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_DST_VOICEIN
);
85 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED
);
86 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_DIGITAL
);
87 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_LINE
);
88 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
);
89 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
);
90 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
);
91 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE
);
92 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER
);
93 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
);
94 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY
);
95 TYPE_TO_STR(MIXERLINE_COMPONENTTYPE_SRC_ANALOG
);
101 static const char * target_type(DWORD dwType
)
103 #define TYPE_TO_STR(x) case x: return #x
105 TYPE_TO_STR(MIXERLINE_TARGETTYPE_UNDEFINED
);
106 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEOUT
);
107 TYPE_TO_STR(MIXERLINE_TARGETTYPE_WAVEIN
);
108 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIOUT
);
109 TYPE_TO_STR(MIXERLINE_TARGETTYPE_MIDIIN
);
110 TYPE_TO_STR(MIXERLINE_TARGETTYPE_AUX
);
116 static const char * control_type(DWORD dwControlType
)
118 #define TYPE_TO_STR(x) case x: return #x
119 switch (dwControlType
) {
120 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_CUSTOM
);
121 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER
);
122 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER
);
123 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PEAKMETER
);
124 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER
);
125 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BOOLEAN
);
126 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_ONOFF
);
127 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUTE
);
128 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MONO
);
129 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_LOUDNESS
);
130 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_STEREOENH
);
131 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS_BOOST
);
132 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BUTTON
);
133 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_DECIBELS
);
134 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SIGNED
);
135 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_UNSIGNED
);
136 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PERCENT
);
137 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SLIDER
);
138 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_PAN
);
139 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN
);
140 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_FADER
);
141 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_VOLUME
);
142 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_BASS
);
143 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_TREBLE
);
144 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_EQUALIZER
);
145 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_SINGLESELECT
);
146 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MUX
);
147 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT
);
148 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MIXER
);
149 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MICROTIME
);
150 TYPE_TO_STR(MIXERCONTROL_CONTROLTYPE_MILLITIME
);
156 static const char * control_flags(DWORD fdwControl
)
158 static char flags
[100];
161 if (fdwControl
&MIXERCONTROL_CONTROLF_UNIFORM
) {
162 strcat(flags
,"MIXERCONTROL_CONTROLF_UNIFORM");
165 if (fdwControl
&MIXERCONTROL_CONTROLF_MULTIPLE
) {
169 strcat(flags
,"MIXERCONTROL_CONTROLF_MULTIPLE");
173 if (fdwControl
&MIXERCONTROL_CONTROLF_DISABLED
) {
177 strcat(flags
,"MIXERCONTROL_CONTROLF_DISABLED");
183 static void test_mixerClose(HMIXER mix
)
187 rc
= mixerClose(mix
);
188 ok(rc
== MMSYSERR_NOERROR
|| rc
== MMSYSERR_INVALHANDLE
,
189 "mixerClose: MMSYSERR_NOERROR or MMSYSERR_INVALHANDLE expected, got %s\n",
193 static void mixer_test_controlA(HMIXEROBJ mix
, MIXERCONTROLA
*control
)
197 if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_VOLUME
) ||
198 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_UNSIGNED
)) {
199 MIXERCONTROLDETAILS details
;
200 MIXERCONTROLDETAILS_UNSIGNED value
;
202 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
203 details
.dwControlID
= control
->dwControlID
;
204 details
.cChannels
= 1;
205 U(details
).cMultipleItems
= 0;
206 details
.cbDetails
= sizeof(value
);
208 /* test NULL paDetails */
209 details
.paDetails
= NULL
;
210 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
211 ok(rc
==MMSYSERR_INVALPARAM
,
212 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
215 /* read the current control value */
216 details
.paDetails
= &value
;
217 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
218 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
219 "MMSYSERR_NOERROR expected, got %s\n",
221 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
222 MIXERCONTROLDETAILS new_details
;
223 MIXERCONTROLDETAILS_UNSIGNED new_value
;
225 trace(" Value=%ld\n",value
.dwValue
);
227 if (value
.dwValue
+ control
->Metrics
.cSteps
< S1(control
->Bounds
).dwMaximum
)
228 new_value
.dwValue
= value
.dwValue
+ control
->Metrics
.cSteps
;
230 new_value
.dwValue
= value
.dwValue
- control
->Metrics
.cSteps
;
232 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
233 new_details
.dwControlID
= control
->dwControlID
;
234 new_details
.cChannels
= 1;
235 U(new_details
).cMultipleItems
= 0;
236 new_details
.paDetails
= &new_value
;
237 new_details
.cbDetails
= sizeof(new_value
);
239 /* change the control value by one step */
240 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
241 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
242 "MMSYSERR_NOERROR expected, got %s\n",
244 if (rc
==MMSYSERR_NOERROR
) {
245 MIXERCONTROLDETAILS ret_details
;
246 MIXERCONTROLDETAILS_UNSIGNED ret_value
;
248 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
249 ret_details
.dwControlID
= control
->dwControlID
;
250 ret_details
.cChannels
= 1;
251 U(ret_details
).cMultipleItems
= 0;
252 ret_details
.paDetails
= &ret_value
;
253 ret_details
.cbDetails
= sizeof(ret_value
);
255 /* read back the new control value */
256 rc
= mixerGetControlDetailsA(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
257 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
258 "MMSYSERR_NOERROR expected, got %s\n",
260 if (rc
==MMSYSERR_NOERROR
) {
261 /* result may not match exactly because of rounding */
262 ok(compare_uint(ret_value
.dwValue
, new_value
.dwValue
, 1),
263 "Couldn't change value from %ld to %ld, returned %ld\n",
264 value
.dwValue
,new_value
.dwValue
,ret_value
.dwValue
);
266 if (compare_uint(ret_value
.dwValue
, new_value
.dwValue
, 1)) {
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 /* restore original value */
275 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
276 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
277 "MMSYSERR_NOERROR expected, got %s\n",
283 } else if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUTE
) ||
284 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BOOLEAN
) ||
285 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BUTTON
)) {
286 MIXERCONTROLDETAILS details
;
287 MIXERCONTROLDETAILS_BOOLEAN value
;
289 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
290 details
.dwControlID
= control
->dwControlID
;
291 details
.cChannels
= 1;
292 U(details
).cMultipleItems
= 0;
293 details
.paDetails
= &value
;
294 details
.cbDetails
= sizeof(value
);
296 rc
= mixerGetControlDetailsA(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
297 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
298 "MMSYSERR_NOERROR expected, got %s\n",
300 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
301 MIXERCONTROLDETAILS new_details
;
302 MIXERCONTROLDETAILS_BOOLEAN new_value
;
304 trace(" Value=%ld\n",value
.fValue
);
306 if (value
.fValue
== FALSE
)
307 new_value
.fValue
= TRUE
;
309 new_value
.fValue
= FALSE
;
311 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
312 new_details
.dwControlID
= control
->dwControlID
;
313 new_details
.cChannels
= 1;
314 U(new_details
).cMultipleItems
= 0;
315 new_details
.paDetails
= &new_value
;
316 new_details
.cbDetails
= sizeof(new_value
);
318 /* change the control value by one step */
319 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
320 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
321 "MMSYSERR_NOERROR expected, got %s\n",
323 if (rc
==MMSYSERR_NOERROR
) {
324 MIXERCONTROLDETAILS ret_details
;
325 MIXERCONTROLDETAILS_BOOLEAN ret_value
;
327 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
328 ret_details
.dwControlID
= control
->dwControlID
;
329 ret_details
.cChannels
= 1;
330 U(ret_details
).cMultipleItems
= 0;
331 ret_details
.paDetails
= &ret_value
;
332 ret_details
.cbDetails
= sizeof(ret_value
);
334 /* read back the new control value */
335 rc
= mixerGetControlDetailsA(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
336 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
337 "MMSYSERR_NOERROR expected, got %s\n",
339 if (rc
==MMSYSERR_NOERROR
) {
340 /* result may not match exactly because of rounding */
341 ok(ret_value
.fValue
==new_value
.fValue
,
342 "Couldn't change value from %ld to %ld, returned %ld\n",
343 value
.fValue
,new_value
.fValue
,ret_value
.fValue
);
345 if (ret_value
.fValue
==new_value
.fValue
) {
346 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
347 details
.dwControlID
= control
->dwControlID
;
348 details
.cChannels
= 1;
349 U(details
).cMultipleItems
= 0;
350 details
.paDetails
= &value
;
351 details
.cbDetails
= sizeof(value
);
353 /* restore original value */
354 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
355 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
356 "MMSYSERR_NOERROR expected, got %s\n",
367 static void mixer_test_deviceA(int device
)
374 rc
=mixerGetDevCapsA(device
,0,sizeof(capsA
));
375 ok(rc
==MMSYSERR_INVALPARAM
,
376 "mixerGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",
379 rc
=mixerGetDevCapsA(device
,&capsA
,4);
380 ok(rc
==MMSYSERR_NOERROR
,
381 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
384 rc
=mixerGetDevCapsA(device
,&capsA
,sizeof(capsA
));
385 ok(rc
==MMSYSERR_NOERROR
,
386 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
389 if (winetest_interactive
) {
390 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%ld\n", device
,
391 capsA
.szPname
, capsA
.vDriverVersion
>> 8,
392 capsA
.vDriverVersion
& 0xff,capsA
.wMid
,capsA
.wPid
,
393 capsA
.cDestinations
);
395 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device
,
396 capsA
.szPname
, capsA
.vDriverVersion
>> 8,
397 capsA
.vDriverVersion
& 0xff,capsA
.wMid
,capsA
.wPid
);
400 rc
= mixerOpen((HMIXER
*)&mix
, device
, 0, 0, 0);
401 ok(rc
==MMSYSERR_NOERROR
,
402 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc
));
403 if (rc
==MMSYSERR_NOERROR
) {
406 rc
=mixerGetDevCapsA((UINT_PTR
)mix
,&capsA2
,sizeof(capsA2
));
407 ok(rc
==MMSYSERR_NOERROR
,
408 "mixerGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",
410 ok(!strcmp(capsA2
.szPname
, capsA
.szPname
), "Got wrong device caps\n");
412 for (d
=0;d
<capsA
.cDestinations
;d
++) {
413 MIXERLINEA mixerlineA
;
414 mixerlineA
.cbStruct
= 0;
415 mixerlineA
.dwDestination
=d
;
416 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
417 ok(rc
==MMSYSERR_INVALPARAM
,
418 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
419 "MMSYSERR_INVALPARAM expected, got %s\n",
422 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
423 mixerlineA
.dwDestination
=capsA
.cDestinations
;
424 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
425 ok(rc
==MMSYSERR_INVALPARAM
||rc
==MIXERR_INVALLINE
,
426 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
427 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
430 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
431 mixerlineA
.dwDestination
=d
;
432 rc
= mixerGetLineInfoA(mix
, 0, MIXER_GETLINEINFOF_DESTINATION
);
433 ok(rc
==MMSYSERR_INVALPARAM
,
434 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
435 "MMSYSERR_INVALPARAM expected, got %s\n",
438 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
439 mixerlineA
.dwDestination
=d
;
440 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, -1);
441 ok(rc
==MMSYSERR_INVALFLAG
,
442 "mixerGetLineInfoA(-1): MMSYSERR_INVALFLAG expected, got %s\n",
445 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
446 mixerlineA
.dwDestination
=d
;
447 mixerlineA
.dwUser
= (ULONG_PTR
)0xdeadbeef;
448 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_DESTINATION
);
449 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
450 "mixerGetLineInfoA(MIXER_GETLINEINFOF_DESTINATION): "
451 "MMSYSERR_NOERROR expected, got %s\n",
453 ok(mixerlineA
.dwUser
== 0, "dwUser was not reset\n");
454 if (rc
==MMSYSERR_NODRIVER
)
455 trace(" No Driver\n");
456 else if (rc
==MMSYSERR_NOERROR
) {
457 if (winetest_interactive
) {
458 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
459 d
,mixerlineA
.szShortName
, mixerlineA
.szName
,
460 mixerlineA
.dwDestination
,mixerlineA
.dwSource
);
461 trace(" LineID=%08lx Channels=%ld "
462 "Connections=%ld Controls=%ld\n",
463 mixerlineA
.dwLineID
,mixerlineA
.cChannels
,
464 mixerlineA
.cConnections
,mixerlineA
.cControls
);
465 trace(" State=0x%08lx(%s)\n",
466 mixerlineA
.fdwLine
,line_flags(mixerlineA
.fdwLine
));
467 trace(" ComponentType=%s\n",
468 component_type(mixerlineA
.dwComponentType
));
470 target_type(mixerlineA
.Target
.dwType
));
471 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
472 mixerlineA
.Target
.dwDeviceID
,
473 mixerlineA
.Target
.szPname
,
474 mixerlineA
.Target
.vDriverVersion
>> 8,
475 mixerlineA
.Target
.vDriverVersion
& 0xff,
476 mixerlineA
.Target
.wMid
, mixerlineA
.Target
.wPid
);
478 ns
=mixerlineA
.cConnections
;
480 mixerlineA
.cbStruct
= sizeof(mixerlineA
);
481 mixerlineA
.dwDestination
=d
;
482 mixerlineA
.dwSource
=s
;
483 rc
= mixerGetLineInfoA(mix
, &mixerlineA
, MIXER_GETLINEINFOF_SOURCE
);
484 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
485 "mixerGetLineInfoA(MIXER_GETLINEINFOF_SOURCE): "
486 "MMSYSERR_NOERROR expected, got %s\n",
488 if (rc
==MMSYSERR_NODRIVER
)
489 trace(" No Driver\n");
490 else if (rc
==MMSYSERR_NOERROR
) {
491 LPMIXERCONTROLA array
;
492 MIXERLINECONTROLSA controls
;
493 if (winetest_interactive
) {
494 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
495 s
,mixerlineA
.szShortName
, mixerlineA
.szName
,
496 mixerlineA
.dwDestination
,mixerlineA
.dwSource
);
497 trace(" LineID=%08lx Channels=%ld "
498 "Connections=%ld Controls=%ld\n",
499 mixerlineA
.dwLineID
,mixerlineA
.cChannels
,
500 mixerlineA
.cConnections
,mixerlineA
.cControls
);
501 trace(" State=0x%08lx(%s)\n",
502 mixerlineA
.fdwLine
,line_flags(mixerlineA
.fdwLine
));
503 trace(" ComponentType=%s\n",
504 component_type(mixerlineA
.dwComponentType
));
506 target_type(mixerlineA
.Target
.dwType
));
507 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
508 mixerlineA
.Target
.dwDeviceID
,
509 mixerlineA
.Target
.szPname
,
510 mixerlineA
.Target
.vDriverVersion
>> 8,
511 mixerlineA
.Target
.vDriverVersion
& 0xff,
512 mixerlineA
.Target
.wMid
, mixerlineA
.Target
.wPid
);
514 if (mixerlineA
.cControls
) {
515 array
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
516 mixerlineA
.cControls
*sizeof(MIXERCONTROLA
));
518 memset(&controls
, 0, sizeof(controls
));
520 rc
= mixerGetLineControlsA(mix
, 0, MIXER_GETLINECONTROLSF_ALL
);
521 ok(rc
==MMSYSERR_INVALPARAM
,
522 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
523 "MMSYSERR_INVALPARAM expected, got %s\n",
526 rc
= mixerGetLineControlsA(mix
, &controls
, -1);
527 ok(rc
==MMSYSERR_INVALFLAG
||rc
==MMSYSERR_INVALPARAM
,
528 "mixerGetLineControlsA(-1): "
529 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
532 controls
.cbStruct
= sizeof(MIXERLINECONTROLSA
);
533 controls
.cControls
= mixerlineA
.cControls
;
534 controls
.dwLineID
= mixerlineA
.dwLineID
;
535 controls
.pamxctrl
= array
;
536 controls
.cbmxctrl
= sizeof(MIXERCONTROLA
);
538 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
539 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
541 rc
= mixerGetLineControlsA(mix
, &controls
, MIXER_GETLINECONTROLSF_ALL
);
542 ok(rc
==MMSYSERR_NOERROR
,
543 "mixerGetLineControlsA(MIXER_GETLINECONTROLSF_ALL): "
544 "MMSYSERR_NOERROR expected, got %s\n",
546 if (rc
==MMSYSERR_NOERROR
) {
547 for(nc
=0;nc
<mixerlineA
.cControls
;nc
++) {
548 if (winetest_interactive
) {
549 trace(" %ld: \"%s\" (%s) ControlID=%ld\n", nc
,
550 array
[nc
].szShortName
,
551 array
[nc
].szName
, array
[nc
].dwControlID
);
552 trace(" ControlType=%s\n",
553 control_type(array
[nc
].dwControlType
));
554 trace(" Control=0x%08lx(%s)\n",
555 array
[nc
].fdwControl
,
556 control_flags(array
[nc
].fdwControl
));
557 trace(" Items=%ld Min=%ld Max=%ld Step=%ld\n",
558 array
[nc
].cMultipleItems
,
559 S1(array
[nc
].Bounds
).dwMinimum
,
560 S1(array
[nc
].Bounds
).dwMaximum
,
561 array
[nc
].Metrics
.cSteps
);
564 mixer_test_controlA(mix
, &array
[nc
]);
568 HeapFree(GetProcessHeap(),0,array
);
575 test_mixerClose((HMIXER
)mix
);
579 static void mixer_test_controlW(HMIXEROBJ mix
, MIXERCONTROLW
*control
)
583 if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_VOLUME
) ||
584 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_UNSIGNED
)) {
585 MIXERCONTROLDETAILS details
;
586 MIXERCONTROLDETAILS_UNSIGNED value
;
588 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
589 details
.dwControlID
= control
->dwControlID
;
590 details
.cChannels
= 1;
591 U(details
).cMultipleItems
= 0;
592 details
.paDetails
= &value
;
593 details
.cbDetails
= sizeof(value
);
595 /* read the current control value */
596 rc
= mixerGetControlDetailsW(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
597 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
598 "MMSYSERR_NOERROR expected, got %s\n",
600 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
601 MIXERCONTROLDETAILS new_details
;
602 MIXERCONTROLDETAILS_UNSIGNED new_value
;
604 trace(" Value=%ld\n",value
.dwValue
);
606 if (value
.dwValue
+ control
->Metrics
.cSteps
< S1(control
->Bounds
).dwMaximum
)
607 new_value
.dwValue
= value
.dwValue
+ control
->Metrics
.cSteps
;
609 new_value
.dwValue
= value
.dwValue
- control
->Metrics
.cSteps
;
611 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
612 new_details
.dwControlID
= control
->dwControlID
;
613 new_details
.cChannels
= 1;
614 U(new_details
).cMultipleItems
= 0;
615 new_details
.paDetails
= &new_value
;
616 new_details
.cbDetails
= sizeof(new_value
);
618 /* change the control value by one step */
619 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
620 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
621 "MMSYSERR_NOERROR expected, got %s\n",
623 if (rc
==MMSYSERR_NOERROR
) {
624 MIXERCONTROLDETAILS ret_details
;
625 MIXERCONTROLDETAILS_UNSIGNED ret_value
;
627 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
628 ret_details
.dwControlID
= control
->dwControlID
;
629 ret_details
.cChannels
= 1;
630 U(ret_details
).cMultipleItems
= 0;
631 ret_details
.paDetails
= &ret_value
;
632 ret_details
.cbDetails
= sizeof(ret_value
);
634 /* read back the new control value */
635 rc
= mixerGetControlDetailsW(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
636 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
637 "MMSYSERR_NOERROR expected, got %s\n",
639 if (rc
==MMSYSERR_NOERROR
) {
640 /* result may not match exactly because of rounding */
641 ok(compare_uint(ret_value
.dwValue
, new_value
.dwValue
, 1),
642 "Couldn't change value from %ld to %ld, returned %ld\n",
643 value
.dwValue
,new_value
.dwValue
,ret_value
.dwValue
);
645 if (compare_uint(ret_value
.dwValue
, new_value
.dwValue
, 1)) {
646 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
647 details
.dwControlID
= control
->dwControlID
;
648 details
.cChannels
= 1;
649 U(details
).cMultipleItems
= 0;
650 details
.paDetails
= &value
;
651 details
.cbDetails
= sizeof(value
);
653 /* restore original value */
654 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
655 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
656 "MMSYSERR_NOERROR expected, got %s\n",
662 } else if ((control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUTE
) ||
663 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BOOLEAN
) ||
664 (control
->dwControlType
== MIXERCONTROL_CONTROLTYPE_BUTTON
)) {
665 MIXERCONTROLDETAILS details
;
666 MIXERCONTROLDETAILS_BOOLEAN value
;
668 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
669 details
.dwControlID
= control
->dwControlID
;
670 details
.cChannels
= 1;
671 U(details
).cMultipleItems
= 0;
672 details
.paDetails
= &value
;
673 details
.cbDetails
= sizeof(value
);
675 rc
= mixerGetControlDetailsW(mix
, &details
, MIXER_GETCONTROLDETAILSF_VALUE
);
676 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
677 "MMSYSERR_NOERROR expected, got %s\n",
679 if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
680 MIXERCONTROLDETAILS new_details
;
681 MIXERCONTROLDETAILS_BOOLEAN new_value
;
683 trace(" Value=%ld\n",value
.fValue
);
685 if (value
.fValue
== FALSE
)
686 new_value
.fValue
= TRUE
;
688 new_value
.fValue
= FALSE
;
690 new_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
691 new_details
.dwControlID
= control
->dwControlID
;
692 new_details
.cChannels
= 1;
693 U(new_details
).cMultipleItems
= 0;
694 new_details
.paDetails
= &new_value
;
695 new_details
.cbDetails
= sizeof(new_value
);
697 /* change the control value by one step */
698 rc
= mixerSetControlDetails(mix
, &new_details
, MIXER_SETCONTROLDETAILSF_VALUE
);
699 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
700 "MMSYSERR_NOERROR expected, got %s\n",
702 if (rc
==MMSYSERR_NOERROR
) {
703 MIXERCONTROLDETAILS ret_details
;
704 MIXERCONTROLDETAILS_BOOLEAN ret_value
;
706 ret_details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
707 ret_details
.dwControlID
= control
->dwControlID
;
708 ret_details
.cChannels
= 1;
709 U(ret_details
).cMultipleItems
= 0;
710 ret_details
.paDetails
= &ret_value
;
711 ret_details
.cbDetails
= sizeof(ret_value
);
713 /* read back the new control value */
714 rc
= mixerGetControlDetailsW(mix
, &ret_details
, MIXER_GETCONTROLDETAILSF_VALUE
);
715 ok(rc
==MMSYSERR_NOERROR
,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): "
716 "MMSYSERR_NOERROR expected, got %s\n",
718 if (rc
==MMSYSERR_NOERROR
) {
719 /* result may not match exactly because of rounding */
720 ok(ret_value
.fValue
==new_value
.fValue
,
721 "Couldn't change value from %ld to %ld, returned %ld\n",
722 value
.fValue
,new_value
.fValue
,ret_value
.fValue
);
724 if (ret_value
.fValue
==new_value
.fValue
) {
725 details
.cbStruct
= sizeof(MIXERCONTROLDETAILS
);
726 details
.dwControlID
= control
->dwControlID
;
727 details
.cChannels
= 1;
728 U(details
).cMultipleItems
= 0;
729 details
.paDetails
= &value
;
730 details
.cbDetails
= sizeof(value
);
732 /* restore original value */
733 rc
= mixerSetControlDetails(mix
, &details
, MIXER_SETCONTROLDETAILSF_VALUE
);
734 ok(rc
==MMSYSERR_NOERROR
,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): "
735 "MMSYSERR_NOERROR expected, got %s\n",
746 static void mixer_test_deviceW(int device
)
752 char szShortName
[MIXER_SHORT_NAME_CHARS
];
753 char szName
[MIXER_LONG_NAME_CHARS
];
754 char szPname
[MAXPNAMELEN
];
756 rc
=mixerGetDevCapsW(device
,0,sizeof(capsW
));
757 ok(rc
==MMSYSERR_INVALPARAM
,
758 "mixerGetDevCapsW: MMSYSERR_INVALPARAM expected, got %s\n",
761 rc
=mixerGetDevCapsW(device
,&capsW
,4);
762 ok(rc
==MMSYSERR_NOERROR
||
763 rc
==MMSYSERR_INVALPARAM
, /* Vista and W2K8 */
764 "mixerGetDevCapsW: MMSYSERR_NOERROR or MMSYSERR_INVALPARAM expected, got %s\n",
767 rc
=mixerGetDevCapsW(device
,&capsW
,sizeof(capsW
));
768 ok(rc
==MMSYSERR_NOERROR
,
769 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
772 WideCharToMultiByte(CP_ACP
,0,capsW
.szPname
, MAXPNAMELEN
,szPname
,
773 MAXPNAMELEN
,NULL
,NULL
);
774 if (winetest_interactive
) {
775 trace(" %d: \"%s\" %d.%d (%d:%d) destinations=%ld\n", device
,
776 szPname
, capsW
.vDriverVersion
>> 8,
777 capsW
.vDriverVersion
& 0xff,capsW
.wMid
,capsW
.wPid
,
778 capsW
.cDestinations
);
780 trace(" %d: \"%s\" %d.%d (%d:%d)\n", device
,
781 szPname
, capsW
.vDriverVersion
>> 8,
782 capsW
.vDriverVersion
& 0xff,capsW
.wMid
,capsW
.wPid
);
786 rc
= mixerOpen((HMIXER
*)&mix
, device
, 0, 0, 0);
787 ok(rc
==MMSYSERR_NOERROR
,
788 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",mmsys_error(rc
));
789 if (rc
==MMSYSERR_NOERROR
) {
792 rc
=mixerGetDevCapsW((UINT_PTR
)mix
,&capsW2
,sizeof(capsW2
));
793 ok(rc
==MMSYSERR_NOERROR
,
794 "mixerGetDevCapsW: MMSYSERR_NOERROR expected, got %s\n",
796 ok(!lstrcmpW(capsW2
.szPname
, capsW
.szPname
), "Got wrong device caps\n");
798 for (d
=0;d
<capsW
.cDestinations
;d
++) {
799 MIXERLINEW mixerlineW
;
800 mixerlineW
.cbStruct
= 0;
801 mixerlineW
.dwDestination
=d
;
802 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
803 ok(rc
==MMSYSERR_INVALPARAM
,
804 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
805 "MMSYSERR_INVALPARAM expected, got %s\n",
808 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
809 mixerlineW
.dwDestination
=capsW
.cDestinations
;
810 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
811 ok(rc
==MMSYSERR_INVALPARAM
||rc
==MIXERR_INVALLINE
,
812 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
813 "MMSYSERR_INVALPARAM or MIXERR_INVALLINE expected, got %s\n",
816 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
817 mixerlineW
.dwDestination
=d
;
818 rc
= mixerGetLineInfoW(mix
, 0, MIXER_GETLINEINFOF_DESTINATION
);
819 ok(rc
==MMSYSERR_INVALPARAM
,
820 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
821 "MMSYSERR_INVALPARAM expected, got %s\n",
824 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
825 mixerlineW
.dwDestination
=d
;
826 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, -1);
827 ok(rc
==MMSYSERR_INVALFLAG
,
828 "mixerGetLineInfoW(-1): MMSYSERR_INVALFLAG expected, got %s\n",
831 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
832 mixerlineW
.dwDestination
=d
;
833 mixerlineW
.dwUser
= (ULONG_PTR
)0xdeadbeef;
834 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_DESTINATION
);
835 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
836 "mixerGetLineInfoW(MIXER_GETLINEINFOF_DESTINATION): "
837 "MMSYSERR_NOERROR expected, got %s\n",
839 ok(mixerlineW
.dwUser
== 0, "dwUser was not reset\n");
840 if (rc
==MMSYSERR_NODRIVER
)
841 trace(" No Driver\n");
842 else if (rc
==MMSYSERR_NOERROR
&& winetest_interactive
) {
843 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szShortName
,
844 MIXER_SHORT_NAME_CHARS
,szShortName
,
845 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
846 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szName
,
847 MIXER_LONG_NAME_CHARS
,szName
,
848 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
849 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.Target
.szPname
,
851 MAXPNAMELEN
,NULL
, NULL
);
852 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
853 d
,szShortName
,szName
,
854 mixerlineW
.dwDestination
,mixerlineW
.dwSource
);
855 trace(" LineID=%08lx Channels=%ld "
856 "Connections=%ld Controls=%ld\n",
857 mixerlineW
.dwLineID
,mixerlineW
.cChannels
,
858 mixerlineW
.cConnections
,mixerlineW
.cControls
);
859 trace(" State=0x%08lx(%s)\n",
860 mixerlineW
.fdwLine
,line_flags(mixerlineW
.fdwLine
));
861 trace(" ComponentType=%s\n",
862 component_type(mixerlineW
.dwComponentType
));
864 target_type(mixerlineW
.Target
.dwType
));
865 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
866 mixerlineW
.Target
.dwDeviceID
,szPname
,
867 mixerlineW
.Target
.vDriverVersion
>> 8,
868 mixerlineW
.Target
.vDriverVersion
& 0xff,
869 mixerlineW
.Target
.wMid
, mixerlineW
.Target
.wPid
);
871 ns
=mixerlineW
.cConnections
;
873 mixerlineW
.cbStruct
= sizeof(mixerlineW
);
874 mixerlineW
.dwDestination
=d
;
875 mixerlineW
.dwSource
=s
;
876 rc
= mixerGetLineInfoW(mix
, &mixerlineW
, MIXER_GETLINEINFOF_SOURCE
);
877 ok(rc
==MMSYSERR_NOERROR
||rc
==MMSYSERR_NODRIVER
,
878 "mixerGetLineInfoW(MIXER_GETLINEINFOF_SOURCE): "
879 "MMSYSERR_NOERROR expected, got %s\n",
881 if (rc
==MMSYSERR_NODRIVER
)
882 trace(" No Driver\n");
883 else if (rc
==MMSYSERR_NOERROR
) {
884 LPMIXERCONTROLW array
;
885 MIXERLINECONTROLSW controls
;
886 if (winetest_interactive
) {
887 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szShortName
,
888 MIXER_SHORT_NAME_CHARS
,szShortName
,
889 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
890 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.szName
,
891 MIXER_LONG_NAME_CHARS
,szName
,
892 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
893 WideCharToMultiByte(CP_ACP
,0,mixerlineW
.Target
.szPname
,
895 MAXPNAMELEN
,NULL
, NULL
);
896 trace(" %ld: \"%s\" (%s) Destination=%ld Source=%ld\n",
897 s
,szShortName
,szName
,
898 mixerlineW
.dwDestination
,mixerlineW
.dwSource
);
899 trace(" LineID=%08lx Channels=%ld "
900 "Connections=%ld Controls=%ld\n",
901 mixerlineW
.dwLineID
,mixerlineW
.cChannels
,
902 mixerlineW
.cConnections
,mixerlineW
.cControls
);
903 trace(" State=0x%08lx(%s)\n",
904 mixerlineW
.fdwLine
,line_flags(mixerlineW
.fdwLine
));
905 trace(" ComponentType=%s\n",
906 component_type(mixerlineW
.dwComponentType
));
908 target_type(mixerlineW
.Target
.dwType
));
909 trace(" Device=%ld (%s) %d.%d (%d:%d)\n",
910 mixerlineW
.Target
.dwDeviceID
,szPname
,
911 mixerlineW
.Target
.vDriverVersion
>> 8,
912 mixerlineW
.Target
.vDriverVersion
& 0xff,
913 mixerlineW
.Target
.wMid
, mixerlineW
.Target
.wPid
);
915 if (mixerlineW
.cControls
) {
916 array
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
917 mixerlineW
.cControls
*sizeof(MIXERCONTROLW
));
919 rc
= mixerGetLineControlsW(mix
, 0, MIXER_GETLINECONTROLSF_ALL
);
920 ok(rc
==MMSYSERR_INVALPARAM
,
921 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
922 "MMSYSERR_INVALPARAM expected, got %s\n",
924 rc
= mixerGetLineControlsW(mix
, &controls
, -1);
925 ok(rc
==MMSYSERR_INVALFLAG
||rc
==MMSYSERR_INVALPARAM
,
926 "mixerGetLineControlsW(-1): "
927 "MMSYSERR_INVALFLAG or MMSYSERR_INVALPARAM expected, got %s\n",
930 controls
.cbStruct
= sizeof(MIXERLINECONTROLSW
);
931 controls
.cControls
= mixerlineW
.cControls
;
932 controls
.dwLineID
= mixerlineW
.dwLineID
;
933 controls
.pamxctrl
= array
;
934 controls
.cbmxctrl
= sizeof(MIXERCONTROLW
);
936 /* FIXME: do MIXER_GETLINECONTROLSF_ONEBYID
937 * and MIXER_GETLINECONTROLSF_ONEBYTYPE
939 rc
= mixerGetLineControlsW(mix
, &controls
, MIXER_GETLINECONTROLSF_ALL
);
940 ok(rc
==MMSYSERR_NOERROR
,
941 "mixerGetLineControlsW(MIXER_GETLINECONTROLSF_ALL): "
942 "MMSYSERR_NOERROR expected, got %s\n",
944 if (rc
==MMSYSERR_NOERROR
) {
945 for(nc
=0;nc
<mixerlineW
.cControls
;nc
++) {
946 if (winetest_interactive
) {
947 WideCharToMultiByte(CP_ACP
,0,array
[nc
].szShortName
,
948 MIXER_SHORT_NAME_CHARS
,szShortName
,
949 MIXER_SHORT_NAME_CHARS
,NULL
,NULL
);
950 WideCharToMultiByte(CP_ACP
,0,array
[nc
].szName
,
951 MIXER_LONG_NAME_CHARS
,szName
,
952 MIXER_LONG_NAME_CHARS
,NULL
,NULL
);
953 trace(" %ld: \"%s\" (%s) ControlID=%ld\n", nc
,
954 szShortName
, szName
, array
[nc
].dwControlID
);
955 trace(" ControlType=%s\n",
956 control_type(array
[nc
].dwControlType
));
957 trace(" Control=0x%08lx(%s)\n",
958 array
[nc
].fdwControl
,
959 control_flags(array
[nc
].fdwControl
));
960 trace(" Items=%ld Min=%ld Max=%ld Step=%ld\n",
961 array
[nc
].cMultipleItems
,
962 S1(array
[nc
].Bounds
).dwMinimum
,
963 S1(array
[nc
].Bounds
).dwMaximum
,
964 array
[nc
].Metrics
.cSteps
);
966 mixer_test_controlW(mix
, &array
[nc
]);
970 HeapFree(GetProcessHeap(),0,array
);
976 test_mixerClose((HMIXER
)mix
);
980 static void mixer_testsA(void)
986 trace("--- Testing ANSI functions ---\n");
988 ndev
=mixerGetNumDevs();
989 trace("found %d Mixer devices\n",ndev
);
991 rc
=mixerGetDevCapsA(ndev
+1,&capsA
,sizeof(capsA
));
992 ok(rc
==MMSYSERR_BADDEVICEID
,
993 "mixerGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",
997 mixer_test_deviceA(d
);
1000 static void mixer_testsW(void)
1006 trace("--- Testing WCHAR functions ---\n");
1008 ndev
=mixerGetNumDevs();
1009 trace("found %d Mixer devices\n",ndev
);
1011 rc
=mixerGetDevCapsW(ndev
+1,&capsW
,sizeof(capsW
));
1012 ok(rc
==MMSYSERR_BADDEVICEID
||rc
==MMSYSERR_NOTSUPPORTED
,
1013 "mixerGetDevCapsW: MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1014 "expected, got %s\n", mmsys_error(rc
));
1015 if (rc
==MMSYSERR_NOTSUPPORTED
)
1018 for (d
=0;d
<ndev
;d
++)
1019 mixer_test_deviceW(d
);
1022 static void test_mixerOpen(void)
1029 ndev
= mixerGetNumDevs();
1031 /* Test mixerOpen with invalid device ID values. */
1032 rc
= mixerOpen(&mix
, ndev
+ 1, 0, 0, 0);
1033 ok(rc
== MMSYSERR_BADDEVICEID
,
1034 "mixerOpen: MMSYSERR_BADDEVICEID expected, got %s\n",
1037 rc
= mixerOpen(&mix
, -1, 0, 0, 0);
1038 ok(rc
== MMSYSERR_BADDEVICEID
||
1039 rc
== MMSYSERR_INVALHANDLE
, /* NT4/W2K */
1040 "mixerOpen: MMSYSERR_BADDEVICEID or MMSYSERR_INVALHANDLE expected, got %s\n",
1043 for (d
= 0; d
< ndev
; d
++) {
1044 /* Test mixerOpen with valid device ID values and invalid parameters. */
1045 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_FUNCTION
);
1046 ok(rc
== MMSYSERR_INVALFLAG
1047 || rc
== MMSYSERR_NOTSUPPORTED
, /* 98/ME */
1048 "mixerOpen: MMSYSERR_INVALFLAG expected, got %s\n",
1051 rc
= mixerOpen(&mix
, d
, 0xdeadbeef, 0, CALLBACK_WINDOW
);
1052 ok(rc
== MMSYSERR_INVALPARAM
||
1053 broken(rc
== MMSYSERR_NOERROR
/* 98 */),
1054 "mixerOpen: MMSYSERR_INVALPARAM expected, got %s\n",
1056 if (rc
== MMSYSERR_NOERROR
)
1057 test_mixerClose(mix
);
1059 /* Test mixerOpen with a NULL dwCallback and CALLBACK_WINDOW flag. */
1060 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_WINDOW
);
1061 ok(rc
== MMSYSERR_NOERROR
,
1062 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1064 if (rc
== MMSYSERR_NOERROR
)
1065 test_mixerClose(mix
);
1067 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_THREAD
);
1068 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1069 rc
== MMSYSERR_NOTSUPPORTED
, /* 98 */
1070 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1072 if (rc
== MMSYSERR_NOERROR
)
1073 test_mixerClose(mix
);
1075 rc
= mixerOpen(&mix
, d
, 0, 0, CALLBACK_EVENT
);
1076 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1077 rc
== MMSYSERR_NOTSUPPORTED
, /* 98 */
1078 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1080 if (rc
== MMSYSERR_NOERROR
)
1081 test_mixerClose(mix
);
1083 event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1085 /* NOTSUPPORTED is not broken, but it enables the todo_wine marker. */
1086 rc
= mixerOpen(&mix
, d
, (DWORD_PTR
)event
, 0, CALLBACK_EVENT
);
1088 ok(rc
== MMSYSERR_NOERROR
/* since w2k */ ||
1089 broken(rc
== MMSYSERR_NOTSUPPORTED
), /* 98 */
1090 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1092 if (rc
== MMSYSERR_NOERROR
)
1093 test_mixerClose(mix
);
1095 /* Test mixerOpen with normal parameters. */
1096 rc
= mixerOpen(&mix
, d
, 0, 0, 0);
1097 ok(rc
== MMSYSERR_NOERROR
,
1098 "mixerOpen: MMSYSERR_NOERROR expected, got %s\n",
1101 if (rc
== MMSYSERR_NOERROR
)
1102 test_mixerClose(mix
);
1104 rc
= WaitForSingleObject(event
, 0);
1105 ok(rc
== WAIT_TIMEOUT
, "WaitEvent %d\n", rc
);