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
* DESTINATION_LINE
) + MixerLine
->dwDestination
;
214 /* get target destination line id */
215 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
218 ASSERT(MixerLineSrc
);
220 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
222 /* copy mixer line */
223 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
225 /* make sure it is null terminated */
226 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
227 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
228 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
231 return MM_STATUS_SUCCESS
;
233 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
235 /* cast to mixer info */
236 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
238 /* try to find line */
239 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
242 /* invalid parameter */
243 DPRINT1("MixerName %S Line not found %lu\n", MixerInfo
->MixCaps
.szPname
, MixerLine
->dwLineID
);
244 return MM_STATUS_INVALID_PARAMETER
;
247 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
250 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
252 /* make sure it is null terminated */
253 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
254 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
255 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
257 return MM_STATUS_SUCCESS
;
259 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
261 /* cast to mixer info */
262 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
264 /* find mixer line by component type */
265 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
268 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
269 return MM_STATUS_UNSUCCESSFUL
;
272 /* copy mixer line */
273 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
275 /* make sure it is null terminated */
276 MixerLine
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
277 MixerLine
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
278 MixerLine
->Target
.szPname
[MAXPNAMELEN
-1] = L
'\0';
281 return MM_STATUS_SUCCESS
;
283 else if (Flags
== MIXER_GETLINEINFOF_TARGETTYPE
)
285 DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
289 DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags
);
292 return MM_STATUS_NOT_IMPLEMENTED
;
296 MMixerGetLineControls(
297 IN PMIXER_CONTEXT MixerContext
,
298 IN HANDLE MixerHandle
,
301 OUT LPMIXERLINECONTROLSW MixerLineControls
)
303 LPMIXER_INFO MixerInfo
;
304 LPMIXERLINE_EXT MixerLineSrc
;
305 LPMIXERCONTROLW MixerControl
;
309 /* verify mixer context */
310 Status
= MMixerVerifyContext(MixerContext
);
312 if (Status
!= MM_STATUS_SUCCESS
)
314 /* invalid context passed */
318 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
320 /* caller passed mixer id */
321 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
325 /* invalid parameter */
326 return MM_STATUS_INVALID_PARAMETER
;
330 Flags
&= ~MIXER_OBJECTF_HMIXER
;
332 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
334 /* cast to mixer info */
335 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
337 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
341 /* invalid line id */
342 return MM_STATUS_INVALID_PARAMETER
;
344 /* copy line control(s) */
345 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
347 return MM_STATUS_SUCCESS
;
349 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
351 /* cast to mixer info */
352 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
354 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
358 /* invalid line id */
359 return MM_STATUS_INVALID_PARAMETER
;
362 ASSERT(MixerLineSrc
);
365 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
367 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
368 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
370 /* found a control with that type */
371 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
372 return MM_STATUS_SUCCESS
;
375 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
376 return MM_STATUS_UNSUCCESSFUL
;
378 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
380 /* cast to mixer info */
381 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
383 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
385 if (Status
!= MM_STATUS_SUCCESS
)
387 /* invalid parameter */
388 return MM_STATUS_INVALID_PARAMETER
;
391 /* copy the controls */
392 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
393 return MM_STATUS_SUCCESS
;
397 return MM_STATUS_NOT_IMPLEMENTED
;
401 MMixerSetControlDetails(
402 IN PMIXER_CONTEXT MixerContext
,
403 IN HANDLE MixerHandle
,
406 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
410 LPMIXER_INFO MixerInfo
;
411 LPMIXERLINE_EXT MixerLine
;
412 LPMIXERCONTROLW MixerControl
;
414 /* verify mixer context */
415 Status
= MMixerVerifyContext(MixerContext
);
417 if (Status
!= MM_STATUS_SUCCESS
)
419 /* invalid context passed */
423 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
425 /* caller passed mixer id */
426 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
430 /* invalid parameter */
431 return MM_STATUS_INVALID_PARAMETER
;
436 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
438 /* get mixer control */
439 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
441 /* check for success */
442 if (Status
!= MM_STATUS_SUCCESS
)
444 /* failed to find control id */
445 return MM_STATUS_INVALID_PARAMETER
;
448 switch(MixerControl
->dwControlType
)
450 case MIXERCONTROL_CONTROLTYPE_MUTE
:
451 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
453 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
454 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
457 Status
= MM_STATUS_NOT_IMPLEMENTED
;
464 MMixerGetControlDetails(
465 IN PMIXER_CONTEXT MixerContext
,
466 IN HANDLE MixerHandle
,
469 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
473 LPMIXER_INFO MixerInfo
;
474 LPMIXERLINE_EXT MixerLine
;
475 LPMIXERCONTROLW MixerControl
;
477 /* verify mixer context */
478 Status
= MMixerVerifyContext(MixerContext
);
480 if (Status
!= MM_STATUS_SUCCESS
)
482 /* invalid context passed */
486 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
488 /* caller passed mixer id */
489 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
493 /* invalid parameter */
494 return MM_STATUS_INVALID_PARAMETER
;
499 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
501 /* get mixer control */
502 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
504 /* check for success */
505 if (Status
!= MM_STATUS_SUCCESS
)
507 /* failed to find control id */
508 return MM_STATUS_INVALID_PARAMETER
;
511 switch(MixerControl
->dwControlType
)
513 case MIXERCONTROL_CONTROLTYPE_MUTE
:
514 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
516 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
517 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
520 Status
= MM_STATUS_NOT_IMPLEMENTED
;
528 IN PMIXER_CONTEXT MixerContext
,
529 IN PMIXER_LIST MixerList
)
531 ULONG Index
, SubIndex
, DestinationLineID
;
532 LPMIXER_INFO MixerInfo
;
533 LPMIXERLINE_EXT DstMixerLine
;
535 DPRINT1("MixerList %p\n", MixerList
);
536 DPRINT1("MidiInCount %lu\n", MixerList
->MidiInListCount
);
537 DPRINT1("MidiOutCount %lu\n", MixerList
->MidiOutListCount
);
538 DPRINT1("WaveInCount %lu\n", MixerList
->WaveInListCount
);
539 DPRINT1("WaveOutCount %lu\n", MixerList
->WaveOutListCount
);
540 DPRINT1("MixerCount %p\n", MixerList
->MixerListCount
);
543 for(Index
= 0; Index
< MixerList
->MixerListCount
; Index
++)
546 MixerInfo
= MMixerGetMixerInfoByIndex(MixerContext
, Index
);
550 DPRINT1("Name :%S\n", MixerInfo
->MixCaps
.szPname
);
551 DPRINT1("cDestinations: %lu\n", MixerInfo
->MixCaps
.cDestinations
);
552 DPRINT1("fdwSupport %lu\n", MixerInfo
->MixCaps
.fdwSupport
);
553 DPRINT1("vDriverVersion %lx\n", MixerInfo
->MixCaps
.vDriverVersion
);
554 DPRINT1("wMid %lx\n", MixerInfo
->MixCaps
.wMid
);
555 DPRINT1("wPid %lx\n", MixerInfo
->MixCaps
.wPid
);
557 for(SubIndex
= 0; SubIndex
< MixerInfo
->MixCaps
.cDestinations
; SubIndex
++)
559 /* calculate destination line id */
560 DestinationLineID
= (SubIndex
+ DESTINATION_LINE
);
562 /* get destination line */
563 DstMixerLine
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DestinationLineID
);
565 DPRINT1("cChannels %lu\n", DstMixerLine
->Line
.cChannels
);
566 DPRINT1("cConnections %lu\n", DstMixerLine
->Line
.cConnections
);
567 DPRINT1("cControls %lu\n", DstMixerLine
->Line
.cControls
);
568 DPRINT1("dwComponentType %lx\n", DstMixerLine
->Line
.dwComponentType
);
569 DPRINT1("dwDestination %lu\n", DstMixerLine
->Line
.dwDestination
);
570 DPRINT1("dwLineID %lx\n", DstMixerLine
->Line
.dwLineID
);
571 DPRINT1("dwSource %lx\n", DstMixerLine
->Line
.dwSource
);
572 DPRINT1("dwUser %lu\n", DstMixerLine
->Line
.dwUser
);
573 DPRINT1("fdwLine %lu\n", DstMixerLine
->Line
.fdwLine
);
574 DPRINT1("szName %S\n", DstMixerLine
->Line
.szName
);
575 DPRINT1("szShortName %S\n", DstMixerLine
->Line
.szShortName
);
576 DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine
->Line
.Target
.dwDeviceID
);
577 DPRINT1("Target.dwType %lu\n", DstMixerLine
->Line
.Target
.dwType
);
578 DPRINT1("Target.szName %S\n", DstMixerLine
->Line
.Target
.szPname
);
579 DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine
->Line
.Target
.vDriverVersion
);
580 DPRINT1("Target.wMid %lx\n", DstMixerLine
->Line
.Target
.wMid
);
581 DPRINT1("Target.wPid %lx\n", DstMixerLine
->Line
.Target
.wPid
);
588 IN PMIXER_CONTEXT MixerContext
,
589 IN PMIXER_ENUM EnumFunction
,
590 IN PVOID EnumContext
)
594 ULONG DeviceIndex
, Count
;
596 LPMIXER_DATA MixerData
;
597 PMIXER_LIST MixerList
;
600 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
602 /* invalid parameter */
603 return MM_STATUS_INVALID_PARAMETER
;
606 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
607 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
608 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
610 /* invalid parameter */
611 return MM_STATUS_INVALID_PARAMETER
;
614 /* allocate a mixer list */
615 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
619 return MM_STATUS_NO_MEMORY
;
622 /* initialize mixer list */
623 MixerList
->MixerListCount
= 0;
624 MixerList
->MixerDataCount
= 0;
625 MixerList
->WaveInListCount
= 0;
626 MixerList
->WaveOutListCount
= 0;
627 MixerList
->MidiInListCount
= 0;
628 MixerList
->MidiOutListCount
= 0;
629 InitializeListHead(&MixerList
->MixerList
);
630 InitializeListHead(&MixerList
->MixerData
);
631 InitializeListHead(&MixerList
->WaveInList
);
632 InitializeListHead(&MixerList
->WaveOutList
);
633 InitializeListHead(&MixerList
->MidiInList
);
634 InitializeListHead(&MixerList
->MidiOutList
);
636 /* store mixer list */
637 MixerContext
->MixerContext
= (PVOID
)MixerList
;
639 /* start enumerating all available devices */
645 /* enumerate a device */
646 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
648 if (Status
!= MM_STATUS_SUCCESS
)
650 /* check error code */
651 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
653 /* enumeration has finished */
658 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex
);
666 /* create a mixer data entry */
667 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
668 if (Status
!= MM_STATUS_SUCCESS
)
672 /* increment device index */
676 /* now all filters have been pre-opened
677 * lets enumerate the filters
679 Entry
= MixerList
->MixerData
.Flink
;
680 while(Entry
!= &MixerList
->MixerData
)
682 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
683 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
684 Entry
= Entry
->Flink
;
687 MMixerPrintMixers(MixerContext
, MixerList
);
690 return MM_STATUS_SUCCESS
;