2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/mmixer.c
5 * PURPOSE: Mixer Handling Functions
6 * PROGRAMMER: Johannes Anderwald
15 IN PMIXER_CONTEXT MixerContext
)
17 PMIXER_LIST MixerList
;
20 /* verify mixer context */
21 Status
= MMixerVerifyContext(MixerContext
);
23 if (Status
!= MM_STATUS_SUCCESS
)
25 /* invalid context passed */
30 MixerList
= (PMIXER_LIST
)MixerContext
->MixerContext
;
32 // return number of mixers
33 return MixerList
->MixerListCount
;
37 MMixerGetCapabilities(
38 IN PMIXER_CONTEXT MixerContext
,
40 OUT LPMIXERCAPSW MixerCaps
)
43 LPMIXER_INFO MixerInfo
;
45 /* verify mixer context */
46 Status
= MMixerVerifyContext(MixerContext
);
48 if (Status
!= MM_STATUS_SUCCESS
)
50 /* invalid context passed */
55 MixerInfo
= MMixerGetMixerInfoByIndex(MixerContext
, MixerIndex
);
59 // invalid device index
60 return MM_STATUS_INVALID_PARAMETER
;
63 MixerCaps
->wMid
= MixerInfo
->MixCaps
.wMid
;
64 MixerCaps
->wPid
= MixerInfo
->MixCaps
.wPid
;
65 MixerCaps
->vDriverVersion
= MixerInfo
->MixCaps
.vDriverVersion
;
66 MixerCaps
->fdwSupport
= MixerInfo
->MixCaps
.fdwSupport
;
67 MixerCaps
->cDestinations
= MixerInfo
->MixCaps
.cDestinations
;
69 ASSERT(MixerInfo
->MixCaps
.szPname
[MAXPNAMELEN
-1] == 0);
70 wcscpy(MixerCaps
->szPname
, MixerInfo
->MixCaps
.szPname
);
72 return MM_STATUS_SUCCESS
;
77 IN PMIXER_CONTEXT MixerContext
,
79 IN PVOID MixerEventContext
,
80 IN PMIXER_EVENT MixerEventRoutine
,
81 OUT PHANDLE MixerHandle
)
84 LPMIXER_INFO MixerInfo
;
86 /* verify mixer context */
87 Status
= MMixerVerifyContext(MixerContext
);
89 if (Status
!= MM_STATUS_SUCCESS
)
91 /* invalid context passed */
92 DPRINT1("invalid context\n");
97 MixerInfo
= (LPMIXER_INFO
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
100 /* invalid mixer id */
101 DPRINT1("invalid mixer id %lu\n", MixerId
);
102 return MM_STATUS_INVALID_PARAMETER
;
106 Status
= MMixerAddEvent(MixerContext
, MixerInfo
, MixerEventContext
, MixerEventRoutine
);
110 *MixerHandle
= (HANDLE
)MixerInfo
;
112 return MM_STATUS_SUCCESS
;
117 IN PMIXER_CONTEXT MixerContext
,
118 IN HANDLE MixerHandle
,
121 OUT LPMIXERLINEW MixerLine
)
124 LPMIXER_INFO MixerInfo
;
125 LPMIXERLINE_EXT MixerLineSrc
;
126 ULONG DestinationLineID
;
128 /* verify mixer context */
129 Status
= MMixerVerifyContext(MixerContext
);
131 if (Status
!= MM_STATUS_SUCCESS
)
133 /* invalid context passed */
136 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
138 /* caller passed mixer id */
139 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
143 /* invalid parameter */
144 return MM_STATUS_INVALID_PARAMETER
;
148 if (MixerLine
->cbStruct
!= sizeof(MIXERLINEW
))
150 DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW
), MixerLine
->cbStruct
);
151 return MM_STATUS_INVALID_PARAMETER
;
155 /* clear hmixer from flags */
156 Flags
&=~MIXER_OBJECTF_HMIXER
;
158 DPRINT1("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId
, Flags
);
160 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
162 /* cast to mixer info */
163 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
165 /* calculate destination line id */
166 DestinationLineID
= (MixerLine
->dwDestination
+ DESTINATION_LINE
);
168 /* get destination line */
169 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
171 if (MixerLineSrc
== NULL
)
173 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo
->MixCaps
.szPname
, MixerInfo
->MixCaps
.cDestinations
, MixerLine
->dwDestination
);
174 return MM_STATUS_UNSUCCESSFUL
;
176 /* copy mixer line */
177 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
179 /* make sure it is null terminated */
180 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
181 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
182 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
185 return MM_STATUS_SUCCESS
;
187 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
189 /* cast to mixer info */
190 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
192 /* calculate destination line id */
193 DestinationLineID
= (MixerLine
->dwDestination
+ DESTINATION_LINE
);
195 /* get destination line */
196 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
198 if (MixerLineSrc
== NULL
)
200 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo
->MixCaps
.szPname
, MixerInfo
->MixCaps
.cDestinations
, MixerLine
->dwDestination
);
201 return MM_STATUS_UNSUCCESSFUL
;
204 /* check if dwSource is out of bounds */
205 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
207 DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo
->MixCaps
.szPname
, MixerLineSrc
->Line
.szName
, MixerLineSrc
->Line
.cConnections
, MixerLine
->dwSource
);
208 return MM_STATUS_UNSUCCESSFUL
;
211 /* calculate destination line id */
212 DestinationLineID
= (MixerLine
->dwSource
* SOURCE_LINE
) + MixerLine
->dwDestination
;
214 DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo
->MixCaps
.szPname
, MixerInfo
->MixCaps
.cDestinations
,
215 MixerLineSrc
->Line
.szName
, MixerLineSrc
->Line
.cConnections
,
216 MixerLine
->dwSource
, MixerLine
->dwDestination
,
218 /* get target destination line id */
219 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
222 ASSERT(MixerLineSrc
);
224 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
226 /* copy mixer line */
227 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
229 /* make sure it is null terminated */
230 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
231 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
232 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
235 return MM_STATUS_SUCCESS
;
237 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
239 /* cast to mixer info */
240 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
242 /* try to find line */
243 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
246 /* invalid parameter */
247 DPRINT1("MMixerGetLineInfo: MixerName %S Line not found %lu\n", MixerInfo
->MixCaps
.szPname
, MixerLine
->dwLineID
);
248 return MM_STATUS_INVALID_PARAMETER
;
251 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
254 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
256 /* make sure it is null terminated */
257 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
258 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
259 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
261 return MM_STATUS_SUCCESS
;
263 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
265 /* cast to mixer info */
266 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
268 /* find mixer line by component type */
269 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
272 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
273 return MM_STATUS_UNSUCCESSFUL
;
276 /* copy mixer line */
277 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
279 /* make sure it is null terminated */
280 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
281 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
282 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
285 return MM_STATUS_SUCCESS
;
287 else if (Flags
== MIXER_GETLINEINFOF_TARGETTYPE
)
289 DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
293 DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags
);
296 return MM_STATUS_NOT_IMPLEMENTED
;
300 MMixerGetLineControls(
301 IN PMIXER_CONTEXT MixerContext
,
302 IN HANDLE MixerHandle
,
305 OUT LPMIXERLINECONTROLSW MixerLineControls
)
307 LPMIXER_INFO MixerInfo
;
308 LPMIXERLINE_EXT MixerLineSrc
;
309 LPMIXERCONTROLW MixerControl
;
313 /* verify mixer context */
314 Status
= MMixerVerifyContext(MixerContext
);
316 if (Status
!= MM_STATUS_SUCCESS
)
318 /* invalid context passed */
322 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
324 /* caller passed mixer id */
325 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
329 /* invalid parameter */
330 return MM_STATUS_INVALID_PARAMETER
;
334 Flags
&= ~MIXER_OBJECTF_HMIXER
;
336 DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId
, Flags
);
339 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
341 /* cast to mixer info */
342 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
344 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
348 /* invalid line id */
349 DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls
->dwLineID
);
350 return MM_STATUS_INVALID_PARAMETER
;
352 /* copy line control(s) */
353 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
355 return MM_STATUS_SUCCESS
;
357 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
359 /* cast to mixer info */
360 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
363 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
367 /* invalid line id */
368 DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls
->dwLineID
);
369 return MM_STATUS_INVALID_PARAMETER
;
373 ASSERT(MixerLineControls
->cControls
== 1);
374 ASSERT(MixerLineControls
->cbmxctrl
== sizeof(MIXERCONTROLW
));
375 ASSERT(MixerLineControls
->pamxctrl
!= NULL
);
378 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
380 DPRINT1("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
381 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
383 /* found a control with that type */
384 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
385 return MM_STATUS_SUCCESS
;
388 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
389 return MM_STATUS_UNSUCCESSFUL
;
391 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
393 /* cast to mixer info */
394 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
396 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
398 if (Status
!= MM_STATUS_SUCCESS
)
400 /* invalid parameter */
401 DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls
->dwLineID
);
402 return MM_STATUS_INVALID_PARAMETER
;
405 ASSERT(MixerLineControls
->cControls
== 1);
406 ASSERT(MixerLineControls
->cbmxctrl
== sizeof(MIXERCONTROLW
));
407 ASSERT(MixerLineControls
->pamxctrl
!= NULL
);
409 DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl
->dwControlID
, MixerControl
->dwControlType
, MixerControl
->szName
);
411 /* copy the controls */
412 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
413 MixerLineControls
->pamxctrl
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
414 MixerLineControls
->pamxctrl
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
416 return MM_STATUS_SUCCESS
;
419 return MM_STATUS_NOT_IMPLEMENTED
;
423 MMixerSetControlDetails(
424 IN PMIXER_CONTEXT MixerContext
,
425 IN HANDLE MixerHandle
,
428 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
432 LPMIXER_INFO MixerInfo
;
433 LPMIXERLINE_EXT MixerLine
;
434 LPMIXERCONTROLW MixerControl
;
436 /* verify mixer context */
437 Status
= MMixerVerifyContext(MixerContext
);
439 if (Status
!= MM_STATUS_SUCCESS
)
441 /* invalid context passed */
445 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
447 /* caller passed mixer id */
448 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
452 /* invalid parameter */
453 return MM_STATUS_INVALID_PARAMETER
;
458 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
460 /* get mixer control */
461 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
463 /* check for success */
464 if (Status
!= MM_STATUS_SUCCESS
)
466 /* failed to find control id */
467 return MM_STATUS_INVALID_PARAMETER
;
470 switch(MixerControl
->dwControlType
)
472 case MIXERCONTROL_CONTROLTYPE_MUTE
:
473 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
475 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
476 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
479 Status
= MM_STATUS_NOT_IMPLEMENTED
;
486 MMixerGetControlDetails(
487 IN PMIXER_CONTEXT MixerContext
,
488 IN HANDLE MixerHandle
,
491 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
495 LPMIXER_INFO MixerInfo
;
496 LPMIXERLINE_EXT MixerLine
;
497 LPMIXERCONTROLW MixerControl
;
499 /* verify mixer context */
500 Status
= MMixerVerifyContext(MixerContext
);
502 if (Status
!= MM_STATUS_SUCCESS
)
504 /* invalid context passed */
508 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
510 /* caller passed mixer id */
511 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
515 /* invalid parameter */
516 return MM_STATUS_INVALID_PARAMETER
;
521 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
523 /* get mixer control */
524 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
526 /* check for success */
527 if (Status
!= MM_STATUS_SUCCESS
)
529 /* failed to find control id */
530 return MM_STATUS_INVALID_PARAMETER
;
533 switch(MixerControl
->dwControlType
)
535 case MIXERCONTROL_CONTROLTYPE_MUTE
:
536 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
538 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
539 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
542 Status
= MM_STATUS_NOT_IMPLEMENTED
;
550 IN PMIXER_CONTEXT MixerContext
,
551 IN PMIXER_LIST MixerList
)
553 ULONG Index
, SubIndex
, DestinationLineID
;
554 LPMIXER_INFO MixerInfo
;
555 LPMIXERLINE_EXT DstMixerLine
;
557 DPRINT1("MixerList %p\n", MixerList
);
558 DPRINT1("MidiInCount %lu\n", MixerList
->MidiInListCount
);
559 DPRINT1("MidiOutCount %lu\n", MixerList
->MidiOutListCount
);
560 DPRINT1("WaveInCount %lu\n", MixerList
->WaveInListCount
);
561 DPRINT1("WaveOutCount %lu\n", MixerList
->WaveOutListCount
);
562 DPRINT1("MixerCount %p\n", MixerList
->MixerListCount
);
565 for(Index
= 0; Index
< MixerList
->MixerListCount
; Index
++)
568 MixerInfo
= MMixerGetMixerInfoByIndex(MixerContext
, Index
);
572 DPRINT1("Name :%S\n", MixerInfo
->MixCaps
.szPname
);
573 DPRINT1("cDestinations: %lu\n", MixerInfo
->MixCaps
.cDestinations
);
574 DPRINT1("fdwSupport %lu\n", MixerInfo
->MixCaps
.fdwSupport
);
575 DPRINT1("vDriverVersion %lx\n", MixerInfo
->MixCaps
.vDriverVersion
);
576 DPRINT1("wMid %lx\n", MixerInfo
->MixCaps
.wMid
);
577 DPRINT1("wPid %lx\n", MixerInfo
->MixCaps
.wPid
);
579 for(SubIndex
= 0; SubIndex
< MixerInfo
->MixCaps
.cDestinations
; SubIndex
++)
581 /* calculate destination line id */
582 DestinationLineID
= (SubIndex
+ DESTINATION_LINE
);
584 /* get destination line */
585 DstMixerLine
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
587 DPRINT1("cChannels %lu\n", DstMixerLine
->Line
.cChannels
);
588 DPRINT1("cConnections %lu\n", DstMixerLine
->Line
.cConnections
);
589 DPRINT1("cControls %lu\n", DstMixerLine
->Line
.cControls
);
590 DPRINT1("dwComponentType %lx\n", DstMixerLine
->Line
.dwComponentType
);
591 DPRINT1("dwDestination %lu\n", DstMixerLine
->Line
.dwDestination
);
592 DPRINT1("dwLineID %lx\n", DstMixerLine
->Line
.dwLineID
);
593 DPRINT1("dwSource %lx\n", DstMixerLine
->Line
.dwSource
);
594 DPRINT1("dwUser %lu\n", DstMixerLine
->Line
.dwUser
);
595 DPRINT1("fdwLine %lu\n", DstMixerLine
->Line
.fdwLine
);
596 DPRINT1("szName %S\n", DstMixerLine
->Line
.szName
);
597 DPRINT1("szShortName %S\n", DstMixerLine
->Line
.szShortName
);
598 DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine
->Line
.Target
.dwDeviceID
);
599 DPRINT1("Target.dwType %lu\n", DstMixerLine
->Line
.Target
.dwType
);
600 DPRINT1("Target.szName %S\n", DstMixerLine
->Line
.Target
.szPname
);
601 DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine
->Line
.Target
.vDriverVersion
);
602 DPRINT1("Target.wMid %lx\n", DstMixerLine
->Line
.Target
.wMid
);
603 DPRINT1("Target.wPid %lx\n", DstMixerLine
->Line
.Target
.wPid
);
610 IN PMIXER_CONTEXT MixerContext
,
611 IN PMIXER_ENUM EnumFunction
,
612 IN PVOID EnumContext
)
616 ULONG DeviceIndex
, Count
;
618 LPMIXER_DATA MixerData
;
619 PMIXER_LIST MixerList
;
622 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
624 /* invalid parameter */
625 return MM_STATUS_INVALID_PARAMETER
;
628 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
629 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
630 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
632 /* invalid parameter */
633 return MM_STATUS_INVALID_PARAMETER
;
636 /* allocate a mixer list */
637 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
641 return MM_STATUS_NO_MEMORY
;
644 /* initialize mixer list */
645 MixerList
->MixerListCount
= 0;
646 MixerList
->MixerDataCount
= 0;
647 MixerList
->WaveInListCount
= 0;
648 MixerList
->WaveOutListCount
= 0;
649 MixerList
->MidiInListCount
= 0;
650 MixerList
->MidiOutListCount
= 0;
651 InitializeListHead(&MixerList
->MixerList
);
652 InitializeListHead(&MixerList
->MixerData
);
653 InitializeListHead(&MixerList
->WaveInList
);
654 InitializeListHead(&MixerList
->WaveOutList
);
655 InitializeListHead(&MixerList
->MidiInList
);
656 InitializeListHead(&MixerList
->MidiOutList
);
658 /* store mixer list */
659 MixerContext
->MixerContext
= (PVOID
)MixerList
;
661 /* start enumerating all available devices */
667 /* enumerate a device */
668 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
670 if (Status
!= MM_STATUS_SUCCESS
)
672 /* check error code */
673 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
675 /* enumeration has finished */
680 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex
);
688 /* create a mixer data entry */
689 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
690 if (Status
!= MM_STATUS_SUCCESS
)
694 /* increment device index */
698 /* now all filters have been pre-opened
699 * lets enumerate the filters
701 Entry
= MixerList
->MixerData
.Flink
;
702 while(Entry
!= &MixerList
->MixerData
)
704 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
705 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
706 Entry
= Entry
->Flink
;
709 MMixerPrintMixers(MixerContext
, MixerList
);
712 return MM_STATUS_SUCCESS
;