ReactOS 0.4.15-dev-7127-g2dd0c6c
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 Value += Range->SteppingDelta;
225 }
226 MixerControl->ExtraData = VolumeData;
227 }
228 }
229 MixerContext->Free(Desc);
230 }
231
232 DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName);
233 return MM_STATUS_SUCCESS;
234}
235
239 IN LPMIXER_INFO MixerInfo,
240 IN ULONG bInputMixer,
241 IN LPWSTR LineName)
242{
243 LPMIXERLINE_EXT DestinationLine;
244
245 /* allocate a mixer destination line */
246 DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
247 if (!MixerInfo)
248 {
249 /* no memory */
250 return MM_STATUS_NO_MEMORY;
251 }
252
253 /* initialize mixer destination line */
254 DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
255 DestinationLine->Line.cChannels = 2; /* FIXME */
256 DestinationLine->Line.cConnections = 0;
257 DestinationLine->Line.cControls = 0;
259 DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations;
260 DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE;
261 DestinationLine->Line.dwSource = MAXULONG;
262 DestinationLine->Line.dwUser = 0;
263 DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
264
265 if (LineName)
266 {
267 MixerContext->Copy(DestinationLine->Line.szShortName, LineName, (min(MIXER_SHORT_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
268 DestinationLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
269
270 MixerContext->Copy(DestinationLine->Line.szName, LineName, (min(MIXER_LONG_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
271 DestinationLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
272
273 }
274
275 DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
276 DestinationLine->Line.Target.dwDeviceID = 0; //FIXME
277 DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
278 DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
279 DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
280
281 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
282 wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
283
284 /* initialize extra line */
285 InitializeListHead(&DestinationLine->ControlsList);
286
287 /* insert into mixer info */
288 InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry);
289
290 /* increment destination count */
291 MixerInfo->MixCaps.cDestinations++;
292
293 /* done */
294 return MM_STATUS_SUCCESS;
295}
296
300 IN LPMIXER_INFO MixerInfo,
302 IN ULONG PinId,
304{
305 KSP_PIN Pin;
309
310 /* prepare pin */
311 Pin.PinId = PinId;
312 Pin.Reserved = 0;
313 Pin.Property.Flags = KSPROPERTY_TYPE_GET;
314 Pin.Property.Set = KSPROPSETID_Pin;
315 Pin.Property.Id = KSPROPERTY_PIN_NAME;
316
317 /* try get pin name size */
319
320 /* check if buffer overflowed */
322 {
323 /* allocate buffer */
325 if (!Buffer)
326 {
327 /* out of memory */
328 return MM_STATUS_NO_MEMORY;
329 }
330
331 /* try get pin name */
334 {
335 /* failed to get pin name */
337 return Status;
338 }
339
340 /* successfully obtained pin name */
341 *OutBuffer = Buffer;
342 return MM_STATUS_SUCCESS;
343 }
344
345 /* failed to get pin name */
346 return Status;
347}
348
352 IN OUT LPMIXER_INFO MixerInfo,
354 IN ULONG PinId,
355 IN ULONG bInput)
356{
357 LPWSTR PinName;
359
360 /* try get pin name */
361 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
363 {
364 /* create mixer destination line */
365
366 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, PinName);
367
368 /* free pin name */
369 MixerContext->Free(PinName);
370 }
371 else
372 {
373 /* create mixer destination line unlocalized */
374 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, L"No Name");
375 }
376
377 return Status;
378}
379
383 IN LPMIXER_DATA MixerData,
384 OUT PTOPOLOGY * OutTopology)
385{
386 ULONG PinsCount;
387 PKSMULTIPLE_ITEM NodeTypes = NULL;
388 PKSMULTIPLE_ITEM NodeConnections = NULL;
390
391 if (MixerData->Topology)
392 {
393 /* re-use existing topology */
394 *OutTopology = MixerData->Topology;
395
396 return MM_STATUS_SUCCESS;
397 }
398
399 /* get connected filter pin count */
400 PinsCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
401
402 if (!PinsCount)
403 {
404 /* referenced filter does not have any pins */
406 }
407
408 /* get topology node types */
411 {
412 /* failed to get topology node types */
413 return Status;
414 }
415
416 /* get topology connections */
419 {
420 /* failed to get topology connections */
421 MixerContext->Free(NodeTypes);
422 return Status;
423 }
424
425 /* create a topology */
426 Status = MMixerCreateTopology(MixerContext, PinsCount, NodeConnections, NodeTypes, OutTopology);
427
428 /* free node types & connections */
429 MixerContext->Free(NodeConnections);
430 MixerContext->Free(NodeTypes);
431
433 {
434 /* store topology object */
435 MixerData->Topology = *OutTopology;
436 }
437
438 /* done */
439 return Status;
440}
441
445 IN PTOPOLOGY Topology,
446 IN ULONG PinId,
447 IN ULONG bInputMixer,
448 IN ULONG bUpStream,
449 OUT PULONG OutNodesCount,
450 OUT PULONG OutNodes,
451 OUT PULONG OutLineTerminator)
452{
453 PULONG Nodes;
454 ULONG NodesCount, NodeIndex, Count, bTerminator;
456
457 /* allocate an array to store all nodes which are upstream of this pin */
459
461 {
462 /* out of memory */
463 return STATUS_NO_MEMORY;
464 }
465
466 /* mark result array as zero */
467 *OutNodesCount = 0;
468
469 /* get next nodes */
470 MMixerGetNextNodesFromPinIndex(MixerContext, Topology, PinId, bUpStream, &NodesCount, Nodes);
471
472 if (NodesCount == 0)
473 {
474 /* a pin which is not connected from any node
475 * a) it is a topology bug (driver bug)
476 * b) the request is from an alternative mixer
477 alternative mixer code scans all pins which have not been used and tries to build lines
478 */
479 DPRINT1("MMixerCountMixerControls PinId %lu is not connected by any node\n", PinId);
480 MMixerPrintTopology(Topology);
482 }
483
484 /* assume no topology split before getting line terminator */
485 ASSERT(NodesCount == 1);
486
487 /* get first node */
488 NodeIndex = Nodes[0];
489 Count = 0;
490
491 do
492 {
493 /* check if the node is a terminator */
494 MMixerIsNodeTerminator(Topology, NodeIndex, &bTerminator);
495
496 if (bTerminator)
497 {
498 /* found terminator */
499 if (bInputMixer)
500 {
501 /* add mux source for source destination line */
502 OutNodes[Count] = NodeIndex;
503 Count++;
504 }
505 break;
506 }
507
508 /* store node id */
509 OutNodes[Count] = NodeIndex;
510
511 /* increment node count */
512 Count++;
513
514 /* get next nodes upstream */
515 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &NodesCount, Nodes);
516
517 if (NodesCount != 1)
518 {
519 DPRINT("PinId %lu bInputMixer %lu bUpStream %lu NodeIndex %lu is not connected", PinId, bInputMixer, bUpStream, NodeIndex);
520 break;
521 }
522
523 ASSERT(NodesCount == 1);
524
525 /* use first index */
526 NodeIndex = Nodes[0];
527
528 }while(TRUE);
529
530 /* free node index */
531 MixerContext->Free(Nodes);
532
533 /* store nodes count */
534 *OutNodesCount = Count;
535
536 /* store line terminator */
537 *OutLineTerminator = NodeIndex;
538
539 /* done */
540 return MM_STATUS_SUCCESS;
541}
542
546 IN LPMIXER_INFO MixerInfo,
548 IN ULONG NodeId,
549 OUT PULONG MaxChannels)
550{
552 PKSPROPERTY_DESCRIPTION NewDescription;
557
558 /* try #1 obtain it via description */
559 Request.NodeId = NodeId;
560 Request.Reserved = 0;
561 Request.Property.Set = KSPROPSETID_Audio;
564
565 /* get description */
568 {
569 if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0))
570 {
571 /* allocate new description */
572 NewDescription = MixerContext->Alloc(Description.DescriptionSize);
573
574 if (!NewDescription)
575 {
576 /* not enough memory */
577 return MM_STATUS_NO_MEMORY;
578 }
579
580 /* get description */
581 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned);
583 {
584 /* get header */
585 Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1);
586
588 {
589 /* found enhanced flag */
590 ASSERT(Header->MembersCount > 1);
591
592 /* store channel count */
593 *MaxChannels = Header->MembersCount;
594
595 /* free description */
596 MixerContext->Free(NewDescription);
597
598 /* done */
599 return MM_STATUS_SUCCESS;
600 }
601 }
602
603 /* free description */
604 MixerContext->Free(NewDescription);
605 }
606 }
607
608 /* failed to get channel count enhanced */
610}
611
612VOID
615 IN LPMIXER_INFO MixerInfo,
617 IN ULONG NodeId,
618 OUT PULONG MaxChannels)
619{
623 LONG Volume;
624
625 /* setup request */
626 Channel.Reserved = 0;
627 Channel.NodeProperty.NodeId = NodeId;
628 Channel.NodeProperty.Reserved = 0;
631 Channel.Channel = 0;
633
634 do
635 {
636 /* get channel volume */
639 break;
640
641 /* increment channel count */
642 Channel.Channel++;
643
644 }while(TRUE);
645
646 /* store channel count */
647 *MaxChannels = Channel.Channel;
648
649}
650
651VOID
654 IN LPMIXER_INFO MixerInfo,
656 IN ULONG NodeId,
657 OUT PULONG MaxChannels)
658{
660
661 /* try to get it enhanced */
662 Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
663
665 {
666 /* get it old-fashioned way */
667 MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
668 }
669}
670
674 IN LPMIXER_INFO MixerInfo,
676 IN PTOPOLOGY Topology,
677 IN OUT LPMIXERLINE_EXT DstLine,
678 IN ULONG NodesCount,
679 IN PULONG Nodes)
680{
681 ULONG Index, Count, bReserved;
684 ULONG MaxChannels;
685
686 /* initialize control count */
687 Count = 0;
688
689 for(Index = 0; Index < NodesCount; Index++)
690 {
691 /* check if the node has already been reserved to a line */
692 MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved);
693#if 0 /* MS lies */
694 if (bReserved)
695 {
696 /* node is already used, skip it */
697 continue;
698 }
699#endif
700 /* set node status as used */
701 MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
702
703 /* query node type */
704 NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]);
705
707 {
708 /* calculate maximum channel count for node */
709 MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels);
710
711 DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID);
712 /* calculate maximum channels */
713 DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels);
714 }
715 else
716 {
717 /* use default of one channel */
718 MaxChannels = 1;
719 }
720
721 /* now add the mixer control */
722 Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine, MaxChannels);
723
725 {
726 /* increment control count */
727 Count++;
728 }
729 }
730
731 /* store control count */
732 DstLine->Line.cControls = Count;
733
734 /* done */
735 return MM_STATUS_SUCCESS;
736}
737
741 IN OUT LPMIXER_INFO MixerInfo,
743 IN ULONG PinId,
744 OUT PULONG ComponentType,
745 OUT PULONG TargetType)
746{
748 KSPIN_COMMUNICATION Communication;
752 GUID Guid;
753 BOOLEAN BridgePin = FALSE;
754 PKSPIN_PHYSICALCONNECTION Connection;
755
756 /* first dataflow type */
758
760 {
761 /* failed to get dataflow */
762 return Status;
763 }
764
765 /* now get pin category guid */
766 Request.PinId = PinId;
767 Request.Reserved = 0;
768 Request.Property.Flags = KSPROPERTY_TYPE_GET;
769 Request.Property.Set = KSPROPSETID_Pin;
770 Request.Property.Id = KSPROPERTY_PIN_CATEGORY;
771
772 /* get pin category */
775 {
776 /* failed to get dataflow */
777 return Status;
778 }
779
780 /* check if it has a physical connection */
783 {
784 /* pin is a brige pin */
785 BridgePin = TRUE;
786
787 /* free physical connection */
788 MixerContext->Free(Connection);
789 }
790
792 {
795 {
796 /* type microphone */
797 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
799 }
803 {
804 /* type waveout */
805 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
807 }
809 {
810 /* type cd player */
811 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
813 }
815 {
816 /* type synthesizer */
817 *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT;
819 }
821 {
822 /* type line */
823 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
824 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
825 }
829 {
830 /* type telephone */
831 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
833 }
835 {
836 /* type analog */
837 if (BridgePin)
838 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
839 else
840 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
841
842 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
843 }
845 {
846 /* type analog */
847 if (BridgePin)
848 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
849 else
850 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
851
853 }
854 else
855 {
856 /* unknown type */
857 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
859 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
860 }
861 }
862 else
863 {
868 {
869 /* type waveout */
870 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
872 }
875 {
876 /* type wavein */
877 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
878 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
879 }
882 {
883 /* type head phones */
884 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
886 }
890 {
891 /* type waveout */
892 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
894 }
896 {
897 /* type analog */
898 if (BridgePin)
899 {
900 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
902 }
903 else
904 {
905 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
906 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
907 }
908 }
910 {
911 /* type spdif */
912 if (BridgePin)
913 {
914 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
916 }
917 else
918 {
919 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
920 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
921 }
922 }
923 else
924 {
925 /* unknown type */
926 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
928 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
929 }
930 }
931
932 /* done */
933 return MM_STATUS_SUCCESS;
934}
935
939 IN OUT LPMIXER_INFO MixerInfo,
941 IN PTOPOLOGY Topology,
942 IN ULONG PinId,
943 IN ULONG NodesCount,
944 IN PULONG Nodes,
945 IN ULONG DestinationLineID,
946 OUT LPMIXERLINE_EXT * OutSrcLine)
947{
948 LPMIXERLINE_EXT SrcLine, DstLine;
949 LPWSTR PinName;
951 ULONG ComponentType, TargetType;
952
953 /* get component and target type */
954 Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType);
956 {
957 /* failed to get component status */
960 }
961
962 /* construct source line */
963 SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT));
964
965 if (!SrcLine)
966 {
967 /* no memory */
968 return MM_STATUS_NO_MEMORY;
969 }
970
971 /* get destination line */
972 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
973 ASSERT(DstLine);
974
975 /* initialize mixer src line */
976 SrcLine->PinId = PinId;
977
978 /* initialize mixer line */
979 SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
980 SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1;
981 SrcLine->Line.dwSource = DstLine->Line.cConnections;
982 SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1);
984 SrcLine->Line.dwComponentType = ComponentType;
985 SrcLine->Line.dwUser = 0;
986 SrcLine->Line.cChannels = DstLine->Line.cChannels;
987 SrcLine->Line.cConnections = 0;
988 SrcLine->Line.Target.dwType = TargetType;
989 SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
990 SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
991 SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
992 SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
994
995 /* copy name */
996 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0');
997 wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
998
999 /* get pin name */
1000 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
1001
1003 {
1004 /* store pin name as line name */
1005 MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
1006 SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
1007
1008 MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
1009 SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
1010
1011 /* free pin name buffer */
1012 MixerContext->Free(PinName);
1013 }
1014
1015 /* add the controls to mixer line */
1016 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes);
1018 {
1019 /* failed */
1020 return Status;
1021 }
1022
1023 /* store result */
1024 *OutSrcLine = SrcLine;
1025
1026 return MM_STATUS_SUCCESS;
1027}
1028
1032 IN OUT LPMIXER_INFO MixerInfo,
1034 IN PTOPOLOGY Topology,
1035 IN ULONG DestinationLineID,
1036 IN ULONG LineTerminator)
1037{
1038 PULONG AllNodes, AllPins, AllPinNodes;
1039 ULONG AllNodesCount, AllPinsCount, AllPinNodesCount;
1040 ULONG Index, SubIndex, PinId, CurNode, bConnected;
1042 LPMIXERLINE_EXT DstLine, SrcLine;
1043
1044 /* get destination line */
1045 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
1046 ASSERT(DstLine);
1047
1048 /* allocate an array to store all nodes which are upstream of the line terminator */
1049 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllNodes);
1050
1051 /* check for success */
1053 {
1054 /* out of memory */
1055 return MM_STATUS_NO_MEMORY;
1056 }
1057
1058 /* allocate an array to store all nodes which are downstream of a particular pin */
1059 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllPinNodes);
1060
1061 /* allocate an array to store all pins which are upstream of this pin */
1062 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &AllPins);
1063
1064 /* check for success */
1066 {
1067 /* out of memory */
1068 MixerContext->Free(AllNodes);
1069 return MM_STATUS_NO_MEMORY;
1070 }
1071
1072 /* get all nodes which indirectly / directly connect to this node */
1073 AllNodesCount = 0;
1074 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllNodesCount, AllNodes);
1075
1076 /* get all pins which indirectly / directly connect to this node */
1077 AllPinsCount = 0;
1078 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins);
1079
1080 DPRINT("LineTerminator %lu\n", LineTerminator);
1081 DPRINT("PinCount %lu\n", AllPinsCount);
1082 DPRINT("AllNodesCount %lu\n", AllNodesCount);
1083
1084 /* now construct the source lines which are attached to the destination line */
1085 Index = AllPinsCount;
1086
1087 do
1088 {
1089 /* get current pin id */
1090 PinId = AllPins[Index - 1];
1091
1092 /* reset nodes count */
1093 AllPinNodesCount = 0;
1094
1095 /* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */
1096 for(SubIndex = 0; SubIndex < AllNodesCount; SubIndex++)
1097 {
1098 /* get current node index */
1099 CurNode = AllNodes[SubIndex];
1100
1101 if (CurNode != MAXULONG && CurNode != LineTerminator)
1102 {
1103 /* check if that node is connected in some way to the current pin */
1104 Status = MMixerIsNodeConnectedToPin(MixerContext, Topology, CurNode, PinId, TRUE, &bConnected);
1105
1107 break;
1108
1109 if (bConnected)
1110 {
1111 /* it is connected */
1112 AllPinNodes[AllPinNodesCount] = CurNode;
1113 AllPinNodesCount++;
1114
1115 /* clear current index */
1116 AllNodes[SubIndex] = MAXULONG;
1117 }
1118 }
1119 }
1120
1121 /* decrement pin index */
1122 Index--;
1123
1124 if (AllPinNodesCount)
1125 {
1126#ifdef MMIXER_DEBUG
1127 ULONG TempIndex;
1128#endif
1129 /* now build the mixer source line */
1130 Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine);
1131
1133 {
1134 /* insert into line list */
1135 InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
1136
1137 /* increment destination line count */
1138 DstLine->Line.cConnections++;
1139
1140 /* mark pin as reserved */
1141 MMixerSetTopologyPinReserved(Topology, PinId);
1142
1143#ifdef MMIXER_DEBUG
1144 DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID);
1145 for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++)
1146 DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]);
1147#endif
1148 }
1149 }
1150 else
1151 {
1152#ifdef MMIXER_DEBUG
1153 DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId);
1154#endif
1155 }
1156
1157 }while(Index != 0);
1158
1159 return MM_STATUS_SUCCESS;
1160}
1161
1165 IN OUT LPMIXER_INFO MixerInfo,
1167 IN PTOPOLOGY Topology,
1168 IN ULONG PinId,
1169 IN ULONG bInput,
1170 IN ULONG DestinationLineId,
1171 OUT PULONG OutLineTerminator)
1172{
1173 PULONG Nodes;
1174 ULONG NodesCount, LineTerminator;
1176 LPMIXERLINE_EXT DstLine;
1177
1178 /* allocate nodes index array */
1180
1181 /* check for success */
1183 {
1184 /* out of memory */
1185 return Status;
1186 }
1187
1188 /* get all destination line controls */
1189 Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator);
1190
1191 /* check for success */
1193 {
1194 /* failed to count controls */
1195 MixerContext->Free(Nodes);
1196 return Status;
1197 }
1198
1199 /* get destination mixer line */
1200 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId);
1201
1202 /* sanity check */
1203 ASSERT(DstLine);
1204
1205 if (NodesCount > 0)
1206 {
1207 /* add all nodes as mixer controls to the destination line */
1208 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes);
1210 {
1211 /* failed to add controls */
1212 MixerContext->Free(Nodes);
1213 return Status;
1214 }
1215 }
1216
1217 /* store result */
1218 *OutLineTerminator = LineTerminator;
1219
1220 /* return result */
1221 return Status;
1222}
1223
1224VOID
1227 IN LPMIXER_DATA MixerData,
1229 IN OUT PULONG PinsCount,
1230 IN OUT PULONG Pins)
1231{
1232 ULONG Count = 0, Index;
1234 PKSPIN_PHYSICALCONNECTION Connection;
1235
1236 for(Index = 0; Index < *PinsCount; Index++)
1237 {
1238 /* check if it has a physical connection */
1240
1242 {
1243 /* remove pin */
1244 MixerContext->Copy(&Pins[Index], &Pins[Index + 1], (*PinsCount - (Index + 1)) * sizeof(ULONG));
1245
1246 /* free physical connection */
1247 MixerContext->Free(Connection);
1248
1249 /* decrement index */
1250 Index--;
1251
1252 /* decrement pin count */
1253 (*PinsCount)--;
1254 }
1255 else
1256 {
1257 /* simple pin */
1258 Count++;
1259 }
1260 }
1261
1262 /* store result */
1263 *PinsCount = Count;
1264}
1265
1269 IN PMIXER_LIST MixerList,
1270 IN LPMIXER_DATA MixerData,
1271 IN OUT LPMIXER_INFO MixerInfo,
1272 IN ULONG bInput,
1273 IN ULONG Pin)
1274{
1276 ULONG PinsCount, LineTerminator, DestinationLineID;
1277 PULONG Pins;
1278 PTOPOLOGY Topology;
1279
1280 /* re-use existing topology */
1281 Topology = MixerData->Topology;
1282
1283 if (!bInput)
1284 {
1285 /* allocate pin index array which will hold all referenced pins */
1288 {
1289 /* failed to create topology */
1290 return Status;
1291 }
1292
1293 /* the mixer is an output mixer
1294 * find end pin of the node path
1295 */
1296 PinsCount = 0;
1298
1299 /* check for success */
1301 {
1302 /* failed to get end pin */
1303 MixerContext->Free(Pins);
1304 //MMixerFreeTopology(Topology);
1305
1306 /* return error code */
1307 return Status;
1308 }
1309 /* HACK:
1310 * some topologies do not have strict boundaries
1311 * WorkArround: remove all pin ids which have a physical connection
1312 * because bridge pins may belong to different render paths
1313 */
1314 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1315
1316 /* sanity checks */
1317 ASSERT(PinsCount != 0);
1318 if (PinsCount != 1)
1319 {
1320 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1321 }
1322
1323 /* create destination line */
1324 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1325
1326 /* calculate destination line id */
1327 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1328
1330 {
1331 /* failed to build destination line */
1332 MixerContext->Free(Pins);
1333
1334 /* return error code */
1335 return Status;
1336 }
1337
1338 /* add mixer controls to destination line */
1339 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1340
1342 {
1343 /* now add the rest of the source lines */
1344 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1345 }
1346
1347 /* mark pin as consumed */
1348 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1349
1350 /* free topology pin array */
1351 MixerContext->Free(Pins);
1352 }
1353 else
1354 {
1355 /* calculate destination line id */
1356 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1357
1358 /* add mixer controls */
1359 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pin, bInput, DestinationLineID, &LineTerminator);
1360
1362 {
1363 /* now add the rest of the source lines */
1364 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1365 }
1366 }
1367 return Status;
1368}
1369
1373 IN PMIXER_LIST MixerList,
1374 IN LPMIXER_DATA MixerData,
1375 IN OUT LPMIXER_INFO MixerInfo,
1376 IN ULONG bInput,
1377 IN PKSPIN_PHYSICALCONNECTION OutConnection)
1378{
1380 ULONG PinsCount, LineTerminator, DestinationLineID;
1381 PULONG Pins;
1382 PTOPOLOGY Topology;
1383
1384 /* first try to open the connected filter */
1385 OutConnection->SymbolicLinkName[1] = L'\\';
1386 MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
1387
1388 /* check if the linked connection is found */
1389 if (!MixerData)
1390 {
1391 /* filter references invalid physical connection */
1393 }
1394
1395 DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
1396
1397 /* sanity check */
1398 ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo);
1399
1400 /* associate with mixer */
1401 MixerData->MixerInfo = MixerInfo;
1402
1403 if (MixerData->Topology == NULL)
1404 {
1405 /* construct new topology */
1406 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1408 {
1409 /* failed to create topology */
1410 return Status;
1411 }
1412
1413 /* store topology */
1414 MixerData->Topology = Topology;
1415 }
1416 else
1417 {
1418 /* re-use existing topology */
1419 Topology = MixerData->Topology;
1420 }
1421
1422 /* mark pin as consumed */
1423 MMixerSetTopologyPinReserved(Topology, OutConnection->Pin);
1424
1425 if (!bInput)
1426 {
1427 /* allocate pin index array which will hold all referenced pins */
1430 {
1431 /* failed to create topology */
1432 return Status;
1433 }
1434
1435 /* the mixer is an output mixer
1436 * find end pin of the node path
1437 */
1438 PinsCount = 0;
1439 Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex(MixerContext, Topology, OutConnection->Pin, FALSE, &PinsCount, Pins);
1440
1441 /* check for success */
1443 {
1444 /* failed to get end pin */
1445 MixerContext->Free(Pins);
1446 //MMixerFreeTopology(Topology);
1447
1448 /* return error code */
1449 return Status;
1450 }
1451 /* HACK:
1452 * some topologies do not have strict boundaries
1453 * WorkArround: remove all pin ids which have a physical connection
1454 * because bridge pins may belong to different render paths
1455 */
1456 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1457
1458 /* sanity checks */
1459 ASSERT(PinsCount != 0);
1460 if (PinsCount != 1)
1461 {
1462 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1463 }
1464
1465 /* create destination line */
1466 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1467
1468 /* calculate destination line id */
1469 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1470
1472 {
1473 /* failed to build destination line */
1474 MixerContext->Free(Pins);
1475
1476 /* return error code */
1477 return Status;
1478 }
1479
1480 /* add mixer controls to destination line */
1481 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1482
1484 {
1485 /* now add the rest of the source lines */
1486 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1487 }
1488
1489 /* mark pin as consumed */
1490 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1491
1492 /* free topology pin array */
1493 MixerContext->Free(Pins);
1494 }
1495 else
1496 {
1497 /* calculate destination line id */
1498 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1499
1500 /* add mixer controls */
1501 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator);
1502
1504 {
1505 /* now add the rest of the source lines */
1506 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1507 }
1508 }
1509
1510 return Status;
1511}
1512
1516 IN PMIXER_LIST MixerList,
1517 IN LPMIXER_DATA MixerData,
1518 IN LPMIXER_INFO MixerInfo,
1519 IN PTOPOLOGY Topology,
1520 IN ULONG NodeIndex,
1521 IN ULONG bInputMixer,
1522 IN OUT LPMIXER_INFO * OutMixerInfo)
1523{
1524 ULONG Index;
1526 PKSPIN_PHYSICALCONNECTION OutConnection;
1527 ULONG * Pins;
1528 ULONG PinsFound;
1529 ULONG NewMixerInfo = FALSE;
1530
1531 if (MixerInfo == NULL)
1532 {
1533 /* allocate a mixer info struct */
1534 MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
1535 if (!MixerInfo)
1536 {
1537 /* no memory */
1538 return MM_STATUS_NO_MEMORY;
1539 }
1540
1541 /* new mixer info */
1542 NewMixerInfo = TRUE;
1543
1544 /* intialize mixer caps */
1545 MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */
1546 MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */
1547 MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */
1548 MixerInfo->MixCaps.fdwSupport = 0;
1549 MixerInfo->MixCaps.cDestinations = 0;
1550
1551 /* get mixer name */
1552 Status = MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
1554 {
1555 /* try get name with component id */
1556 Status = MMixerGetDeviceNameWithComponentId(MixerContext, MixerData->hDevice, MixerInfo->MixCaps.szPname);
1558 {
1559 MixerInfo->MixCaps.szPname[0] = L'\0';
1560 }
1561 }
1562
1563 /* initialize line list */
1564 InitializeListHead(&MixerInfo->LineList);
1565 InitializeListHead(&MixerInfo->EventList);
1566
1567 /* associate with mixer data */
1568 MixerData->MixerInfo = MixerInfo;
1569 }
1570
1571 /* store mixer info */
1572 *OutMixerInfo = MixerInfo;
1573
1574 /* now allocate an array which will receive the indices of the pin
1575 * which has a ADC / DAC nodetype in its path
1576 */
1579
1580 PinsFound = 0;
1581
1582 /* now get all sink / source pins, which are attached to the ADC / DAC node
1583 * For sink pins (wave out) search up stream
1584 * For source pins (wave in) search down stream
1585 * The search direction is always the opposite of the current mixer type
1586 */
1587 PinsFound = 0;
1588 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins);
1589
1590 /* if there is no pin found, we have a broken topology */
1591 ASSERT(PinsFound != 0);
1592
1593 /* now create a wave info struct */
1594 Status = MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinsFound, Pins);
1596 {
1597 /* failed to create wave info struct */
1598 MixerContext->Free(MixerInfo);
1599 MixerContext->Free(Pins);
1600 return Status;
1601 }
1602
1603 /* mark all found pins as reserved */
1604 for(Index = 0; Index < PinsFound; Index++)
1605 {
1606 MMixerSetTopologyPinReserved(Topology, Pins[Index]);
1607 }
1608
1609 if (bInputMixer)
1610 {
1611 /* pre create the mixer destination line for input mixers */
1612 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer);
1613
1615 {
1616 /* failed to create mixer destination line */
1617 return Status;
1618 }
1619 }
1620
1621 /* now get the bridge pin which is at the end of node path
1622 * For sink pins (wave out) search down stream
1623 * For source pins (wave in) search up stream
1624 */
1625 MixerContext->Free(Pins);
1628
1629 PinsFound = 0;
1630 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bInputMixer, &PinsFound, Pins);
1631
1632 /* if there is no pin found, we have a broken topology */
1633 ASSERT(PinsFound != 0);
1634
1635 /* there should be exactly one bridge pin */
1636 ASSERT(PinsFound == 1);
1637
1638 DPRINT("BridgePin %lu bInputMixer %lu\n", Pins[0], bInputMixer);
1639
1640 /* does the pin have a physical connection */
1641 Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[0], &OutConnection);
1642
1644 {
1645 /* mark pin as reserved */
1646 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1647
1648 /* topology on the topoloy filter */
1649 Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection);
1650
1651 /* free physical connection data */
1652 MixerContext->Free(OutConnection);
1653 }
1654 else
1655 {
1656 /* topology is on the same filter */
1657 Status = MMixerHandleTopologyFilter(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, Pins[0]);
1658 }
1659
1660 /* free pins */
1661 MixerContext->Free(Pins);
1662
1663 if (NewMixerInfo)
1664 {
1665 /* insert mixer */
1666 InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
1667 /* increment mixer count */
1668 MixerList->MixerListCount++;
1669 }
1670
1671 /* done */
1672 return Status;
1673}
1674
1675VOID
1678 IN PMIXER_LIST MixerList,
1679 IN LPMIXER_DATA MixerData,
1680 IN PTOPOLOGY Topology)
1681{
1684 ULONG DestinationLineID, LineTerminator;
1685 LPMIXERLINE_EXT DstLine;
1686
1687 DPRINT("DeviceName %S\n", MixerData->DeviceName);
1688
1689 /* get topology pin count */
1691
1692 for(Index = 0; Index < PinCount; Index++)
1693 {
1695
1696 /* check if it has already been reserved */
1697 if (Reserved)
1698 {
1699 /* pin has already been reserved */
1700 continue;
1701 }
1702
1703 DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index);
1704
1705 /* sanity check */
1706 //ASSERT(MixerData->MixerInfo);
1707
1708 if (!MixerData->MixerInfo)
1709 {
1710 DPRINT1("Expected mixer info\n");
1711 continue;
1712 }
1713
1714 /* build the destination line */
1715 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE);
1717 {
1718 /* failed to build destination line */
1719 continue;
1720 }
1721
1722 /* calculate destination line id */
1723 DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1);
1724
1725 /* add mixer controls to destination line */
1726 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator);
1728 {
1729 /* now add the rest of the source lines */
1730 Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator);
1731 }
1732
1733 /* mark pin as consumed */
1735
1736 /* now grab destination line */
1737 DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID);
1738
1739 /* set type and target as undefined */
1741 DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1742 DstLine->Line.Target.vDriverVersion = 0;
1743 DstLine->Line.Target.wMid = 0;
1744 DstLine->Line.Target.wPid = 0;
1745 }
1746}
1747
1751 IN PMIXER_LIST MixerList,
1752 IN LPMIXER_DATA MixerData,
1754{
1756 PTOPOLOGY Topology;
1757 ULONG NodeIndex;
1758 LPMIXER_INFO MixerInfo = NULL;
1759
1760 /* check if topology has already been built */
1761 if (MixerData->Topology == NULL)
1762 {
1763 /* build topology */
1764 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1765
1767 {
1768 /* failed to build topology */
1769 return Status;
1770 }
1771
1772 /* store topology */
1773 MixerData->Topology = Topology;
1774 }
1775 else
1776 {
1777 /* re-use topology */
1778 Topology = MixerData->Topology;
1779 }
1780
1781 /* check if the filter has an wave out node */
1782 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_DAC);
1783 if (NodeIndex != MAXULONG)
1784 {
1785 /* it has */
1786 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo);
1787
1788 /* check for success */
1790 {
1791 /* increment mixer count */
1792 (*DeviceCount)++;
1793 }
1794 else
1795 {
1796 /* reset mixer info in case of error */
1797 MixerInfo = NULL;
1798 }
1799 }
1800
1801 /* check if the filter has an wave in node */
1802 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_ADC);
1803 if (NodeIndex != MAXULONG)
1804 {
1805 /* it has */
1806 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo);
1807
1808 /* check for success */
1810 {
1811 /* increment mixer count */
1812 (*DeviceCount)++;
1813 }
1814
1815 }
1816
1817 /* TODO: apply hacks for Wave source line */
1818
1819 /* activate midi devices */
1820 //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
1821
1822 /* done */
1823 return Status;
1824}
1825
1829 IN OUT LPMIXER_INFO MixerInfo,
1830 IN PVOID MixerEventContext,
1831 IN PMIXER_EVENT MixerEventRoutine)
1832{
1833 //KSE_NODE Property;
1834 //KSEVENTDATA EventData
1835 //ULONG BytesReturned;
1836 //MIXER_STATUS Status;
1837 PEVENT_NOTIFICATION_ENTRY EventNotification;
1838
1840 if (!EventNotification)
1841 {
1842 /* not enough memory */
1843 return MM_STATUS_NO_MEMORY;
1844 }
1845
1846 /* FIXME: what is it supposed to happen with KSEVENTDATA ? */
1847#if 0
1848 /* setup request */
1852
1853 Property.NodeId = NodeId;
1854 Property.Reserved = 0;
1855
1856 Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned);
1858 {
1859 /* failed to add event */
1860 MixerContext->FreeEventData(EventData);
1861 return Status;
1862 }
1863#endif
1864
1865 /* initialize notification entry */
1866 EventNotification->MixerEventContext = MixerEventContext;
1867 EventNotification->MixerEventRoutine = MixerEventRoutine;
1868
1869 /* store event */
1870 InsertTailList(&MixerInfo->EventList, &EventNotification->Entry);
1871 return MM_STATUS_SUCCESS;
1872}
1873
1877 IN OUT LPMIXER_INFO MixerInfo,
1878 IN PVOID MixerEventContext,
1879 IN PMIXER_EVENT MixerEventRoutine)
1880{
1881 PLIST_ENTRY EventList;
1883
1884 /* Lookup through mixers */
1885 EventList = MixerInfo->EventList.Flink;
1886 while(EventList != &MixerInfo->EventList)
1887 {
1889 EventList = EventList->Flink;
1890 /* TODO: find a better way to identify an event ? */
1891 if(NotificationEntry->MixerEventRoutine == MixerEventRoutine &&
1892 NotificationEntry->MixerEventContext == MixerEventContext)
1893 {
1894 DPRINT1("Freeing entry %p\n", NotificationEntry);
1895 /* We found the event to remove */
1898 }
1899 }
1900 return MM_STATUS_SUCCESS;
1901}
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
#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:1827
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:739
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:1371
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:937
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:672
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:1676
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:1267
MIXER_STATUS MMixerGetPinName(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG PinId, IN OUT LPWSTR *OutBuffer)
Definition: controls.c:298
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:544
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:1030
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:1749
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:1875
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:443
MIXER_STATUS MMixerCreateDestinationLine(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN ULONG bInputMixer, IN LPWSTR LineName)
Definition: controls.c:237
MIXER_STATUS MMixerBuildTopology(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, OUT PTOPOLOGY *OutTopology)
Definition: controls.c:381
VOID MMixerGetMaxChannelsForNode(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:652
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:1163
VOID MMixerApplyOutputFilterHack(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, IN HANDLE hMixer, IN OUT PULONG PinsCount, IN OUT PULONG Pins)
Definition: controls.c:1225
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:1514
VOID MMixerGetChannelCountLegacy(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:613
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:350
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 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:427
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
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
struct tagRange Range
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_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:756
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:852
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:324
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:804
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:71
_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
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
DWORD cMultipleItems
Definition: mmsystem.h:1308
WCHAR szShortName[MIXER_SHORT_NAME_CHARS]
Definition: mmsystem.h:1309
union tagMIXERCONTROLW::@3036 Bounds
DWORD dwReserved[6]
Definition: mmsystem.h:1320
union tagMIXERCONTROLW::@3037 Metrics
struct tagMIXERLINEW::@3031 Target
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
DWORD cbStruct
Definition: mmsystem.h:1255
DWORD dwComponentType
Definition: mmsystem.h:1261
WCHAR szShortName[MIXER_SHORT_NAME_CHARS]
Definition: mmsystem.h:1265
Definition: range.c:39
#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
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