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
;
68 wcscpy(MixerCaps
->szPname
, MixerInfo
->MixCaps
.szPname
);
70 return MM_STATUS_SUCCESS
;
75 IN PMIXER_CONTEXT MixerContext
,
78 IN PMIXER_EVENT MixerEventRoutine
,
79 OUT PHANDLE MixerHandle
)
82 LPMIXER_INFO MixerInfo
;
84 // verify mixer context
85 Status
= MMixerVerifyContext(MixerContext
);
87 if (Status
!= MM_STATUS_SUCCESS
)
89 // invalid context passed
93 MixerInfo
= (LPMIXER_INFO
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
97 return MM_STATUS_INVALID_PARAMETER
;
101 // handle event notification
103 Status
= MMixerAddEvents(MixerContext
, MixerInfo
);
107 *MixerHandle
= (HANDLE
)MixerInfo
;
109 return MM_STATUS_SUCCESS
;
114 IN PMIXER_CONTEXT MixerContext
,
115 IN HANDLE MixerHandle
,
117 OUT LPMIXERLINEW MixerLine
)
120 LPMIXER_INFO MixerInfo
;
121 LPMIXERLINE_EXT MixerLineSrc
;
123 // verify mixer context
124 Status
= MMixerVerifyContext(MixerContext
);
126 if (Status
!= MM_STATUS_SUCCESS
)
128 // invalid context passed
132 // clear hmixer from flags
133 Flags
&=~MIXER_OBJECTF_HMIXER
;
135 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
137 // cast to mixer info
138 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
140 if (MixerLine
->dwDestination
!= 0)
142 // destination line member must be zero
143 return MM_STATUS_INVALID_PARAMETER
;
146 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
147 ASSERT(MixerLineSrc
);
148 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
150 return MM_STATUS_SUCCESS
;
152 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
154 // cast to mixer info
155 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
158 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
159 ASSERT(MixerLineSrc
);
161 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
163 DPRINT1("dwSource %u > Destinations %u\n", MixerLine
->dwSource
, MixerLineSrc
->Line
.cConnections
);
166 return MM_STATUS_INVALID_PARAMETER
;
169 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwSource
* 0x10000);
172 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
173 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
174 return MM_STATUS_SUCCESS
;
176 return MM_STATUS_UNSUCCESSFUL
;
178 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
180 // cast to mixer info
181 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
183 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
187 return MM_STATUS_INVALID_PARAMETER
;
190 /* copy cached data */
191 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
192 return MM_STATUS_SUCCESS
;
194 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
196 // cast to mixer info
197 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
199 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
202 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
203 return MM_STATUS_UNSUCCESSFUL
;
206 ASSERT(MixerLineSrc
);
208 /* copy cached data */
209 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
210 return MM_STATUS_SUCCESS
;
213 return MM_STATUS_NOT_IMPLEMENTED
;
217 MMixerGetLineControls(
218 IN PMIXER_CONTEXT MixerContext
,
219 IN HANDLE MixerHandle
,
221 OUT LPMIXERLINECONTROLSW MixerLineControls
)
223 LPMIXER_INFO MixerInfo
;
224 LPMIXERLINE_EXT MixerLineSrc
;
225 LPMIXERCONTROLW MixerControl
;
229 // verify mixer context
230 Status
= MMixerVerifyContext(MixerContext
);
232 if (Status
!= MM_STATUS_SUCCESS
)
234 // invalid context passed
238 Flags
&= ~MIXER_OBJECTF_HMIXER
;
240 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
242 // cast to mixer info
243 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
245 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
250 return MM_STATUS_INVALID_PARAMETER
;
252 // copy line control(s)
253 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
255 return MM_STATUS_SUCCESS
;
257 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
259 // cast to mixer info
260 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
262 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
267 return MM_STATUS_INVALID_PARAMETER
;
270 ASSERT(MixerLineSrc
);
273 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
275 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
276 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
278 // found a control with that type
279 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
280 return MM_STATUS_SUCCESS
;
283 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
284 return MM_STATUS_UNSUCCESSFUL
;
286 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
288 // cast to mixer info
289 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
291 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
293 if (Status
!= MM_STATUS_SUCCESS
)
296 return MM_STATUS_INVALID_PARAMETER
;
300 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
301 return MM_STATUS_SUCCESS
;
305 return MM_STATUS_NOT_IMPLEMENTED
;
309 MMixerSetControlDetails(
310 IN PMIXER_CONTEXT MixerContext
,
311 IN HANDLE MixerHandle
,
313 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
317 LPMIXER_INFO MixerInfo
;
318 LPMIXERLINE_EXT MixerLine
;
319 LPMIXERCONTROLW MixerControl
;
321 // verify mixer context
322 Status
= MMixerVerifyContext(MixerContext
);
324 if (Status
!= MM_STATUS_SUCCESS
)
326 // invalid context passed
331 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
334 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
337 if (Status
!= MM_STATUS_SUCCESS
)
339 // failed to find control id
340 return MM_STATUS_INVALID_PARAMETER
;
343 switch(MixerControl
->dwControlType
)
345 case MIXERCONTROL_CONTROLTYPE_MUTE
:
346 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
348 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
349 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
352 Status
= MM_STATUS_NOT_IMPLEMENTED
;
359 MMixerGetControlDetails(
360 IN PMIXER_CONTEXT MixerContext
,
361 IN HANDLE MixerHandle
,
363 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
367 LPMIXER_INFO MixerInfo
;
368 LPMIXERLINE_EXT MixerLine
;
369 LPMIXERCONTROLW MixerControl
;
371 // verify mixer context
372 Status
= MMixerVerifyContext(MixerContext
);
374 if (Status
!= MM_STATUS_SUCCESS
)
376 // invalid context passed
381 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
384 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
387 if (Status
!= MM_STATUS_SUCCESS
)
389 // failed to find control id
390 return MM_STATUS_INVALID_PARAMETER
;
393 switch(MixerControl
->dwControlType
)
395 case MIXERCONTROL_CONTROLTYPE_MUTE
:
396 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
398 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
399 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
402 Status
= MM_STATUS_NOT_IMPLEMENTED
;
410 IN PMIXER_CONTEXT MixerContext
,
411 IN PMIXER_ENUM EnumFunction
,
412 IN PVOID EnumContext
)
416 ULONG DeviceIndex
, Count
;
418 LPMIXER_DATA MixerData
;
419 PMIXER_LIST MixerList
;
422 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
425 return MM_STATUS_INVALID_PARAMETER
;
428 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
429 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
430 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
433 return MM_STATUS_INVALID_PARAMETER
;
436 // allocate a mixer list
437 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
441 return MM_STATUS_NO_MEMORY
;
444 //initialize mixer list
445 MixerList
->MixerListCount
= 0;
446 MixerList
->MixerDataCount
= 0;
447 MixerList
->WaveInListCount
= 0;
448 MixerList
->WaveOutListCount
= 0;
449 InitializeListHead(&MixerList
->MixerList
);
450 InitializeListHead(&MixerList
->MixerData
);
451 InitializeListHead(&MixerList
->WaveInList
);
452 InitializeListHead(&MixerList
->WaveOutList
);
456 MixerContext
->MixerContext
= (PVOID
)MixerList
;
458 // start enumerating all available devices
464 // enumerate a device
465 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
467 if (Status
!= MM_STATUS_SUCCESS
)
470 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
472 // enumeration has finished
478 // create a mixer data entry
479 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
480 if (Status
!= MM_STATUS_SUCCESS
)
484 // increment device index
488 //now all filters have been pre-opened
489 // lets enumerate the filters
490 Entry
= MixerList
->MixerData
.Flink
;
491 while(Entry
!= &MixerList
->MixerData
)
493 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
494 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
495 Entry
= Entry
->Flink
;
499 return MM_STATUS_SUCCESS
;