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