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
,
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
95 MixerInfo
= (LPMIXER_INFO
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
99 return MM_STATUS_INVALID_PARAMETER
;
103 // handle event notification
105 Status
= MMixerAddEvents(MixerContext
, MixerInfo
);
109 *MixerHandle
= (HANDLE
)MixerInfo
;
111 return MM_STATUS_SUCCESS
;
116 IN PMIXER_CONTEXT MixerContext
,
117 IN HANDLE MixerHandle
,
119 OUT LPMIXERLINEW MixerLine
)
122 LPMIXER_INFO MixerInfo
;
123 LPMIXERLINE_EXT MixerLineSrc
;
125 // verify mixer context
126 Status
= MMixerVerifyContext(MixerContext
);
128 if (Status
!= MM_STATUS_SUCCESS
)
130 // invalid context passed
134 // clear hmixer from flags
135 Flags
&=~MIXER_OBJECTF_HMIXER
;
137 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
139 // cast to mixer info
140 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
142 if (MixerLine
->dwDestination
!= 0)
144 // destination line member must be zero
145 return MM_STATUS_INVALID_PARAMETER
;
148 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
149 ASSERT(MixerLineSrc
);
150 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
152 return MM_STATUS_SUCCESS
;
154 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
156 // cast to mixer info
157 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
160 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
161 ASSERT(MixerLineSrc
);
163 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
165 DPRINT1("dwSource %u > Destinations %u\n", MixerLine
->dwSource
, MixerLineSrc
->Line
.cConnections
);
168 return MM_STATUS_INVALID_PARAMETER
;
171 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwSource
* 0x10000);
174 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
175 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
176 return MM_STATUS_SUCCESS
;
178 return MM_STATUS_UNSUCCESSFUL
;
180 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
182 // cast to mixer info
183 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
185 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
189 return MM_STATUS_INVALID_PARAMETER
;
192 /* copy cached data */
193 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
194 return MM_STATUS_SUCCESS
;
196 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
198 // cast to mixer info
199 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
201 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
204 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
205 return MM_STATUS_UNSUCCESSFUL
;
208 ASSERT(MixerLineSrc
);
210 /* copy cached data */
211 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
212 return MM_STATUS_SUCCESS
;
215 return MM_STATUS_NOT_IMPLEMENTED
;
219 MMixerGetLineControls(
220 IN PMIXER_CONTEXT MixerContext
,
221 IN HANDLE MixerHandle
,
223 OUT LPMIXERLINECONTROLSW MixerLineControls
)
225 LPMIXER_INFO MixerInfo
;
226 LPMIXERLINE_EXT MixerLineSrc
;
227 LPMIXERCONTROLW MixerControl
;
231 // verify mixer context
232 Status
= MMixerVerifyContext(MixerContext
);
234 if (Status
!= MM_STATUS_SUCCESS
)
236 // invalid context passed
240 Flags
&= ~MIXER_OBJECTF_HMIXER
;
242 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
244 // cast to mixer info
245 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
247 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
252 return MM_STATUS_INVALID_PARAMETER
;
254 // copy line control(s)
255 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
257 return MM_STATUS_SUCCESS
;
259 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
261 // cast to mixer info
262 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
264 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
269 return MM_STATUS_INVALID_PARAMETER
;
272 ASSERT(MixerLineSrc
);
275 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
277 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
278 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
280 // found a control with that type
281 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
282 return MM_STATUS_SUCCESS
;
285 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
286 return MM_STATUS_UNSUCCESSFUL
;
288 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
290 // cast to mixer info
291 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
293 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
295 if (Status
!= MM_STATUS_SUCCESS
)
298 return MM_STATUS_INVALID_PARAMETER
;
302 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
303 return MM_STATUS_SUCCESS
;
307 return MM_STATUS_NOT_IMPLEMENTED
;
311 MMixerSetControlDetails(
312 IN PMIXER_CONTEXT MixerContext
,
313 IN HANDLE MixerHandle
,
315 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
319 LPMIXER_INFO MixerInfo
;
320 LPMIXERLINE_EXT MixerLine
;
321 LPMIXERCONTROLW MixerControl
;
323 // verify mixer context
324 Status
= MMixerVerifyContext(MixerContext
);
326 if (Status
!= MM_STATUS_SUCCESS
)
328 // invalid context passed
333 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
336 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
339 if (Status
!= MM_STATUS_SUCCESS
)
341 // failed to find control id
342 return MM_STATUS_INVALID_PARAMETER
;
345 switch(MixerControl
->dwControlType
)
347 case MIXERCONTROL_CONTROLTYPE_MUTE
:
348 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
350 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
351 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
354 Status
= MM_STATUS_NOT_IMPLEMENTED
;
361 MMixerGetControlDetails(
362 IN PMIXER_CONTEXT MixerContext
,
363 IN HANDLE MixerHandle
,
365 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
369 LPMIXER_INFO MixerInfo
;
370 LPMIXERLINE_EXT MixerLine
;
371 LPMIXERCONTROLW MixerControl
;
373 // verify mixer context
374 Status
= MMixerVerifyContext(MixerContext
);
376 if (Status
!= MM_STATUS_SUCCESS
)
378 // invalid context passed
383 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
386 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
389 if (Status
!= MM_STATUS_SUCCESS
)
391 // failed to find control id
392 return MM_STATUS_INVALID_PARAMETER
;
395 switch(MixerControl
->dwControlType
)
397 case MIXERCONTROL_CONTROLTYPE_MUTE
:
398 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
400 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
401 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
404 Status
= MM_STATUS_NOT_IMPLEMENTED
;
412 IN PMIXER_CONTEXT MixerContext
,
413 IN PMIXER_ENUM EnumFunction
,
414 IN PVOID EnumContext
)
418 ULONG DeviceIndex
, Count
;
420 LPMIXER_DATA MixerData
;
421 PMIXER_LIST MixerList
;
424 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
427 return MM_STATUS_INVALID_PARAMETER
;
430 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
431 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
432 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
435 return MM_STATUS_INVALID_PARAMETER
;
438 // allocate a mixer list
439 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
443 return MM_STATUS_NO_MEMORY
;
446 //initialize mixer list
447 MixerList
->MixerListCount
= 0;
448 MixerList
->MixerDataCount
= 0;
449 MixerList
->WaveInListCount
= 0;
450 MixerList
->WaveOutListCount
= 0;
451 InitializeListHead(&MixerList
->MixerList
);
452 InitializeListHead(&MixerList
->MixerData
);
453 InitializeListHead(&MixerList
->WaveInList
);
454 InitializeListHead(&MixerList
->WaveOutList
);
458 MixerContext
->MixerContext
= (PVOID
)MixerList
;
460 // start enumerating all available devices
466 // enumerate a device
467 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
469 if (Status
!= MM_STATUS_SUCCESS
)
472 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
474 // enumeration has finished
479 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex
);
487 // create a mixer data entry
488 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
489 if (Status
!= MM_STATUS_SUCCESS
)
493 // increment device index
497 //now all filters have been pre-opened
498 // lets enumerate the filters
499 Entry
= MixerList
->MixerData
.Flink
;
500 while(Entry
!= &MixerList
->MixerData
)
502 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
503 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
504 Entry
= Entry
->Flink
;
508 return MM_STATUS_SUCCESS
;