- Rewrite topology node enumeration algorithm
- Old algorithm didnt properly take in account sum/mux nodes, may assign nodes to multiple lines and was not able to detect circuits which may lead to infinite loops
- New algorithm properly partitions the nodes and also checks if nodes has already been assigned. As a plus, it is also faster
- Algorithm based on msdn http://msdn.microsoft.com/en-us/library/ff538873(v=VS.85).aspx
- Tested on VBox 3.28 (AC97)
- Please retest supported soundcards for regressions


svn path=/trunk/; revision=49150
This commit is contained in:
Johannes Anderwald 2010-10-15 00:20:15 +00:00
parent 4758da752f
commit 8a0913d231
8 changed files with 2121 additions and 1071 deletions

File diff suppressed because it is too large Load diff

View file

@ -19,15 +19,15 @@ MMixerGetFilterPinCount(
MIXER_STATUS Status;
ULONG NumPins, BytesReturned;
// setup property request
/* setup property request */
Pin.Flags = KSPROPERTY_TYPE_GET;
Pin.Set = KSPROPSETID_Pin;
Pin.Id = KSPROPERTY_PIN_CTYPES;
// query pin count
/* query pin count */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), (PULONG)&BytesReturned);
// check for success
/* check for success */
if (Status != MM_STATUS_SUCCESS)
return 0;
@ -46,43 +46,43 @@ MMixerGetFilterTopologyProperty(
MIXER_STATUS Status;
ULONG BytesReturned;
// setup property request
/* setup property request */
Property.Id = PropertyId;
Property.Flags = KSPROPERTY_TYPE_GET;
Property.Set = KSPROPSETID_Topology;
// query for the size
/* query for the size */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
if (Status != MM_STATUS_MORE_ENTRIES)
return Status;
//sanity check
/* sanity check */
ASSERT(BytesReturned);
// allocate an result buffer
/* allocate an result buffer */
MultipleItem = (PKSMULTIPLE_ITEM)MixerContext->Alloc(BytesReturned);
if (!MultipleItem)
{
// not enough memory
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
// query again with allocated buffer
/* query again with allocated buffer */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
{
// failed
/* failed */
MixerContext->Free((PVOID)MultipleItem);
return Status;
}
// store result
/* store result */
*OutMultipleItem = MultipleItem;
// done
/* done */
return Status;
}
@ -109,24 +109,23 @@ MMixerGetPhysicalConnection(
if (Status == MM_STATUS_UNSUCCESSFUL)
{
// pin does not have a physical connection
/* pin does not have a physical connection */
return Status;
}
DPRINT("Status %u BytesReturned %lu\n", Status, BytesReturned);
Connection = (PKSPIN_PHYSICALCONNECTION)MixerContext->Alloc(BytesReturned);
if (!Connection)
{
// not enough memory
/* not enough memory */
return MM_STATUS_NO_MEMORY;
}
// query the pin for the physical connection
/* query the pin for the physical connection */
Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
{
// failed to query the physical connection
/* failed to query the physical connection */
MixerContext->Free(Connection);
DPRINT("Status %u\n", Status);
return Status;
}
@ -141,73 +140,76 @@ MMixerGetControlTypeFromTopologyNode(
{
if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_AGC))
{
// automatic gain control
/* automatic gain control */
return MIXERCONTROL_CONTROLTYPE_ONOFF;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_LOUDNESS))
{
// loudness control
/* loudness control */
return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE ))
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE))
{
// mute control
/* mute control */
return MIXERCONTROL_CONTROLTYPE_MUTE;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_TONE))
{
// tpne control
//FIXME
// MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported
// MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported
// MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported
/* tone control
* FIXME
* MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported
* MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported
* MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported
*/
UNIMPLEMENTED;
return MIXERCONTROL_CONTROLTYPE_ONOFF;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_VOLUME))
{
// volume control
/* volume control */
return MIXERCONTROL_CONTROLTYPE_VOLUME;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_PEAKMETER))
{
// peakmeter control
/* peakmeter control */
return MIXERCONTROL_CONTROLTYPE_PEAKMETER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
{
// mux control
/* mux control */
return MIXERCONTROL_CONTROLTYPE_MUX;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
{
// mux control
/* mux control */
return MIXERCONTROL_CONTROLTYPE_MUX;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE))
{
// stero wide control
/* stero wide control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_CHORUS))
{
// chorus control
/* chorus control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_REVERB))
{
// reverb control
/* reverb control */
return MIXERCONTROL_CONTROLTYPE_FADER;
}
else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_SUPERMIX))
{
// supermix control
// MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported
/* supermix control
* MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported
*/
UNIMPLEMENTED;
return MIXERCONTROL_CONTROLTYPE_VOLUME;
}
//TODO
//check for other supported node types
/* TODO
* check for other supported node types
*/
//UNIMPLEMENTED
return 0;
}
@ -279,4 +281,3 @@ MMixerGetPinInstanceCount(
ASSERT(Status == MM_STATUS_SUCCESS);
return PinInstances.CurrentCount;
}

View file

@ -17,16 +17,16 @@ MMixerGetCount(
PMIXER_LIST MixerList;
MIXER_STATUS Status;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
// return number of mixers
@ -42,16 +42,16 @@ MMixerGetCapabilities(
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// get mixer info
/* get mixer info */
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex);
if (!MixerInfo)
@ -83,29 +83,30 @@ MMixerOpen(
MIXER_STATUS Status;
LPMIXER_INFO MixerInfo;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
if (!MixerInfo)
{
// invalid mixer id
/* invalid mixer id */
return MM_STATUS_INVALID_PARAMETER;
}
// FIXME
// handle event notification
/* FIXME
* handle event notification
*/
Status = MMixerAddEvents(MixerContext, MixerInfo);
// store result
/* store result */
*MixerHandle = (HANDLE)MixerInfo;
return MM_STATUS_SUCCESS;
@ -122,26 +123,26 @@ MMixerGetLineInfo(
LPMIXER_INFO MixerInfo;
LPMIXERLINE_EXT MixerLineSrc;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// clear hmixer from flags
/* clear hmixer from flags */
Flags &=~MIXER_OBJECTF_HMIXER;
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
if (MixerLine->dwDestination != 0)
{
// destination line member must be zero
/* destination line member must be zero */
return MM_STATUS_INVALID_PARAMETER;
}
@ -153,7 +154,7 @@ MMixerGetLineInfo(
}
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
@ -162,9 +163,9 @@ MMixerGetLineInfo(
if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
{
DPRINT1("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections);
DPRINT("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections);
// invalid parameter
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
@ -179,13 +180,13 @@ MMixerGetLineInfo(
}
else if (Flags == MIXER_GETLINEINFOF_LINEID)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
if (!MixerLineSrc)
{
// invalid parameter
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
@ -195,7 +196,7 @@ MMixerGetLineInfo(
}
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
@ -228,12 +229,12 @@ MMixerGetLineControls(
MIXER_STATUS Status;
ULONG Index;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
@ -241,31 +242,31 @@ MMixerGetLineControls(
if (Flags == MIXER_GETLINECONTROLSF_ALL)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
if (!MixerLineSrc)
{
// invalid line id
/* invalid line id */
return MM_STATUS_INVALID_PARAMETER;
}
// copy line control(s)
/* copy line control(s) */
MixerContext->Copy(MixerLineControls->pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, MixerLineControls->cControls) * sizeof(MIXERCONTROLW));
return MM_STATUS_SUCCESS;
}
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
if (!MixerLineSrc)
{
// invalid line id
/* invalid line id */
return MM_STATUS_INVALID_PARAMETER;
}
@ -277,7 +278,7 @@ MMixerGetLineControls(
DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType);
if (MixerLineControls->dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
{
// found a control with that type
/* found a control with that type */
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
return MM_STATUS_SUCCESS;
}
@ -287,18 +288,18 @@ MMixerGetLineControls(
}
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
{
// cast to mixer info
/* cast to mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL);
if (Status != MM_STATUS_SUCCESS)
{
// invalid parameter
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
// copy the controls
/* copy the controls */
MixerContext->Copy(MixerLineControls->pamxctrl, MixerControl, sizeof(MIXERCONTROLW));
return MM_STATUS_SUCCESS;
}
@ -320,25 +321,25 @@ MMixerSetControlDetails(
LPMIXERLINE_EXT MixerLine;
LPMIXERCONTROLW MixerControl;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// get mixer info
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
// get mixer control
/* get mixer control */
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
// check for success
/* check for success */
if (Status != MM_STATUS_SUCCESS)
{
// failed to find control id
/* failed to find control id */
return MM_STATUS_INVALID_PARAMETER;
}
@ -370,25 +371,25 @@ MMixerGetControlDetails(
LPMIXERLINE_EXT MixerLine;
LPMIXERCONTROLW MixerControl;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// get mixer info
/* get mixer info */
MixerInfo = (LPMIXER_INFO)MixerHandle;
// get mixer control
/* get mixer control */
Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId);
// check for success
/* check for success */
if (Status != MM_STATUS_SUCCESS)
{
// failed to find control id
/* failed to find control id */
return MM_STATUS_INVALID_PARAMETER;
}
@ -423,7 +424,7 @@ MMixerInitialize(
if (!MixerContext || !EnumFunction || !EnumContext)
{
// invalid parameter
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
@ -431,19 +432,19 @@ MMixerInitialize(
!MixerContext->AllocEventData || !MixerContext->FreeEventData ||
!MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey)
{
// invalid parameter
/* invalid parameter */
return MM_STATUS_INVALID_PARAMETER;
}
// allocate a mixer list
/* allocate a mixer list */
MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST));
if (!MixerList)
{
// no memory
/* no memory */
return MM_STATUS_NO_MEMORY;
}
//initialize mixer list
/* initialize mixer list */
MixerList->MixerListCount = 0;
MixerList->MixerDataCount = 0;
MixerList->WaveInListCount = 0;
@ -454,48 +455,49 @@ MMixerInitialize(
InitializeListHead(&MixerList->WaveOutList);
// store mixer list
/* store mixer list */
MixerContext->MixerContext = (PVOID)MixerList;
// start enumerating all available devices
/* start enumerating all available devices */
Count = 0;
DeviceIndex = 0;
do
{
// enumerate a device
/* enumerate a device */
Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey);
if (Status != MM_STATUS_SUCCESS)
{
//check error code
/* check error code */
if (Status == MM_STATUS_NO_MORE_DEVICES)
{
// enumeration has finished
/* enumeration has finished */
break;
}
else
{
DPRINT1("Failed to enumerate device %lu\n", DeviceIndex);
// TODO cleanup
/* TODO cleanup */
return Status;
}
}
else
{
// create a mixer data entry
/* create a mixer data entry */
Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey);
if (Status != MM_STATUS_SUCCESS)
break;
}
// increment device index
/* increment device index */
DeviceIndex++;
}while(TRUE);
//now all filters have been pre-opened
// lets enumerate the filters
/* now all filters have been pre-opened
* lets enumerate the filters
*/
Entry = MixerList->MixerData.Flink;
while(Entry != &MixerList->MixerData)
{
@ -504,6 +506,6 @@ MMixerInitialize(
Entry = Entry->Flink;
}
// done
/* done */
return MM_STATUS_SUCCESS;
}

View file

@ -8,4 +8,5 @@
<file>mixer.c</file>
<file>sup.c</file>
<file>wave.c</file>
<file>topology.c</file>
</module>

View file

@ -17,6 +17,52 @@
#define YDEBUG
#include <debug.h>
typedef struct __TOPOLOGY_NODE__
{
GUID NodeType;
ULONG NodeIndex;
ULONG NodeConnectedToCount;
struct __TOPOLOGY_NODE__ ** NodeConnectedTo;
ULONG NodeConnectedFromCount;
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom;
ULONG PinConnectedFromCount;
PULONG PinConnectedFrom;
ULONG PinConnectedToCount;
PULONG PinConnectedTo;
ULONG Visited;
ULONG Reserved;
}TOPOLOGY_NODE, *PTOPOLOGY_NODE;
typedef struct
{
ULONG PinId;
ULONG NodesConnectedToCount;
PTOPOLOGY_NODE * NodesConnectedTo;
ULONG NodesConnectedFromCount;
PTOPOLOGY_NODE * NodesConnectedFrom;
ULONG Visited;
}PIN, *PPIN;
typedef struct
{
ULONG TopologyPinsCount;
PPIN TopologyPins;
ULONG TopologyNodesCount;
PTOPOLOGY_NODE TopologyNodes;
}TOPOLOGY, *PTOPOLOGY;
typedef struct
{
KSEVENTDATA EventData;
@ -68,6 +114,7 @@ typedef struct
HANDLE hDevice;
HANDLE hDeviceInterfaceKey;
LPWSTR DeviceName;
PTOPOLOGY Topology;
}MIXER_DATA, *LPMIXER_DATA;
typedef struct
@ -273,9 +320,122 @@ MMixerInitializeWaveInfo(
IN LPMIXER_DATA MixerData,
IN LPWSTR DeviceName,
IN ULONG bWaveIn,
IN ULONG PinId);
IN ULONG PinCount,
IN PULONG Pins);
MIXER_STATUS
MMixerAddEvents(
IN PMIXER_CONTEXT MixerContext,
IN OUT LPMIXER_INFO MixerInfo);
/* topology.c */
MIXER_STATUS
MMixerCreateTopology(
IN PMIXER_CONTEXT MixerContext,
IN ULONG PinCount,
IN PKSMULTIPLE_ITEM NodeConnections,
IN PKSMULTIPLE_ITEM NodeTypes,
OUT PTOPOLOGY *OutTopology);
VOID
MMixerGetAllUpOrDownstreamPinsFromNodeIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
IN ULONG bUpStream,
OUT PULONG OutPinsCount,
OUT PULONG OutPins);
MIXER_STATUS
MMixerGetAllUpOrDownstreamPinsFromPinIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG PinIndex,
IN ULONG bUpStream,
OUT PULONG OutPinsCount,
OUT PULONG OutPins);
VOID
MMixerGetNextNodesFromPinIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG PinIndex,
IN ULONG bUpStream,
OUT PULONG OutNodesCount,
OUT PULONG OutNodes);
MIXER_STATUS
MMixerAllocateTopologyPinArray(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
OUT PULONG * OutPins);
MIXER_STATUS
MMixerAllocateTopologyNodeArray(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
OUT PULONG * OutPins);
VOID
MMixerGetAllUpOrDownstreamNodesFromPinIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG PinIndex,
IN ULONG bUpStream,
OUT PULONG OutNodesCount,
OUT PULONG OutNodes);
VOID
MMixerIsNodeTerminator(
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
OUT ULONG * bTerminator);
VOID
MMixerGetNextNodesFromNodeIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
IN ULONG bUpStream,
OUT PULONG OutNodesCount,
OUT PULONG OutNodes);
LPGUID
MMixerGetNodeTypeFromTopology(
IN PTOPOLOGY Topology,
IN ULONG NodeIndex);
MIXER_STATUS
MMixerGetAllUpOrDownstreamNodesFromNodeIndex(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
IN ULONG bUpStream,
OUT PULONG OutNodesCount,
OUT PULONG OutNodes);
MIXER_STATUS
MMixerIsNodeConnectedToPin(
IN PMIXER_CONTEXT MixerContext,
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
IN ULONG PinId,
IN ULONG bUpStream,
OUT PULONG bConnected);
ULONG
MMixerGetNodeIndexFromGuid(
IN PTOPOLOGY Topology,
IN const GUID *NodeType);
VOID
MMixerSetTopologyNodeReserved(
IN PTOPOLOGY Topology,
IN ULONG NodeIndex);
VOID
MMixerIsTopologyNodeReserved(
IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
OUT PULONG bReserved);

View file

@ -54,9 +54,10 @@ MMixerFreeMixerInfo(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo)
{
//UNIMPLEMENTED
// FIXME
// free all lines
/* UNIMPLEMENTED
* FIXME
* free all lines
*/
MixerContext->Free((PVOID)MixerInfo);
}
@ -71,7 +72,7 @@ MMixerGetMixerInfoByIndex(
PMIXER_LIST MixerList;
ULONG Index = 0;
// get mixer list
/* get mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
if (!MixerList->MixerListCount)
@ -86,7 +87,7 @@ MMixerGetMixerInfoByIndex(
if (Index == MixerIndex)
return MixerInfo;
// move to next mixer entry
/* move to next mixer entry */
Index++;
Entry = Entry->Flink;
}
@ -141,42 +142,6 @@ MMixerGetSourceMixerLineByLineId(
return NULL;
}
ULONG
MMixerGetIndexOfGuid(
PKSMULTIPLE_ITEM MultipleItem,
LPCGUID NodeType)
{
ULONG Index;
LPGUID Guid;
Guid = (LPGUID)(MultipleItem+1);
/* iterate through node type array */
for(Index = 0; Index < MultipleItem->Count; Index++)
{
if (IsEqualGUIDAligned(NodeType, Guid))
{
/* found matching guid */
return Index;
}
Guid++;
}
return MAXULONG;
}
PKSTOPOLOGY_CONNECTION
MMixerGetConnectionByIndex(
IN PKSMULTIPLE_ITEM MultipleItem,
IN ULONG Index)
{
PKSTOPOLOGY_CONNECTION Descriptor;
ASSERT(Index < MultipleItem->Count);
Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
return &Descriptor[Index];
}
LPGUID
MMixerGetNodeType(
IN PKSMULTIPLE_ITEM MultipleItem,
@ -190,183 +155,6 @@ MMixerGetNodeType(
return &NodeType[Index];
}
MIXER_STATUS
MMixerGetNodeIndexes(
IN PMIXER_CONTEXT MixerContext,
IN PKSMULTIPLE_ITEM MultipleItem,
IN ULONG NodeIndex,
IN ULONG bNode,
IN ULONG bFrom,
OUT PULONG NodeReferenceCount,
OUT PULONG *NodeReference)
{
ULONG Index, Count = 0;
PKSTOPOLOGY_CONNECTION Connection;
PULONG Refs;
// KSMULTIPLE_ITEM is followed by several KSTOPOLOGY_CONNECTION
Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
// first count all referenced nodes
for(Index = 0; Index < MultipleItem->Count; Index++)
{
if (bNode)
{
if (bFrom)
{
if (Connection->FromNode == NodeIndex)
{
// node id has a connection
Count++;
}
}
else
{
if (Connection->ToNode == NodeIndex)
{
// node id has a connection
Count++;
}
}
}
else
{
if (bFrom)
{
if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
{
// node id has a connection
Count++;
}
}
else
{
if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
{
// node id has a connection
Count++;
}
}
}
// move to next connection
Connection++;
}
if (!Count)
{
*NodeReferenceCount = 0;
*NodeReference = NULL;
return MM_STATUS_SUCCESS;
}
ASSERT(Count != 0);
/* now allocate node index array */
Refs = (PULONG)MixerContext->Alloc(sizeof(ULONG) * Count);
if (!Refs)
{
// not enough memory
return MM_STATUS_NO_MEMORY;
}
Count = 0;
Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
for(Index = 0; Index < MultipleItem->Count; Index++)
{
if (bNode)
{
if (bFrom)
{
if (Connection->FromNode == NodeIndex)
{
/* node id has a connection */
Refs[Count] = Index;
Count++;
}
}
else
{
if (Connection->ToNode == NodeIndex)
{
/* node id has a connection */
Refs[Count] = Index;
Count++;
}
}
}
else
{
if (bFrom)
{
if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
{
/* node id has a connection */
Refs[Count] = Index;
Count++;
}
}
else
{
if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
{
/* node id has a connection */
Refs[Count] = Index;
Count++;
}
}
}
/* move to next connection */
Connection++;
}
/* store result */
*NodeReference = Refs;
*NodeReferenceCount = Count;
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
MMixerGetTargetPins(
IN PMIXER_CONTEXT MixerContext,
IN PKSMULTIPLE_ITEM NodeTypes,
IN PKSMULTIPLE_ITEM NodeConnections,
IN ULONG NodeIndex,
IN ULONG bUpDirection,
OUT PULONG Pins,
IN ULONG PinCount)
{
ULONG NodeConnectionCount, Index;
MIXER_STATUS Status;
PULONG NodeConnection;
// sanity check */
ASSERT(NodeIndex != (ULONG)-1);
/* get all node indexes referenced by that pin */
if (bUpDirection)
Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
else
Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
//DPRINT("NodeIndex %u Status %x Count %u\n", NodeIndex, Status, NodeConnectionCount);
if (Status == MM_STATUS_SUCCESS)
{
for(Index = 0; Index < NodeConnectionCount; Index++)
{
Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], PinCount, Pins);
ASSERT(Status == STATUS_SUCCESS);
}
MixerContext->Free((PVOID)NodeConnection);
}
return Status;
}
LPMIXERLINE_EXT
MMixerGetSourceMixerLineByComponentType(
LPMIXER_INFO MixerInfo,
@ -482,7 +270,7 @@ MMixerSetGetMuteControlDetails(
}
else
{
// FIXME notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID
/* FIXME notify wdmaud clients MM_MIXM_LINE_CHANGE dwLineID */
}
return Status;
@ -590,7 +378,7 @@ MMixerGetDataByDeviceName(
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
if (wcsicmp(&DeviceName[2], &MixerData->DeviceName[2]) == 0)
{
// found entry
/* found entry */
return MixerData;
}
Entry = Entry->Flink;
@ -617,6 +405,9 @@ MMixerCreateMixerData(
MixerData->DeviceName = DeviceName;
MixerData->hDevice = hDevice;
MixerData->hDeviceInterfaceKey = hKey;
MixerData->Topology = NULL;
InsertTailList(&MixerList->MixerData, &MixerData->Entry);
MixerList->MixerDataCount++;
@ -638,16 +429,16 @@ MMixerGetDeviceName(
Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type);
if (Status == MM_STATUS_SUCCESS)
{
// copy device name
/* copy device name */
MixerContext->Copy(MixerInfo->MixCaps.szPname, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR));
// make sure its null terminated
/* make sure its null terminated */
MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
// free device name
/* free device name */
MixerContext->Free(Name);
// done
/* done */
return Status;
}
@ -658,13 +449,13 @@ MMixerGetDeviceName(
Status = MixerContext->QueryKeyValue(hKey, L"FriendlyName", (PVOID*)&Name, &Length, &Type);
if (Status == MM_STATUS_SUCCESS)
{
// copy device name
/* copy device name */
MixerContext->Copy(MixerInfo->MixCaps.szPname, Name, min(wcslen(Name), MAXPNAMELEN-1) * sizeof(WCHAR));
// make sure its null terminated
/* make sure its null terminated */
MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
// free device name
/* free device name */
MixerContext->Free(Name);
}

File diff suppressed because it is too large Load diff

View file

@ -345,7 +345,8 @@ MMixerInitializeWaveInfo(
IN LPMIXER_DATA MixerData,
IN LPWSTR DeviceName,
IN ULONG bWaveIn,
IN ULONG PinId)
IN ULONG PinCount,
IN PULONG Pins)
{
MIXER_STATUS Status;
PKSMULTIPLE_ITEM MultipleItem;
@ -356,11 +357,14 @@ MMixerInitializeWaveInfo(
if (!WaveInfo)
return MM_STATUS_NO_MEMORY;
/* FIXME support multiple pins for wave device */
ASSERT(PinCount == 1);
/* initialize wave info */
WaveInfo->DeviceId = MixerData->DeviceId;
WaveInfo->PinId = PinId;
WaveInfo->PinId = Pins[0];
// sanity check
/* sanity check */
ASSERT(wcslen(DeviceName) < MAXPNAMELEN);
/* copy device name */
@ -388,7 +392,7 @@ MMixerInitializeWaveInfo(
}
/* get audio pin data ranges */
Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, PinId, &MultipleItem);
Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Pins[0], &MultipleItem);
if (Status != MM_STATUS_SUCCESS)
{
/* failed to get audio pin data ranges */
@ -451,21 +455,21 @@ MMixerOpenWave(
LPWAVE_INFO WaveInfo;
ACCESS_MASK DesiredAccess = 0;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM)
{
// not implemented
/* not implemented */
return MM_STATUS_NOT_IMPLEMENTED;
}
@ -501,16 +505,16 @@ MMixerWaveInCapabilities(
MIXER_STATUS Status;
LPWAVE_INFO WaveInfo;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
/* find destination wave */
@ -521,7 +525,7 @@ MMixerWaveInCapabilities(
return MM_STATUS_UNSUCCESSFUL;
}
//copy capabilities
/* copy capabilities */
MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW));
return MM_STATUS_SUCCESS;
@ -537,16 +541,16 @@ MMixerWaveOutCapabilities(
MIXER_STATUS Status;
LPWAVE_INFO WaveInfo;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
/* find destination wave */
@ -557,7 +561,7 @@ MMixerWaveOutCapabilities(
return MM_STATUS_UNSUCCESSFUL;
}
//copy capabilities
/* copy capabilities */
MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW));
return MM_STATUS_SUCCESS;
@ -570,16 +574,16 @@ MMixerGetWaveInCount(
PMIXER_LIST MixerList;
MIXER_STATUS Status;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
return 0;
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
return MixerList->WaveInListCount;
@ -592,16 +596,16 @@ MMixerGetWaveOutCount(
PMIXER_LIST MixerList;
MIXER_STATUS Status;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
return 0;
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
return MixerList->WaveOutListCount;
@ -637,16 +641,16 @@ MMixerGetWaveDevicePath(
ULONG Length;
MIXER_STATUS Status;
// verify mixer context
/* verify mixer context */
Status = MMixerVerifyContext(MixerContext);
if (Status != MM_STATUS_SUCCESS)
{
// invalid context passed
/* invalid context passed */
return Status;
}
// grab mixer list
/* grab mixer list */
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
/* find destination wave */