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 if (MixerContext
->SizeOfStruct
!= sizeof(MIXER_CONTEXT
))
18 return MM_STATUS_INVALID_PARAMETER
;
20 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
)
21 return MM_STATUS_INVALID_PARAMETER
;
23 if (!MixerContext
->MixerContext
)
24 return MM_STATUS_INVALID_PARAMETER
;
26 return MM_STATUS_SUCCESS
;
31 IN PMIXER_CONTEXT MixerContext
,
32 IN LPMIXER_INFO MixerInfo
)
38 MixerContext
->Free((PVOID
)MixerInfo
);
42 MMixerGetFilterPinCount(
43 IN PMIXER_CONTEXT MixerContext
,
48 ULONG NumPins
, BytesReturned
;
50 // setup property request
51 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
52 Pin
.Set
= KSPROPSETID_Pin
;
53 Pin
.Id
= KSPROPERTY_PIN_CTYPES
;
56 Status
= MixerContext
->Control(hMixer
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&NumPins
, sizeof(ULONG
), (PULONG
)&BytesReturned
);
59 if (Status
!= MM_STATUS_SUCCESS
)
67 PKSMULTIPLE_ITEM MultipleItem
,
73 Guid
= (LPGUID
)(MultipleItem
+1);
75 /* iterate through node type array */
76 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
78 if (IsEqualGUIDAligned(NodeType
, Guid
))
80 /* found matching guid */
90 MMixerGetFilterTopologyProperty(
91 IN PMIXER_CONTEXT MixerContext
,
94 OUT PKSMULTIPLE_ITEM
* OutMultipleItem
)
97 PKSMULTIPLE_ITEM MultipleItem
;
101 // setup property request
102 Property
.Id
= PropertyId
;
103 Property
.Flags
= KSPROPERTY_TYPE_GET
;
104 Property
.Set
= KSPROPSETID_Topology
;
106 // query for the size
107 Status
= MixerContext
->Control(hMixer
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), NULL
, 0, &BytesReturned
);
109 if (Status
!= MM_STATUS_MORE_ENTRIES
)
112 // allocate an result buffer
113 MultipleItem
= (PKSMULTIPLE_ITEM
)MixerContext
->Alloc(BytesReturned
);
118 return MM_STATUS_NO_MEMORY
;
121 // query again with allocated buffer
122 Status
= MixerContext
->Control(hMixer
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
124 if (Status
!= MM_STATUS_SUCCESS
)
127 MixerContext
->Free((PVOID
)MultipleItem
);
132 *OutMultipleItem
= MultipleItem
;
139 MMixerCreateDestinationLine(
140 IN PMIXER_CONTEXT MixerContext
,
141 IN LPMIXER_INFO MixerInfo
,
142 IN ULONG bInputMixer
)
144 LPMIXERLINE_EXT DestinationLine
;
146 // allocate a mixer destination line
147 DestinationLine
= (LPMIXERLINE_EXT
) MixerContext
->Alloc(sizeof(MIXERLINE_EXT
));
151 return MM_STATUS_NO_MEMORY
;
154 /* initialize mixer destination line */
155 DestinationLine
->Line
.cbStruct
= sizeof(MIXERLINEW
);
156 DestinationLine
->Line
.dwSource
= MAXULONG
;
157 DestinationLine
->Line
.dwLineID
= DESTINATION_LINE
;
158 DestinationLine
->Line
.fdwLine
= MIXERLINE_LINEF_ACTIVE
;
159 DestinationLine
->Line
.dwUser
= 0;
160 DestinationLine
->Line
.dwComponentType
= (bInputMixer
== 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
: MIXERLINE_COMPONENTTYPE_DST_WAVEIN
);
161 DestinationLine
->Line
.cChannels
= 2; //FIXME
162 wcscpy(DestinationLine
->Line
.szShortName
, L
"Summe"); //FIXME
163 wcscpy(DestinationLine
->Line
.szName
, L
"Summe"); //FIXME
164 DestinationLine
->Line
.Target
.dwType
= (bInputMixer
== 0 ? MIXERLINE_TARGETTYPE_WAVEOUT
: MIXERLINE_TARGETTYPE_WAVEIN
);
165 DestinationLine
->Line
.Target
.dwDeviceID
= !bInputMixer
;
166 DestinationLine
->Line
.Target
.wMid
= MixerInfo
->MixCaps
.wMid
;
167 DestinationLine
->Line
.Target
.wPid
= MixerInfo
->MixCaps
.wPid
;
168 DestinationLine
->Line
.Target
.vDriverVersion
= MixerInfo
->MixCaps
.vDriverVersion
;
169 wcscpy(DestinationLine
->Line
.Target
.szPname
, MixerInfo
->MixCaps
.szPname
);
172 // insert into mixer info
173 InsertHeadList(&MixerInfo
->LineList
, &DestinationLine
->Entry
);
176 return MM_STATUS_SUCCESS
;
180 MMixerInitializeFilter(
181 IN PMIXER_CONTEXT MixerContext
,
183 IN LPWSTR DeviceName
,
184 IN PKSMULTIPLE_ITEM NodeTypes
,
185 IN PKSMULTIPLE_ITEM NodeConnections
,
188 IN ULONG bInputMixer
)
190 LPMIXER_INFO MixerInfo
;
194 // allocate a mixer info struct
195 MixerInfo
= (LPMIXER_INFO
) MixerContext
->Alloc(sizeof(MIXER_INFO
));
199 return MM_STATUS_NO_MEMORY
;
202 // intialize mixer caps */
203 MixerInfo
->MixCaps
.wMid
= MM_MICROSOFT
; //FIXME
204 MixerInfo
->MixCaps
.wPid
= MM_PID_UNMAPPED
; //FIXME
205 MixerInfo
->MixCaps
.vDriverVersion
= 1; //FIXME
206 MixerInfo
->MixCaps
.fdwSupport
= 0;
207 MixerInfo
->MixCaps
.cDestinations
= 1;
208 MixerInfo
->hMixer
= hMixer
;
210 // initialize line list
211 InitializeListHead(&MixerInfo
->LineList
);
213 /* FIXME find mixer name */
215 Status
= MMixerCreateDestinationLine(MixerContext
, MixerInfo
, bInputMixer
);
216 if (Status
!= MM_STATUS_SUCCESS
)
218 // failed to create destination line
219 MixerContext
->Free(MixerInfo
);
224 // now allocate an array which will receive the indices of the pin
225 // which has a ADC / DAC nodetype in its path
226 Pins
= (PULONG
)MixerContext
->Alloc(PinCount
* sizeof(ULONG
));
231 MMixerFreeMixerInfo(MixerContext
, MixerInfo
);
232 return MM_STATUS_NO_MEMORY
;
237 // get target pins and find all nodes
238 return MM_STATUS_NOT_IMPLEMENTED
;
243 IN PMIXER_CONTEXT MixerContext
,
245 IN PULONG DeviceCount
,
246 IN LPWSTR DeviceName
)
248 PKSMULTIPLE_ITEM NodeTypes
, NodeConnections
;
253 // get number of pins
254 PinCount
= MMixerGetFilterPinCount(MixerContext
, hMixer
);
258 // get filter node types
259 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hMixer
, KSPROPERTY_TOPOLOGY_NODES
, &NodeTypes
);
260 if (Status
!= MM_STATUS_SUCCESS
)
266 // get filter node connections
267 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hMixer
, KSPROPERTY_TOPOLOGY_CONNECTIONS
, &NodeConnections
);
268 if (Status
!= MM_STATUS_SUCCESS
)
271 MixerContext
->Free(NodeTypes
);
275 // check if the filter has an wave out node
276 NodeIndex
= MMixerGetIndexOfGuid(NodeTypes
, &KSNODETYPE_DAC
);
277 if (NodeIndex
!= MAXULONG
)
280 Status
= MMixerInitializeFilter(MixerContext
, hMixer
, DeviceName
, NodeTypes
, NodeConnections
, PinCount
, NodeIndex
, FALSE
);
283 if (Status
== MM_STATUS_SUCCESS
)
285 // increment mixer count
291 // check if the filter has an wave in node
292 NodeIndex
= MMixerGetIndexOfGuid(NodeTypes
, &KSNODETYPE_ADC
);
293 if (NodeIndex
!= MAXULONG
)
296 Status
= MMixerInitializeFilter(MixerContext
, hMixer
, DeviceName
, NodeTypes
, NodeConnections
, PinCount
, NodeIndex
, TRUE
);
299 if (Status
== MM_STATUS_SUCCESS
)
301 // increment mixer count
308 MixerContext
->Free((PVOID
)NodeTypes
);
309 MixerContext
->Free((PVOID
)NodeConnections
);
318 IN PMIXER_CONTEXT MixerContext
,
319 IN PMIXER_ENUM EnumFunction
,
320 IN PVOID EnumContext
)
324 ULONG DeviceIndex
, Count
;
327 if (!MixerContext
|| !EnumFunction
|| !EnumContext
)
330 return MM_STATUS_INVALID_PARAMETER
;
333 if (!MixerContext
->Alloc
|| !MixerContext
->Control
|| !MixerContext
->Free
)
336 return MM_STATUS_INVALID_PARAMETER
;
340 // start enumerating all available devices
346 // enumerate a device
347 Status
= EnumFunction(EnumContext
, DeviceIndex
, &DeviceName
, &hMixer
);
349 if (Status
!= MM_STATUS_SUCCESS
)
352 if (Status
!= MM_STATUS_NO_MORE_DEVICES
)
354 // enumeration has failed
362 // increment device index
365 Status
= MMixerSetupFilter(MixerContext
, hMixer
, &Count
, DeviceName
);
367 if (Status
!= MM_STATUS_SUCCESS
)