xref: /reactos/sdk/lib/drivers/sound/mmixer/filter.c (revision 09965760)
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