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 */
96 MixerInfo
= (LPMIXER_INFO
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
99 /* invalid mixer id */
100 return MM_STATUS_INVALID_PARAMETER
;
104 Status
= MMixerAddEvent(MixerContext
, MixerInfo
, MixerEventContext
, MixerEventRoutine
);
108 *MixerHandle
= (HANDLE
)MixerInfo
;
110 return MM_STATUS_SUCCESS
;
115 IN PMIXER_CONTEXT MixerContext
,
116 IN HANDLE MixerHandle
,
118 OUT LPMIXERLINEW MixerLine
)
121 LPMIXER_INFO MixerInfo
;
122 LPMIXERLINE_EXT MixerLineSrc
;
124 /* verify mixer context */
125 Status
= MMixerVerifyContext(MixerContext
);
127 if (Status
!= MM_STATUS_SUCCESS
)
129 /* invalid context passed */
133 /* clear hmixer from flags */
134 Flags
&=~MIXER_OBJECTF_HMIXER
;
136 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
138 /* cast to mixer info */
139 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
141 if (MixerLine
->dwDestination
!= 0)
143 /* destination line member must be zero */
144 return MM_STATUS_INVALID_PARAMETER
;
147 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
148 ASSERT(MixerLineSrc
);
149 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
151 return MM_STATUS_SUCCESS
;
153 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
155 /* cast to mixer info */
156 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
159 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
160 ASSERT(MixerLineSrc
);
162 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
164 DPRINT("dwSource %u > Destinations %u\n", MixerLine
->dwSource
, MixerLineSrc
->Line
.cConnections
);
166 /* invalid parameter */
167 return MM_STATUS_INVALID_PARAMETER
;
170 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwSource
* 0x10000);
173 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
174 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
175 return MM_STATUS_SUCCESS
;
177 return MM_STATUS_UNSUCCESSFUL
;
179 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
181 /* cast to mixer info */
182 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
184 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
187 /* invalid parameter */
188 return MM_STATUS_INVALID_PARAMETER
;
191 /* copy cached data */
192 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
193 return MM_STATUS_SUCCESS
;
195 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
197 /* cast to mixer info */
198 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
200 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
203 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
204 return MM_STATUS_UNSUCCESSFUL
;
207 ASSERT(MixerLineSrc
);
209 /* copy cached data */
210 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
211 return MM_STATUS_SUCCESS
;
214 return MM_STATUS_NOT_IMPLEMENTED
;
218 MMixerGetLineControls(
219 IN PMIXER_CONTEXT MixerContext
,
220 IN HANDLE MixerHandle
,
222 OUT LPMIXERLINECONTROLSW MixerLineControls
)
224 LPMIXER_INFO MixerInfo
;
225 LPMIXERLINE_EXT MixerLineSrc
;
226 LPMIXERCONTROLW MixerControl
;
230 /* verify mixer context */
231 Status
= MMixerVerifyContext(MixerContext
);
233 if (Status
!= MM_STATUS_SUCCESS
)
235 /* invalid context passed */
239 Flags
&= ~MIXER_OBJECTF_HMIXER
;
241 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
243 /* cast to mixer info */
244 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
246 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
250 /* invalid line id */
251 return MM_STATUS_INVALID_PARAMETER
;
253 /* copy line control(s) */
254 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
256 return MM_STATUS_SUCCESS
;
258 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
260 /* cast to mixer info */
261 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
263 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
267 /* invalid line id */
268 return MM_STATUS_INVALID_PARAMETER
;
271 ASSERT(MixerLineSrc
);
274 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
276 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
277 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
279 /* found a control with that type */
280 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
281 return MM_STATUS_SUCCESS
;
284 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
285 return MM_STATUS_UNSUCCESSFUL
;
287 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
289 /* cast to mixer info */
290 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
292 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
294 if (Status
!= MM_STATUS_SUCCESS
)
296 /* invalid parameter */
297 return MM_STATUS_INVALID_PARAMETER
;
300 /* copy the controls */
301 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
302 return MM_STATUS_SUCCESS
;
306 return MM_STATUS_NOT_IMPLEMENTED
;
310 MMixerSetControlDetails(
311 IN PMIXER_CONTEXT MixerContext
,
312 IN HANDLE MixerHandle
,
314 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
318 LPMIXER_INFO MixerInfo
;
319 LPMIXERLINE_EXT MixerLine
;
320 LPMIXERCONTROLW MixerControl
;
322 /* verify mixer context */
323 Status
= MMixerVerifyContext(MixerContext
);
325 if (Status
!= MM_STATUS_SUCCESS
)
327 /* invalid context passed */
332 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
334 /* get mixer control */
335 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
337 /* check for success */
338 if (Status
!= MM_STATUS_SUCCESS
)
340 /* failed to find control id */
341 return MM_STATUS_INVALID_PARAMETER
;
344 switch(MixerControl
->dwControlType
)
346 case MIXERCONTROL_CONTROLTYPE_MUTE
:
347 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
349 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
350 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
353 Status
= MM_STATUS_NOT_IMPLEMENTED
;
360 MMixerGetControlDetails(
361 IN PMIXER_CONTEXT MixerContext
,
362 IN HANDLE MixerHandle
,
364 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
368 LPMIXER_INFO MixerInfo
;
369 LPMIXERLINE_EXT MixerLine
;
370 LPMIXERCONTROLW MixerControl
;
372 /* verify mixer context */
373 Status
= MMixerVerifyContext(MixerContext
);
375 if (Status
!= MM_STATUS_SUCCESS
)
377 /* invalid context passed */
382 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
384 /* get mixer control */
385 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
387 /* check for success */
388 if (Status
!= MM_STATUS_SUCCESS
)
390 /* failed to find control id */
391 return MM_STATUS_INVALID_PARAMETER
;
394 switch(MixerControl
->dwControlType
)
396 case MIXERCONTROL_CONTROLTYPE_MUTE
:
397 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
399 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
400 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
403 Status
= MM_STATUS_NOT_IMPLEMENTED
;
411 IN PMIXER_CONTEXT MixerContext
,
412 IN PMIXER_ENUM EnumFunction
,
413 IN PVOID EnumContext
)
417 ULONG DeviceIndex
, Count
;
419 LPMIXER_DATA MixerData
;
420 PMIXER_LIST MixerList
;
423 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
425 /* invalid parameter */
426 return MM_STATUS_INVALID_PARAMETER
;
429 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
430 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
431 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
433 /* invalid parameter */
434 return MM_STATUS_INVALID_PARAMETER
;
437 /* allocate a mixer list */
438 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
442 return MM_STATUS_NO_MEMORY
;
445 /* initialize mixer list */
446 MixerList
->MixerListCount
= 0;
447 MixerList
->MixerDataCount
= 0;
448 MixerList
->WaveInListCount
= 0;
449 MixerList
->WaveOutListCount
= 0;
450 InitializeListHead(&MixerList
->MixerList
);
451 InitializeListHead(&MixerList
->MixerData
);
452 InitializeListHead(&MixerList
->WaveInList
);
453 InitializeListHead(&MixerList
->WaveOutList
);
456 /* store mixer list */
457 MixerContext
->MixerContext
= (PVOID
)MixerList
;
459 /* start enumerating all available devices */
465 /* enumerate a device */
466 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
468 if (Status
!= MM_STATUS_SUCCESS
)
470 /* check error code */
471 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
473 /* enumeration has finished */
478 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex
);
486 /* create a mixer data entry */
487 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
488 if (Status
!= MM_STATUS_SUCCESS
)
492 /* increment device index */
496 /* now all filters have been pre-opened
497 * 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
;