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
104 *MixerHandle
= (HANDLE
)MixerInfo
;
106 return MM_STATUS_SUCCESS
;
111 IN PMIXER_CONTEXT MixerContext
,
112 IN HANDLE MixerHandle
,
114 OUT LPMIXERLINEW MixerLine
)
117 LPMIXER_INFO MixerInfo
;
118 LPMIXERLINE_EXT MixerLineSrc
;
120 // verify mixer context
121 Status
= MMixerVerifyContext(MixerContext
);
123 if (Status
!= MM_STATUS_SUCCESS
)
125 // invalid context passed
129 // clear hmixer from flags
130 Flags
&=~MIXER_OBJECTF_HMIXER
;
132 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
134 // cast to mixer info
135 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
137 if (MixerLine
->dwDestination
!= 0)
139 // destination line member must be zero
140 return MM_STATUS_INVALID_PARAMETER
;
143 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
144 ASSERT(MixerLineSrc
);
145 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
147 return MM_STATUS_SUCCESS
;
149 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
151 // cast to mixer info
152 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
155 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
156 ASSERT(MixerLineSrc
);
158 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
160 DPRINT1("dwSource %u > Destinations %u\n", MixerLine
->dwSource
, MixerLineSrc
->Line
.cConnections
);
163 return MM_STATUS_INVALID_PARAMETER
;
166 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwSource
);
169 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
170 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
171 return MM_STATUS_SUCCESS
;
173 return MM_STATUS_UNSUCCESSFUL
;
175 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
177 // cast to mixer info
178 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
180 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
184 return MM_STATUS_INVALID_PARAMETER
;
187 /* copy cached data */
188 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
189 return MM_STATUS_SUCCESS
;
191 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
193 // cast to mixer info
194 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
196 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
199 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
200 return MM_STATUS_UNSUCCESSFUL
;
203 ASSERT(MixerLineSrc
);
205 /* copy cached data */
206 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
207 return MM_STATUS_SUCCESS
;
210 return MM_STATUS_NOT_IMPLEMENTED
;
214 MMixerGetLineControls(
215 IN PMIXER_CONTEXT MixerContext
,
216 IN HANDLE MixerHandle
,
218 OUT LPMIXERLINECONTROLS MixerLineControls
)
220 LPMIXER_INFO MixerInfo
;
221 LPMIXERLINE_EXT MixerLineSrc
;
222 LPMIXERCONTROLW MixerControl
;
226 // verify mixer context
227 Status
= MMixerVerifyContext(MixerContext
);
229 if (Status
!= MM_STATUS_SUCCESS
)
231 // invalid context passed
235 Flags
&= ~MIXER_OBJECTF_HMIXER
;
237 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
239 // cast to mixer info
240 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
242 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
247 return MM_STATUS_INVALID_PARAMETER
;
249 // copy line control(s)
250 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
252 return MM_STATUS_SUCCESS
;
254 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
256 // cast to mixer info
257 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
259 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
264 return MM_STATUS_INVALID_PARAMETER
;
267 ASSERT(MixerLineSrc
);
270 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
272 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
273 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
275 // found a control with that type
276 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
277 return MM_STATUS_SUCCESS
;
280 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
281 return MM_STATUS_UNSUCCESSFUL
;
283 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
285 // cast to mixer info
286 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
288 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
290 if (Status
!= MM_STATUS_SUCCESS
)
293 return MM_STATUS_INVALID_PARAMETER
;
297 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
298 return MM_STATUS_SUCCESS
;
302 return MM_STATUS_NOT_IMPLEMENTED
;
306 MMixerSetControlDetails(
307 IN PMIXER_CONTEXT MixerContext
,
308 IN HANDLE MixerHandle
,
310 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
314 LPMIXER_INFO MixerInfo
;
315 LPMIXERLINE_EXT MixerLine
;
316 LPMIXERCONTROLW MixerControl
;
318 // verify mixer context
319 Status
= MMixerVerifyContext(MixerContext
);
321 if (Status
!= MM_STATUS_SUCCESS
)
323 // invalid context passed
328 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
331 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
334 if (Status
!= MM_STATUS_SUCCESS
)
336 // failed to find control id
337 return MM_STATUS_INVALID_PARAMETER
;
340 switch(MixerControl
->dwControlType
)
342 case MIXERCONTROL_CONTROLTYPE_MUTE
:
343 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
345 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
346 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
349 Status
= MM_STATUS_NOT_IMPLEMENTED
;
356 MMixerGetControlDetails(
357 IN PMIXER_CONTEXT MixerContext
,
358 IN HANDLE MixerHandle
,
360 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
364 LPMIXER_INFO MixerInfo
;
365 LPMIXERLINE_EXT MixerLine
;
366 LPMIXERCONTROLW MixerControl
;
368 // verify mixer context
369 Status
= MMixerVerifyContext(MixerContext
);
371 if (Status
!= MM_STATUS_SUCCESS
)
373 // invalid context passed
378 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
381 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
384 if (Status
!= MM_STATUS_SUCCESS
)
386 // failed to find control id
387 return MM_STATUS_INVALID_PARAMETER
;
390 switch(MixerControl
->dwControlType
)
392 case MIXERCONTROL_CONTROLTYPE_MUTE
:
393 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
395 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
396 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
399 Status
= MM_STATUS_NOT_IMPLEMENTED
;
407 IN PMIXER_CONTEXT MixerContext
,
408 IN PMIXER_ENUM EnumFunction
,
409 IN PVOID EnumContext
)
413 ULONG DeviceIndex
, Count
;
415 LPMIXER_DATA MixerData
;
416 PMIXER_LIST MixerList
;
419 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
422 return MM_STATUS_INVALID_PARAMETER
;
425 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
426 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
429 return MM_STATUS_INVALID_PARAMETER
;
432 // allocate a mixer list
433 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
437 return MM_STATUS_NO_MEMORY
;
440 //initialize mixer list
441 MixerList
->MixerListCount
= 0;
442 MixerList
->MixerDataCount
= 0;
443 InitializeListHead(&MixerList
->MixerList
);
444 InitializeListHead(&MixerList
->MixerData
);
447 MixerContext
->MixerContext
= (PVOID
)MixerList
;
449 // start enumerating all available devices
455 // enumerate a device
456 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
458 if (Status
!= MM_STATUS_SUCCESS
)
461 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
463 // enumeration has finished
469 // create a mixer data entry
470 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
471 if (Status
!= MM_STATUS_SUCCESS
)
475 // increment device index
479 //now all filters have been pre-opened
480 // lets enumerate the filters
481 Entry
= MixerList
->MixerData
.Flink
;
482 while(Entry
!= &MixerList
->MixerData
)
484 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
485 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
486 Entry
= Entry
->Flink
;
490 return MM_STATUS_SUCCESS
;