[MMIXER]
[reactos.git] / reactos / lib / drivers / sound / mmixer / sup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/sup.c
5 * PURPOSE: Mixer Support Functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10
11 #include "priv.h"
12
13 MIXER_STATUS
14 MMixerVerifyContext(
15 IN PMIXER_CONTEXT MixerContext)
16 {
17 if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT))
18 return MM_STATUS_INVALID_PARAMETER;
19
20 if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free)
21 return MM_STATUS_INVALID_PARAMETER;
22
23 if (!MixerContext->MixerContext)
24 return MM_STATUS_INVALID_PARAMETER;
25
26 return MM_STATUS_SUCCESS;
27 }
28
29 VOID
30 MMixerFreeMixerInfo(
31 IN PMIXER_CONTEXT MixerContext,
32 IN LPMIXER_INFO MixerInfo)
33 {
34 //UNIMPLEMENTED
35 // FIXME
36 // free all lines
37
38 MixerContext->Free((PVOID)MixerInfo);
39 }
40
41 LPMIXERLINE_EXT
42 MMixerGetSourceMixerLineByLineId(
43 LPMIXER_INFO MixerInfo,
44 DWORD dwLineID)
45 {
46 PLIST_ENTRY Entry;
47 LPMIXERLINE_EXT MixerLineSrc;
48
49 /* get first entry */
50 Entry = MixerInfo->LineList.Flink;
51
52 while(Entry != &MixerInfo->LineList)
53 {
54 MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
55 DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID);
56 if (MixerLineSrc->Line.dwLineID == dwLineID)
57 return MixerLineSrc;
58
59 Entry = Entry->Flink;
60 }
61
62 return NULL;
63 }
64
65 ULONG
66 MMixerGetIndexOfGuid(
67 PKSMULTIPLE_ITEM MultipleItem,
68 LPCGUID NodeType)
69 {
70 ULONG Index;
71 LPGUID Guid;
72
73 Guid = (LPGUID)(MultipleItem+1);
74
75 /* iterate through node type array */
76 for(Index = 0; Index < MultipleItem->Count; Index++)
77 {
78 if (IsEqualGUIDAligned(NodeType, Guid))
79 {
80 /* found matching guid */
81 return Index;
82 }
83 Guid++;
84 }
85 return MAXULONG;
86 }
87
88 PKSTOPOLOGY_CONNECTION
89 MMixerGetConnectionByIndex(
90 IN PKSMULTIPLE_ITEM MultipleItem,
91 IN ULONG Index)
92 {
93 PKSTOPOLOGY_CONNECTION Descriptor;
94
95 ASSERT(Index < MultipleItem->Count);
96
97 Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
98 return &Descriptor[Index];
99 }
100
101 LPGUID
102 MMixerGetNodeType(
103 IN PKSMULTIPLE_ITEM MultipleItem,
104 IN ULONG Index)
105 {
106 LPGUID NodeType;
107
108 ASSERT(Index < MultipleItem->Count);
109
110 NodeType = (LPGUID)(MultipleItem + 1);
111 return &NodeType[Index];
112 }
113
114 MIXER_STATUS
115 MMixerGetNodeIndexes(
116 IN PMIXER_CONTEXT MixerContext,
117 IN PKSMULTIPLE_ITEM MultipleItem,
118 IN ULONG NodeIndex,
119 IN ULONG bNode,
120 IN ULONG bFrom,
121 OUT PULONG NodeReferenceCount,
122 OUT PULONG *NodeReference)
123 {
124 ULONG Index, Count = 0;
125 PKSTOPOLOGY_CONNECTION Connection;
126 PULONG Refs;
127
128 // KSMULTIPLE_ITEM is followed by several KSTOPOLOGY_CONNECTION
129 Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
130
131 // first count all referenced nodes
132 for(Index = 0; Index < MultipleItem->Count; Index++)
133 {
134 if (bNode)
135 {
136 if (bFrom)
137 {
138 if (Connection->FromNode == NodeIndex)
139 {
140 // node id has a connection
141 Count++;
142 }
143 }
144 else
145 {
146 if (Connection->ToNode == NodeIndex)
147 {
148 // node id has a connection
149 Count++;
150 }
151 }
152 }
153 else
154 {
155 if (bFrom)
156 {
157 if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
158 {
159 // node id has a connection
160 Count++;
161 }
162 }
163 else
164 {
165 if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
166 {
167 // node id has a connection
168 Count++;
169 }
170 }
171 }
172
173
174 // move to next connection
175 Connection++;
176 }
177
178 ASSERT(Count != 0);
179
180 /* now allocate node index array */
181 Refs = (PULONG)MixerContext->Alloc(sizeof(ULONG) * Count);
182 if (!Refs)
183 {
184 // not enough memory
185 return MM_STATUS_NO_MEMORY;
186 }
187
188 Count = 0;
189 Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
190 for(Index = 0; Index < MultipleItem->Count; Index++)
191 {
192 if (bNode)
193 {
194 if (bFrom)
195 {
196 if (Connection->FromNode == NodeIndex)
197 {
198 /* node id has a connection */
199 Refs[Count] = Index;
200 Count++;
201 }
202 }
203 else
204 {
205 if (Connection->ToNode == NodeIndex)
206 {
207 /* node id has a connection */
208 Refs[Count] = Index;
209 Count++;
210 }
211 }
212 }
213 else
214 {
215 if (bFrom)
216 {
217 if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
218 {
219 /* node id has a connection */
220 Refs[Count] = Index;
221 Count++;
222 }
223 }
224 else
225 {
226 if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
227 {
228 /* node id has a connection */
229 Refs[Count] = Index;
230 Count++;
231 }
232 }
233 }
234
235 /* move to next connection */
236 Connection++;
237 }
238
239 /* store result */
240 *NodeReference = Refs;
241 *NodeReferenceCount = Count;
242
243 return MM_STATUS_SUCCESS;
244 }
245
246 MIXER_STATUS
247 MMixerGetTargetPins(
248 IN PMIXER_CONTEXT MixerContext,
249 IN PKSMULTIPLE_ITEM NodeTypes,
250 IN PKSMULTIPLE_ITEM NodeConnections,
251 IN ULONG NodeIndex,
252 IN ULONG bUpDirection,
253 OUT PULONG Pins,
254 IN ULONG PinCount)
255 {
256 ULONG NodeConnectionCount, Index;
257 MIXER_STATUS Status;
258 PULONG NodeConnection;
259
260 // sanity check */
261 ASSERT(NodeIndex != (ULONG)-1);
262
263 /* get all node indexes referenced by that pin */
264 if (bUpDirection)
265 Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
266 else
267 Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
268
269 //DPRINT("NodeIndex %u Status %x Count %u\n", NodeIndex, Status, NodeConnectionCount);
270
271 if (Status == MM_STATUS_SUCCESS)
272 {
273 for(Index = 0; Index < NodeConnectionCount; Index++)
274 {
275 Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins);
276 ASSERT(Status == STATUS_SUCCESS);
277 }
278 MixerContext->Free((PVOID)NodeConnection);
279 }
280
281 return Status;
282 }