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