ReactOS 0.4.16-dev-1506-g117cd33
controls.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/controls.c
5 * PURPOSE: Mixer Control Iteration Functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9#include "precomp.h"
10
11// #define NDEBUG
12#include <debug.h>
13
14const GUID KSNODETYPE_DESKTOP_MICROPHONE = {0xDFF21BE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
15const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR = {0xDFF21FE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
16const GUID KSNODETYPE_TELEPHONE = {0xDFF21EE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
17const GUID KSNODETYPE_PHONE_LINE = {0xDFF21EE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
18const GUID KSNODETYPE_DOWN_LINE_PHONE = {0xDFF21EE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
19const GUID KSNODETYPE_DESKTOP_SPEAKER = {0xDFF21CE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
20const GUID KSNODETYPE_ROOM_SPEAKER = {0xDFF21CE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
21const GUID KSNODETYPE_COMMUNICATION_SPEAKER = {0xDFF21CE6, 0xF70F, 0x11D0, {0xB9,0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
22const GUID KSNODETYPE_HEADPHONES = {0xDFF21CE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
23const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO = {0xDFF21CE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
24const GUID KSNODETYPE_MICROPHONE = {0xDFF21BE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9,0x22, 0x31, 0x96}};
25const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
26const GUID KSNODETYPE_SPDIF_INTERFACE = {0xDFF21FE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
27const GUID KSNODETYPE_ANALOG_CONNECTOR = {0xDFF21FE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
28const GUID KSNODETYPE_SPEAKER = {0xDFF21CE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
29const GUID KSNODETYPE_CD_PLAYER = {0xDFF220E3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
30const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
31const GUID KSNODETYPE_LINE_CONNECTOR = {0xDFF21FE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0,0xC9, 0x22, 0x31, 0x96}};
32const GUID PINNAME_VIDEO_CAPTURE = {0xfb6c4281, 0x353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}};
33
37 IN LPMIXER_INFO MixerInfo,
39 IN PTOPOLOGY Topology,
40 IN ULONG NodeIndex,
41 IN LPMIXERLINE_EXT MixerLine,
42 IN ULONG MaxChannels)
43{
49 LPMIXERCONTROL_EXT MixerControl;
50
51 /* allocate mixer control */
52 MixerControl = MixerContext->Alloc(sizeof(MIXERCONTROL_EXT));
53 if (!MixerControl)
54 {
55 /* no memory */
57 }
58
59 /* initialize mixer control */
60 MixerControl->hDevice = hMixer;
61 MixerControl->NodeID = NodeIndex;
62 MixerControl->ExtraData = NULL;
63
64 MixerControl->Control.cbStruct = sizeof(MIXERCONTROLW);
65 MixerControl->Control.dwControlID = MixerInfo->ControlId;
66
67 /* get node type */
68 NodeType = MMixerGetNodeTypeFromTopology(Topology, NodeIndex);
69 /* store control type */
71
72 MixerControl->Control.fdwControl = (MaxChannels > 1 ? 0 : MIXERCONTROL_CONTROLF_UNIFORM);
73 MixerControl->Control.cMultipleItems = 0;
74
75 /* setup request to retrieve name */
76 Node.NodeId = NodeIndex;
77 Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME;
78 Node.Property.Flags = KSPROPERTY_TYPE_GET;
79 Node.Property.Set = KSPROPSETID_Topology;
80 Node.Reserved = 0;
81
82 /* get node name size */
84
86 {
89 if (!Name)
90 {
91 /* not enough memory */
93 }
94
95 /* get node name */
97
99 {
101 MixerControl->Control.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
102
103 MixerContext->Copy(MixerControl->Control.szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
104 MixerControl->Control.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
105 }
106
107 /* free name buffer */
109 }
110
111 /* increment control count */
112 MixerInfo->ControlId++;
113
114 /* insert control */
115 InsertTailList(&MixerLine->ControlsList, &MixerControl->Entry);
116
118 {
119 ULONG NodesCount;
120 PULONG Nodes;
121
122 /* allocate topology nodes array */
124
126 {
127 /* out of memory */
128 return STATUS_NO_MEMORY;
129 }
130
131 /* get connected node count */
132 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, TRUE, &NodesCount, Nodes);
133
134 /* TODO */
135 MixerContext->Free(Nodes);
136
137 /* setup mux bounds */
138 MixerControl->Control.Bounds.dwMinimum = 0;
139 MixerControl->Control.Bounds.dwMaximum = NodesCount - 1;
140 MixerControl->Control.Metrics.dwReserved[0] = NodesCount;
141 MixerControl->Control.cMultipleItems = NodesCount;
143 }
144 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
145 {
146 MixerControl->Control.Bounds.dwMinimum = 0;
147 MixerControl->Control.Bounds.dwMaximum = 1;
148 }
149 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF)
150 {
151 /* only needs to set bounds */
152 MixerControl->Control.Bounds.dwMinimum = 0;
153 MixerControl->Control.Bounds.dwMaximum = 1;
154 }
155 else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
156 {
162
163 MixerControl->Control.Bounds.dwMinimum = 0;
164 MixerControl->Control.Bounds.dwMaximum = 0xFFFF;
165 MixerControl->Control.Metrics.cSteps = 0xC0; /* FIXME */
166
169 ASSERT(Desc);
170
171 /* setup the request */
173
174 Property.NodeProperty.NodeId = NodeIndex;
177 Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
178
179 /* get node volume level info */
181
183 {
184 LPMIXERVOLUME_DATA VolumeData;
185 ULONG Steps, MaxRange, Index;
186 LONG Value;
187
188 Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1);
189 Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1);
190
191 DPRINT("NodeIndex %u Range Min %d Max %d Steps %x UMin %x UMax %x\n", NodeIndex, Range->Bounds.SignedMinimum, Range->Bounds.SignedMaximum, Range->SteppingDelta, Range->Bounds.UnsignedMinimum, Range->Bounds.UnsignedMaximum);
192
193 MaxRange = Range->Bounds.UnsignedMaximum - Range->Bounds.UnsignedMinimum;
194
195 if (MaxRange)
196 {
197 ASSERT(MaxRange);
199 if (!VolumeData)
200 return MM_STATUS_NO_MEMORY;
201
202 Steps = MaxRange / Range->SteppingDelta + 1;
203
204 /* store mixer control info there */
205 VolumeData->Header.dwControlID = MixerControl->Control.dwControlID;
206 VolumeData->SignedMaximum = Range->Bounds.SignedMaximum;
207 VolumeData->SignedMinimum = Range->Bounds.SignedMinimum;
208 VolumeData->SteppingDelta = Range->SteppingDelta;
209 VolumeData->ValuesCount = Steps;
210 VolumeData->InputSteppingDelta = 0x10000 / Steps;
211
212 VolumeData->Values = (PLONG)MixerContext->Alloc(sizeof(LONG) * Steps);
213 if (!VolumeData->Values)
214 {
215 MixerContext->Free(Desc);
216 MixerContext->Free(VolumeData);
217 return MM_STATUS_NO_MEMORY;
218 }
219
220 Value = Range->Bounds.SignedMinimum;
221 for (Index = 0; Index < Steps; Index++)
222 {
223 VolumeData->Values[Index] = Value;
224 // HACK: use '- 1' to make the left and right volume controls behave independently.
225 Value += Range->SteppingDelta - 1;
226 }
227 MixerControl->ExtraData = VolumeData;
228 }
229 }
230 MixerContext->Free(Desc);
231 }
232
233 DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName);
234 return MM_STATUS_SUCCESS;
235}
236
240 IN LPMIXER_INFO MixerInfo,
241 IN ULONG bInputMixer,
242 IN LPWSTR LineName)
243{
244 LPMIXERLINE_EXT DestinationLine;
245
246 /* allocate a mixer destination line */
247 DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
248 if (!MixerInfo)
249 {
250 /* no memory */
251 return MM_STATUS_NO_MEMORY;
252 }
253
254 /* initialize mixer destination line */
255 DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
256 DestinationLine->Line.cChannels = 2; /* FIXME */
257 DestinationLine->Line.cConnections = 0;
258 DestinationLine->Line.cControls = 0;
260 DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations;
261 DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE;
262 DestinationLine->Line.dwSource = MAXULONG;
263 DestinationLine->Line.dwUser = 0;
264 DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
265
266 if (LineName)
267 {
268 MixerContext->Copy(DestinationLine->Line.szShortName, LineName, (min(MIXER_SHORT_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
269 DestinationLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
270
271 MixerContext->Copy(DestinationLine->Line.szName, LineName, (min(MIXER_LONG_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
272 DestinationLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
273
274 }
275
276 DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
277 DestinationLine->Line.Target.dwDeviceID = 0; //FIXME
278 DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
279 DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
280 DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
281
282 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
283 wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
284
285 /* initialize extra line */
286 InitializeListHead(&DestinationLine->ControlsList);
287
288 /* insert into mixer info */
289 InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry);
290
291 /* increment destination count */
292 MixerInfo->MixCaps.cDestinations++;
293
294 /* done */
295 return MM_STATUS_SUCCESS;
296}
297
301 IN LPMIXER_INFO MixerInfo,
303 IN ULONG PinId,
305{
306 KSP_PIN Pin;
310
311 /* prepare pin */
312 Pin.PinId = PinId;
313 Pin.Reserved = 0;
314 Pin.Property.Flags = KSPROPERTY_TYPE_GET;
315 Pin.Property.Set = KSPROPSETID_Pin;
316 Pin.Property.Id = KSPROPERTY_PIN_NAME;
317
318 /* try get pin name size */
320
321 /* check if buffer overflowed */
323 {
324 /* allocate buffer */
326 if (!Buffer)
327 {
328 /* out of memory */
329 return MM_STATUS_NO_MEMORY;
330 }
331
332 /* try get pin name */
335 {
336 /* failed to get pin name */
338 return Status;
339 }
340
341 /* successfully obtained pin name */
342 *OutBuffer = Buffer;
343 return MM_STATUS_SUCCESS;
344 }
345
346 /* failed to get pin name */
347 return Status;
348}
349
353 IN OUT LPMIXER_INFO MixerInfo,
355 IN ULONG PinId,
356 IN ULONG bInput)
357{
358 LPWSTR PinName;
360
361 /* try get pin name */
362 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
364 {
365 /* create mixer destination line */
366
367 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, PinName);
368
369 /* free pin name */
370 MixerContext->Free(PinName);
371 }
372 else
373 {
374 /* create mixer destination line unlocalized */
375 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, L"No Name");
376 }
377
378 return Status;
379}
380
384 IN LPMIXER_DATA MixerData,
385 OUT PTOPOLOGY * OutTopology)
386{
387 ULONG PinsCount;
388 PKSMULTIPLE_ITEM NodeTypes = NULL;
389 PKSMULTIPLE_ITEM NodeConnections = NULL;
391
392 if (MixerData->Topology)
393 {
394 /* re-use existing topology */
395 *OutTopology = MixerData->Topology;
396
397 return MM_STATUS_SUCCESS;
398 }
399
400 /* get connected filter pin count */
401 PinsCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
402
403 if (!PinsCount)
404 {
405 /* referenced filter does not have any pins */
407 }
408
409 /* get topology node types */
412 {
413 /* failed to get topology node types */
414 return Status;
415 }
416
417 /* get topology connections */
420 {
421 /* failed to get topology connections */
422 MixerContext->Free(NodeTypes);
423 return Status;
424 }
425
426 /* create a topology */
427 Status = MMixerCreateTopology(MixerContext, PinsCount, NodeConnections, NodeTypes, OutTopology);
428
429 /* free node types & connections */
430 MixerContext->Free(NodeConnections);
431 MixerContext->Free(NodeTypes);
432
434 {
435 /* store topology object */
436 MixerData->Topology = *OutTopology;
437 }
438
439 /* done */
440 return Status;
441}
442
446 IN PTOPOLOGY Topology,
447 IN ULONG PinId,
448 IN ULONG bInputMixer,
449 IN ULONG bUpStream,
450 OUT PULONG OutNodesCount,
451 OUT PULONG OutNodes,
452 OUT PULONG OutLineTerminator)
453{
454 PULONG Nodes;
455 ULONG NodesCount, NodeIndex, Count, bTerminator;
457
458 /* allocate an array to store all nodes which are upstream of this pin */
460
462 {
463 /* out of memory */
464 return STATUS_NO_MEMORY;
465 }
466
467 /* mark result array as zero */
468 *OutNodesCount = 0;
469
470 /* get next nodes */
471 MMixerGetNextNodesFromPinIndex(MixerContext, Topology, PinId, bUpStream, &NodesCount, Nodes);
472
473 if (NodesCount == 0)
474 {
475 /* a pin which is not connected from any node
476 * a) it is a topology bug (driver bug)
477 * b) the request is from an alternative mixer
478 alternative mixer code scans all pins which have not been used and tries to build lines
479 */
480 DPRINT1("MMixerCountMixerControls PinId %lu is not connected by any node\n", PinId);
481 MMixerPrintTopology(Topology);
483 }
484
485 /* assume no topology split before getting line terminator */
486 ASSERT(NodesCount == 1);
487
488 /* get first node */
489 NodeIndex = Nodes[0];
490 Count = 0;
491
492 do
493 {
494 /* check if the node is a terminator */
495 MMixerIsNodeTerminator(Topology, NodeIndex, &bTerminator);
496
497 if (bTerminator)
498 {
499 /* found terminator */
500 if (bInputMixer)
501 {
502 /* add mux source for source destination line */
503 OutNodes[Count] = NodeIndex;
504 Count++;
505 }
506 break;
507 }
508
509 /* store node id */
510 OutNodes[Count] = NodeIndex;
511
512 /* increment node count */
513 Count++;
514
515 /* get next nodes upstream */
516 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &NodesCount, Nodes);
517
518 if (NodesCount != 1)
519 {
520 DPRINT("PinId %lu bInputMixer %lu bUpStream %lu NodeIndex %lu is not connected", PinId, bInputMixer, bUpStream, NodeIndex);
521 break;
522 }
523
524 ASSERT(NodesCount == 1);
525
526 /* use first index */
527 NodeIndex = Nodes[0];
528
529 }while(TRUE);
530
531 /* free node index */
532 MixerContext->Free(Nodes);
533
534 /* store nodes count */
535 *OutNodesCount = Count;
536
537 /* store line terminator */
538 *OutLineTerminator = NodeIndex;
539
540 /* done */
541 return MM_STATUS_SUCCESS;
542}
543
547 IN LPMIXER_INFO MixerInfo,
549 IN ULONG NodeId,
550 OUT PULONG MaxChannels)
551{
553 PKSPROPERTY_DESCRIPTION NewDescription;
558
559 /* try #1 obtain it via description */
560 Request.NodeId = NodeId;
561 Request.Reserved = 0;
562 Request.Property.Set = KSPROPSETID_Audio;
565
566 /* get description */
569 {
570 if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0))
571 {
572 /* allocate new description */
573 NewDescription = MixerContext->Alloc(Description.DescriptionSize);
574
575 if (!NewDescription)
576 {
577 /* not enough memory */
578 return MM_STATUS_NO_MEMORY;
579 }
580
581 /* get description */
582 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned);
584 {
585 /* get header */
586 Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1);
587
589 {
590 /* found enhanced flag */
591 ASSERT(Header->MembersCount > 1);
592
593 /* store channel count */
594 *MaxChannels = Header->MembersCount;
595
596 /* free description */
597 MixerContext->Free(NewDescription);
598
599 /* done */
600 return MM_STATUS_SUCCESS;
601 }
602 }
603
604 /* free description */
605 MixerContext->Free(NewDescription);
606 }
607 }
608
609 /* failed to get channel count enhanced */
611}
612
613VOID
616 IN LPMIXER_INFO MixerInfo,
618 IN ULONG NodeId,
619 OUT PULONG MaxChannels)
620{
624 LONG Volume;
625
626 /* setup request */
627 Channel.Reserved = 0;
628 Channel.NodeProperty.NodeId = NodeId;
629 Channel.NodeProperty.Reserved = 0;
632 Channel.Channel = 0;
634
635 do
636 {
637 /* get channel volume */
640 break;
641
642 /* increment channel count */
643 Channel.Channel++;
644
645 }while(TRUE);
646
647 /* store channel count */
648 *MaxChannels = Channel.Channel;
649
650}
651
652VOID
655 IN LPMIXER_INFO MixerInfo,
657 IN ULONG NodeId,
658 OUT PULONG MaxChannels)
659{
661
662 /* try to get it enhanced */
663 Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
664
666 {
667 /* get it old-fashioned way */
668 MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
669 }
670}
671
675 IN LPMIXER_INFO MixerInfo,
677 IN PTOPOLOGY Topology,
678 IN OUT LPMIXERLINE_EXT DstLine,
679 IN ULONG NodesCount,
680 IN PULONG Nodes)
681{
682 ULONG Index, Count, bReserved;
685 ULONG MaxChannels;
686
687 /* initialize control count */
688 Count = 0;
689
690 for(Index = 0; Index < NodesCount; Index++)
691 {
692 /* check if the node has already been reserved to a line */
693 MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved);
694#if 0 /* MS lies */
695 if (bReserved)
696 {
697 /* node is already used, skip it */
698 continue;
699 }
700#endif
701 /* set node status as used */
702 MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
703
704 /* query node type */
705 NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]);
706
708 {
709 /* calculate maximum channel count for node */
710 MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels);
711
712 DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID);
713 /* calculate maximum channels */
714 DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels);
715 }
716 else
717 {
718 /* use default of one channel */
719 MaxChannels = 1;
720 }
721
722 /* now add the mixer control */
723 Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine, MaxChannels);
724
726 {
727 /* increment control count */
728 Count++;
729 }
730 }
731
732 /* store control count */
733 DstLine->Line.cControls = Count;
734
735 /* done */
736 return MM_STATUS_SUCCESS;
737}
738
742 IN OUT LPMIXER_INFO MixerInfo,
744 IN ULONG PinId,
745 OUT PULONG ComponentType,
746 OUT PULONG TargetType)
747{
749 KSPIN_COMMUNICATION Communication;
753 GUID Guid;
754 BOOLEAN BridgePin = FALSE;
755 PKSPIN_PHYSICALCONNECTION Connection;
756
757 /* first dataflow type */
759
761 {
762 /* failed to get dataflow */
763 return Status;
764 }
765
766 /* now get pin category guid */
767 Request.PinId = PinId;
768 Request.Reserved = 0;
769 Request.Property.Flags = KSPROPERTY_TYPE_GET;
770 Request.Property.Set = KSPROPSETID_Pin;
771 Request.Property.Id = KSPROPERTY_PIN_CATEGORY;
772
773 /* get pin category */
776 {
777 /* failed to get dataflow */
778 return Status;
779 }
780
781 /* check if it has a physical connection */
784 {
785 /* pin is a brige pin */
786 BridgePin = TRUE;
787
788 /* free physical connection */
789 MixerContext->Free(Connection);
790 }
791
793 {
796 {
797 /* type microphone */
798 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
800 }
804 {
805 /* type waveout */
806 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
808 }
810 {
811 /* type cd player */
812 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
814 }
816 {
817 /* type synthesizer */
818 *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT;
820 }
822 {
823 /* type line */
824 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
825 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
826 }
830 {
831 /* type telephone */
832 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
834 }
836 {
837 /* type analog */
838 if (BridgePin)
839 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
840 else
841 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
842
843 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
844 }
846 {
847 /* type analog */
848 if (BridgePin)
849 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
850 else
851 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
852
854 }
855 else
856 {
857 /* unknown type */
858 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
860 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
861 }
862 }
863 else
864 {
869 {
870 /* type waveout */
871 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
873 }
876 {
877 /* type wavein */
878 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
879 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
880 }
883 {
884 /* type head phones */
885 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
887 }
891 {
892 /* type waveout */
893 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
895 }
897 {
898 /* type analog */
899 if (BridgePin)
900 {
901 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
903 }
904 else
905 {
906 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
907 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
908 }
909 }
911 {
912 /* type spdif */
913 if (BridgePin)
914 {
915 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
917 }
918 else
919 {
920 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
921 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
922 }
923 }
924 else
925 {
926 /* unknown type */
927 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
929 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
930 }
931 }
932
933 /* done */
934 return MM_STATUS_SUCCESS;
935}
936
940 IN OUT LPMIXER_INFO MixerInfo,
942 IN PTOPOLOGY Topology,
943 IN ULONG PinId,
944 IN ULONG NodesCount,
945 IN PULONG Nodes,
946 IN ULONG DestinationLineID,
947 OUT LPMIXERLINE_EXT * OutSrcLine)
948{
949 LPMIXERLINE_EXT SrcLine, DstLine;
950 LPWSTR PinName;
952 ULONG ComponentType, TargetType;
953
954 /* get component and target type */
955 Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType);
957 {
958 /* failed to get component status */
961 }
962
963 /* construct source line */
964 SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT));
965
966 if (!SrcLine)
967 {
968 /* no memory */
969 return MM_STATUS_NO_MEMORY;
970 }
971
972 /* get destination line */
973 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
974 ASSERT(DstLine);
975
976 /* initialize mixer src line */
977 SrcLine->PinId = PinId;
978
979 /* initialize mixer line */
980 SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
981 SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1;
982 SrcLine->Line.dwSource = DstLine->Line.cConnections;
983 SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1);
985 SrcLine->Line.dwComponentType = ComponentType;
986 SrcLine->Line.dwUser = 0;
987 SrcLine->Line.cChannels = DstLine->Line.cChannels;
988 SrcLine->Line.cConnections = 0;
989 SrcLine->Line.Target.dwType = TargetType;
990 SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
991 SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
992 SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
993 SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
995
996 /* copy name */
997 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0');
998 wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
999
1000 /* get pin name */
1001 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
1002
1004 {
1005 /* store pin name as line name */
1006 MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
1007 SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
1008
1009 MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
1010 SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
1011
1012 /* free pin name buffer */
1013 MixerContext->Free(PinName);
1014 }
1015
1016 /* add the controls to mixer line */
1017 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes);
1019 {
1020 /* failed */
1021 return Status;
1022 }
1023
1024 /* store result */
1025 *OutSrcLine = SrcLine;
1026
1027 return MM_STATUS_SUCCESS;
1028}
1029
1033 IN OUT LPMIXER_INFO MixerInfo,
1035 IN PTOPOLOGY Topology,
1036 IN ULONG DestinationLineID,
1037 IN ULONG LineTerminator)
1038{
1039 PULONG AllNodes, AllPins, AllPinNodes;
1040 ULONG AllNodesCount, AllPinsCount, AllPinNodesCount;
1041 ULONG Index, SubIndex, PinId, CurNode, bConnected;
1043 LPMIXERLINE_EXT DstLine, SrcLine;
1044
1045 /* get destination line */
1046 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
1047 ASSERT(DstLine);
1048
1049 /* allocate an array to store all nodes which are upstream of the line terminator */
1050 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllNodes);
1051
1052 /* check for success */
1054 {
1055 /* out of memory */
1056 return MM_STATUS_NO_MEMORY;
1057 }
1058
1059 /* allocate an array to store all nodes which are downstream of a particular pin */
1060 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllPinNodes);
1061
1062 /* allocate an array to store all pins which are upstream of this pin */
1063 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &AllPins);
1064
1065 /* check for success */
1067 {
1068 /* out of memory */
1069 MixerContext->Free(AllNodes);
1070 return MM_STATUS_NO_MEMORY;
1071 }
1072
1073 /* get all nodes which indirectly / directly connect to this node */
1074 AllNodesCount = 0;
1075 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllNodesCount, AllNodes);
1076
1077 /* get all pins which indirectly / directly connect to this node */
1078 AllPinsCount = 0;
1079 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins);
1080
1081 DPRINT("LineTerminator %lu\n", LineTerminator);
1082 DPRINT("PinCount %lu\n", AllPinsCount);
1083 DPRINT("AllNodesCount %lu\n", AllNodesCount);
1084
1085 /* now construct the source lines which are attached to the destination line */
1086 Index = AllPinsCount;
1087
1088 do
1089 {
1090 /* get current pin id */
1091 PinId = AllPins[Index - 1];
1092
1093 /* reset nodes count */
1094 AllPinNodesCount = 0;
1095
1096 /* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */
1097 for(SubIndex = 0; SubIndex < AllNodesCount; SubIndex++)
1098 {
1099 /* get current node index */
1100 CurNode = AllNodes[SubIndex];
1101
1102 if (CurNode != MAXULONG && CurNode != LineTerminator)
1103 {
1104 /* check if that node is connected in some way to the current pin */
1105 Status = MMixerIsNodeConnectedToPin(MixerContext, Topology, CurNode, PinId, TRUE, &bConnected);
1106
1108 break;
1109
1110 if (bConnected)
1111 {
1112 /* it is connected */
1113 AllPinNodes[AllPinNodesCount] = CurNode;
1114 AllPinNodesCount++;
1115
1116 /* clear current index */
1117 AllNodes[SubIndex] = MAXULONG;
1118 }
1119 }
1120 }
1121
1122 /* decrement pin index */
1123 Index--;
1124
1125 if (AllPinNodesCount)
1126 {
1127#ifdef MMIXER_DEBUG
1128 ULONG TempIndex;
1129#endif
1130 /* now build the mixer source line */
1131 Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine);
1132
1134 {
1135 /* insert into line list */
1136 InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
1137
1138 /* increment destination line count */
1139 DstLine->Line.cConnections++;
1140
1141 /* mark pin as reserved */
1142 MMixerSetTopologyPinReserved(Topology, PinId);
1143
1144#ifdef MMIXER_DEBUG
1145 DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID);
1146 for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++)
1147 DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]);
1148#endif
1149 }
1150 }
1151 else
1152 {
1153#ifdef MMIXER_DEBUG
1154 DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId);
1155#endif
1156 }
1157
1158 }while(Index != 0);
1159
1160 return MM_STATUS_SUCCESS;
1161}
1162
1166 IN OUT LPMIXER_INFO MixerInfo,
1168 IN PTOPOLOGY Topology,
1169 IN ULONG PinId,
1170 IN ULONG bInput,
1171 IN ULONG DestinationLineId,
1172 OUT PULONG OutLineTerminator)
1173{
1174 PULONG Nodes;
1175 ULONG NodesCount, LineTerminator;
1177 LPMIXERLINE_EXT DstLine;
1178
1179 /* allocate nodes index array */
1181
1182 /* check for success */
1184 {
1185 /* out of memory */
1186 return Status;
1187 }
1188
1189 /* get all destination line controls */
1190 Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator);
1191
1192 /* check for success */
1194 {
1195 /* failed to count controls */
1196 MixerContext->Free(Nodes);
1197 return Status;
1198 }
1199
1200 /* get destination mixer line */
1201 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId);
1202
1203 /* sanity check */
1204 ASSERT(DstLine);
1205
1206 if (NodesCount > 0)
1207 {
1208 /* add all nodes as mixer controls to the destination line */
1209 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes);
1211 {
1212 /* failed to add controls */
1213 MixerContext->Free(Nodes);
1214 return Status;
1215 }
1216 }
1217
1218 /* store result */
1219 *OutLineTerminator = LineTerminator;
1220
1221 /* return result */
1222 return Status;
1223}
1224
1225VOID
1228 IN LPMIXER_DATA MixerData,
1230 IN OUT PULONG PinsCount,
1231 IN OUT PULONG Pins)
1232{
1233 ULONG Count = 0, Index;
1235 PKSPIN_PHYSICALCONNECTION Connection;
1236
1237 for(Index = 0; Index < *PinsCount; Index++)
1238 {
1239 /* check if it has a physical connection */
1241
1243 {
1244 /* remove pin */
1245 MixerContext->Copy(&Pins[Index], &Pins[Index + 1], (*PinsCount - (Index + 1)) * sizeof(ULONG));
1246
1247 /* free physical connection */
1248 MixerContext->Free(Connection);
1249
1250 /* decrement index */
1251 Index--;
1252
1253 /* decrement pin count */
1254 (*PinsCount)--;
1255 }
1256 else
1257 {
1258 /* simple pin */
1259 Count++;
1260 }
1261 }
1262
1263 /* store result */
1264 *PinsCount = Count;
1265}
1266
1270 IN PMIXER_LIST MixerList,
1271 IN LPMIXER_DATA MixerData,
1272 IN OUT LPMIXER_INFO MixerInfo,
1273 IN ULONG bInput,
1274 IN ULONG Pin)
1275{
1277 ULONG PinsCount, LineTerminator, DestinationLineID;
1278 PULONG Pins;
1279 PTOPOLOGY Topology;
1280
1281 /* re-use existing topology */
1282 Topology = MixerData->Topology;
1283
1284 if (!bInput)
1285 {
1286 /* allocate pin index array which will hold all referenced pins */
1289 {
1290 /* failed to create topology */
1291 return Status;
1292 }
1293
1294 /* the mixer is an output mixer
1295 * find end pin of the node path
1296 */
1297 PinsCount = 0;
1299
1300 /* check for success */
1302 {
1303 /* failed to get end pin */
1304 MixerContext->Free(Pins);
1305 //MMixerFreeTopology(Topology);
1306
1307 /* return error code */
1308 return Status;
1309 }
1310 /* HACK:
1311 * some topologies do not have strict boundaries
1312 * WorkArround: remove all pin ids which have a physical connection
1313 * because bridge pins may belong to different render paths
1314 */
1315 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1316
1317 /* sanity checks */
1318 ASSERT(PinsCount != 0);
1319 if (PinsCount != 1)
1320 {
1321 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1322 }
1323
1324 /* create destination line */
1325 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1326
1327 /* calculate destination line id */
1328 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1329
1331 {
1332 /* failed to build destination line */
1333 MixerContext->Free(Pins);
1334
1335 /* return error code */
1336 return Status;
1337 }
1338
1339 /* add mixer controls to destination line */
1340 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1341
1343 {
1344 /* now add the rest of the source lines */
1345 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1346 }
1347
1348 /* mark pin as consumed */
1349 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1350
1351 /* free topology pin array */
1352 MixerContext->Free(Pins);
1353 }
1354 else
1355 {
1356 /* calculate destination line id */
1357 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1358
1359 /* add mixer controls */
1360 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pin, bInput, DestinationLineID, &LineTerminator);
1361
1363 {
1364 /* now add the rest of the source lines */
1365 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1366 }
1367 }
1368 return Status;
1369}
1370
1374 IN PMIXER_LIST MixerList,
1375 IN LPMIXER_DATA MixerData,
1376 IN OUT LPMIXER_INFO MixerInfo,
1377 IN ULONG bInput,
1378 IN PKSPIN_PHYSICALCONNECTION OutConnection)
1379{
1381 ULONG PinsCount, LineTerminator, DestinationLineID;
1382 PULONG Pins;
1383 PTOPOLOGY Topology;
1384
1385 /* first try to open the connected filter */
1386 OutConnection->SymbolicLinkName[1] = L'\\';
1387 MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
1388
1389 /* check if the linked connection is found */
1390 if (!MixerData)
1391 {
1392 /* filter references invalid physical connection */
1394 }
1395
1396 DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
1397
1398 /* sanity check */
1399 ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo);
1400
1401 /* associate with mixer */
1402 MixerData->MixerInfo = MixerInfo;
1403
1404 if (MixerData->Topology == NULL)
1405 {
1406 /* construct new topology */
1407 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1409 {
1410 /* failed to create topology */
1411 return Status;
1412 }
1413
1414 /* store topology */
1415 MixerData->Topology = Topology;
1416 }
1417 else
1418 {
1419 /* re-use existing topology */
1420 Topology = MixerData->Topology;
1421 }
1422
1423 /* mark pin as consumed */
1424 MMixerSetTopologyPinReserved(Topology, OutConnection->Pin);
1425
1426 if (!bInput)
1427 {
1428 /* allocate pin index array which will hold all referenced pins */
1431 {
1432 /* failed to create topology */
1433 return Status;
1434 }
1435
1436 /* the mixer is an output mixer
1437 * find end pin of the node path
1438 */
1439 PinsCount = 0;
1440 Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex(MixerContext, Topology, OutConnection->Pin, FALSE, &PinsCount, Pins);
1441
1442 /* check for success */
1444 {
1445 /* failed to get end pin */
1446 MixerContext->Free(Pins);
1447 //MMixerFreeTopology(Topology);
1448
1449 /* return error code */
1450 return Status;
1451 }
1452 /* HACK:
1453 * some topologies do not have strict boundaries
1454 * WorkArround: remove all pin ids which have a physical connection
1455 * because bridge pins may belong to different render paths
1456 */
1457 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1458
1459 /* sanity checks */
1460 ASSERT(PinsCount != 0);
1461 if (PinsCount != 1)
1462 {
1463 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1464 }
1465
1466 /* create destination line */
1467 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1468
1469 /* calculate destination line id */
1470 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1471
1473 {
1474 /* failed to build destination line */
1475 MixerContext->Free(Pins);
1476
1477 /* return error code */
1478 return Status;
1479 }
1480
1481 /* add mixer controls to destination line */
1482 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1483
1485 {
1486 /* now add the rest of the source lines */
1487 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1488 }
1489
1490 /* mark pin as consumed */
1491 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1492
1493 /* free topology pin array */
1494 MixerContext->Free(Pins);
1495 }
1496 else
1497 {
1498 /* calculate destination line id */
1499 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1500
1501 /* add mixer controls */
1502 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator);
1503
1505 {
1506 /* now add the rest of the source lines */
1507 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1508 }
1509 }
1510
1511 return Status;
1512}
1513
1517 IN PMIXER_LIST MixerList,
1518 IN LPMIXER_DATA MixerData,
1519 IN LPMIXER_INFO MixerInfo,
1520 IN PTOPOLOGY Topology,
1521 IN ULONG NodeIndex,
1522 IN ULONG bInputMixer,
1523 IN OUT LPMIXER_INFO * OutMixerInfo)
1524{
1525 ULONG Index;
1527 PKSPIN_PHYSICALCONNECTION OutConnection;
1528 ULONG * Pins;
1529 ULONG PinsFound;
1530 ULONG NewMixerInfo = FALSE;
1531
1532 if (MixerInfo == NULL)
1533 {
1534 /* allocate a mixer info struct */
1535 MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
1536 if (!MixerInfo)
1537 {
1538 /* no memory */
1539 return MM_STATUS_NO_MEMORY;
1540 }
1541
1542 /* new mixer info */
1543 NewMixerInfo = TRUE;
1544
1545 /* intialize mixer caps */
1546 MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */
1547 MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */
1548 MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */
1549 MixerInfo->MixCaps.fdwSupport = 0;
1550 MixerInfo->MixCaps.cDestinations = 0;
1551
1552 /* get mixer name */
1553 Status = MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
1555 {
1556 /* try get name with component id */
1557 Status = MMixerGetDeviceNameWithComponentId(MixerContext, MixerData->hDevice, MixerInfo->MixCaps.szPname);
1559 {
1560 MixerInfo->MixCaps.szPname[0] = L'\0';
1561 }
1562 }
1563
1564 /* initialize line list */
1565 InitializeListHead(&MixerInfo->LineList);
1566 InitializeListHead(&MixerInfo->EventList);
1567
1568 /* associate with mixer data */
1569 MixerData->MixerInfo = MixerInfo;
1570 }
1571
1572 /* store mixer info */
1573 *OutMixerInfo = MixerInfo;
1574
1575 /* now allocate an array which will receive the indices of the pin
1576 * which has a ADC / DAC nodetype in its path
1577 */
1580
1581 PinsFound = 0;
1582
1583 /* now get all sink / source pins, which are attached to the ADC / DAC node
1584 * For sink pins (wave out) search up stream
1585 * For source pins (wave in) search down stream
1586 * The search direction is always the opposite of the current mixer type
1587 */
1588 PinsFound = 0;
1589 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins);
1590
1591 /* if there is no pin found, we have a broken topology */
1592 ASSERT(PinsFound != 0);
1593
1594 /* now create a wave info struct */
1595 Status = MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinsFound, Pins);
1597 {
1598 /* failed to create wave info struct */
1599 MixerContext->Free(MixerInfo);
1600 MixerContext->Free(Pins);
1601 return Status;
1602 }
1603
1604 /* mark all found pins as reserved */
1605 for(Index = 0; Index < PinsFound; Index++)
1606 {
1607 MMixerSetTopologyPinReserved(Topology, Pins[Index]);
1608 }
1609
1610 if (bInputMixer)
1611 {
1612 /* pre create the mixer destination line for input mixers */
1613 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer);
1614
1616 {
1617 /* failed to create mixer destination line */
1618 return Status;
1619 }
1620 }
1621
1622 /* now get the bridge pin which is at the end of node path
1623 * For sink pins (wave out) search down stream
1624 * For source pins (wave in) search up stream
1625 */
1626 MixerContext->Free(Pins);
1629
1630 PinsFound = 0;
1631 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bInputMixer, &PinsFound, Pins);
1632
1633 /* if there is no pin found, we have a broken topology */
1634 ASSERT(PinsFound != 0);
1635
1636 /* there should be exactly one bridge pin */
1637 ASSERT(PinsFound == 1);
1638
1639 DPRINT("BridgePin %lu bInputMixer %lu\n", Pins[0], bInputMixer);
1640
1641 /* does the pin have a physical connection */
1642 Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[0], &OutConnection);
1643
1645 {
1646 /* mark pin as reserved */
1647 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1648
1649 /* topology on the topoloy filter */
1650 Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection);
1651
1652 /* free physical connection data */
1653 MixerContext->Free(OutConnection);
1654 }
1655 else
1656 {
1657 /* topology is on the same filter */
1658 Status = MMixerHandleTopologyFilter(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, Pins[0]);
1659 }
1660
1661 /* free pins */
1662 MixerContext->Free(Pins);
1663
1664 if (NewMixerInfo)
1665 {
1666 /* insert mixer */
1667 InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
1668 /* increment mixer count */
1669 MixerList->MixerListCount++;
1670 }
1671
1672 /* done */
1673 return Status;
1674}
1675
1676VOID
1679 IN PMIXER_LIST MixerList,
1680 IN LPMIXER_DATA MixerData,
1681 IN PTOPOLOGY Topology)
1682{
1685 ULONG DestinationLineID, LineTerminator;
1686 LPMIXERLINE_EXT DstLine;
1687
1688 DPRINT("DeviceName %S\n", MixerData->DeviceName);
1689
1690 /* get topology pin count */
1692
1693 for(Index = 0; Index < PinCount; Index++)
1694 {
1696
1697 /* check if it has already been reserved */
1698 if (Reserved)
1699 {
1700 /* pin has already been reserved */
1701 continue;
1702 }
1703
1704 DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index);
1705
1706 /* sanity check */
1707 //ASSERT(MixerData->MixerInfo);
1708
1709 if (!MixerData->MixerInfo)
1710 {
1711 DPRINT1("Expected mixer info\n");
1712 continue;
1713 }
1714
1715 /* build the destination line */
1716 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE);
1718 {
1719 /* failed to build destination line */
1720 continue;
1721 }
1722
1723 /* calculate destination line id */
1724 DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1);
1725
1726 /* add mixer controls to destination line */
1727 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator);
1729 {
1730 /* now add the rest of the source lines */
1731 Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator);
1732 }
1733
1734 /* mark pin as consumed */
1736
1737 /* now grab destination line */
1738 DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID);
1739
1740 /* set type and target as undefined */
1742 DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1743 DstLine->Line.Target.vDriverVersion = 0;
1744 DstLine->Line.Target.wMid = 0;
1745 DstLine->Line.Target.wPid = 0;
1746 }
1747}
1748
1752 IN PMIXER_LIST MixerList,
1753 IN LPMIXER_DATA MixerData,
1755{
1757 PTOPOLOGY Topology;
1758 ULONG NodeIndex;
1759 LPMIXER_INFO MixerInfo = NULL;
1760
1761 /* check if topology has already been built */
1762 if (MixerData->Topology == NULL)
1763 {
1764 /* build topology */
1765 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1766
1768 {
1769 /* failed to build topology */
1770 return Status;
1771 }
1772
1773 /* store topology */
1774 MixerData->Topology = Topology;
1775 }
1776 else
1777 {
1778 /* re-use topology */
1779 Topology = MixerData->Topology;
1780 }
1781
1782 /* check if the filter has an wave out node */
1783 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_DAC);
1784 if (NodeIndex != MAXULONG)
1785 {
1786 /* it has */
1787 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo);
1788
1789 /* check for success */
1791 {
1792 /* increment mixer count */
1793 (*DeviceCount)++;
1794 }
1795 else
1796 {
1797 /* reset mixer info in case of error */
1798 MixerInfo = NULL;
1799 }
1800 }
1801
1802 /* check if the filter has an wave in node */
1803 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_ADC);
1804 if (NodeIndex != MAXULONG)
1805 {
1806 /* it has */
1807 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo);
1808
1809 /* check for success */
1811 {
1812 /* increment mixer count */
1813 (*DeviceCount)++;
1814 }
1815
1816 }
1817
1818 /* TODO: apply hacks for Wave source line */
1819
1820 /* activate midi devices */
1821 //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
1822
1823 /* done */
1824 return Status;
1825}
1826
1830 IN OUT LPMIXER_INFO MixerInfo,
1831 IN PVOID MixerEventContext,
1832 IN PMIXER_EVENT MixerEventRoutine)
1833{
1834 //KSE_NODE Property;
1835 //KSEVENTDATA EventData
1836 //ULONG BytesReturned;
1837 //MIXER_STATUS Status;
1838 PEVENT_NOTIFICATION_ENTRY EventNotification;
1839
1841 if (!EventNotification)
1842 {
1843 /* not enough memory */
1844 return MM_STATUS_NO_MEMORY;
1845 }
1846
1847 /* FIXME: what is it supposed to happen with KSEVENTDATA ? */
1848#if 0
1849 /* setup request */
1853
1854 Property.NodeId = NodeId;
1855 Property.Reserved = 0;
1856
1857 Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned);
1859 {
1860 /* failed to add event */
1861 MixerContext->FreeEventData(EventData);
1862 return Status;
1863 }
1864#endif
1865
1866 /* initialize notification entry */
1867 EventNotification->MixerEventContext = MixerEventContext;
1868 EventNotification->MixerEventRoutine = MixerEventRoutine;
1869
1870 /* store event */
1871 InsertTailList(&MixerInfo->EventList, &EventNotification->Entry);
1872 return MM_STATUS_SUCCESS;
1873}
1874
1878 IN OUT LPMIXER_INFO MixerInfo,
1879 IN PVOID MixerEventContext,
1880 IN PMIXER_EVENT MixerEventRoutine)
1881{
1882 PLIST_ENTRY EventList;
1884
1885 /* Lookup through mixers */
1886 EventList = MixerInfo->EventList.Flink;
1887 while(EventList != &MixerInfo->EventList)
1888 {
1890 EventList = EventList->Flink;
1891 /* TODO: find a better way to identify an event ? */
1892 if(NotificationEntry->MixerEventRoutine == MixerEventRoutine &&
1893 NotificationEntry->MixerEventContext == MixerEventContext)
1894 {
1895 DPRINT1("Freeing entry %p\n", NotificationEntry);
1896 /* We found the event to remove */
1899 }
1900 }
1901 return MM_STATUS_SUCCESS;
1902}
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:45
Definition: Header.h:9
const GUID KSNODETYPE_PHONE_LINE
Definition: controls.c:17
const GUID PINNAME_VIDEO_CAPTURE
Definition: controls.c:32
MIXER_STATUS MMixerAddEvent(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN PVOID MixerEventContext, IN PMIXER_EVENT MixerEventRoutine)
Definition: controls.c:1828
const GUID KSNODETYPE_ROOM_SPEAKER
Definition: controls.c:20
const GUID KSNODETYPE_SPEAKER
Definition: controls.c:28
MIXER_STATUS MMixerGetComponentAndTargetType(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG PinId, OUT PULONG ComponentType, OUT PULONG TargetType)
Definition: controls.c:740
MIXER_STATUS MMixerHandlePhysicalConnection(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN OUT LPMIXER_INFO MixerInfo, IN ULONG bInput, IN PKSPIN_PHYSICALCONNECTION OutConnection)
Definition: controls.c:1372
MIXER_STATUS MMixerBuildMixerSourceLine(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG PinId, IN ULONG NodesCount, IN PULONG Nodes, IN ULONG DestinationLineID, OUT LPMIXERLINE_EXT *OutSrcLine)
Definition: controls.c:938
MIXER_STATUS MMixerAddMixerControlsToMixerLineByNodeIndexArray(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN PTOPOLOGY Topology, IN OUT LPMIXERLINE_EXT DstLine, IN ULONG NodesCount, IN PULONG Nodes)
Definition: controls.c:673
const GUID KSNODETYPE_HEADPHONES
Definition: controls.c:22
VOID MMixerHandleAlternativeMixers(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN PTOPOLOGY Topology)
Definition: controls.c:1677
MIXER_STATUS MMixerHandleTopologyFilter(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN OUT LPMIXER_INFO MixerInfo, IN ULONG bInput, IN ULONG Pin)
Definition: controls.c:1268
MIXER_STATUS MMixerGetPinName(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG PinId, IN OUT LPWSTR *OutBuffer)
Definition: controls.c:299
const GUID KSNODETYPE_COMMUNICATION_SPEAKER
Definition: controls.c:21
MIXER_STATUS MMixerGetChannelCountEnhanced(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:545
MIXER_STATUS MMixerAddMixerSourceLines(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG DestinationLineID, IN ULONG LineTerminator)
Definition: controls.c:1031
const GUID KSNODETYPE_DESKTOP_SPEAKER
Definition: controls.c:19
MIXER_STATUS MMixerSetupFilter(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN PULONG DeviceCount)
Definition: controls.c:1750
const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR
Definition: controls.c:15
MIXER_STATUS MMixerRemoveEvent(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN PVOID MixerEventContext, IN PMIXER_EVENT MixerEventRoutine)
Definition: controls.c:1876
MIXER_STATUS MMixerCountMixerControls(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinId, IN ULONG bInputMixer, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes, OUT PULONG OutLineTerminator)
Definition: controls.c:444
MIXER_STATUS MMixerCreateDestinationLine(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN ULONG bInputMixer, IN LPWSTR LineName)
Definition: controls.c:238
MIXER_STATUS MMixerBuildTopology(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, OUT PTOPOLOGY *OutTopology)
Definition: controls.c:382
VOID MMixerGetMaxChannelsForNode(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:653
const GUID KSNODETYPE_DOWN_LINE_PHONE
Definition: controls.c:18
const GUID KSNODETYPE_TELEPHONE
Definition: controls.c:16
MIXER_STATUS MMixerAddMixerControlsToDestinationLine(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG PinId, IN ULONG bInput, IN ULONG DestinationLineId, OUT PULONG OutLineTerminator)
Definition: controls.c:1164
VOID MMixerApplyOutputFilterHack(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, IN HANDLE hMixer, IN OUT PULONG PinsCount, IN OUT PULONG Pins)
Definition: controls.c:1226
const GUID KSNODETYPE_LINE_CONNECTOR
Definition: controls.c:31
const GUID KSNODETYPE_MICROPHONE
Definition: controls.c:24
MIXER_STATUS MMixerInitializeFilter(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN LPMIXER_INFO MixerInfo, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bInputMixer, IN OUT LPMIXER_INFO *OutMixerInfo)
Definition: controls.c:1515
VOID MMixerGetChannelCountLegacy(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:614
const GUID KSNODETYPE_ANALOG_CONNECTOR
Definition: controls.c:27
const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO
Definition: controls.c:23
MIXER_STATUS MMixerAddMixerControl(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN LPMIXERLINE_EXT MixerLine, IN ULONG MaxChannels)
Definition: controls.c:35
const GUID KSNODETYPE_SYNTHESIZER
Definition: controls.c:30
const GUID KSCATEGORY_AUDIO
Definition: controls.c:25
const GUID KSNODETYPE_DESKTOP_MICROPHONE
Definition: controls.c:14
const GUID KSNODETYPE_CD_PLAYER
Definition: controls.c:29
const GUID KSNODETYPE_SPDIF_INTERFACE
Definition: controls.c:26
MIXER_STATUS MMixerBuildMixerDestinationLine(IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG PinId, IN ULONG bInput)
Definition: controls.c:351
wcscpy
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
LPWSTR Name
Definition: desk.c:124
DataFlow
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
union node Node
Definition: types.h:1255
static const WCHAR Description[]
Definition: oid.c:1266
MIXER_CONTEXT MixerContext
Definition: mmixer.c:41
#define L(x)
Definition: resources.c:13
#define NodeType(P)
Definition: nodetype.h:51
#define KSPROPERTY_TYPE_TOPOLOGY
Definition: dmksctrl.h:53
#define KSPROPERTY_TYPE_BASICSUPPORT
Definition: dmksctrl.h:45
#define KSPROPERTY_TYPE_GET
Definition: dmksctrl.h:42
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
IN PDCB IN VBO IN ULONG IN BOOLEAN Pin
Definition: fatprocs.h:428
BOOL bConnected
Definition: fdebug.c:27
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL
Definition: ks.h:1564
#define IOCTL_KS_PROPERTY
Definition: ks.h:127
#define KSPROPSETID_Pin
Definition: ks.h:617
@ KSPROPERTY_TOPOLOGY_NAME
Definition: ks.h:848
@ KSPROPERTY_TOPOLOGY_NODES
Definition: ks.h:846
@ KSPROPERTY_TOPOLOGY_CONNECTIONS
Definition: ks.h:847
@ KSPROPERTY_PIN_CATEGORY
Definition: ks.h:636
@ KSPROPERTY_PIN_NAME
Definition: ks.h:637
KSPIN_DATAFLOW
Definition: ks.h:1248
@ KSPIN_DATAFLOW_IN
Definition: ks.h:1249
KSPIN_COMMUNICATION
Definition: ks.h:1253
#define KSEVENT_TYPE_TOPOLOGY
Definition: ks.h:1796
#define KSEVENT_TYPE_ENABLE
Definition: ks.h:1789
struct KSPROPERTY_STEPPING_LONG * PKSPROPERTY_STEPPING_LONG
#define IOCTL_KS_ENABLE_EVENT
Definition: ks.h:130
#define KSPROPSETID_Topology
Definition: ks.h:842
struct KSPROPERTY_DESCRIPTION * PKSPROPERTY_DESCRIPTION
struct KSPROPERTY_MEMBERSHEADER * PKSPROPERTY_MEMBERSHEADER
@ KSPROPERTY_AUDIO_VOLUMELEVEL
Definition: ksmedia.h:1057
@ KSEVENT_CONTROL_CHANGE
Definition: ksmedia.h:1120
#define KSNODETYPE_VOLUME
Definition: ksmedia.h:338
#define KSNODETYPE_ADC
Definition: ksmedia.h:262
#define PINNAME_CAPTURE
Definition: ksmedia.h:147
#define KSNODETYPE_DAC
Definition: ksmedia.h:287
#define KSEVENTSETID_AudioControlChange
Definition: ksmedia.h:1117
#define KSPROPSETID_Audio
Definition: ksmedia.h:1051
VOID(CALLBACK * PMIXER_EVENT)(IN PVOID MixerEventContext, IN HANDLE hMixer, IN ULONG NotificationType, IN ULONG Value)
Definition: mmixer.h:50
MIXER_STATUS
Definition: mmixer.h:4
@ MM_STATUS_UNSUCCESSFUL
Definition: mmixer.h:11
@ MM_STATUS_NO_MEMORY
Definition: mmixer.h:12
@ MM_STATUS_SUCCESS
Definition: mmixer.h:5
@ MM_STATUS_MORE_ENTRIES
Definition: mmixer.h:9
#define MM_PID_UNMAPPED
Definition: mmreg.h:141
#define MM_MICROSOFT
Definition: mmreg.h:144
#define MIXERLINE_COMPONENTTYPE_DST_TELEPHONE
Definition: mmsystem.h:321
#define MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED
Definition: mmsystem.h:326
#define MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
Definition: mmsystem.h:319
#define MIXERLINE_COMPONENTTYPE_SRC_DIGITAL
Definition: mmsystem.h:327
#define MIXERLINE_TARGETTYPE_WAVEOUT
Definition: mmsystem.h:339
#define MIXERCONTROL_CONTROLF_UNIFORM
Definition: mmsystem.h:350
#define MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE
Definition: mmsystem.h:329
#define MIXERCONTROL_CONTROLTYPE_ONOFF
Definition: mmsystem.h:383
#define MIXERLINE_TARGETTYPE_MIDIOUT
Definition: mmsystem.h:341
#define MIXERLINE_COMPONENTTYPE_DST_HEADPHONES
Definition: mmsystem.h:320
#define MIXERLINE_COMPONENTTYPE_DST_UNDEFINED
Definition: mmsystem.h:315
#define MIXERLINE_COMPONENTTYPE_SRC_ANALOG
Definition: mmsystem.h:336
#define MIXERCONTROL_CONTROLTYPE_MUX
Definition: mmsystem.h:403
#define MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER
Definition: mmsystem.h:330
#define MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT
Definition: mmsystem.h:334
#define MIXERLINE_TARGETTYPE_WAVEIN
Definition: mmsystem.h:340
struct tagMIXERCONTROLW MIXERCONTROLW
#define MIXERCONTROL_CONTROLF_MULTIPLE
Definition: mmsystem.h:351
#define MIXERLINE_COMPONENTTYPE_SRC_LINE
Definition: mmsystem.h:328
#define MIXERCONTROL_CONTROLTYPE_VOLUME
Definition: mmsystem.h:398
#define MIXER_LONG_NAME_CHARS
Definition: mmsystem.h:294
#define MIXERLINE_COMPONENTTYPE_DST_WAVEIN
Definition: mmsystem.h:322
#define MAXPNAMELEN
Definition: mmsystem.h:24
#define MIXERLINE_LINEF_ACTIVE
Definition: mmsystem.h:311
#define MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE
Definition: mmsystem.h:332
#define MIXER_SHORT_NAME_CHARS
Definition: mmsystem.h:293
#define MIXERLINE_TARGETTYPE_UNDEFINED
Definition: mmsystem.h:338
struct tagMIXERLINEW MIXERLINEW
#define MIXERCONTROL_CONTROLTYPE_MUTE
Definition: mmsystem.h:384
#define MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC
Definition: mmsystem.h:331
#define MIXERLINE_LINEF_SOURCE
Definition: mmsystem.h:313
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ASSERT(a)
Definition: mode.c:44
HMIXER hMixer
Definition: test.c:10
#define min(a, b)
Definition: monoChain.cc:55
ULONG DeviceCount
Definition: mpu401.c:26
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
long LONG
Definition: pedump.c:60
_In_ UCHAR _In_ ULONG _Out_ PUCHAR _Outptr_result_bytebuffer_ OutBufferLength PVOID * OutBuffer
Definition: scsi.h:4071
ULONG MMixerGetFilterPinCount(IN PMIXER_CONTEXT MixerContext, IN HANDLE hMixer)
Definition: filter.c:15
MIXER_STATUS MMixerGetPhysicalConnection(IN PMIXER_CONTEXT MixerContext, IN HANDLE hMixer, IN ULONG PinId, OUT PKSPIN_PHYSICALCONNECTION *OutConnection)
Definition: filter.c:91
ULONG MMixerGetControlTypeFromTopologyNode(IN LPGUID NodeType)
Definition: filter.c:139
MIXER_STATUS MMixerGetFilterTopologyProperty(IN PMIXER_CONTEXT MixerContext, IN HANDLE hMixer, IN ULONG PropertyId, OUT PKSMULTIPLE_ITEM *OutMultipleItem)
Definition: filter.c:39
MIXER_STATUS MMixerGetPinDataFlowAndCommunication(IN PMIXER_CONTEXT MixerContext, IN HANDLE hDevice, IN ULONG PinId, OUT PKSPIN_DATAFLOW DataFlow, OUT PKSPIN_COMMUNICATION Communication)
Definition: midi.c:15
struct MIXERLINE_EXT * LPMIXERLINE_EXT
VOID MMixerGetNextNodesFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:922
VOID MMixerGetTopologyPinCount(IN PTOPOLOGY Topology, OUT PULONG PinCount)
Definition: topology.c:1004
struct EVENT_NOTIFICATION_ENTRY * PEVENT_NOTIFICATION_ENTRY
LPMIXER_DATA MMixerGetDataByDeviceName(IN PMIXER_LIST MixerList, IN LPWSTR DeviceName)
Definition: sup.c:749
struct MIXERVOLUME_DATA * LPMIXERVOLUME_DATA
VOID MMixerIsTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId, OUT PULONG bReserved)
Definition: topology.c:1207
ULONG MMixerGetNodeIndexFromGuid(IN PTOPOLOGY Topology, IN const GUID *NodeType)
Definition: topology.c:691
VOID MMixerIsTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG bReserved)
Definition: topology.c:1232
MIXER_STATUS MMixerGetDeviceName(IN PMIXER_CONTEXT MixerContext, OUT LPWSTR DeviceName, IN HANDLE hKey)
Definition: sup.c:845
VOID MMixerIsNodeTerminator(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT ULONG *bTerminator)
Definition: topology.c:1077
MIXER_STATUS MMixerInitializeWaveInfo(IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, IN LPWSTR DeviceName, IN ULONG bWaveIn, IN ULONG PinCount, IN PULONG Pins)
Definition: wave.c:347
VOID MMixerSetTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId)
Definition: topology.c:1195
MIXER_STATUS MMixerGetAllUpOrDownstreamNodesFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:781
VOID MMixerGetAllUpOrDownstreamPinsFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutPinsCount, OUT PULONG OutPins)
Definition: topology.c:709
#define DESTINATION_LINE
Definition: precomp.h:176
LPGUID MMixerGetNodeTypeFromTopology(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1184
MIXER_STATUS MMixerCreateTopology(IN PMIXER_CONTEXT MixerContext, IN ULONG PinCount, IN PKSMULTIPLE_ITEM NodeConnections, IN PKSMULTIPLE_ITEM NodeTypes, OUT PTOPOLOGY *OutTopology)
Definition: topology.c:1245
LPMIXERLINE_EXT MMixerGetSourceMixerLineByLineId(LPMIXER_INFO MixerInfo, DWORD dwLineID)
Definition: sup.c:218
#define SOURCE_LINE
Definition: precomp.h:177
MIXER_STATUS MMixerAllocateTopologyNodeArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutPins)
Definition: topology.c:1045
VOID MMixerGetNextNodesFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:965
struct MIXER_INFO * LPMIXER_INFO
VOID MMixerPrintTopology()
MIXER_STATUS MMixerIsNodeConnectedToPin(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG PinId, IN ULONG bUpStream, OUT PULONG bConnected)
Definition: topology.c:1112
MIXER_STATUS MMixerGetDeviceNameWithComponentId(IN PMIXER_CONTEXT MixerContext, IN HANDLE hMixer, OUT LPWSTR DeviceName)
Definition: sup.c:797
MIXER_STATUS MMixerAllocateTopologyPinArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutPins)
Definition: topology.c:1013
MIXER_STATUS MMixerGetAllUpOrDownstreamPinsFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutPinsCount, OUT PULONG OutPins)
Definition: topology.c:809
VOID MMixerSetTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1220
#define DPRINT
Definition: sndvol32.h:73
_In_ const GUID _In_ ULONG PinCount
Definition: strmini.h:505
Definition: precomp.h:169
PVOID MixerEventContext
Definition: precomp.h:171
LIST_ENTRY Entry
Definition: precomp.h:170
PMIXER_EVENT MixerEventRoutine
Definition: precomp.h:172
base of all file and directory entries
Definition: entries.h:83
ULONG Id
Definition: dmksctrl.h:77
ULONG Flags
Definition: dmksctrl.h:78
GUID Set
Definition: dmksctrl.h:76
KSNODEPROPERTY NodeProperty
Definition: ksmedia.h:1240
ULONG NodeId
Definition: ksmedia.h:1234
KSPROPERTY Property
Definition: ksmedia.h:1233
ULONG Reserved
Definition: ksmedia.h:1235
KSPROPERTY_BOUNDS_LONG Bounds
Definition: ks.h:1644
Definition: ks.h:2074
Definition: ks.h:642
ULONG dwControlID
Definition: precomp.h:97
HANDLE hDevice
Definition: precomp.h:81
MIXERCONTROLW Control
Definition: precomp.h:79
PVOID ExtraData
Definition: precomp.h:82
ULONG NodeID
Definition: precomp.h:80
LIST_ENTRY Entry
Definition: precomp.h:78
MIXERLINEW Line
Definition: precomp.h:89
LIST_ENTRY Entry
Definition: precomp.h:87
LIST_ENTRY ControlsList
Definition: precomp.h:90
ULONG PinId
Definition: precomp.h:88
MIXERCONTROL_DATA Header
Definition: precomp.h:102
LONG SignedMinimum
Definition: precomp.h:103
ULONG ValuesCount
Definition: precomp.h:107
ULONG InputSteppingDelta
Definition: precomp.h:106
LONG SignedMaximum
Definition: precomp.h:104
LONG SteppingDelta
Definition: precomp.h:105
PMIXER_DEVICE_CONTROL Control
Definition: mmixer.h:95
PMIXER_COPY Copy
Definition: mmixer.h:99
PMIXER_FREE_EVENT_DATA FreeEventData
Definition: mmixer.h:104
PMIXER_FREE Free
Definition: mmixer.h:96
PMIXER_ALLOC Alloc
Definition: mmixer.h:94
Property(long _type, long _tag, INREAL _value)
Definition: reader.h:125
ULONG Flags
Definition: ntfs.h:536
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
WCHAR szName[MIXER_LONG_NAME_CHARS]
Definition: mmsystem.h:1310
DWORD dwControlType
Definition: mmsystem.h:1306
union tagMIXERCONTROLW::@3229 Metrics
union tagMIXERCONTROLW::@3228 Bounds
DWORD cMultipleItems
Definition: mmsystem.h:1308
WCHAR szShortName[MIXER_SHORT_NAME_CHARS]
Definition: mmsystem.h:1309
DWORD dwReserved[6]
Definition: mmsystem.h:1320
DWORD fdwLine
Definition: mmsystem.h:1259
DWORD dwDestination
Definition: mmsystem.h:1256
DWORD cControls
Definition: mmsystem.h:1264
DWORD dwSource
Definition: mmsystem.h:1257
DWORD dwLineID
Definition: mmsystem.h:1258
WCHAR szName[MIXER_LONG_NAME_CHARS]
Definition: mmsystem.h:1266
DWORD cChannels
Definition: mmsystem.h:1262
DWORD cConnections
Definition: mmsystem.h:1263
DWORD_PTR dwUser
Definition: mmsystem.h:1260
struct tagMIXERLINEW::@3223 Target
DWORD cbStruct
Definition: mmsystem.h:1255
DWORD dwComponentType
Definition: mmsystem.h:1261
WCHAR szShortName[MIXER_SHORT_NAME_CHARS]
Definition: mmsystem.h:1265
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
ULONG UnsignedMinimum
Definition: ks.h:1505
ULONG UnsignedMaximum
Definition: ks.h:1506
Definition: dlist.c:348
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_ ULONG _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesReturned
Definition: wdfiotarget.h:1052
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:235
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
_In_ ULONG _In_opt_ PVOID _In_ PDRIVER_OBJECT _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE _Inout_opt_ __drv_aliasesMem PVOID _Outptr_result_nullonfailure_ _At_ * NotificationEntry(return==0, __drv_allocatesMem(Mem))) PVOID *NotificationEntry
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184