1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/filter.c
5 * PURPOSE: Mixer Filter Functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "precomp.h"
10
11 // #define NDEBUG
12 #include <debug.h>
13
14 ULONG
MMixerGetFilterPinCount(IN PMIXER_CONTEXT MixerContext,IN HANDLE hMixer)15 MMixerGetFilterPinCount(
16 IN PMIXER_CONTEXT MixerContext,
17 IN HANDLE hMixer)
18 {
19 KSPROPERTY Pin;
20 MIXER_STATUS Status;
21 ULONG NumPins, BytesReturned;
22
23 /* setup property request */
24 Pin.Flags = KSPROPERTY_TYPE_GET;
25 Pin.Set = KSPROPSETID_Pin;
26 Pin.Id = KSPROPERTY_PIN_CTYPES;
27
28 /* query pin count */
29 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), (PULONG)&BytesReturned);
30
31 /* check for success */
32 if (Status != MM_STATUS_SUCCESS)
33 return 0;
34
35 return NumPins;
36 }
37
38 MIXER_STATUS
MMixerGetFilterTopologyProperty(IN PMIXER_CONTEXT MixerContext,IN HANDLE hMixer,IN ULONG PropertyId,OUT PKSMULTIPLE_ITEM * OutMultipleItem)39 MMixerGetFilterTopologyProperty(
40 IN PMIXER_CONTEXT MixerContext,
41 IN HANDLE hMixer,
42 IN ULONG PropertyId,
43 OUT PKSMULTIPLE_ITEM * OutMultipleItem)
44 {
45 KSPROPERTY Property;
46 PKSMULTIPLE_ITEM MultipleItem;
47 MIXER_STATUS Status;
48 ULONG BytesReturned;
49
50 /* setup property request */
51 Property.Id = PropertyId;
52 Property.Flags = KSPROPERTY_TYPE_GET;
53 Property.Set = KSPROPSETID_Topology;
54
55 /* query for the size */
56 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
57
58 if (Status != MM_STATUS_MORE_ENTRIES)
59 return Status;
60
61 /* sanity check */
62 ASSERT(BytesReturned);
63
64 /* allocate an result buffer */
65 MultipleItem = (PKSMULTIPLE_ITEM)MixerContext->Alloc(BytesReturned);
66
67 if (!MultipleItem)
68 {
69 /* not enough memory */
70 return MM_STATUS_NO_MEMORY;
71 }
72
73 /* query again with allocated buffer */
74 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
75
76 if (Status != MM_STATUS_SUCCESS)
77 {
78 /* failed */
79 MixerContext->Free((PVOID)MultipleItem);
80 return Status;
81 }
82
83 /* store result */
84 *OutMultipleItem = MultipleItem;
85
86 /* done */
87 return Status;
88 }
89
90 MIXER_STATUS
MMixerGetPhysicalConnection(IN PMIXER_CONTEXT MixerContext,IN HANDLE hMixer,IN ULONG PinId,OUT PKSPIN_PHYSICALCONNECTION * OutConnection)91 MMixerGetPhysicalConnection(
92 IN PMIXER_CONTEXT MixerContext,
93 IN HANDLE hMixer,
94 IN ULONG PinId,
95 OUT PKSPIN_PHYSICALCONNECTION *OutConnection)
96 {
97 KSP_PIN Pin;
98 MIXER_STATUS Status;
99 ULONG BytesReturned;
100 PKSPIN_PHYSICALCONNECTION Connection;
101
102 /* setup the request */
103 Pin.Property.Flags = KSPROPERTY_TYPE_GET;
104 Pin.Property.Id = KSPROPERTY_PIN_PHYSICALCONNECTION;
105 Pin.Property.Set = KSPROPSETID_Pin;
106 Pin.PinId = PinId;
107
108 /* query the pin for the physical connection */
109 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
110
111 if (Status == MM_STATUS_UNSUCCESSFUL)
112 {
113 /* pin does not have a physical connection */
114 return Status;
115 }
116 DPRINT("Status %u BytesReturned %lu\n", Status, BytesReturned);
117 Connection = (PKSPIN_PHYSICALCONNECTION)MixerContext->Alloc(BytesReturned);
118 if (!Connection)
119 {
120 /* not enough memory */
121 return MM_STATUS_NO_MEMORY;
122 }
123
124 /* query the pin for the physical connection */
125 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned);
126 if (Status != MM_STATUS_SUCCESS)
127 {
128 /* failed to query the physical connection */
129 MixerContext->Free(Connection);
130 return Status;
131 }
132
133 // store connection
134 *OutConnection = Connection;
135 return Status;
136 }
137
138 ULONG
MMixerGetControlTypeFromTopologyNode(IN LPGUID NodeType)139 MMixerGetControlTypeFromTopologyNode(
140 IN LPGUID NodeType)
141 {
142 if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_AGC))
143 {
144 /* automatic gain control */
145 return MIXERCONTROL_CONTROLTYPE_ONOFF;
146 }
147 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_LOUDNESS))
148 {
149 /* loudness control */
150 return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
151 }
152 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE))
153 {
154 /* mute control */
155 return MIXERCONTROL_CONTROLTYPE_MUTE;
156 }
157 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_TONE))
158 {
159 /* tone control
160 * FIXME
161 * MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported
162 * MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported
163 * MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported
164 */
165 UNIMPLEMENTED;
166 return MIXERCONTROL_CONTROLTYPE_ONOFF;
167 }
168 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_VOLUME))
169 {
170 /* volume control */
171 return MIXERCONTROL_CONTROLTYPE_VOLUME;
172 }
173 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_PEAKMETER))
174 {
175 /* peakmeter control */
176 return MIXERCONTROL_CONTROLTYPE_PEAKMETER;
177 }
178 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
179 {
180 /* mux control */
181 return MIXERCONTROL_CONTROLTYPE_MUX;
182 }
183 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE))
184 {
185 /* stero wide control */
186 return MIXERCONTROL_CONTROLTYPE_FADER;
187 }
188 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_CHORUS))
189 {
190 /* chorus control */
191 return MIXERCONTROL_CONTROLTYPE_FADER;
192 }
193 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_REVERB))
194 {
195 /* reverb control */
196 return MIXERCONTROL_CONTROLTYPE_FADER;
197 }
198 else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_SUPERMIX))
199 {
200 /* supermix control
201 * MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported
202 */
203 UNIMPLEMENTED;
204 return MIXERCONTROL_CONTROLTYPE_VOLUME;
205 }
206 /* TODO
207 * check for other supported node types
208 */
209 //UNIMPLEMENTED;
210 return 0;
211 }
212
213 MIXER_STATUS
MMixerSetGetControlDetails(IN PMIXER_CONTEXT MixerContext,IN HANDLE hMixer,IN ULONG NodeId,IN ULONG bSet,IN ULONG PropertyId,IN ULONG Channel,IN PLONG InputValue)214 MMixerSetGetControlDetails(
215 IN PMIXER_CONTEXT MixerContext,
216 IN HANDLE hMixer,
217 IN ULONG NodeId,
218 IN ULONG bSet,
219 IN ULONG PropertyId,
220 IN ULONG Channel,
221 IN PLONG InputValue)
222 {
223 KSNODEPROPERTY_AUDIO_CHANNEL Property;
224 MIXER_STATUS Status;
225 LONG Value;
226 ULONG BytesReturned;
227
228 if (bSet)
229 Value = *InputValue;
230
231 /* setup the request */
232 RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL));
233
234 Property.NodeProperty.NodeId = NodeId;
235 Property.NodeProperty.Property.Id = PropertyId;
236 Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY;
237 Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
238 Property.Channel = Channel;
239 Property.Reserved = 0;
240
241 if (bSet)
242 Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET;
243 else
244 Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET;
245
246 /* send the request */
247 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(LONG), &BytesReturned);
248
249 if (!bSet && Status == MM_STATUS_SUCCESS)
250 {
251 *InputValue = Value;
252 }
253
254 DPRINT("Status %x bSet %u NodeId %u Value %d PropertyId %u\n", Status, bSet, NodeId, Value, PropertyId);
255 return Status;
256 }
257
258 ULONG
MMixerGetPinInstanceCount(PMIXER_CONTEXT MixerContext,HANDLE hFilter,ULONG PinId)259 MMixerGetPinInstanceCount(
260 PMIXER_CONTEXT MixerContext,
261 HANDLE hFilter,
262 ULONG PinId)
263 {
264 KSP_PIN PinRequest;
265 KSPIN_CINSTANCES PinInstances;
266 ULONG BytesReturned;
267 MIXER_STATUS Status;
268
269 /* query the instance count */
270 PinRequest.Reserved = 0;
271 PinRequest.PinId = PinId;
272 PinRequest.Property.Set = KSPROPSETID_Pin;
273 PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
274 PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
275
276 Status = MixerContext->Control(hFilter, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
277 ASSERT(Status == MM_STATUS_SUCCESS);
278 return PinInstances.CurrentCount;
279 }
280