ReactOS 0.4.16-dev-2206-gc56950d
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 LPMIXERVOLUME_DATA VolumeData;
163
164 MixerControl->Control.Bounds.dwMinimum = 0;
165 MixerControl->Control.Bounds.dwMaximum = 0xFFFF;
166 MixerControl->Control.Metrics.cSteps = 0xC0; /* FIXME */
167
170 ASSERT(Desc);
171
172 /* setup the request */
174
175 Property.NodeProperty.NodeId = NodeIndex;
178 Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
179
180 /* get node volume level info */
182
183 VolumeData = (LPMIXERVOLUME_DATA)MixerContext->Alloc(sizeof(*VolumeData));
184 if (!VolumeData)
185 return MM_STATUS_NO_MEMORY;
186
188 {
189 Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1);
190 Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1);
191
192 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);
193
194 /* Store mixer control info there */
195 VolumeData->Header.dwControlID = MixerControl->Control.dwControlID;
196 VolumeData->SignedMinimum = Range->Bounds.SignedMinimum;
197 VolumeData->SignedMaximum = Range->Bounds.SignedMaximum;
198
199 /* Fallback to defaults if: 1) the range is not defined (typically is 0) */
200 if (VolumeData->SignedMinimum == VolumeData->SignedMaximum)
201 {
202 VolumeData->SignedMinimum = -96 * 0x10000; // -96 DB
203 VolumeData->SignedMaximum = 0; // 0 DB
204 }
205 }
206 else
207 {
208 /* or 2) when some failure occurs */
209 VolumeData->Header.dwControlID = MixerControl->Control.dwControlID;
210 VolumeData->SignedMinimum = -96 * 0x10000; // -96 DB
211 VolumeData->SignedMaximum = 0; // 0 DB
212 }
213 MixerControl->ExtraData = VolumeData;
214 MixerContext->Free(Desc);
215 }
216
217 DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName);
218 return MM_STATUS_SUCCESS;
219}
220
224 IN LPMIXER_INFO MixerInfo,
225 IN ULONG bInputMixer,
226 IN LPWSTR LineName)
227{
228 LPMIXERLINE_EXT DestinationLine;
229
230 /* allocate a mixer destination line */
231 DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
232 if (!MixerInfo)
233 {
234 /* no memory */
235 return MM_STATUS_NO_MEMORY;
236 }
237
238 /* initialize mixer destination line */
239 DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
240 DestinationLine->Line.cChannels = 2; /* FIXME */
241 DestinationLine->Line.cConnections = 0;
242 DestinationLine->Line.cControls = 0;
244 DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations;
245 DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE;
246 DestinationLine->Line.dwSource = MAXULONG;
247 DestinationLine->Line.dwUser = 0;
248 DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
249
250 if (LineName)
251 {
252 MixerContext->Copy(DestinationLine->Line.szShortName, LineName, (min(MIXER_SHORT_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
253 DestinationLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
254
255 MixerContext->Copy(DestinationLine->Line.szName, LineName, (min(MIXER_LONG_NAME_CHARS, wcslen(LineName)+1)) * sizeof(WCHAR));
256 DestinationLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
257
258 }
259
260 DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
261 DestinationLine->Line.Target.dwDeviceID = 0; //FIXME
262 DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
263 DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
264 DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
265
266 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
267 wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
268
269 /* initialize extra line */
270 InitializeListHead(&DestinationLine->ControlsList);
271
272 /* insert into mixer info */
273 InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry);
274
275 /* increment destination count */
276 MixerInfo->MixCaps.cDestinations++;
277
278 /* done */
279 return MM_STATUS_SUCCESS;
280}
281
285 IN LPMIXER_INFO MixerInfo,
287 IN ULONG PinId,
289{
290 KSP_PIN Pin;
294
295 /* prepare pin */
296 Pin.PinId = PinId;
297 Pin.Reserved = 0;
298 Pin.Property.Flags = KSPROPERTY_TYPE_GET;
299 Pin.Property.Set = KSPROPSETID_Pin;
300 Pin.Property.Id = KSPROPERTY_PIN_NAME;
301
302 /* try get pin name size */
304
305 /* check if buffer overflowed */
307 {
308 /* allocate buffer */
310 if (!Buffer)
311 {
312 /* out of memory */
313 return MM_STATUS_NO_MEMORY;
314 }
315
316 /* try get pin name */
319 {
320 /* failed to get pin name */
322 return Status;
323 }
324
325 /* successfully obtained pin name */
326 *OutBuffer = Buffer;
327 return MM_STATUS_SUCCESS;
328 }
329
330 /* failed to get pin name */
331 return Status;
332}
333
337 IN OUT LPMIXER_INFO MixerInfo,
339 IN ULONG PinId,
340 IN ULONG bInput)
341{
342 LPWSTR PinName;
344
345 /* try get pin name */
346 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
348 {
349 /* create mixer destination line */
350
351 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, PinName);
352
353 /* free pin name */
354 MixerContext->Free(PinName);
355 }
356 else
357 {
358 /* create mixer destination line unlocalized */
359 Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, L"No Name");
360 }
361
362 return Status;
363}
364
368 IN LPMIXER_DATA MixerData,
369 OUT PTOPOLOGY * OutTopology)
370{
371 ULONG PinsCount;
372 PKSMULTIPLE_ITEM NodeTypes = NULL;
373 PKSMULTIPLE_ITEM NodeConnections = NULL;
375
376 if (MixerData->Topology)
377 {
378 /* re-use existing topology */
379 *OutTopology = MixerData->Topology;
380
381 return MM_STATUS_SUCCESS;
382 }
383
384 /* get connected filter pin count */
385 PinsCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
386
387 if (!PinsCount)
388 {
389 /* referenced filter does not have any pins */
391 }
392
393 /* get topology node types */
396 {
397 /* failed to get topology node types */
398 return Status;
399 }
400
401 /* get topology connections */
404 {
405 /* failed to get topology connections */
406 MixerContext->Free(NodeTypes);
407 return Status;
408 }
409
410 /* create a topology */
411 Status = MMixerCreateTopology(MixerContext, PinsCount, NodeConnections, NodeTypes, OutTopology);
412
413 /* free node types & connections */
414 MixerContext->Free(NodeConnections);
415 MixerContext->Free(NodeTypes);
416
418 {
419 /* store topology object */
420 MixerData->Topology = *OutTopology;
421 }
422
423 /* done */
424 return Status;
425}
426
430 IN PTOPOLOGY Topology,
431 IN ULONG PinId,
432 IN ULONG bInputMixer,
433 IN ULONG bUpStream,
434 OUT PULONG OutNodesCount,
435 OUT PULONG OutNodes,
436 OUT PULONG OutLineTerminator)
437{
438 PULONG Nodes;
439 ULONG NodesCount, NodeIndex, Count, bTerminator;
441
442 /* allocate an array to store all nodes which are upstream of this pin */
444
446 {
447 /* out of memory */
448 return STATUS_NO_MEMORY;
449 }
450
451 /* mark result array as zero */
452 *OutNodesCount = 0;
453
454 /* get next nodes */
455 MMixerGetNextNodesFromPinIndex(MixerContext, Topology, PinId, bUpStream, &NodesCount, Nodes);
456
457 if (NodesCount == 0)
458 {
459 /* a pin which is not connected from any node
460 * a) it is a topology bug (driver bug)
461 * b) the request is from an alternative mixer
462 alternative mixer code scans all pins which have not been used and tries to build lines
463 */
464 DPRINT1("MMixerCountMixerControls PinId %lu is not connected by any node\n", PinId);
465 MMixerPrintTopology(Topology);
467 }
468
469 /* assume no topology split before getting line terminator */
470 ASSERT(NodesCount == 1);
471
472 /* get first node */
473 NodeIndex = Nodes[0];
474 Count = 0;
475
476 do
477 {
478 /* check if the node is a terminator */
479 MMixerIsNodeTerminator(Topology, NodeIndex, &bTerminator);
480
481 if (bTerminator)
482 {
483 /* found terminator */
484 if (bInputMixer)
485 {
486 /* add mux source for source destination line */
487 OutNodes[Count] = NodeIndex;
488 Count++;
489 }
490 break;
491 }
492
493 /* store node id */
494 OutNodes[Count] = NodeIndex;
495
496 /* increment node count */
497 Count++;
498
499 /* get next nodes upstream */
500 MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &NodesCount, Nodes);
501
502 if (NodesCount != 1)
503 {
504 DPRINT("PinId %lu bInputMixer %lu bUpStream %lu NodeIndex %lu is not connected", PinId, bInputMixer, bUpStream, NodeIndex);
505 break;
506 }
507
508 ASSERT(NodesCount == 1);
509
510 /* use first index */
511 NodeIndex = Nodes[0];
512
513 }while(TRUE);
514
515 /* free node index */
516 MixerContext->Free(Nodes);
517
518 /* store nodes count */
519 *OutNodesCount = Count;
520
521 /* store line terminator */
522 *OutLineTerminator = NodeIndex;
523
524 /* done */
525 return MM_STATUS_SUCCESS;
526}
527
531 IN LPMIXER_INFO MixerInfo,
533 IN ULONG NodeId,
534 OUT PULONG MaxChannels)
535{
537 PKSPROPERTY_DESCRIPTION NewDescription;
542
543 /* try #1 obtain it via description */
544 Request.NodeId = NodeId;
545 Request.Reserved = 0;
546 Request.Property.Set = KSPROPSETID_Audio;
549
550 /* get description */
553 {
554 if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0))
555 {
556 /* allocate new description */
557 NewDescription = MixerContext->Alloc(Description.DescriptionSize);
558
559 if (!NewDescription)
560 {
561 /* not enough memory */
562 return MM_STATUS_NO_MEMORY;
563 }
564
565 /* get description */
566 Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned);
568 {
569 /* get header */
570 Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1);
571
573 {
574 /* found enhanced flag */
575 ASSERT(Header->MembersCount > 1);
576
577 /* store channel count */
578 *MaxChannels = Header->MembersCount;
579
580 /* free description */
581 MixerContext->Free(NewDescription);
582
583 /* done */
584 return MM_STATUS_SUCCESS;
585 }
586 }
587
588 /* free description */
589 MixerContext->Free(NewDescription);
590 }
591 }
592
593 /* failed to get channel count enhanced */
595}
596
597VOID
600 IN LPMIXER_INFO MixerInfo,
602 IN ULONG NodeId,
603 OUT PULONG MaxChannels)
604{
608 LONG Volume;
609
610 /* setup request */
611 Channel.Reserved = 0;
612 Channel.NodeProperty.NodeId = NodeId;
613 Channel.NodeProperty.Reserved = 0;
616 Channel.Channel = 0;
618
619 do
620 {
621 /* get channel volume */
624 break;
625
626 /* increment channel count */
627 Channel.Channel++;
628
629 }while(TRUE);
630
631 /* store channel count */
632 *MaxChannels = Channel.Channel;
633
634}
635
636VOID
639 IN LPMIXER_INFO MixerInfo,
641 IN ULONG NodeId,
642 OUT PULONG MaxChannels)
643{
645
646 /* try to get it enhanced */
647 Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
648
650 {
651 /* get it old-fashioned way */
652 MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
653 }
654}
655
659 IN LPMIXER_INFO MixerInfo,
661 IN PTOPOLOGY Topology,
662 IN OUT LPMIXERLINE_EXT DstLine,
663 IN ULONG NodesCount,
664 IN PULONG Nodes)
665{
666 ULONG Index, Count, bReserved;
669 ULONG MaxChannels;
670
671 /* initialize control count */
672 Count = 0;
673
674 for(Index = 0; Index < NodesCount; Index++)
675 {
676 /* check if the node has already been reserved to a line */
677 MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved);
678#if 0 /* MS lies */
679 if (bReserved)
680 {
681 /* node is already used, skip it */
682 continue;
683 }
684#endif
685 /* set node status as used */
686 MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
687
688 /* query node type */
689 NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]);
690
692 {
693 /* calculate maximum channel count for node */
694 MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels);
695
696 DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID);
697 /* calculate maximum channels */
698 DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels);
699 }
700 else
701 {
702 /* use default of one channel */
703 MaxChannels = 1;
704 }
705
706 /* now add the mixer control */
707 Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine, MaxChannels);
708
710 {
711 /* increment control count */
712 Count++;
713 }
714 }
715
716 /* store control count */
717 DstLine->Line.cControls = Count;
718
719 /* done */
720 return MM_STATUS_SUCCESS;
721}
722
726 IN OUT LPMIXER_INFO MixerInfo,
728 IN ULONG PinId,
729 OUT PULONG ComponentType,
730 OUT PULONG TargetType)
731{
733 KSPIN_COMMUNICATION Communication;
737 GUID Guid;
738 BOOLEAN BridgePin = FALSE;
739 PKSPIN_PHYSICALCONNECTION Connection;
740
741 /* first dataflow type */
743
745 {
746 /* failed to get dataflow */
747 return Status;
748 }
749
750 /* now get pin category guid */
751 Request.PinId = PinId;
752 Request.Reserved = 0;
753 Request.Property.Flags = KSPROPERTY_TYPE_GET;
754 Request.Property.Set = KSPROPSETID_Pin;
755 Request.Property.Id = KSPROPERTY_PIN_CATEGORY;
756
757 /* get pin category */
760 {
761 /* failed to get dataflow */
762 return Status;
763 }
764
765 /* check if it has a physical connection */
768 {
769 /* pin is a brige pin */
770 BridgePin = TRUE;
771
772 /* free physical connection */
773 MixerContext->Free(Connection);
774 }
775
777 {
780 {
781 /* type microphone */
782 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
784 }
788 {
789 /* type waveout */
790 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
792 }
794 {
795 /* type cd player */
796 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
798 }
800 {
801 /* type synthesizer */
802 *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT;
804 }
806 {
807 /* type line */
808 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
809 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
810 }
814 {
815 /* type telephone */
816 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
818 }
820 {
821 /* type analog */
822 if (BridgePin)
823 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
824 else
825 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
826
827 *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
828 }
830 {
831 /* type analog */
832 if (BridgePin)
833 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
834 else
835 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
836
838 }
839 else
840 {
841 /* unknown type */
842 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
844 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
845 }
846 }
847 else
848 {
853 {
854 /* type waveout */
855 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
857 }
860 {
861 /* type wavein */
862 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
863 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
864 }
867 {
868 /* type head phones */
869 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
871 }
875 {
876 /* type waveout */
877 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
879 }
881 {
882 /* type analog */
883 if (BridgePin)
884 {
885 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
887 }
888 else
889 {
890 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
891 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
892 }
893 }
895 {
896 /* type spdif */
897 if (BridgePin)
898 {
899 *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
901 }
902 else
903 {
904 *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
905 *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
906 }
907 }
908 else
909 {
910 /* unknown type */
911 *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
913 DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
914 }
915 }
916
917 /* done */
918 return MM_STATUS_SUCCESS;
919}
920
924 IN OUT LPMIXER_INFO MixerInfo,
926 IN PTOPOLOGY Topology,
927 IN ULONG PinId,
928 IN ULONG NodesCount,
929 IN PULONG Nodes,
930 IN ULONG DestinationLineID,
931 OUT LPMIXERLINE_EXT * OutSrcLine)
932{
933 LPMIXERLINE_EXT SrcLine, DstLine;
934 LPWSTR PinName;
936 ULONG ComponentType, TargetType;
937
938 /* get component and target type */
939 Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType);
941 {
942 /* failed to get component status */
945 }
946
947 /* construct source line */
948 SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT));
949
950 if (!SrcLine)
951 {
952 /* no memory */
953 return MM_STATUS_NO_MEMORY;
954 }
955
956 /* get destination line */
957 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
958 ASSERT(DstLine);
959
960 /* initialize mixer src line */
961 SrcLine->PinId = PinId;
962
963 /* initialize mixer line */
964 SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
965 SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1;
966 SrcLine->Line.dwSource = DstLine->Line.cConnections;
967 SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1);
969 SrcLine->Line.dwComponentType = ComponentType;
970 SrcLine->Line.dwUser = 0;
971 SrcLine->Line.cChannels = DstLine->Line.cChannels;
972 SrcLine->Line.cConnections = 0;
973 SrcLine->Line.Target.dwType = TargetType;
974 SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
975 SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
976 SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
977 SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
979
980 /* copy name */
981 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0');
982 wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
983
984 /* get pin name */
985 Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
986
988 {
989 /* store pin name as line name */
990 MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
991 SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
992
993 MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
994 SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
995
996 /* free pin name buffer */
997 MixerContext->Free(PinName);
998 }
999
1000 /* add the controls to mixer line */
1001 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes);
1003 {
1004 /* failed */
1005 return Status;
1006 }
1007
1008 /* store result */
1009 *OutSrcLine = SrcLine;
1010
1011 return MM_STATUS_SUCCESS;
1012}
1013
1017 IN OUT LPMIXER_INFO MixerInfo,
1019 IN PTOPOLOGY Topology,
1020 IN ULONG DestinationLineID,
1021 IN ULONG LineTerminator)
1022{
1023 PULONG AllNodes, AllPins, AllPinNodes;
1024 ULONG AllNodesCount, AllPinsCount, AllPinNodesCount;
1025 ULONG Index, SubIndex, PinId, CurNode, bConnected;
1027 LPMIXERLINE_EXT DstLine, SrcLine;
1028
1029 /* get destination line */
1030 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
1031 ASSERT(DstLine);
1032
1033 /* allocate an array to store all nodes which are upstream of the line terminator */
1034 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllNodes);
1035
1036 /* check for success */
1038 {
1039 /* out of memory */
1040 return MM_STATUS_NO_MEMORY;
1041 }
1042
1043 /* allocate an array to store all nodes which are downstream of a particular pin */
1044 Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllPinNodes);
1045
1046 /* allocate an array to store all pins which are upstream of this pin */
1047 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &AllPins);
1048
1049 /* check for success */
1051 {
1052 /* out of memory */
1053 MixerContext->Free(AllNodes);
1054 return MM_STATUS_NO_MEMORY;
1055 }
1056
1057 /* get all nodes which indirectly / directly connect to this node */
1058 AllNodesCount = 0;
1059 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllNodesCount, AllNodes);
1060
1061 /* get all pins which indirectly / directly connect to this node */
1062 AllPinsCount = 0;
1063 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins);
1064
1065 DPRINT("LineTerminator %lu\n", LineTerminator);
1066 DPRINT("PinCount %lu\n", AllPinsCount);
1067 DPRINT("AllNodesCount %lu\n", AllNodesCount);
1068
1069 /* now construct the source lines which are attached to the destination line */
1070 Index = AllPinsCount;
1071
1072 do
1073 {
1074 /* get current pin id */
1075 PinId = AllPins[Index - 1];
1076
1077 /* reset nodes count */
1078 AllPinNodesCount = 0;
1079
1080 /* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */
1081 for(SubIndex = 0; SubIndex < AllNodesCount; SubIndex++)
1082 {
1083 /* get current node index */
1084 CurNode = AllNodes[SubIndex];
1085
1086 if (CurNode != MAXULONG && CurNode != LineTerminator)
1087 {
1088 /* check if that node is connected in some way to the current pin */
1089 Status = MMixerIsNodeConnectedToPin(MixerContext, Topology, CurNode, PinId, TRUE, &bConnected);
1090
1092 break;
1093
1094 if (bConnected)
1095 {
1096 /* it is connected */
1097 AllPinNodes[AllPinNodesCount] = CurNode;
1098 AllPinNodesCount++;
1099
1100 /* clear current index */
1101 AllNodes[SubIndex] = MAXULONG;
1102 }
1103 }
1104 }
1105
1106 /* decrement pin index */
1107 Index--;
1108
1109 if (AllPinNodesCount)
1110 {
1111#ifdef MMIXER_DEBUG
1112 ULONG TempIndex;
1113#endif
1114 /* now build the mixer source line */
1115 Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine);
1116
1118 {
1119 /* insert into line list */
1120 InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
1121
1122 /* increment destination line count */
1123 DstLine->Line.cConnections++;
1124
1125 /* mark pin as reserved */
1126 MMixerSetTopologyPinReserved(Topology, PinId);
1127
1128#ifdef MMIXER_DEBUG
1129 DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID);
1130 for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++)
1131 DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]);
1132#endif
1133 }
1134 }
1135 else
1136 {
1137#ifdef MMIXER_DEBUG
1138 DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId);
1139#endif
1140 }
1141
1142 }while(Index != 0);
1143
1144 return MM_STATUS_SUCCESS;
1145}
1146
1150 IN OUT LPMIXER_INFO MixerInfo,
1152 IN PTOPOLOGY Topology,
1153 IN ULONG PinId,
1154 IN ULONG bInput,
1155 IN ULONG DestinationLineId,
1156 OUT PULONG OutLineTerminator)
1157{
1158 PULONG Nodes;
1159 ULONG NodesCount, LineTerminator;
1161 LPMIXERLINE_EXT DstLine;
1162
1163 /* allocate nodes index array */
1165
1166 /* check for success */
1168 {
1169 /* out of memory */
1170 return Status;
1171 }
1172
1173 /* get all destination line controls */
1174 Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator);
1175
1176 /* check for success */
1178 {
1179 /* failed to count controls */
1180 MixerContext->Free(Nodes);
1181 return Status;
1182 }
1183
1184 /* get destination mixer line */
1185 DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId);
1186
1187 /* sanity check */
1188 ASSERT(DstLine);
1189
1190 if (NodesCount > 0)
1191 {
1192 /* add all nodes as mixer controls to the destination line */
1193 Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes);
1195 {
1196 /* failed to add controls */
1197 MixerContext->Free(Nodes);
1198 return Status;
1199 }
1200 }
1201
1202 /* store result */
1203 *OutLineTerminator = LineTerminator;
1204
1205 /* return result */
1206 return Status;
1207}
1208
1209VOID
1212 IN LPMIXER_DATA MixerData,
1214 IN OUT PULONG PinsCount,
1215 IN OUT PULONG Pins)
1216{
1217 ULONG Count = 0, Index;
1219 PKSPIN_PHYSICALCONNECTION Connection;
1220
1221 for(Index = 0; Index < *PinsCount; Index++)
1222 {
1223 /* check if it has a physical connection */
1225
1227 {
1228 /* remove pin */
1229 MixerContext->Copy(&Pins[Index], &Pins[Index + 1], (*PinsCount - (Index + 1)) * sizeof(ULONG));
1230
1231 /* free physical connection */
1232 MixerContext->Free(Connection);
1233
1234 /* decrement index */
1235 Index--;
1236
1237 /* decrement pin count */
1238 (*PinsCount)--;
1239 }
1240 else
1241 {
1242 /* simple pin */
1243 Count++;
1244 }
1245 }
1246
1247 /* store result */
1248 *PinsCount = Count;
1249}
1250
1254 IN PMIXER_LIST MixerList,
1255 IN LPMIXER_DATA MixerData,
1256 IN OUT LPMIXER_INFO MixerInfo,
1257 IN ULONG bInput,
1258 IN ULONG Pin)
1259{
1261 ULONG PinsCount, LineTerminator, DestinationLineID;
1262 PULONG Pins;
1263 PTOPOLOGY Topology;
1264
1265 /* re-use existing topology */
1266 Topology = MixerData->Topology;
1267
1268 if (!bInput)
1269 {
1270 /* allocate pin index array which will hold all referenced pins */
1273 {
1274 /* failed to create topology */
1275 return Status;
1276 }
1277
1278 /* the mixer is an output mixer
1279 * find end pin of the node path
1280 */
1281 PinsCount = 0;
1283
1284 /* check for success */
1286 {
1287 /* failed to get end pin */
1288 MixerContext->Free(Pins);
1289 //MMixerFreeTopology(Topology);
1290
1291 /* return error code */
1292 return Status;
1293 }
1294 /* HACK:
1295 * some topologies do not have strict boundaries
1296 * WorkArround: remove all pin ids which have a physical connection
1297 * because bridge pins may belong to different render paths
1298 */
1299 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1300
1301 /* sanity checks */
1302 ASSERT(PinsCount != 0);
1303 if (PinsCount != 1)
1304 {
1305 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1306 }
1307
1308 /* create destination line */
1309 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1310
1311 /* calculate destination line id */
1312 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1313
1315 {
1316 /* failed to build destination line */
1317 MixerContext->Free(Pins);
1318
1319 /* return error code */
1320 return Status;
1321 }
1322
1323 /* add mixer controls to destination line */
1324 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1325
1327 {
1328 /* now add the rest of the source lines */
1329 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1330 }
1331
1332 /* mark pin as consumed */
1333 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1334
1335 /* free topology pin array */
1336 MixerContext->Free(Pins);
1337 }
1338 else
1339 {
1340 /* calculate destination line id */
1341 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations - 1);
1342
1343 /* add mixer controls */
1344 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pin, bInput, DestinationLineID, &LineTerminator);
1345
1347 {
1348 /* now add the rest of the source lines */
1349 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1350 }
1351 }
1352 return Status;
1353}
1354
1358 IN PMIXER_LIST MixerList,
1359 IN LPMIXER_DATA MixerData,
1360 IN OUT LPMIXER_INFO MixerInfo,
1361 IN ULONG bInput,
1362 IN PKSPIN_PHYSICALCONNECTION OutConnection)
1363{
1365 ULONG PinsCount, LineTerminator, DestinationLineID;
1366 PULONG Pins;
1367 PTOPOLOGY Topology;
1368
1369 /* first try to open the connected filter */
1370 OutConnection->SymbolicLinkName[1] = L'\\';
1371 MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
1372
1373 /* check if the linked connection is found */
1374 if (!MixerData)
1375 {
1376 /* filter references invalid physical connection */
1378 }
1379
1380 DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
1381
1382 /* sanity check */
1383 ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo);
1384
1385 /* associate with mixer */
1386 MixerData->MixerInfo = MixerInfo;
1387
1388 if (MixerData->Topology == NULL)
1389 {
1390 /* construct new topology */
1391 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1393 {
1394 /* failed to create topology */
1395 return Status;
1396 }
1397
1398 /* store topology */
1399 MixerData->Topology = Topology;
1400 }
1401 else
1402 {
1403 /* re-use existing topology */
1404 Topology = MixerData->Topology;
1405 }
1406
1407 /* mark pin as consumed */
1408 MMixerSetTopologyPinReserved(Topology, OutConnection->Pin);
1409
1410 if (!bInput)
1411 {
1412 /* allocate pin index array which will hold all referenced pins */
1415 {
1416 /* failed to create topology */
1417 return Status;
1418 }
1419
1420 /* the mixer is an output mixer
1421 * find end pin of the node path
1422 */
1423 PinsCount = 0;
1424 Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex(MixerContext, Topology, OutConnection->Pin, FALSE, &PinsCount, Pins);
1425
1426 /* check for success */
1428 {
1429 /* failed to get end pin */
1430 MixerContext->Free(Pins);
1431 //MMixerFreeTopology(Topology);
1432
1433 /* return error code */
1434 return Status;
1435 }
1436 /* HACK:
1437 * some topologies do not have strict boundaries
1438 * WorkArround: remove all pin ids which have a physical connection
1439 * because bridge pins may belong to different render paths
1440 */
1441 MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
1442
1443 /* sanity checks */
1444 ASSERT(PinsCount != 0);
1445 if (PinsCount != 1)
1446 {
1447 DPRINT1("MMixerHandlePhysicalConnection Expected 1 pin but got %lu\n", PinsCount);
1448 }
1449
1450 /* create destination line */
1451 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
1452
1453 /* calculate destination line id */
1454 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1455
1457 {
1458 /* failed to build destination line */
1459 MixerContext->Free(Pins);
1460
1461 /* return error code */
1462 return Status;
1463 }
1464
1465 /* add mixer controls to destination line */
1466 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
1467
1469 {
1470 /* now add the rest of the source lines */
1471 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1472 }
1473
1474 /* mark pin as consumed */
1475 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1476
1477 /* free topology pin array */
1478 MixerContext->Free(Pins);
1479 }
1480 else
1481 {
1482 /* calculate destination line id */
1483 DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
1484
1485 /* add mixer controls */
1486 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator);
1487
1489 {
1490 /* now add the rest of the source lines */
1491 Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
1492 }
1493 }
1494
1495 return Status;
1496}
1497
1501 IN PMIXER_LIST MixerList,
1502 IN LPMIXER_DATA MixerData,
1503 IN LPMIXER_INFO MixerInfo,
1504 IN PTOPOLOGY Topology,
1505 IN ULONG NodeIndex,
1506 IN ULONG bInputMixer,
1507 IN OUT LPMIXER_INFO * OutMixerInfo)
1508{
1509 ULONG Index;
1511 PKSPIN_PHYSICALCONNECTION OutConnection;
1512 ULONG * Pins;
1513 ULONG PinsFound;
1514 ULONG NewMixerInfo = FALSE;
1515
1516 if (MixerInfo == NULL)
1517 {
1518 /* allocate a mixer info struct */
1519 MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
1520 if (!MixerInfo)
1521 {
1522 /* no memory */
1523 return MM_STATUS_NO_MEMORY;
1524 }
1525
1526 /* new mixer info */
1527 NewMixerInfo = TRUE;
1528
1529 /* intialize mixer caps */
1530 MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */
1531 MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */
1532 MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */
1533 MixerInfo->MixCaps.fdwSupport = 0;
1534 MixerInfo->MixCaps.cDestinations = 0;
1535
1536 /* get mixer name */
1537 Status = MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
1539 {
1540 /* try get name with component id */
1541 Status = MMixerGetDeviceNameWithComponentId(MixerContext, MixerData->hDevice, MixerInfo->MixCaps.szPname);
1543 {
1544 MixerInfo->MixCaps.szPname[0] = L'\0';
1545 }
1546 }
1547
1548 /* initialize line list */
1549 InitializeListHead(&MixerInfo->LineList);
1550 InitializeListHead(&MixerInfo->EventList);
1551
1552 /* associate with mixer data */
1553 MixerData->MixerInfo = MixerInfo;
1554 }
1555
1556 /* store mixer info */
1557 *OutMixerInfo = MixerInfo;
1558
1559 /* now allocate an array which will receive the indices of the pin
1560 * which has a ADC / DAC nodetype in its path
1561 */
1564
1565 PinsFound = 0;
1566
1567 /* now get all sink / source pins, which are attached to the ADC / DAC node
1568 * For sink pins (wave out) search up stream
1569 * For source pins (wave in) search down stream
1570 * The search direction is always the opposite of the current mixer type
1571 */
1572 PinsFound = 0;
1573 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins);
1574
1575 /* if there is no pin found, we have a broken topology */
1576 ASSERT(PinsFound != 0);
1577
1578 /* now create a wave info struct */
1579 Status = MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinsFound, Pins);
1581 {
1582 /* failed to create wave info struct */
1583 MixerContext->Free(MixerInfo);
1584 MixerContext->Free(Pins);
1585 return Status;
1586 }
1587
1588 /* mark all found pins as reserved */
1589 for(Index = 0; Index < PinsFound; Index++)
1590 {
1591 MMixerSetTopologyPinReserved(Topology, Pins[Index]);
1592 }
1593
1594 if (bInputMixer)
1595 {
1596 /* pre create the mixer destination line for input mixers */
1597 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer);
1598
1600 {
1601 /* failed to create mixer destination line */
1602 return Status;
1603 }
1604 }
1605
1606 /* now get the bridge pin which is at the end of node path
1607 * For sink pins (wave out) search down stream
1608 * For source pins (wave in) search up stream
1609 */
1610 MixerContext->Free(Pins);
1613
1614 PinsFound = 0;
1615 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bInputMixer, &PinsFound, Pins);
1616
1617 /* if there is no pin found, we have a broken topology */
1618 ASSERT(PinsFound != 0);
1619
1620 /* there should be exactly one bridge pin */
1621 ASSERT(PinsFound == 1);
1622
1623 DPRINT("BridgePin %lu bInputMixer %lu\n", Pins[0], bInputMixer);
1624
1625 /* does the pin have a physical connection */
1626 Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[0], &OutConnection);
1627
1629 {
1630 /* mark pin as reserved */
1631 MMixerSetTopologyPinReserved(Topology, Pins[0]);
1632
1633 /* topology on the topoloy filter */
1634 Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection);
1635
1636 /* free physical connection data */
1637 MixerContext->Free(OutConnection);
1638 }
1639 else
1640 {
1641 /* topology is on the same filter */
1642 Status = MMixerHandleTopologyFilter(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, Pins[0]);
1643 }
1644
1645 /* free pins */
1646 MixerContext->Free(Pins);
1647
1648 if (NewMixerInfo)
1649 {
1650 /* insert mixer */
1651 InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
1652 /* increment mixer count */
1653 MixerList->MixerListCount++;
1654 }
1655
1656 /* done */
1657 return Status;
1658}
1659
1660VOID
1663 IN PMIXER_LIST MixerList,
1664 IN LPMIXER_DATA MixerData,
1665 IN PTOPOLOGY Topology)
1666{
1669 ULONG DestinationLineID, LineTerminator;
1670 LPMIXERLINE_EXT DstLine;
1671
1672 DPRINT("DeviceName %S\n", MixerData->DeviceName);
1673
1674 /* get topology pin count */
1676
1677 for(Index = 0; Index < PinCount; Index++)
1678 {
1680
1681 /* check if it has already been reserved */
1682 if (Reserved)
1683 {
1684 /* pin has already been reserved */
1685 continue;
1686 }
1687
1688 DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index);
1689
1690 /* sanity check */
1691 //ASSERT(MixerData->MixerInfo);
1692
1693 if (!MixerData->MixerInfo)
1694 {
1695 DPRINT1("Expected mixer info\n");
1696 continue;
1697 }
1698
1699 /* build the destination line */
1700 Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE);
1702 {
1703 /* failed to build destination line */
1704 continue;
1705 }
1706
1707 /* calculate destination line id */
1708 DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1);
1709
1710 /* add mixer controls to destination line */
1711 Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator);
1713 {
1714 /* now add the rest of the source lines */
1715 Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator);
1716 }
1717
1718 /* mark pin as consumed */
1720
1721 /* now grab destination line */
1722 DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID);
1723
1724 /* set type and target as undefined */
1726 DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
1727 DstLine->Line.Target.vDriverVersion = 0;
1728 DstLine->Line.Target.wMid = 0;
1729 DstLine->Line.Target.wPid = 0;
1730 }
1731}
1732
1736 IN PMIXER_LIST MixerList,
1737 IN LPMIXER_DATA MixerData,
1739{
1741 PTOPOLOGY Topology;
1742 ULONG NodeIndex;
1743 LPMIXER_INFO MixerInfo = NULL;
1744
1745 /* check if topology has already been built */
1746 if (MixerData->Topology == NULL)
1747 {
1748 /* build topology */
1749 Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
1750
1752 {
1753 /* failed to build topology */
1754 return Status;
1755 }
1756
1757 /* store topology */
1758 MixerData->Topology = Topology;
1759 }
1760 else
1761 {
1762 /* re-use topology */
1763 Topology = MixerData->Topology;
1764 }
1765
1766 /* check if the filter has an wave out node */
1767 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_DAC);
1768 if (NodeIndex != MAXULONG)
1769 {
1770 /* it has */
1771 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo);
1772
1773 /* check for success */
1775 {
1776 /* increment mixer count */
1777 (*DeviceCount)++;
1778 }
1779 else
1780 {
1781 /* reset mixer info in case of error */
1782 MixerInfo = NULL;
1783 }
1784 }
1785
1786 /* check if the filter has an wave in node */
1787 NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_ADC);
1788 if (NodeIndex != MAXULONG)
1789 {
1790 /* it has */
1791 Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo);
1792
1793 /* check for success */
1795 {
1796 /* increment mixer count */
1797 (*DeviceCount)++;
1798 }
1799
1800 }
1801
1802 /* TODO: apply hacks for Wave source line */
1803
1804 /* activate midi devices */
1805 //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
1806
1807 /* done */
1808 return Status;
1809}
1810
1814 IN OUT LPMIXER_INFO MixerInfo,
1815 IN PVOID MixerEventContext,
1816 IN PMIXER_EVENT MixerEventRoutine)
1817{
1818 //KSE_NODE Property;
1819 //KSEVENTDATA EventData
1820 //ULONG BytesReturned;
1821 //MIXER_STATUS Status;
1822 PEVENT_NOTIFICATION_ENTRY EventNotification;
1823
1825 if (!EventNotification)
1826 {
1827 /* not enough memory */
1828 return MM_STATUS_NO_MEMORY;
1829 }
1830
1831 /* FIXME: what is it supposed to happen with KSEVENTDATA ? */
1832#if 0
1833 /* setup request */
1837
1838 Property.NodeId = NodeId;
1839 Property.Reserved = 0;
1840
1841 Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned);
1843 {
1844 /* failed to add event */
1845 MixerContext->FreeEventData(EventData);
1846 return Status;
1847 }
1848#endif
1849
1850 /* initialize notification entry */
1851 EventNotification->MixerEventContext = MixerEventContext;
1852 EventNotification->MixerEventRoutine = MixerEventRoutine;
1853
1854 /* store event */
1855 InsertTailList(&MixerInfo->EventList, &EventNotification->Entry);
1856 return MM_STATUS_SUCCESS;
1857}
1858
1862 IN OUT LPMIXER_INFO MixerInfo,
1863 IN PVOID MixerEventContext,
1864 IN PMIXER_EVENT MixerEventRoutine)
1865{
1866 PLIST_ENTRY EventList;
1868
1869 /* Lookup through mixers */
1870 EventList = MixerInfo->EventList.Flink;
1871 while(EventList != &MixerInfo->EventList)
1872 {
1874 EventList = EventList->Flink;
1875 /* TODO: find a better way to identify an event ? */
1876 if(NotificationEntry->MixerEventRoutine == MixerEventRoutine &&
1877 NotificationEntry->MixerEventContext == MixerEventContext)
1878 {
1879 DPRINT1("Freeing entry %p\n", NotificationEntry);
1880 /* We found the event to remove */
1883 }
1884 }
1885 return MM_STATUS_SUCCESS;
1886}
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:1812
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:724
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:1356
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:922
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:657
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:1661
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:1252
MIXER_STATUS MMixerGetPinName(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG PinId, IN OUT LPWSTR *OutBuffer)
Definition: controls.c:283
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:529
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:1015
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:1734
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:1860
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:428
MIXER_STATUS MMixerCreateDestinationLine(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN ULONG bInputMixer, IN LPWSTR LineName)
Definition: controls.c:222
MIXER_STATUS MMixerBuildTopology(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, OUT PTOPOLOGY *OutTopology)
Definition: controls.c:366
VOID MMixerGetMaxChannelsForNode(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:637
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:1148
VOID MMixerApplyOutputFilterHack(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, IN HANDLE hMixer, IN OUT PULONG PinsCount, IN OUT PULONG Pins)
Definition: controls.c:1210
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:1499
VOID MMixerGetChannelCountLegacy(IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, IN HANDLE hMixer, IN ULONG NodeId, OUT PULONG MaxChannels)
Definition: controls.c:598
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:335
#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
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
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
#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:4117
wcscpy
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:729
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:825
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:172
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:173
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:777
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:165
PVOID MixerEventContext
Definition: precomp.h:167
LIST_ENTRY Entry
Definition: precomp.h:166
PMIXER_EVENT MixerEventRoutine
Definition: precomp.h:168
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
LONG SignedMaximum
Definition: precomp.h:104
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::@3267 Metrics
DWORD cMultipleItems
Definition: mmsystem.h:1308
union tagMIXERCONTROLW::@3266 Bounds
WCHAR szShortName[MIXER_SHORT_NAME_CHARS]
Definition: mmsystem.h:1309
DWORD dwReserved[6]
Definition: mmsystem.h:1320
struct tagMIXERLINEW::@3261 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
#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
#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
#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