[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 LPMIXERCONTROL_EXT MixerControl;
310 MIXER_STATUS Status;
311 PLIST_ENTRY Entry;
312 ULONG Index;
313
314 /* verify mixer context */
315 Status = MMixerVerifyContext(MixerContext);
316
317 if (Status != MM_STATUS_SUCCESS)
318 {
319 /* invalid context passed */
320 return Status;
321 }
322
323 if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW))
324 {
325 DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
326 /* invalid parameter */
327 return MM_STATUS_INVALID_PARAMETER;
328 }
329
330 if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
331 {
332 DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
333 /* invalid parameter */
334 return MM_STATUS_INVALID_PARAMETER;
335 }
336
337 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
338 {
339 /* caller passed mixer id */
340 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
341
342 if (!MixerHandle)
343 {
344 /* invalid parameter */
345 return MM_STATUS_INVALID_PARAMETER;
346 }
347 }
348
349 Flags &= ~MIXER_OBJECTF_HMIXER;
350
351 DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
352
353 if (Flags == MIXER_GETLINECONTROLSF_ALL)
354 {
355 /* cast to mixer info */
356 MixerInfo = (LPMIXER_INFO)MixerHandle;
357
358 /* get mixer line */
359 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
360
361 if (!MixerLineSrc)
362 {
363 /* invalid line id */
364 DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
365 return MM_STATUS_INVALID_PARAMETER;
366 }
367
368 if (MixerLineSrc->Line.cControls != MixerLineControls->cControls)
369 {
370 /* invalid parameter */
371 DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls);
372 return MM_STATUS_INVALID_PARAMETER;
373 }
374
375 /* copy line control(s) */
376 Entry = MixerLineSrc->ControlsList.Flink;
377 Index = 0;
378 while(Entry != &MixerLineSrc->ControlsList)
379 {
380 /* get mixer control */
381 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
382
383 /* copy mixer control */
384 MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW));
385
386 /* move to next */
387 Entry = Entry->Flink;
388
389 /* increment mixer control offset */
390 Index++;
391 }
392 return MM_STATUS_SUCCESS;
393 }
394 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
395 {
396 /* cast to mixer info */
397 MixerInfo = (LPMIXER_INFO)MixerHandle;
398
399 /* get mixer line */
400 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
401
402 if (!MixerLineSrc)
403 {
404 /* invalid line id */
405 DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
406 return MM_STATUS_INVALID_PARAMETER;
407 }
408
409 /* sanity checks */
410 ASSERT(MixerLineControls->cControls == 1);
411 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
412 ASSERT(MixerLineControls->pamxctrl != NULL);
413
414 Entry = MixerLineSrc->ControlsList.Flink;
415 while(Entry != &MixerLineSrc->ControlsList)
416 {
417 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
418 if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
419 {
420 /* found a control with that type */
421 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
422 return MM_STATUS_SUCCESS;
423 }
424
425 /* move to next entry */
426 Entry = Entry->Flink;
427 }
428
429 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
430 return MM_STATUS_UNSUCCESSFUL;
431 }
432 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
433 {
434 /* cast to mixer info */
435 MixerInfo = (LPMIXER_INFO)MixerHandle;
436
437 Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
438
439 if (Status != MM_STATUS_SUCCESS)
440 {
441 /* invalid parameter */
442 DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
443 return MM_STATUS_INVALID_PARAMETER;
444 }
445
446 ASSERT(MixerLineControls->cControls == 1);
447 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
448 ASSERT(MixerLineControls->pamxctrl != NULL);
449
450 DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName);
451
452 /* copy the controls */
453 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
454 MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
455 MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
456
457 return MM_STATUS_SUCCESS;
458 }
459 UNIMPLEMENTED
460 return MM_STATUS_NOT_IMPLEMENTED;
461 }
462
463 MIXER_STATUS
464 MMixerSetControlDetails(
465 IN PMIXER_CONTEXT MixerContext,
466 IN HANDLE MixerHandle,
467 IN ULONG MixerId,
468 IN ULONG Flags,
469 OUT LPMIXERCONTROLDETAILS MixerControlDetails)
470 {
471 MIXER_STATUS Status;
472 ULONG NodeId;
473 LPMIXER_INFO MixerInfo;
474 LPMIXERLINE_EXT MixerLine;
475 LPMIXERCONTROL_EXT MixerControl;
476
477 /* verify mixer context */
478 Status = MMixerVerifyContext(MixerContext);
479
480 if (Status != MM_STATUS_SUCCESS)
481 {
482 /* invalid context passed */
483 DPRINT1("invalid context\n");
484 return Status;
485 }
486
487 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
488 {
489 /* caller passed mixer id */
490 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
491
492 if (!MixerHandle)
493 {
494 /* invalid parameter */
495 DPRINT1("invalid handle\n");
496 return MM_STATUS_INVALID_PARAMETER;
497 }
498 }
499
500 /* get mixer info */
501 MixerInfo = (LPMIXER_INFO)MixerHandle;
502
503 /* get mixer control */
504 Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
505
506 /* check for success */
507 if (Status != MM_STATUS_SUCCESS)
508 {
509 /* failed to find control id */
510 DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
511 return MM_STATUS_INVALID_PARAMETER;
512 }
513
514 DPRINT1("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId);
515 switch(MixerControl->Control.dwControlType)
516 {
517 case MIXERCONTROL_CONTROLTYPE_MUTE:
518 Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
519 break;
520 case MIXERCONTROL_CONTROLTYPE_VOLUME:
521 Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
522 break;
523 default:
524 ASSERT(0);
525 Status = MM_STATUS_NOT_IMPLEMENTED;
526 }
527
528 return Status;
529 }
530
531 MIXER_STATUS
532 MMixerGetControlDetails(
533 IN PMIXER_CONTEXT MixerContext,
534 IN HANDLE MixerHandle,
535 IN ULONG MixerId,
536 IN ULONG Flags,
537 OUT LPMIXERCONTROLDETAILS MixerControlDetails)
538 {
539 MIXER_STATUS Status;
540 ULONG NodeId;
541 LPMIXER_INFO MixerInfo;
542 LPMIXERLINE_EXT MixerLine;
543 LPMIXERCONTROL_EXT MixerControl;
544
545 /* verify mixer context */
546 Status = MMixerVerifyContext(MixerContext);
547
548 if (Status != MM_STATUS_SUCCESS)
549 {
550 /* invalid context passed */
551 return Status;
552 }
553
554 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
555 {
556 /* caller passed mixer id */
557 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
558
559 if (!MixerHandle)
560 {
561 /* invalid parameter */
562 return MM_STATUS_INVALID_PARAMETER;
563 }
564 }
565
566 /* get mixer info */
567 MixerInfo = (LPMIXER_INFO)MixerHandle;
568
569 /* get mixer control */
570 Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
571
572 /* check for success */
573 if (Status != MM_STATUS_SUCCESS)
574 {
575 /* failed to find control id */
576 return MM_STATUS_INVALID_PARAMETER;
577 }
578
579 switch(MixerControl->Control.dwControlType)
580 {
581 case MIXERCONTROL_CONTROLTYPE_MUTE:
582 Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
583 break;
584 case MIXERCONTROL_CONTROLTYPE_VOLUME:
585 Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
586 break;
587 default:
588 Status = MM_STATUS_NOT_IMPLEMENTED;
589 DPRINT1("ControlType %lu not implemented\n", MixerControl->Control.dwControlType);
590 }
591
592 return Status;
593 }
594
595 VOID
596 MMixerPrintMixerLineControls(
597 IN LPMIXERLINE_EXT MixerLine)
598 {
599 PLIST_ENTRY Entry;
600 LPMIXERCONTROL_EXT MixerControl;
601 ULONG Index = 0;
602
603 Entry = MixerLine->ControlsList.Flink;
604 while(Entry != &MixerLine->ControlsList)
605 {
606 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
607
608 DPRINT1("\n");
609 DPRINT1("Control Index: %lu\n", Index);
610 DPRINT("\n");
611 DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct);
612 DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID);
613 DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType);
614 DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl);
615 DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems);
616 DPRINT1("szShortName %S\n", MixerControl->Control.szShortName);
617 DPRINT1("szName %S\n", MixerControl->Control.szName);
618 DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum);
619 DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum);
620
621 DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]);
622 DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]);
623 DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]);
624 DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]);
625 DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]);
626 DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]);
627
628 Entry = Entry->Flink;
629 Index++;
630 }
631 }
632
633 VOID
634 MMixerPrintMixers(
635 IN PMIXER_CONTEXT MixerContext,
636 IN PMIXER_LIST MixerList)
637 {
638 ULONG Index, SubIndex, DestinationLineID, SrcIndex;
639 LPMIXER_INFO MixerInfo;
640 LPMIXERLINE_EXT DstMixerLine, SrcMixerLine;
641
642 DPRINT1("MixerList %p\n", MixerList);
643 DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
644 DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
645 DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
646 DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
647 DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
648
649
650 for(Index = 0; Index < MixerList->MixerListCount; Index++)
651 {
652 /* get mixer info */
653 MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
654
655 ASSERT(MixerInfo);
656 DPRINT1("\n");
657 DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
658 DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
659 DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
660 DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
661 DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
662 DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
663
664 for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
665 {
666 /* calculate destination line id */
667 DestinationLineID = (SubIndex + DESTINATION_LINE);
668
669 /* get destination line */
670 DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
671 DPRINT1("//----------------------------------------------------------------------------------------------\n");
672 DPRINT1("\n");
673 DPRINT1("Destination Index %lu\n", SubIndex);
674 DPRINT1("\n");
675 DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
676 DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
677 DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
678 DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
679 DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
680 DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
681 DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
682 DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
683 DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
684 DPRINT1("szName %S\n", DstMixerLine->Line.szName);
685 DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
686 DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
687 DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
688 DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
689 DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
690 DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
691 DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
692 MMixerPrintMixerLineControls(DstMixerLine);
693
694 for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++)
695 {
696 /* calculate destination line id */
697 DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex;
698
699 /* get source line */
700 SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
701 DPRINT1("//==============================================================================================\n");
702 DPRINT1("\n");
703 DPRINT1("SrcLineIndex : %lu\n", SrcIndex);
704 DPRINT1("\n");
705 DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels);
706 DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections);
707 DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls);
708 DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType);
709 DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination);
710 DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID);
711 DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource);
712 DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser);
713 DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine);
714 DPRINT1("szName %S\n", SrcMixerLine->Line.szName);
715 DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName);
716 DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID);
717 DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType);
718 DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname);
719 DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion);
720 DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid );
721 DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid);
722 MMixerPrintMixerLineControls(SrcMixerLine);
723 }
724 }
725 }
726 }
727
728 MIXER_STATUS
729 MMixerInitialize(
730 IN PMIXER_CONTEXT MixerContext,
731 IN PMIXER_ENUM EnumFunction,
732 IN PVOID EnumContext)
733 {
734 MIXER_STATUS Status;
735 HANDLE hMixer, hKey;
736 ULONG DeviceIndex, Count;
737 LPWSTR DeviceName;
738 LPMIXER_DATA MixerData;
739 PMIXER_LIST MixerList;
740 PLIST_ENTRY Entry;
741
742 if (!MixerContext || !EnumFunction || !EnumContext)
743 {
744 /* invalid parameter */
745 return MM_STATUS_INVALID_PARAMETER;
746 }
747
748 if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open ||
749 !MixerContext->AllocEventData || !MixerContext->FreeEventData ||
750 !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
751 {
752 /* invalid parameter */
753 return MM_STATUS_INVALID_PARAMETER;
754 }
755
756 /* allocate a mixer list */
757 MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
758 if (!MixerList)
759 {
760 /* no memory */
761 return MM_STATUS_NO_MEMORY;
762 }
763
764 /* initialize mixer list */
765 MixerList->MixerListCount = 0;
766 MixerList->MixerDataCount = 0;
767 MixerList->WaveInListCount = 0;
768 MixerList->WaveOutListCount = 0;
769 MixerList->MidiInListCount = 0;
770 MixerList->MidiOutListCount = 0;
771 InitializeListHead(&MixerList->MixerList);
772 InitializeListHead(&MixerList->MixerData);
773 InitializeListHead(&MixerList->WaveInList);
774 InitializeListHead(&MixerList->WaveOutList);
775 InitializeListHead(&MixerList->MidiInList);
776 InitializeListHead(&MixerList->MidiOutList);
777
778 /* store mixer list */
779 MixerContext->MixerContext = (PVOID)MixerList;
780
781 /* start enumerating all available devices */
782 Count = 0;
783 DeviceIndex = 0;
784
785 do
786 {
787 /* enumerate a device */
788 Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
789
790 if (Status != MM_STATUS_SUCCESS)
791 {
792 /* check error code */
793 if (Status == MM_STATUS_NO_MORE_DEVICES)
794 {
795 /* enumeration has finished */
796 break;
797 }
798 else
799 {
800 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
801
802 /* TODO cleanup */
803 return Status;
804 }
805 }
806 else
807 {
808 /* create a mixer data entry */
809 Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
810 if (Status != MM_STATUS_SUCCESS)
811 break;
812 }
813
814 /* increment device index */
815 DeviceIndex++;
816 }while(TRUE);
817
818 /* now all filters have been pre-opened
819 * lets enumerate the filters
820 */
821 Entry = MixerList->MixerData.Flink;
822 while(Entry != &MixerList->MixerData)
823 {
824 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
825 MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count);
826 Entry = Entry->Flink;
827 }
828
829 Entry = MixerList->MixerData.Flink;
830 while(Entry != &MixerList->MixerData)
831 {
832 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
833
834 /* now handle alternative mixer types */
835 MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology);
836 Entry = Entry->Flink;
837 }
838
839 //MMixerPrintMixers(MixerContext, MixerList);
840
841 /* done */
842 return MM_STATUS_SUCCESS;
843 }