1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS Kernel Streaming
4c2c66affSColin Finck * FILE: lib/drivers/sound/mmixer/mmixer.c
5c2c66affSColin Finck * PURPOSE: Mixer Handling Functions
6c2c66affSColin Finck * PROGRAMMER: Johannes Anderwald
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck #include "precomp.h"
10c2c66affSColin Finck
11*60b0afc3SSerge Gautherie // #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck
14c2c66affSColin Finck ULONG
MMixerGetCount(IN PMIXER_CONTEXT MixerContext)15c2c66affSColin Finck MMixerGetCount(
16c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext)
17c2c66affSColin Finck {
18c2c66affSColin Finck PMIXER_LIST MixerList;
19c2c66affSColin Finck MIXER_STATUS Status;
20c2c66affSColin Finck
21c2c66affSColin Finck /* verify mixer context */
22c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
23c2c66affSColin Finck
24c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
25c2c66affSColin Finck {
26c2c66affSColin Finck /* invalid context passed */
27c2c66affSColin Finck return Status;
28c2c66affSColin Finck }
29c2c66affSColin Finck
30c2c66affSColin Finck /* grab mixer list */
31c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->MixerContext;
32c2c66affSColin Finck
33c2c66affSColin Finck // return number of mixers
34c2c66affSColin Finck return MixerList->MixerListCount;
35c2c66affSColin Finck }
36c2c66affSColin Finck
37c2c66affSColin Finck MIXER_STATUS
MMixerGetCapabilities(IN PMIXER_CONTEXT MixerContext,IN ULONG MixerIndex,OUT LPMIXERCAPSW MixerCaps)38c2c66affSColin Finck MMixerGetCapabilities(
39c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
40c2c66affSColin Finck IN ULONG MixerIndex,
41c2c66affSColin Finck OUT LPMIXERCAPSW MixerCaps)
42c2c66affSColin Finck {
43c2c66affSColin Finck MIXER_STATUS Status;
44c2c66affSColin Finck LPMIXER_INFO MixerInfo;
45c2c66affSColin Finck
46c2c66affSColin Finck /* verify mixer context */
47c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
48c2c66affSColin Finck
49c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
50c2c66affSColin Finck {
51c2c66affSColin Finck /* invalid context passed */
52c2c66affSColin Finck return Status;
53c2c66affSColin Finck }
54c2c66affSColin Finck
55c2c66affSColin Finck /* get mixer info */
56c2c66affSColin Finck MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex);
57c2c66affSColin Finck
58c2c66affSColin Finck if (!MixerInfo)
59c2c66affSColin Finck {
60c2c66affSColin Finck // invalid device index
61c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
62c2c66affSColin Finck }
63c2c66affSColin Finck
64c2c66affSColin Finck MixerCaps->wMid = MixerInfo->MixCaps.wMid;
65c2c66affSColin Finck MixerCaps->wPid = MixerInfo->MixCaps.wPid;
66c2c66affSColin Finck MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
67c2c66affSColin Finck MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport;
68c2c66affSColin Finck MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations;
69c2c66affSColin Finck
70c2c66affSColin Finck ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
71c2c66affSColin Finck wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname);
72c2c66affSColin Finck
73c2c66affSColin Finck return MM_STATUS_SUCCESS;
74c2c66affSColin Finck }
75c2c66affSColin Finck
76c2c66affSColin Finck MIXER_STATUS
MMixerOpen(IN PMIXER_CONTEXT MixerContext,IN ULONG MixerId,IN PVOID MixerEventContext,IN PMIXER_EVENT MixerEventRoutine,OUT PHANDLE MixerHandle)77c2c66affSColin Finck MMixerOpen(
78c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
79c2c66affSColin Finck IN ULONG MixerId,
80c2c66affSColin Finck IN PVOID MixerEventContext,
81c2c66affSColin Finck IN PMIXER_EVENT MixerEventRoutine,
82c2c66affSColin Finck OUT PHANDLE MixerHandle)
83c2c66affSColin Finck {
84c2c66affSColin Finck MIXER_STATUS Status;
85c2c66affSColin Finck LPMIXER_INFO MixerInfo;
86c2c66affSColin Finck
87c2c66affSColin Finck /* verify mixer context */
88c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
89c2c66affSColin Finck
90c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
91c2c66affSColin Finck {
92c2c66affSColin Finck /* invalid context passed */
93c2c66affSColin Finck DPRINT1("invalid context\n");
94c2c66affSColin Finck return Status;
95c2c66affSColin Finck }
96c2c66affSColin Finck
97c2c66affSColin Finck /* get mixer info */
98c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
99c2c66affSColin Finck if (!MixerInfo)
100c2c66affSColin Finck {
101c2c66affSColin Finck /* invalid mixer id */
102c2c66affSColin Finck DPRINT1("invalid mixer id %lu\n", MixerId);
103c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
104c2c66affSColin Finck }
105c2c66affSColin Finck
106c2c66affSColin Finck /* add the event */
107c2c66affSColin Finck Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
108c2c66affSColin Finck
109c2c66affSColin Finck /* store result */
110c2c66affSColin Finck *MixerHandle = (HANDLE)MixerInfo;
111c2c66affSColin Finck return MM_STATUS_SUCCESS;
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck MIXER_STATUS
MMixerClose(IN PMIXER_CONTEXT MixerContext,IN ULONG MixerId,IN PVOID MixerEventContext,IN PMIXER_EVENT MixerEventRoutine)115c2c66affSColin Finck MMixerClose(
116c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
117c2c66affSColin Finck IN ULONG MixerId,
118c2c66affSColin Finck IN PVOID MixerEventContext,
119c2c66affSColin Finck IN PMIXER_EVENT MixerEventRoutine)
120c2c66affSColin Finck {
121c2c66affSColin Finck MIXER_STATUS Status;
122c2c66affSColin Finck LPMIXER_INFO MixerInfo;
123c2c66affSColin Finck
124c2c66affSColin Finck /* verify mixer context */
125c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
126c2c66affSColin Finck
127c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
128c2c66affSColin Finck {
129c2c66affSColin Finck /* invalid context passed */
130c2c66affSColin Finck DPRINT1("invalid context\n");
131c2c66affSColin Finck return Status;
132c2c66affSColin Finck }
133c2c66affSColin Finck
134c2c66affSColin Finck /* get mixer info */
135c2c66affSColin Finck MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerId);
136c2c66affSColin Finck if (!MixerInfo)
137c2c66affSColin Finck {
138c2c66affSColin Finck /* invalid mixer id */
139c2c66affSColin Finck DPRINT1("invalid mixer id %lu\n", MixerId);
140c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
141c2c66affSColin Finck }
142c2c66affSColin Finck
143c2c66affSColin Finck /* remove event from list */
144c2c66affSColin Finck return MMixerRemoveEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine);
145c2c66affSColin Finck }
146c2c66affSColin Finck
147c2c66affSColin Finck MIXER_STATUS
MMixerGetLineInfo(IN PMIXER_CONTEXT MixerContext,IN HANDLE MixerHandle,IN ULONG MixerId,IN ULONG Flags,OUT LPMIXERLINEW MixerLine)148c2c66affSColin Finck MMixerGetLineInfo(
149c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
150c2c66affSColin Finck IN HANDLE MixerHandle,
151c2c66affSColin Finck IN ULONG MixerId,
152c2c66affSColin Finck IN ULONG Flags,
153c2c66affSColin Finck OUT LPMIXERLINEW MixerLine)
154c2c66affSColin Finck {
155c2c66affSColin Finck MIXER_STATUS Status;
156c2c66affSColin Finck LPMIXER_INFO MixerInfo;
157c2c66affSColin Finck LPMIXERLINE_EXT MixerLineSrc;
158c2c66affSColin Finck ULONG DestinationLineID;
159c2c66affSColin Finck
160c2c66affSColin Finck /* verify mixer context */
161c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
162c2c66affSColin Finck
163c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
164c2c66affSColin Finck {
165c2c66affSColin Finck /* invalid context passed */
166c2c66affSColin Finck return Status;
167c2c66affSColin Finck }
168c2c66affSColin Finck if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
169c2c66affSColin Finck {
170c2c66affSColin Finck /* caller passed mixer id */
171c2c66affSColin Finck MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
172c2c66affSColin Finck
173c2c66affSColin Finck if (!MixerHandle)
174c2c66affSColin Finck {
175c2c66affSColin Finck /* invalid parameter */
176c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
177c2c66affSColin Finck }
178c2c66affSColin Finck }
179c2c66affSColin Finck
180c2c66affSColin Finck if (MixerLine->cbStruct != sizeof(MIXERLINEW))
181c2c66affSColin Finck {
182c2c66affSColin Finck DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct);
183c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
184c2c66affSColin Finck }
185c2c66affSColin Finck
186c2c66affSColin Finck /* clear hmixer from flags */
187c2c66affSColin Finck Flags &=~MIXER_OBJECTF_HMIXER;
188c2c66affSColin Finck
189c2c66affSColin Finck DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
190c2c66affSColin Finck
191c2c66affSColin Finck if (Flags == MIXER_GETLINEINFOF_DESTINATION)
192c2c66affSColin Finck {
193c2c66affSColin Finck /* cast to mixer info */
194c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
195c2c66affSColin Finck
196c2c66affSColin Finck /* calculate destination line id */
197c2c66affSColin Finck DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
198c2c66affSColin Finck
199c2c66affSColin Finck /* get destination line */
200c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
201c2c66affSColin Finck
202c2c66affSColin Finck if (MixerLineSrc == NULL)
203c2c66affSColin Finck {
204c2c66affSColin Finck DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
205c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
206c2c66affSColin Finck }
207c2c66affSColin Finck /* copy mixer line */
208c2c66affSColin Finck MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
209c2c66affSColin Finck
210c2c66affSColin Finck /* make sure it is null terminated */
211c2c66affSColin Finck MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
212c2c66affSColin Finck MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
213c2c66affSColin Finck MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
214c2c66affSColin Finck
215c2c66affSColin Finck /* done */
216c2c66affSColin Finck return MM_STATUS_SUCCESS;
217c2c66affSColin Finck }
218c2c66affSColin Finck else if (Flags == MIXER_GETLINEINFOF_SOURCE)
219c2c66affSColin Finck {
220c2c66affSColin Finck /* cast to mixer info */
221c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
222c2c66affSColin Finck
223c2c66affSColin Finck /* calculate destination line id */
224c2c66affSColin Finck DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
225c2c66affSColin Finck
226c2c66affSColin Finck /* get destination line */
227c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
228c2c66affSColin Finck
229c2c66affSColin Finck if (MixerLineSrc == NULL)
230c2c66affSColin Finck {
231c2c66affSColin Finck DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
232c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck /* check if dwSource is out of bounds */
236c2c66affSColin Finck if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
237c2c66affSColin Finck {
238c2c66affSColin Finck DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource);
239c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
240c2c66affSColin Finck }
241c2c66affSColin Finck
242c2c66affSColin Finck /* calculate destination line id */
243c2c66affSColin Finck DestinationLineID = (MixerLine->dwSource * SOURCE_LINE) + MixerLine->dwDestination;
244c2c66affSColin Finck
245c2c66affSColin Finck DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations,
246c2c66affSColin Finck MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections,
247c2c66affSColin Finck MixerLine->dwSource, MixerLine->dwDestination,
248c2c66affSColin Finck DestinationLineID);
249c2c66affSColin Finck /* get target destination line id */
250c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
251c2c66affSColin Finck
252c2c66affSColin Finck /* sanity check */
253c2c66affSColin Finck ASSERT(MixerLineSrc);
254c2c66affSColin Finck
255c2c66affSColin Finck DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
256c2c66affSColin Finck
257c2c66affSColin Finck /* copy mixer line */
258c2c66affSColin Finck MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
259c2c66affSColin Finck
260c2c66affSColin Finck /* make sure it is null terminated */
261c2c66affSColin Finck MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
262c2c66affSColin Finck MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
263c2c66affSColin Finck MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
264c2c66affSColin Finck
265c2c66affSColin Finck /* done */
266c2c66affSColin Finck return MM_STATUS_SUCCESS;
267c2c66affSColin Finck }
268c2c66affSColin Finck else if (Flags == MIXER_GETLINEINFOF_LINEID)
269c2c66affSColin Finck {
270c2c66affSColin Finck /* cast to mixer info */
271c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
272c2c66affSColin Finck
273c2c66affSColin Finck /* try to find line */
274c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
275c2c66affSColin Finck if (!MixerLineSrc)
276c2c66affSColin Finck {
277c2c66affSColin Finck /* invalid parameter */
278c2c66affSColin Finck DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
279c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
280c2c66affSColin Finck }
281c2c66affSColin Finck
282c2c66affSColin Finck DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
283c2c66affSColin Finck
284c2c66affSColin Finck /* copy mixer line*/
285c2c66affSColin Finck MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
286c2c66affSColin Finck
287c2c66affSColin Finck /* make sure it is null terminated */
288c2c66affSColin Finck MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
289c2c66affSColin Finck MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
290c2c66affSColin Finck MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
291c2c66affSColin Finck
292c2c66affSColin Finck return MM_STATUS_SUCCESS;
293c2c66affSColin Finck }
294c2c66affSColin Finck else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
295c2c66affSColin Finck {
296c2c66affSColin Finck /* cast to mixer info */
297c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
298c2c66affSColin Finck
299c2c66affSColin Finck /* find mixer line by component type */
300c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
301c2c66affSColin Finck if (!MixerLineSrc)
302c2c66affSColin Finck {
303c2c66affSColin Finck DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType);
304c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
305c2c66affSColin Finck }
306c2c66affSColin Finck
307c2c66affSColin Finck /* copy mixer line */
308c2c66affSColin Finck MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
309c2c66affSColin Finck
310c2c66affSColin Finck /* make sure it is null terminated */
311c2c66affSColin Finck MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
312c2c66affSColin Finck MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
313c2c66affSColin Finck MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
314c2c66affSColin Finck
315c2c66affSColin Finck /* done */
316c2c66affSColin Finck return MM_STATUS_SUCCESS;
317c2c66affSColin Finck }
318c2c66affSColin Finck else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE)
319c2c66affSColin Finck {
320c2c66affSColin Finck DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
321c2c66affSColin Finck }
322c2c66affSColin Finck else
323c2c66affSColin Finck {
324c2c66affSColin Finck DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags);
325c2c66affSColin Finck }
326c2c66affSColin Finck
327c2c66affSColin Finck return MM_STATUS_NOT_IMPLEMENTED;
328c2c66affSColin Finck }
329c2c66affSColin Finck
330c2c66affSColin Finck MIXER_STATUS
MMixerGetLineControls(IN PMIXER_CONTEXT MixerContext,IN HANDLE MixerHandle,IN ULONG MixerId,IN ULONG Flags,OUT LPMIXERLINECONTROLSW MixerLineControls)331c2c66affSColin Finck MMixerGetLineControls(
332c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
333c2c66affSColin Finck IN HANDLE MixerHandle,
334c2c66affSColin Finck IN ULONG MixerId,
335c2c66affSColin Finck IN ULONG Flags,
336c2c66affSColin Finck OUT LPMIXERLINECONTROLSW MixerLineControls)
337c2c66affSColin Finck {
338c2c66affSColin Finck LPMIXER_INFO MixerInfo;
339c2c66affSColin Finck LPMIXERLINE_EXT MixerLineSrc;
340c2c66affSColin Finck LPMIXERCONTROL_EXT MixerControl;
341c2c66affSColin Finck MIXER_STATUS Status;
342c2c66affSColin Finck PLIST_ENTRY Entry;
343c2c66affSColin Finck ULONG Index;
344c2c66affSColin Finck
345c2c66affSColin Finck /* verify mixer context */
346c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
347c2c66affSColin Finck
348c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
349c2c66affSColin Finck {
350c2c66affSColin Finck /* invalid context passed */
351c2c66affSColin Finck return Status;
352c2c66affSColin Finck }
353c2c66affSColin Finck
354c2c66affSColin Finck if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW))
355c2c66affSColin Finck {
356c2c66affSColin Finck DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
357c2c66affSColin Finck /* invalid parameter */
358c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
359c2c66affSColin Finck }
360c2c66affSColin Finck
361c2c66affSColin Finck if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
362c2c66affSColin Finck {
363c2c66affSColin Finck DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbmxctrl, sizeof(MIXERCONTROLW));
364c2c66affSColin Finck /* invalid parameter */
365c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
366c2c66affSColin Finck }
367c2c66affSColin Finck
368c2c66affSColin Finck if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
369c2c66affSColin Finck {
370c2c66affSColin Finck /* caller passed mixer id */
371c2c66affSColin Finck MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
372c2c66affSColin Finck
373c2c66affSColin Finck if (!MixerHandle)
374c2c66affSColin Finck {
375c2c66affSColin Finck /* invalid parameter */
376c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
377c2c66affSColin Finck }
378c2c66affSColin Finck }
379c2c66affSColin Finck
380c2c66affSColin Finck Flags &= ~MIXER_OBJECTF_HMIXER;
381c2c66affSColin Finck
382c2c66affSColin Finck DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
383c2c66affSColin Finck
384c2c66affSColin Finck if (Flags == MIXER_GETLINECONTROLSF_ALL)
385c2c66affSColin Finck {
386c2c66affSColin Finck /* cast to mixer info */
387c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
388c2c66affSColin Finck
389c2c66affSColin Finck /* get mixer line */
390c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
391c2c66affSColin Finck
392c2c66affSColin Finck if (!MixerLineSrc)
393c2c66affSColin Finck {
394c2c66affSColin Finck /* invalid line id */
395c2c66affSColin Finck DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
396c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
397c2c66affSColin Finck }
398c2c66affSColin Finck
399c2c66affSColin Finck if (MixerLineSrc->Line.cControls != MixerLineControls->cControls)
400c2c66affSColin Finck {
401c2c66affSColin Finck /* invalid parameter */
402c2c66affSColin Finck DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls);
403c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
404c2c66affSColin Finck }
405c2c66affSColin Finck
406c2c66affSColin Finck /* copy line control(s) */
407c2c66affSColin Finck Entry = MixerLineSrc->ControlsList.Flink;
408c2c66affSColin Finck Index = 0;
409c2c66affSColin Finck while(Entry != &MixerLineSrc->ControlsList)
410c2c66affSColin Finck {
411c2c66affSColin Finck /* get mixer control */
412c2c66affSColin Finck MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
413c2c66affSColin Finck
414c2c66affSColin Finck /* copy mixer control */
415c2c66affSColin Finck MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW));
416c2c66affSColin Finck
417c2c66affSColin Finck /* move to next */
418c2c66affSColin Finck Entry = Entry->Flink;
419c2c66affSColin Finck
420c2c66affSColin Finck /* increment mixer control offset */
421c2c66affSColin Finck Index++;
422c2c66affSColin Finck }
423c2c66affSColin Finck return MM_STATUS_SUCCESS;
424c2c66affSColin Finck }
425c2c66affSColin Finck else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
426c2c66affSColin Finck {
427c2c66affSColin Finck /* cast to mixer info */
428c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
429c2c66affSColin Finck
430c2c66affSColin Finck /* get mixer line */
431c2c66affSColin Finck MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
432c2c66affSColin Finck
433c2c66affSColin Finck if (!MixerLineSrc)
434c2c66affSColin Finck {
435c2c66affSColin Finck /* invalid line id */
436c2c66affSColin Finck DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
437c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
438c2c66affSColin Finck }
439c2c66affSColin Finck
440c2c66affSColin Finck /* sanity checks */
441c2c66affSColin Finck ASSERT(MixerLineControls->cControls == 1);
442c2c66affSColin Finck ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
443c2c66affSColin Finck ASSERT(MixerLineControls->pamxctrl != NULL);
444c2c66affSColin Finck
445c2c66affSColin Finck Entry = MixerLineSrc->ControlsList.Flink;
446c2c66affSColin Finck while(Entry != &MixerLineSrc->ControlsList)
447c2c66affSColin Finck {
448c2c66affSColin Finck MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
449c2c66affSColin Finck if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
450c2c66affSColin Finck {
451c2c66affSColin Finck /* found a control with that type */
452c2c66affSColin Finck MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
453c2c66affSColin Finck return MM_STATUS_SUCCESS;
454c2c66affSColin Finck }
455c2c66affSColin Finck
456c2c66affSColin Finck /* move to next entry */
457c2c66affSColin Finck Entry = Entry->Flink;
458c2c66affSColin Finck }
459c2c66affSColin Finck
460c2c66affSColin Finck DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
461c2c66affSColin Finck return MM_STATUS_UNSUCCESSFUL;
462c2c66affSColin Finck }
463c2c66affSColin Finck else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
464c2c66affSColin Finck {
465c2c66affSColin Finck /* cast to mixer info */
466c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
467c2c66affSColin Finck
468c2c66affSColin Finck Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
469c2c66affSColin Finck
470c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
471c2c66affSColin Finck {
472c2c66affSColin Finck /* invalid parameter */
473c2c66affSColin Finck DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
474c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
475c2c66affSColin Finck }
476c2c66affSColin Finck
477c2c66affSColin Finck ASSERT(MixerLineControls->cControls == 1);
478c2c66affSColin Finck ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
479c2c66affSColin Finck ASSERT(MixerLineControls->pamxctrl != NULL);
480c2c66affSColin Finck
481c2c66affSColin Finck DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName);
482c2c66affSColin Finck
483c2c66affSColin Finck /* copy the controls */
484c2c66affSColin Finck MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
485c2c66affSColin Finck MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
486c2c66affSColin Finck MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
487c2c66affSColin Finck
488c2c66affSColin Finck return MM_STATUS_SUCCESS;
489c2c66affSColin Finck }
490c2c66affSColin Finck UNIMPLEMENTED;
491c2c66affSColin Finck return MM_STATUS_NOT_IMPLEMENTED;
492c2c66affSColin Finck }
493c2c66affSColin Finck
494c2c66affSColin Finck MIXER_STATUS
MMixerSetControlDetails(IN PMIXER_CONTEXT MixerContext,IN HANDLE MixerHandle,IN ULONG MixerId,IN ULONG Flags,OUT LPMIXERCONTROLDETAILS MixerControlDetails)495c2c66affSColin Finck MMixerSetControlDetails(
496c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
497c2c66affSColin Finck IN HANDLE MixerHandle,
498c2c66affSColin Finck IN ULONG MixerId,
499c2c66affSColin Finck IN ULONG Flags,
500c2c66affSColin Finck OUT LPMIXERCONTROLDETAILS MixerControlDetails)
501c2c66affSColin Finck {
502c2c66affSColin Finck MIXER_STATUS Status;
503c2c66affSColin Finck ULONG NodeId;
504c2c66affSColin Finck LPMIXER_INFO MixerInfo;
505c2c66affSColin Finck LPMIXERLINE_EXT MixerLine;
506c2c66affSColin Finck LPMIXERCONTROL_EXT MixerControl;
507c2c66affSColin Finck
508c2c66affSColin Finck /* verify mixer context */
509c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
510c2c66affSColin Finck
511c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
512c2c66affSColin Finck {
513c2c66affSColin Finck /* invalid context passed */
514c2c66affSColin Finck DPRINT1("invalid context\n");
515c2c66affSColin Finck return Status;
516c2c66affSColin Finck }
517c2c66affSColin Finck
518c2c66affSColin Finck if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
519c2c66affSColin Finck {
520c2c66affSColin Finck /* caller passed mixer id */
521c2c66affSColin Finck MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
522c2c66affSColin Finck
523c2c66affSColin Finck if (!MixerHandle)
524c2c66affSColin Finck {
525c2c66affSColin Finck /* invalid parameter */
526c2c66affSColin Finck DPRINT1("invalid handle\n");
527c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
528c2c66affSColin Finck }
529c2c66affSColin Finck }
530c2c66affSColin Finck
531c2c66affSColin Finck /* get mixer info */
532c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
533c2c66affSColin Finck
534c2c66affSColin Finck /* get mixer control */
535c2c66affSColin Finck Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
536c2c66affSColin Finck
537c2c66affSColin Finck /* check for success */
538c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
539c2c66affSColin Finck {
540c2c66affSColin Finck /* failed to find control id */
541c2c66affSColin Finck DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
542c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
543c2c66affSColin Finck }
544c2c66affSColin Finck
545c2c66affSColin Finck DPRINT("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId);
546c2c66affSColin Finck switch(MixerControl->Control.dwControlType)
547c2c66affSColin Finck {
548c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_MUTE:
549c2c66affSColin Finck Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
550c2c66affSColin Finck break;
551c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_VOLUME:
552c2c66affSColin Finck Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
553c2c66affSColin Finck break;
554c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_MUX:
555c2c66affSColin Finck Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine);
556c2c66affSColin Finck break;
557c2c66affSColin Finck default:
558c2c66affSColin Finck Status = MM_STATUS_NOT_IMPLEMENTED;
559c2c66affSColin Finck }
560c2c66affSColin Finck
561c2c66affSColin Finck return Status;
562c2c66affSColin Finck }
563c2c66affSColin Finck
564c2c66affSColin Finck MIXER_STATUS
MMixerGetControlDetails(IN PMIXER_CONTEXT MixerContext,IN HANDLE MixerHandle,IN ULONG MixerId,IN ULONG Flags,OUT LPMIXERCONTROLDETAILS MixerControlDetails)565c2c66affSColin Finck MMixerGetControlDetails(
566c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
567c2c66affSColin Finck IN HANDLE MixerHandle,
568c2c66affSColin Finck IN ULONG MixerId,
569c2c66affSColin Finck IN ULONG Flags,
570c2c66affSColin Finck OUT LPMIXERCONTROLDETAILS MixerControlDetails)
571c2c66affSColin Finck {
572c2c66affSColin Finck MIXER_STATUS Status;
573c2c66affSColin Finck ULONG NodeId;
574c2c66affSColin Finck LPMIXER_INFO MixerInfo;
575c2c66affSColin Finck LPMIXERLINE_EXT MixerLine;
576c2c66affSColin Finck LPMIXERCONTROL_EXT MixerControl;
577c2c66affSColin Finck
578c2c66affSColin Finck /* verify mixer context */
579c2c66affSColin Finck Status = MMixerVerifyContext(MixerContext);
580c2c66affSColin Finck
581c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
582c2c66affSColin Finck {
583c2c66affSColin Finck /* invalid context passed */
584c2c66affSColin Finck return Status;
585c2c66affSColin Finck }
586c2c66affSColin Finck
587c2c66affSColin Finck if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
588c2c66affSColin Finck {
589c2c66affSColin Finck /* caller passed mixer id */
590c2c66affSColin Finck MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
591c2c66affSColin Finck
592c2c66affSColin Finck if (!MixerHandle)
593c2c66affSColin Finck {
594c2c66affSColin Finck /* invalid parameter */
595c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
596c2c66affSColin Finck }
597c2c66affSColin Finck }
598c2c66affSColin Finck
599c2c66affSColin Finck /* get mixer info */
600c2c66affSColin Finck MixerInfo = (LPMIXER_INFO)MixerHandle;
601c2c66affSColin Finck
602c2c66affSColin Finck /* get mixer control */
603c2c66affSColin Finck Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
604c2c66affSColin Finck
605c2c66affSColin Finck /* check for success */
606c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
607c2c66affSColin Finck {
608c2c66affSColin Finck /* failed to find control id */
609c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
610c2c66affSColin Finck }
611c2c66affSColin Finck
612c2c66affSColin Finck switch(MixerControl->Control.dwControlType)
613c2c66affSColin Finck {
614c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_MUTE:
615c2c66affSColin Finck Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
616c2c66affSColin Finck break;
617c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_VOLUME:
618c2c66affSColin Finck Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
619c2c66affSColin Finck break;
620c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_ONOFF:
621c2c66affSColin Finck DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n");
622c2c66affSColin Finck break;
623c2c66affSColin Finck case MIXERCONTROL_CONTROLTYPE_MUX:
624c2c66affSColin Finck Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine);
625c2c66affSColin Finck break;
626c2c66affSColin Finck
627c2c66affSColin Finck default:
628c2c66affSColin Finck Status = MM_STATUS_NOT_IMPLEMENTED;
629c2c66affSColin Finck DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType);
630c2c66affSColin Finck }
631c2c66affSColin Finck
632c2c66affSColin Finck return Status;
633c2c66affSColin Finck }
634c2c66affSColin Finck
635c2c66affSColin Finck VOID
MMixerPrintMixerLineControls(IN LPMIXERLINE_EXT MixerLine)636c2c66affSColin Finck MMixerPrintMixerLineControls(
637c2c66affSColin Finck IN LPMIXERLINE_EXT MixerLine)
638c2c66affSColin Finck {
639c2c66affSColin Finck PLIST_ENTRY Entry;
640c2c66affSColin Finck LPMIXERCONTROL_EXT MixerControl;
641c2c66affSColin Finck ULONG Index = 0;
642c2c66affSColin Finck
643c2c66affSColin Finck Entry = MixerLine->ControlsList.Flink;
644c2c66affSColin Finck while(Entry != &MixerLine->ControlsList)
645c2c66affSColin Finck {
646c2c66affSColin Finck MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
647c2c66affSColin Finck
648c2c66affSColin Finck DPRINT1("\n");
649c2c66affSColin Finck DPRINT1("Control Index: %lu\n", Index);
650c2c66affSColin Finck DPRINT("\n");
651c2c66affSColin Finck DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct);
652c2c66affSColin Finck DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID);
653c2c66affSColin Finck DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType);
654c2c66affSColin Finck DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl);
655c2c66affSColin Finck DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems);
656c2c66affSColin Finck DPRINT1("szShortName %S\n", MixerControl->Control.szShortName);
657c2c66affSColin Finck DPRINT1("szName %S\n", MixerControl->Control.szName);
658c2c66affSColin Finck DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum);
659c2c66affSColin Finck DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum);
660c2c66affSColin Finck
661c2c66affSColin Finck DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]);
662c2c66affSColin Finck DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]);
663c2c66affSColin Finck DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]);
664c2c66affSColin Finck DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]);
665c2c66affSColin Finck DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]);
666c2c66affSColin Finck DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]);
667c2c66affSColin Finck
668c2c66affSColin Finck Entry = Entry->Flink;
669c2c66affSColin Finck Index++;
670c2c66affSColin Finck }
671c2c66affSColin Finck }
672c2c66affSColin Finck
673c2c66affSColin Finck VOID
MMixerPrintMixers(IN PMIXER_CONTEXT MixerContext,IN PMIXER_LIST MixerList)674c2c66affSColin Finck MMixerPrintMixers(
675c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
676c2c66affSColin Finck IN PMIXER_LIST MixerList)
677c2c66affSColin Finck {
678c2c66affSColin Finck ULONG Index, SubIndex, DestinationLineID, SrcIndex;
679c2c66affSColin Finck LPMIXER_INFO MixerInfo;
680c2c66affSColin Finck LPMIXERLINE_EXT DstMixerLine, SrcMixerLine;
681c2c66affSColin Finck
682c2c66affSColin Finck DPRINT1("MixerList %p\n", MixerList);
683c2c66affSColin Finck DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
684c2c66affSColin Finck DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
685c2c66affSColin Finck DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
686c2c66affSColin Finck DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
687c2c66affSColin Finck DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
688c2c66affSColin Finck
689c2c66affSColin Finck for(Index = 0; Index < MixerList->MixerListCount; Index++)
690c2c66affSColin Finck {
691c2c66affSColin Finck /* get mixer info */
692c2c66affSColin Finck MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
693c2c66affSColin Finck
694c2c66affSColin Finck ASSERT(MixerInfo);
695c2c66affSColin Finck DPRINT1("\n");
696c2c66affSColin Finck DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
697c2c66affSColin Finck DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
698c2c66affSColin Finck DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
699c2c66affSColin Finck DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
700c2c66affSColin Finck DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
701c2c66affSColin Finck DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
702c2c66affSColin Finck
703c2c66affSColin Finck for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
704c2c66affSColin Finck {
705c2c66affSColin Finck /* calculate destination line id */
706c2c66affSColin Finck DestinationLineID = (SubIndex + DESTINATION_LINE);
707c2c66affSColin Finck
708c2c66affSColin Finck /* get destination line */
709c2c66affSColin Finck DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
710c2c66affSColin Finck DPRINT1("//----------------------------------------------------------------------------------------------\n");
711c2c66affSColin Finck DPRINT1("\n");
712c2c66affSColin Finck DPRINT1("Destination Index %lu\n", SubIndex);
713c2c66affSColin Finck DPRINT1("\n");
714c2c66affSColin Finck DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
715c2c66affSColin Finck DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
716c2c66affSColin Finck DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
717c2c66affSColin Finck DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
718c2c66affSColin Finck DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
719c2c66affSColin Finck DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
720c2c66affSColin Finck DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
721c2c66affSColin Finck DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
722c2c66affSColin Finck DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
723c2c66affSColin Finck DPRINT1("szName %S\n", DstMixerLine->Line.szName);
724c2c66affSColin Finck DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
725c2c66affSColin Finck DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
726c2c66affSColin Finck DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
727c2c66affSColin Finck DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
728c2c66affSColin Finck DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
729c2c66affSColin Finck DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
730c2c66affSColin Finck DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
731c2c66affSColin Finck MMixerPrintMixerLineControls(DstMixerLine);
732c2c66affSColin Finck
733c2c66affSColin Finck for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++)
734c2c66affSColin Finck {
735c2c66affSColin Finck /* calculate destination line id */
736c2c66affSColin Finck DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex;
737c2c66affSColin Finck
738c2c66affSColin Finck /* get source line */
739c2c66affSColin Finck SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
740c2c66affSColin Finck DPRINT1("//==============================================================================================\n");
741c2c66affSColin Finck DPRINT1("\n");
742c2c66affSColin Finck DPRINT1("SrcLineIndex : %lu\n", SrcIndex);
743c2c66affSColin Finck DPRINT1("\n");
744c2c66affSColin Finck DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels);
745c2c66affSColin Finck DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections);
746c2c66affSColin Finck DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls);
747c2c66affSColin Finck DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType);
748c2c66affSColin Finck DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination);
749c2c66affSColin Finck DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID);
750c2c66affSColin Finck DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource);
751c2c66affSColin Finck DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser);
752c2c66affSColin Finck DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine);
753c2c66affSColin Finck DPRINT1("szName %S\n", SrcMixerLine->Line.szName);
754c2c66affSColin Finck DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName);
755c2c66affSColin Finck DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID);
756c2c66affSColin Finck DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType);
757c2c66affSColin Finck DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname);
758c2c66affSColin Finck DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion);
759c2c66affSColin Finck DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid );
760c2c66affSColin Finck DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid);
761c2c66affSColin Finck MMixerPrintMixerLineControls(SrcMixerLine);
762c2c66affSColin Finck }
763c2c66affSColin Finck }
764c2c66affSColin Finck }
765c2c66affSColin Finck }
766c2c66affSColin Finck
767c2c66affSColin Finck MIXER_STATUS
MMixerInitialize(IN PMIXER_CONTEXT MixerContext,IN PMIXER_ENUM EnumFunction,IN PVOID EnumContext)768c2c66affSColin Finck MMixerInitialize(
769c2c66affSColin Finck IN PMIXER_CONTEXT MixerContext,
770c2c66affSColin Finck IN PMIXER_ENUM EnumFunction,
771c2c66affSColin Finck IN PVOID EnumContext)
772c2c66affSColin Finck {
773c2c66affSColin Finck MIXER_STATUS Status;
774c2c66affSColin Finck HANDLE hMixer, hKey;
775c2c66affSColin Finck ULONG DeviceIndex, Count;
776c2c66affSColin Finck LPWSTR DeviceName;
777c2c66affSColin Finck LPMIXER_DATA MixerData;
778c2c66affSColin Finck PMIXER_LIST MixerList;
779c2c66affSColin Finck PLIST_ENTRY Entry;
780c2c66affSColin Finck
781c2c66affSColin Finck if (!MixerContext || !EnumFunction || !EnumContext)
782c2c66affSColin Finck {
783c2c66affSColin Finck /* invalid parameter */
784c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
785c2c66affSColin Finck }
786c2c66affSColin Finck
787c2c66affSColin Finck if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open ||
788c2c66affSColin Finck !MixerContext->AllocEventData || !MixerContext->FreeEventData ||
789c2c66affSColin Finck !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
790c2c66affSColin Finck {
791c2c66affSColin Finck /* invalid parameter */
792c2c66affSColin Finck return MM_STATUS_INVALID_PARAMETER;
793c2c66affSColin Finck }
794c2c66affSColin Finck
795c2c66affSColin Finck /* allocate a mixer list */
796c2c66affSColin Finck MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
797c2c66affSColin Finck if (!MixerList)
798c2c66affSColin Finck {
799c2c66affSColin Finck /* no memory */
800c2c66affSColin Finck return MM_STATUS_NO_MEMORY;
801c2c66affSColin Finck }
802c2c66affSColin Finck
803c2c66affSColin Finck /* initialize mixer list */
804c2c66affSColin Finck MixerList->MixerListCount = 0;
805c2c66affSColin Finck MixerList->MixerDataCount = 0;
806c2c66affSColin Finck MixerList->WaveInListCount = 0;
807c2c66affSColin Finck MixerList->WaveOutListCount = 0;
808c2c66affSColin Finck MixerList->MidiInListCount = 0;
809c2c66affSColin Finck MixerList->MidiOutListCount = 0;
810c2c66affSColin Finck InitializeListHead(&MixerList->MixerList);
811c2c66affSColin Finck InitializeListHead(&MixerList->MixerData);
812c2c66affSColin Finck InitializeListHead(&MixerList->WaveInList);
813c2c66affSColin Finck InitializeListHead(&MixerList->WaveOutList);
814c2c66affSColin Finck InitializeListHead(&MixerList->MidiInList);
815c2c66affSColin Finck InitializeListHead(&MixerList->MidiOutList);
816c2c66affSColin Finck
817c2c66affSColin Finck /* store mixer list */
818c2c66affSColin Finck MixerContext->MixerContext = (PVOID)MixerList;
819c2c66affSColin Finck
820c2c66affSColin Finck /* start enumerating all available devices */
821c2c66affSColin Finck Count = 0;
822c2c66affSColin Finck DeviceIndex = 0;
823c2c66affSColin Finck
824c2c66affSColin Finck do
825c2c66affSColin Finck {
826c2c66affSColin Finck /* enumerate a device */
827c2c66affSColin Finck Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
828c2c66affSColin Finck
829c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
830c2c66affSColin Finck {
831c2c66affSColin Finck /* check error code */
832c2c66affSColin Finck if (Status == MM_STATUS_NO_MORE_DEVICES)
833c2c66affSColin Finck {
834c2c66affSColin Finck /* enumeration has finished */
835c2c66affSColin Finck break;
836c2c66affSColin Finck }
837c2c66affSColin Finck else
838c2c66affSColin Finck {
839c2c66affSColin Finck DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
840c2c66affSColin Finck
841c2c66affSColin Finck /* TODO cleanup */
842c2c66affSColin Finck return Status;
843c2c66affSColin Finck }
844c2c66affSColin Finck }
845c2c66affSColin Finck else
846c2c66affSColin Finck {
847c2c66affSColin Finck /* create a mixer data entry */
848c2c66affSColin Finck Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
849c2c66affSColin Finck if (Status != MM_STATUS_SUCCESS)
850c2c66affSColin Finck break;
851c2c66affSColin Finck }
852c2c66affSColin Finck
853c2c66affSColin Finck /* increment device index */
854c2c66affSColin Finck DeviceIndex++;
855c2c66affSColin Finck }while(TRUE);
856c2c66affSColin Finck
857c2c66affSColin Finck /* now all filters have been pre-opened
858c2c66affSColin Finck * lets enumerate the filters
859c2c66affSColin Finck */
860c2c66affSColin Finck Entry = MixerList->MixerData.Flink;
861c2c66affSColin Finck while(Entry != &MixerList->MixerData)
862c2c66affSColin Finck {
863c2c66affSColin Finck MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
864c2c66affSColin Finck MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count);
865c2c66affSColin Finck Entry = Entry->Flink;
866c2c66affSColin Finck }
867c2c66affSColin Finck
868c2c66affSColin Finck Entry = MixerList->MixerData.Flink;
869c2c66affSColin Finck while(Entry != &MixerList->MixerData)
870c2c66affSColin Finck {
871c2c66affSColin Finck MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
872c2c66affSColin Finck
873c2c66affSColin Finck /* now handle alternative mixer types */
874c2c66affSColin Finck MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology);
875c2c66affSColin Finck Entry = Entry->Flink;
876c2c66affSColin Finck }
877c2c66affSColin Finck
878c2c66affSColin Finck //MMixerPrintMixers(MixerContext, MixerList);
879c2c66affSColin Finck
880c2c66affSColin Finck /* done */
881c2c66affSColin Finck return MM_STATUS_SUCCESS;
882c2c66affSColin Finck }
883