[MMEBUDDY]
[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
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 return MM_STATUS_SUCCESS;
112 }
113
114 MIXER_STATUS
115 MMixerGetLineInfo(
116 IN PMIXER_CONTEXT MixerContext,
117 IN HANDLE MixerHandle,
118 IN ULONG MixerId,
119 IN ULONG Flags,
120 OUT LPMIXERLINEW MixerLine)
121 {
122 MIXER_STATUS Status;
123 LPMIXER_INFO MixerInfo;
124 LPMIXERLINE_EXT MixerLineSrc;
125 ULONG DestinationLineID;
126
127 /* verify mixer context */
128 Status = MMixerVerifyContext(MixerContext);
129
130 if (Status != MM_STATUS_SUCCESS)
131 {
132 /* invalid context passed */
133 return Status;
134 }
135 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
136 {
137 /* caller passed mixer id */
138 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
139
140 if (!MixerHandle)
141 {
142 /* invalid parameter */
143 return MM_STATUS_INVALID_PARAMETER;
144 }
145 }
146
147 if (MixerLine->cbStruct != sizeof(MIXERLINEW))
148 {
149 DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct);
150 return MM_STATUS_INVALID_PARAMETER;
151 }
152
153 /* clear hmixer from flags */
154 Flags &=~MIXER_OBJECTF_HMIXER;
155
156 DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
157
158 if (Flags == MIXER_GETLINEINFOF_DESTINATION)
159 {
160 /* cast to mixer info */
161 MixerInfo = (LPMIXER_INFO)MixerHandle;
162
163 /* calculate destination line id */
164 DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
165
166 /* get destination line */
167 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
168
169 if (MixerLineSrc == NULL)
170 {
171 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
172 return MM_STATUS_UNSUCCESSFUL;
173 }
174 /* copy mixer line */
175 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
176
177 /* make sure it is null terminated */
178 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
179 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
180 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
181
182 /* done */
183 return MM_STATUS_SUCCESS;
184 }
185 else if (Flags == MIXER_GETLINEINFOF_SOURCE)
186 {
187 /* cast to mixer info */
188 MixerInfo = (LPMIXER_INFO)MixerHandle;
189
190 /* calculate destination line id */
191 DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
192
193 /* get destination line */
194 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
195
196 if (MixerLineSrc == NULL)
197 {
198 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
199 return MM_STATUS_UNSUCCESSFUL;
200 }
201
202 /* check if dwSource is out of bounds */
203 if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
204 {
205 DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource);
206 return MM_STATUS_UNSUCCESSFUL;
207 }
208
209 /* calculate destination line id */
210 DestinationLineID = (MixerLine->dwSource * SOURCE_LINE) + MixerLine->dwDestination;
211
212 DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations,
213 MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections,
214 MixerLine->dwSource, MixerLine->dwDestination,
215 DestinationLineID);
216 /* get target destination line id */
217 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
218
219 /* sanity check */
220 ASSERT(MixerLineSrc);
221
222 DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
223
224 /* copy mixer line */
225 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
226
227 /* make sure it is null terminated */
228 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
229 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
230 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
231
232 /* done */
233 return MM_STATUS_SUCCESS;
234 }
235 else if (Flags == MIXER_GETLINEINFOF_LINEID)
236 {
237 /* cast to mixer info */
238 MixerInfo = (LPMIXER_INFO)MixerHandle;
239
240 /* try to find line */
241 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
242 if (!MixerLineSrc)
243 {
244 /* invalid parameter */
245 DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
246 return MM_STATUS_INVALID_PARAMETER;
247 }
248
249 DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
250
251 /* copy mixer line*/
252 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
253
254 /* make sure it is null terminated */
255 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
256 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
257 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
258
259 return MM_STATUS_SUCCESS;
260 }
261 else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
262 {
263 /* cast to mixer info */
264 MixerInfo = (LPMIXER_INFO)MixerHandle;
265
266 /* find mixer line by component type */
267 MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
268 if (!MixerLineSrc)
269 {
270 DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType);
271 return MM_STATUS_UNSUCCESSFUL;
272 }
273
274 /* copy mixer line */
275 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
276
277 /* make sure it is null terminated */
278 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
279 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
280 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
281
282 /* done */
283 return MM_STATUS_SUCCESS;
284 }
285 else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE)
286 {
287 DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
288 }
289 else
290 {
291 DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags);
292 }
293
294 return MM_STATUS_NOT_IMPLEMENTED;
295 }
296
297 MIXER_STATUS
298 MMixerGetLineControls(
299 IN PMIXER_CONTEXT MixerContext,
300 IN HANDLE MixerHandle,
301 IN ULONG MixerId,
302 IN ULONG Flags,
303 OUT LPMIXERLINECONTROLSW MixerLineControls)
304 {
305 LPMIXER_INFO MixerInfo;
306 LPMIXERLINE_EXT MixerLineSrc;
307 LPMIXERCONTROL_EXT MixerControl;
308 MIXER_STATUS Status;
309 PLIST_ENTRY Entry;
310 ULONG Index;
311
312 /* verify mixer context */
313 Status = MMixerVerifyContext(MixerContext);
314
315 if (Status != MM_STATUS_SUCCESS)
316 {
317 /* invalid context passed */
318 return Status;
319 }
320
321 if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW))
322 {
323 DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
324 /* invalid parameter */
325 return MM_STATUS_INVALID_PARAMETER;
326 }
327
328 if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
329 {
330 DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
331 /* invalid parameter */
332 return MM_STATUS_INVALID_PARAMETER;
333 }
334
335 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
336 {
337 /* caller passed mixer id */
338 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
339
340 if (!MixerHandle)
341 {
342 /* invalid parameter */
343 return MM_STATUS_INVALID_PARAMETER;
344 }
345 }
346
347 Flags &= ~MIXER_OBJECTF_HMIXER;
348
349 DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
350
351 if (Flags == MIXER_GETLINECONTROLSF_ALL)
352 {
353 /* cast to mixer info */
354 MixerInfo = (LPMIXER_INFO)MixerHandle;
355
356 /* get mixer line */
357 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
358
359 if (!MixerLineSrc)
360 {
361 /* invalid line id */
362 DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
363 return MM_STATUS_INVALID_PARAMETER;
364 }
365
366 if (MixerLineSrc->Line.cControls != MixerLineControls->cControls)
367 {
368 /* invalid parameter */
369 DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls);
370 return MM_STATUS_INVALID_PARAMETER;
371 }
372
373 /* copy line control(s) */
374 Entry = MixerLineSrc->ControlsList.Flink;
375 Index = 0;
376 while(Entry != &MixerLineSrc->ControlsList)
377 {
378 /* get mixer control */
379 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
380
381 /* copy mixer control */
382 MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW));
383
384 /* move to next */
385 Entry = Entry->Flink;
386
387 /* increment mixer control offset */
388 Index++;
389 }
390 return MM_STATUS_SUCCESS;
391 }
392 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
393 {
394 /* cast to mixer info */
395 MixerInfo = (LPMIXER_INFO)MixerHandle;
396
397 /* get mixer line */
398 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
399
400 if (!MixerLineSrc)
401 {
402 /* invalid line id */
403 DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
404 return MM_STATUS_INVALID_PARAMETER;
405 }
406
407 /* sanity checks */
408 ASSERT(MixerLineControls->cControls == 1);
409 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
410 ASSERT(MixerLineControls->pamxctrl != NULL);
411
412 Entry = MixerLineSrc->ControlsList.Flink;
413 while(Entry != &MixerLineSrc->ControlsList)
414 {
415 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
416 if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
417 {
418 /* found a control with that type */
419 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
420 return MM_STATUS_SUCCESS;
421 }
422
423 /* move to next entry */
424 Entry = Entry->Flink;
425 }
426
427 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
428 return MM_STATUS_UNSUCCESSFUL;
429 }
430 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
431 {
432 /* cast to mixer info */
433 MixerInfo = (LPMIXER_INFO)MixerHandle;
434
435 Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
436
437 if (Status != MM_STATUS_SUCCESS)
438 {
439 /* invalid parameter */
440 DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
441 return MM_STATUS_INVALID_PARAMETER;
442 }
443
444 ASSERT(MixerLineControls->cControls == 1);
445 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
446 ASSERT(MixerLineControls->pamxctrl != NULL);
447
448 DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName);
449
450 /* copy the controls */
451 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
452 MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
453 MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
454
455 return MM_STATUS_SUCCESS;
456 }
457 UNIMPLEMENTED
458 return MM_STATUS_NOT_IMPLEMENTED;
459 }
460
461 MIXER_STATUS
462 MMixerSetControlDetails(
463 IN PMIXER_CONTEXT MixerContext,
464 IN HANDLE MixerHandle,
465 IN ULONG MixerId,
466 IN ULONG Flags,
467 OUT LPMIXERCONTROLDETAILS MixerControlDetails)
468 {
469 MIXER_STATUS Status;
470 ULONG NodeId;
471 LPMIXER_INFO MixerInfo;
472 LPMIXERLINE_EXT MixerLine;
473 LPMIXERCONTROL_EXT MixerControl;
474
475 /* verify mixer context */
476 Status = MMixerVerifyContext(MixerContext);
477
478 if (Status != MM_STATUS_SUCCESS)
479 {
480 /* invalid context passed */
481 DPRINT1("invalid context\n");
482 return Status;
483 }
484
485 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
486 {
487 /* caller passed mixer id */
488 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
489
490 if (!MixerHandle)
491 {
492 /* invalid parameter */
493 DPRINT1("invalid handle\n");
494 return MM_STATUS_INVALID_PARAMETER;
495 }
496 }
497
498 /* get mixer info */
499 MixerInfo = (LPMIXER_INFO)MixerHandle;
500
501 /* get mixer control */
502 Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
503
504 /* check for success */
505 if (Status != MM_STATUS_SUCCESS)
506 {
507 /* failed to find control id */
508 DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
509 return MM_STATUS_INVALID_PARAMETER;
510 }
511
512 DPRINT("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId);
513 switch(MixerControl->Control.dwControlType)
514 {
515 case MIXERCONTROL_CONTROLTYPE_MUTE:
516 Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
517 break;
518 case MIXERCONTROL_CONTROLTYPE_VOLUME:
519 Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
520 break;
521 case MIXERCONTROL_CONTROLTYPE_MUX:
522 Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine);
523 break;
524 default:
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 case MIXERCONTROL_CONTROLTYPE_ONOFF:
588 DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n");
589 break;
590 case MIXERCONTROL_CONTROLTYPE_MUX:
591 Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine);
592 break;
593
594 default:
595 Status = MM_STATUS_NOT_IMPLEMENTED;
596 DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType);
597 }
598
599 return Status;
600 }
601
602 VOID
603 MMixerPrintMixerLineControls(
604 IN LPMIXERLINE_EXT MixerLine)
605 {
606 PLIST_ENTRY Entry;
607 LPMIXERCONTROL_EXT MixerControl;
608 ULONG Index = 0;
609
610 Entry = MixerLine->ControlsList.Flink;
611 while(Entry != &MixerLine->ControlsList)
612 {
613 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
614
615 DPRINT1("\n");
616 DPRINT1("Control Index: %lu\n", Index);
617 DPRINT("\n");
618 DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct);
619 DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID);
620 DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType);
621 DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl);
622 DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems);
623 DPRINT1("szShortName %S\n", MixerControl->Control.szShortName);
624 DPRINT1("szName %S\n", MixerControl->Control.szName);
625 DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum);
626 DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum);
627
628 DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]);
629 DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]);
630 DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]);
631 DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]);
632 DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]);
633 DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]);
634
635 Entry = Entry->Flink;
636 Index++;
637 }
638 }
639
640 VOID
641 MMixerPrintMixers(
642 IN PMIXER_CONTEXT MixerContext,
643 IN PMIXER_LIST MixerList)
644 {
645 ULONG Index, SubIndex, DestinationLineID, SrcIndex;
646 LPMIXER_INFO MixerInfo;
647 LPMIXERLINE_EXT DstMixerLine, SrcMixerLine;
648
649 DPRINT1("MixerList %p\n", MixerList);
650 DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
651 DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
652 DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
653 DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
654 DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
655
656
657 for(Index = 0; Index < MixerList->MixerListCount; Index++)
658 {
659 /* get mixer info */
660 MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
661
662 ASSERT(MixerInfo);
663 DPRINT1("\n");
664 DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
665 DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
666 DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
667 DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
668 DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
669 DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
670
671 for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
672 {
673 /* calculate destination line id */
674 DestinationLineID = (SubIndex + DESTINATION_LINE);
675
676 /* get destination line */
677 DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
678 DPRINT1("//----------------------------------------------------------------------------------------------\n");
679 DPRINT1("\n");
680 DPRINT1("Destination Index %lu\n", SubIndex);
681 DPRINT1("\n");
682 DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
683 DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
684 DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
685 DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
686 DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
687 DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
688 DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
689 DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
690 DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
691 DPRINT1("szName %S\n", DstMixerLine->Line.szName);
692 DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
693 DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
694 DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
695 DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
696 DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
697 DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
698 DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
699 MMixerPrintMixerLineControls(DstMixerLine);
700
701 for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++)
702 {
703 /* calculate destination line id */
704 DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex;
705
706 /* get source line */
707 SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
708 DPRINT1("//==============================================================================================\n");
709 DPRINT1("\n");
710 DPRINT1("SrcLineIndex : %lu\n", SrcIndex);
711 DPRINT1("\n");
712 DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels);
713 DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections);
714 DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls);
715 DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType);
716 DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination);
717 DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID);
718 DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource);
719 DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser);
720 DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine);
721 DPRINT1("szName %S\n", SrcMixerLine->Line.szName);
722 DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName);
723 DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID);
724 DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType);
725 DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname);
726 DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion);
727 DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid );
728 DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid);
729 MMixerPrintMixerLineControls(SrcMixerLine);
730 }
731 }
732 }
733 }
734
735 MIXER_STATUS
736 MMixerInitialize(
737 IN PMIXER_CONTEXT MixerContext,
738 IN PMIXER_ENUM EnumFunction,
739 IN PVOID EnumContext)
740 {
741 MIXER_STATUS Status;
742 HANDLE hMixer, hKey;
743 ULONG DeviceIndex, Count;
744 LPWSTR DeviceName;
745 LPMIXER_DATA MixerData;
746 PMIXER_LIST MixerList;
747 PLIST_ENTRY Entry;
748
749 if (!MixerContext || !EnumFunction || !EnumContext)
750 {
751 /* invalid parameter */
752 return MM_STATUS_INVALID_PARAMETER;
753 }
754
755 if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open ||
756 !MixerContext->AllocEventData || !MixerContext->FreeEventData ||
757 !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
758 {
759 /* invalid parameter */
760 return MM_STATUS_INVALID_PARAMETER;
761 }
762
763 /* allocate a mixer list */
764 MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
765 if (!MixerList)
766 {
767 /* no memory */
768 return MM_STATUS_NO_MEMORY;
769 }
770
771 /* initialize mixer list */
772 MixerList->MixerListCount = 0;
773 MixerList->MixerDataCount = 0;
774 MixerList->WaveInListCount = 0;
775 MixerList->WaveOutListCount = 0;
776 MixerList->MidiInListCount = 0;
777 MixerList->MidiOutListCount = 0;
778 InitializeListHead(&MixerList->MixerList);
779 InitializeListHead(&MixerList->MixerData);
780 InitializeListHead(&MixerList->WaveInList);
781 InitializeListHead(&MixerList->WaveOutList);
782 InitializeListHead(&MixerList->MidiInList);
783 InitializeListHead(&MixerList->MidiOutList);
784
785 /* store mixer list */
786 MixerContext->MixerContext = (PVOID)MixerList;
787
788 /* start enumerating all available devices */
789 Count = 0;
790 DeviceIndex = 0;
791
792 do
793 {
794 /* enumerate a device */
795 Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
796
797 if (Status != MM_STATUS_SUCCESS)
798 {
799 /* check error code */
800 if (Status == MM_STATUS_NO_MORE_DEVICES)
801 {
802 /* enumeration has finished */
803 break;
804 }
805 else
806 {
807 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
808
809 /* TODO cleanup */
810 return Status;
811 }
812 }
813 else
814 {
815 /* create a mixer data entry */
816 Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
817 if (Status != MM_STATUS_SUCCESS)
818 break;
819 }
820
821 /* increment device index */
822 DeviceIndex++;
823 }while(TRUE);
824
825 /* now all filters have been pre-opened
826 * lets enumerate the filters
827 */
828 Entry = MixerList->MixerData.Flink;
829 while(Entry != &MixerList->MixerData)
830 {
831 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
832 MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count);
833 Entry = Entry->Flink;
834 }
835
836 Entry = MixerList->MixerData.Flink;
837 while(Entry != &MixerList->MixerData)
838 {
839 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
840
841 /* now handle alternative mixer types */
842 MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology);
843 Entry = Entry->Flink;
844 }
845
846 //MMixerPrintMixers(MixerContext, MixerList);
847
848 /* done */
849 return MM_STATUS_SUCCESS;
850 }