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