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
;
127 /* verify mixer context */
128 Status
= MMixerVerifyContext(MixerContext
);
130 if (Status
!= MM_STATUS_SUCCESS
)
132 /* invalid context passed */
135 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
137 /* caller passed mixer id */
138 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
142 /* invalid parameter */
143 return MM_STATUS_INVALID_PARAMETER
;
147 /* clear hmixer from flags */
148 Flags
&=~MIXER_OBJECTF_HMIXER
;
150 if (Flags
== MIXER_GETLINEINFOF_DESTINATION
)
152 /* cast to mixer info */
153 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
155 if (MixerLine
->dwDestination
!= 0)
157 /* destination line member must be zero */
158 return MM_STATUS_INVALID_PARAMETER
;
161 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
162 ASSERT(MixerLineSrc
);
163 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
165 return MM_STATUS_SUCCESS
;
167 else if (Flags
== MIXER_GETLINEINFOF_SOURCE
)
169 /* cast to mixer info */
170 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
173 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
174 ASSERT(MixerLineSrc
);
176 if (MixerLine
->dwSource
>= MixerLineSrc
->Line
.cConnections
)
178 DPRINT("dwSource %u > Destinations %u\n", MixerLine
->dwSource
, MixerLineSrc
->Line
.cConnections
);
180 /* invalid parameter */
181 return MM_STATUS_INVALID_PARAMETER
;
184 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwSource
* 0x10000);
187 DPRINT("Line %u Name %S\n", MixerLineSrc
->Line
.dwSource
, MixerLineSrc
->Line
.szName
);
188 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
189 return MM_STATUS_SUCCESS
;
191 return MM_STATUS_UNSUCCESSFUL
;
193 else if (Flags
== MIXER_GETLINEINFOF_LINEID
)
195 /* cast to mixer info */
196 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
198 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLine
->dwLineID
);
201 /* invalid parameter */
202 return MM_STATUS_INVALID_PARAMETER
;
205 /* copy cached data */
206 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
207 return MM_STATUS_SUCCESS
;
209 else if (Flags
== MIXER_GETLINEINFOF_COMPONENTTYPE
)
211 /* cast to mixer info */
212 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
214 MixerLineSrc
= MMixerGetSourceMixerLineByComponentType(MixerInfo
, MixerLine
->dwComponentType
);
217 DPRINT1("Failed to find component type %x\n", MixerLine
->dwComponentType
);
218 return MM_STATUS_UNSUCCESSFUL
;
221 ASSERT(MixerLineSrc
);
223 /* copy cached data */
224 MixerContext
->Copy(MixerLine
, &MixerLineSrc
->Line
, sizeof(MIXERLINEW
));
225 return MM_STATUS_SUCCESS
;
228 return MM_STATUS_NOT_IMPLEMENTED
;
232 MMixerGetLineControls(
233 IN PMIXER_CONTEXT MixerContext
,
234 IN HANDLE MixerHandle
,
237 OUT LPMIXERLINECONTROLSW MixerLineControls
)
239 LPMIXER_INFO MixerInfo
;
240 LPMIXERLINE_EXT MixerLineSrc
;
241 LPMIXERCONTROLW MixerControl
;
245 /* verify mixer context */
246 Status
= MMixerVerifyContext(MixerContext
);
248 if (Status
!= MM_STATUS_SUCCESS
)
250 /* invalid context passed */
254 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
256 /* caller passed mixer id */
257 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
261 /* invalid parameter */
262 return MM_STATUS_INVALID_PARAMETER
;
266 Flags
&= ~MIXER_OBJECTF_HMIXER
;
268 if (Flags
== MIXER_GETLINECONTROLSF_ALL
)
270 /* cast to mixer info */
271 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
273 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
277 /* invalid line id */
278 return MM_STATUS_INVALID_PARAMETER
;
280 /* copy line control(s) */
281 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerLineSrc
->LineControls
, min(MixerLineSrc
->Line
.cControls
, MixerLineControls
->cControls
) * sizeof(MIXERCONTROLW
));
283 return MM_STATUS_SUCCESS
;
285 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYTYPE
)
287 /* cast to mixer info */
288 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
290 MixerLineSrc
= MMixerGetSourceMixerLineByLineId(MixerInfo
, MixerLineControls
->dwLineID
);
294 /* invalid line id */
295 return MM_STATUS_INVALID_PARAMETER
;
298 ASSERT(MixerLineSrc
);
301 for(Index
= 0; Index
< MixerLineSrc
->Line
.cControls
; Index
++)
303 DPRINT("dwControlType %x\n", MixerLineSrc
->LineControls
[Index
].dwControlType
);
304 if (MixerLineControls
->dwControlType
== MixerLineSrc
->LineControls
[Index
].dwControlType
)
306 /* found a control with that type */
307 MixerContext
->Copy(MixerLineControls
->pamxctrl
, &MixerLineSrc
->LineControls
[Index
], sizeof(MIXERCONTROLW
));
308 return MM_STATUS_SUCCESS
;
311 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls
->dwControlType
, MixerLineControls
->dwLineID
, MixerLineSrc
->Line
.cControls
);
312 return MM_STATUS_UNSUCCESSFUL
;
314 else if (Flags
== MIXER_GETLINECONTROLSF_ONEBYID
)
316 /* cast to mixer info */
317 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
319 Status
= MMixerGetMixerControlById(MixerInfo
, MixerLineControls
->dwControlID
, NULL
, &MixerControl
, NULL
);
321 if (Status
!= MM_STATUS_SUCCESS
)
323 /* invalid parameter */
324 return MM_STATUS_INVALID_PARAMETER
;
327 /* copy the controls */
328 MixerContext
->Copy(MixerLineControls
->pamxctrl
, MixerControl
, sizeof(MIXERCONTROLW
));
329 return MM_STATUS_SUCCESS
;
333 return MM_STATUS_NOT_IMPLEMENTED
;
337 MMixerSetControlDetails(
338 IN PMIXER_CONTEXT MixerContext
,
339 IN HANDLE MixerHandle
,
342 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
346 LPMIXER_INFO MixerInfo
;
347 LPMIXERLINE_EXT MixerLine
;
348 LPMIXERCONTROLW MixerControl
;
350 /* verify mixer context */
351 Status
= MMixerVerifyContext(MixerContext
);
353 if (Status
!= MM_STATUS_SUCCESS
)
355 /* invalid context passed */
359 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
361 /* caller passed mixer id */
362 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
366 /* invalid parameter */
367 return MM_STATUS_INVALID_PARAMETER
;
372 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
374 /* get mixer control */
375 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
377 /* check for success */
378 if (Status
!= MM_STATUS_SUCCESS
)
380 /* failed to find control id */
381 return MM_STATUS_INVALID_PARAMETER
;
384 switch(MixerControl
->dwControlType
)
386 case MIXERCONTROL_CONTROLTYPE_MUTE
:
387 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, TRUE
);
389 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
390 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
->hMixer
, NodeId
, TRUE
, MixerControl
, MixerControlDetails
, MixerLine
);
393 Status
= MM_STATUS_NOT_IMPLEMENTED
;
400 MMixerGetControlDetails(
401 IN PMIXER_CONTEXT MixerContext
,
402 IN HANDLE MixerHandle
,
405 OUT LPMIXERCONTROLDETAILS MixerControlDetails
)
409 LPMIXER_INFO MixerInfo
;
410 LPMIXERLINE_EXT MixerLine
;
411 LPMIXERCONTROLW MixerControl
;
413 /* verify mixer context */
414 Status
= MMixerVerifyContext(MixerContext
);
416 if (Status
!= MM_STATUS_SUCCESS
)
418 /* invalid context passed */
422 if ((Flags
& (MIXER_OBJECTF_MIXER
| MIXER_OBJECTF_HMIXER
)) == MIXER_OBJECTF_MIXER
)
424 /* caller passed mixer id */
425 MixerHandle
= (HANDLE
)MMixerGetMixerInfoByIndex(MixerContext
, MixerId
);
429 /* invalid parameter */
430 return MM_STATUS_INVALID_PARAMETER
;
435 MixerInfo
= (LPMIXER_INFO
)MixerHandle
;
437 /* get mixer control */
438 Status
= MMixerGetMixerControlById(MixerInfo
, MixerControlDetails
->dwControlID
, &MixerLine
, &MixerControl
, &NodeId
);
440 /* check for success */
441 if (Status
!= MM_STATUS_SUCCESS
)
443 /* failed to find control id */
444 return MM_STATUS_INVALID_PARAMETER
;
447 switch(MixerControl
->dwControlType
)
449 case MIXERCONTROL_CONTROLTYPE_MUTE
:
450 Status
= MMixerSetGetMuteControlDetails(MixerContext
, MixerInfo
, NodeId
, MixerLine
->Line
.dwLineID
, MixerControlDetails
, FALSE
);
452 case MIXERCONTROL_CONTROLTYPE_VOLUME
:
453 Status
= MMixerSetGetVolumeControlDetails(MixerContext
, MixerInfo
, NodeId
, FALSE
, MixerControl
, MixerControlDetails
, MixerLine
);
456 Status
= MM_STATUS_NOT_IMPLEMENTED
;
464 IN PMIXER_CONTEXT MixerContext
,
465 IN PMIXER_ENUM EnumFunction
,
466 IN PVOID EnumContext
)
470 ULONG DeviceIndex
, Count
;
472 LPMIXER_DATA MixerData
;
473 PMIXER_LIST MixerList
;
476 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
478 /* invalid parameter */
479 return MM_STATUS_INVALID_PARAMETER
;
482 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
|| !MixerContext
->Open
||
483 !MixerContext
->AllocEventData
|| !MixerContext
->FreeEventData
||
484 !MixerContext
->Close
|| !MixerContext
->OpenKey
|| !MixerContext
->QueryKeyValue
|| !MixerContext
->CloseKey
)
486 /* invalid parameter */
487 return MM_STATUS_INVALID_PARAMETER
;
490 /* allocate a mixer list */
491 MixerList
= (PMIXER_LIST
)MixerContext
->Alloc(sizeof(MIXER_LIST
));
495 return MM_STATUS_NO_MEMORY
;
498 /* initialize mixer list */
499 MixerList
->MixerListCount
= 0;
500 MixerList
->MixerDataCount
= 0;
501 MixerList
->WaveInListCount
= 0;
502 MixerList
->WaveOutListCount
= 0;
503 MixerList
->MidiInListCount
= 0;
504 MixerList
->MidiOutListCount
= 0;
505 InitializeListHead(&MixerList
->MixerList
);
506 InitializeListHead(&MixerList
->MixerData
);
507 InitializeListHead(&MixerList
->WaveInList
);
508 InitializeListHead(&MixerList
->WaveOutList
);
509 InitializeListHead(&MixerList
->MidiInList
);
510 InitializeListHead(&MixerList
->MidiOutList
);
512 /* store mixer list */
513 MixerContext
->MixerContext
= (PVOID
)MixerList
;
515 /* start enumerating all available devices */
521 /* enumerate a device */
522 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
, &hKey
);
524 if (Status
!= MM_STATUS_SUCCESS
)
526 /* check error code */
527 if (Status
== MM_STATUS_NO_MORE_DEVICES
)
529 /* enumeration has finished */
534 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex
);
542 /* create a mixer data entry */
543 Status
= MMixerCreateMixerData(MixerContext
, MixerList
, DeviceIndex
, DeviceName
, hMixer
, hKey
);
544 if (Status
!= MM_STATUS_SUCCESS
)
548 /* increment device index */
552 /* now all filters have been pre-opened
553 * lets enumerate the filters
555 Entry
= MixerList
->MixerData
.Flink
;
556 while(Entry
!= &MixerList
->MixerData
)
558 MixerData
= (LPMIXER_DATA
)CONTAINING_RECORD(Entry
, MIXER_DATA
, Entry
);
559 MMixerSetupFilter(MixerContext
, MixerList
, MixerData
, &Count
);
560 Entry
= Entry
->Flink
;
564 return MM_STATUS_SUCCESS
;