656 lines
15 KiB
C++
656 lines
15 KiB
C++
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Module: lfn.cpp
|
||
|
//
|
||
|
// Description:
|
||
|
//
|
||
|
//
|
||
|
//@@BEGIN_MSINTERNAL
|
||
|
// Development Team:
|
||
|
// Mike McLaughlin
|
||
|
//
|
||
|
// History: Date Author Comment
|
||
|
//
|
||
|
// To Do: Date Author Comment
|
||
|
//
|
||
|
//@@END_MSINTERNAL
|
||
|
//
|
||
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
||
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
||
|
// PURPOSE.
|
||
|
//
|
||
|
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
ULONG gcMixers = 0;
|
||
|
ULONG gcSplitters = 0;
|
||
|
ULONG gcLogicalFilterNodes = 0;
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
CLogicalFilterNode::Create(
|
||
|
OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode,
|
||
|
IN PFILTER_NODE pFilterNode
|
||
|
)
|
||
|
{
|
||
|
PLOGICAL_FILTER_NODE pLogicalFilterNode;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
pLogicalFilterNode = new LOGICAL_FILTER_NODE(pFilterNode);
|
||
|
if(pLogicalFilterNode == NULL) {
|
||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
Status = pLogicalFilterNode->AddList(&pFilterNode->lstLogicalFilterNode);
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
if(pLogicalFilterNode->GetType() & FILTER_TYPE_LOGICAL_FILTER) {
|
||
|
Status = pLogicalFilterNode->AddListOrdered(
|
||
|
gplstLogicalFilterNode,
|
||
|
FIELD_OFFSET(LOGICAL_FILTER_NODE, ulOrder));
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
exit:
|
||
|
*ppLogicalFilterNode = pLogicalFilterNode;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
CLogicalFilterNode::CLogicalFilterNode(
|
||
|
PFILTER_NODE pFilterNode
|
||
|
)
|
||
|
{
|
||
|
Assert(pFilterNode);
|
||
|
this->pFilterNode = pFilterNode;
|
||
|
|
||
|
// The type/order is the same as filter node
|
||
|
SetType(pFilterNode->GetType());
|
||
|
|
||
|
// Determine the overhead here, default to software (higher)
|
||
|
ulOverhead = OVERHEAD_SOFTWARE;
|
||
|
if(GetType() & FILTER_TYPE_ENDPOINT) {
|
||
|
ulOverhead = OVERHEAD_HARDWARE;
|
||
|
}
|
||
|
|
||
|
// Count the mixers, splitters and lfns
|
||
|
if(GetType() & FILTER_TYPE_MIXER) {
|
||
|
++gcMixers;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_SPLITTER) {
|
||
|
++gcSplitters;
|
||
|
}
|
||
|
++gcLogicalFilterNodes;
|
||
|
|
||
|
DPF3(60, "CLogicalFilterNode: %08x FN: %08x %s",
|
||
|
this,
|
||
|
pFilterNode,
|
||
|
pFilterNode->DumpName());
|
||
|
}
|
||
|
|
||
|
CLogicalFilterNode::~CLogicalFilterNode(
|
||
|
)
|
||
|
{
|
||
|
PLOGICAL_FILTER_NODE pLogicalFilterNode;
|
||
|
PDEVICE_NODE pDeviceNode;
|
||
|
PGRAPH_NODE pGraphNode;
|
||
|
PPIN_NODE pPinNode;
|
||
|
BOOL fDestroy;
|
||
|
|
||
|
Assert(this);
|
||
|
DPF2(60, "~CLogicalFilterNode: %08x %s", this, pFilterNode->DumpName());
|
||
|
//
|
||
|
// Need to NULL the pPinNode's LFN field because it is used in AddPinNodes
|
||
|
// to indicate that this PN hasn't been assigned a LFN yet.
|
||
|
//
|
||
|
FOR_EACH_LIST_ITEM(&lstPinNode, pPinNode) {
|
||
|
|
||
|
Assert(pPinNode);
|
||
|
if(pPinNode->pLogicalFilterNode == this) {
|
||
|
pPinNode->pLogicalFilterNode = NULL;
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
|
||
|
|
||
|
fDestroy = FALSE;
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(
|
||
|
&pDeviceNode->lstLogicalFilterNode,
|
||
|
pLogicalFilterNode) {
|
||
|
|
||
|
if(pLogicalFilterNode == this) {
|
||
|
DPF2(50, "~CLogicalFilterNode: %08x GN %08x Destroy",
|
||
|
pLogicalFilterNode,
|
||
|
pGraphNode);
|
||
|
fDestroy = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
if(!fDestroy) {
|
||
|
FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(
|
||
|
&pGraphNode->lstLogicalFilterNode,
|
||
|
pLogicalFilterNode) {
|
||
|
|
||
|
if(pLogicalFilterNode == this) {
|
||
|
DPF2(50, "~CLogicalFilterNode: %08x GN %08x Destroy",
|
||
|
pLogicalFilterNode,
|
||
|
pGraphNode);
|
||
|
fDestroy = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
}
|
||
|
|
||
|
if(fDestroy) {
|
||
|
pDeviceNode->lstGraphNode.DestroyList();
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
if(GetType() & FILTER_TYPE_MIXER) {
|
||
|
--gcMixers;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_SPLITTER) {
|
||
|
--gcSplitters;
|
||
|
}
|
||
|
--gcLogicalFilterNodes;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CLogicalFilterNode::SetType(
|
||
|
ULONG fulType
|
||
|
)
|
||
|
{
|
||
|
pFilterNode->SetType(fulType);
|
||
|
SetOrder(pFilterNode->GetOrder());
|
||
|
|
||
|
ulFlags = 0;
|
||
|
if(GetType() & FILTER_TYPE_RENDER) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_RENDER;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_CAPTURE) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_CAPTURE;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_NORMAL_TOPOLOGY) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_NORMAL_TOPOLOGY;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_MIXER_TOPOLOGY) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_MIXER_TOPOLOGY;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_NO_BYPASS) {
|
||
|
ulFlags |= LFN_FLAGS_NO_BYPASS;
|
||
|
}
|
||
|
if(GetType() & FILTER_TYPE_NOT_SELECT) {
|
||
|
ulFlags |= LFN_FLAGS_NOT_SELECT;
|
||
|
}
|
||
|
if(pFilterNode->GetFlags() & FN_FLAGS_RENDER) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_RENDER;
|
||
|
}
|
||
|
if(pFilterNode->GetFlags() & FN_FLAGS_NO_RENDER) {
|
||
|
ulFlags &= ~LFN_FLAGS_CONNECT_RENDER;
|
||
|
}
|
||
|
if(pFilterNode->GetFlags() & FN_FLAGS_CAPTURE) {
|
||
|
ulFlags |= LFN_FLAGS_CONNECT_CAPTURE;
|
||
|
}
|
||
|
if(pFilterNode->GetFlags() & FN_FLAGS_NO_CAPTURE) {
|
||
|
ulFlags &= ~LFN_FLAGS_CONNECT_CAPTURE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
SwitchLogicalFilterNodes(
|
||
|
IN PLOGICAL_FILTER_NODE pLogicalFilterNode,
|
||
|
IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
PTOPOLOGY_NODE pTopologyNode;
|
||
|
PPIN_NODE pPinNode;
|
||
|
|
||
|
Assert(pLogicalFilterNode);
|
||
|
Assert(*ppLogicalFilterNode);
|
||
|
if(pLogicalFilterNode != *ppLogicalFilterNode) {
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(&(*ppLogicalFilterNode)->lstPinNode, pPinNode) {
|
||
|
Assert(pPinNode);
|
||
|
pPinNode->pLogicalFilterNode = pLogicalFilterNode;
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
pLogicalFilterNode->lstPinNode.JoinList(
|
||
|
&(*ppLogicalFilterNode)->lstPinNode);
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(
|
||
|
&(*ppLogicalFilterNode)->lstTopologyNode,
|
||
|
pTopologyNode) {
|
||
|
Assert(pTopologyNode);
|
||
|
|
||
|
(*ppLogicalFilterNode)->RemoveList(
|
||
|
&pTopologyNode->lstLogicalFilterNode);
|
||
|
|
||
|
Status = pLogicalFilterNode->AddList(
|
||
|
&pTopologyNode->lstLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
Status = pLogicalFilterNode->lstTopologyNode.AddList(pTopologyNode);
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
pLogicalFilterNode->lstTopologyConnection.JoinList(
|
||
|
&(*ppLogicalFilterNode)->lstTopologyConnection);
|
||
|
|
||
|
delete *ppLogicalFilterNode;
|
||
|
*ppLogicalFilterNode = pLogicalFilterNode;
|
||
|
}
|
||
|
exit:
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
AddPinNodes(
|
||
|
IN PPIN_INFO pPinInfo,
|
||
|
IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
PPIN_NODE pPinNode;
|
||
|
|
||
|
Assert(pPinInfo);
|
||
|
Assert(*ppLogicalFilterNode);
|
||
|
|
||
|
FOR_EACH_LIST_ITEM(&pPinInfo->lstPinNode, pPinNode) {
|
||
|
|
||
|
if(pPinNode->pLogicalFilterNode == NULL) {
|
||
|
pPinNode->pLogicalFilterNode = *ppLogicalFilterNode;
|
||
|
}
|
||
|
else {
|
||
|
Status = SwitchLogicalFilterNodes(
|
||
|
pPinNode->pLogicalFilterNode,
|
||
|
ppLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
Status = (*ppLogicalFilterNode)->lstPinNode.AddList(pPinNode);
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
DPF2(100, "AddPinNodes: add PN %08x LFN %08x",
|
||
|
pPinNode,
|
||
|
*ppLogicalFilterNode);
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
exit:
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
CLogicalFilterNode::EnumerateFilterTopology(
|
||
|
IN PTOPOLOGY_CONNECTION pTopologyConnection,
|
||
|
IN BOOL fToDirection,
|
||
|
IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
|
||
|
)
|
||
|
{
|
||
|
PTOPOLOGY_NODE pTopologyNode;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
Assert(pTopologyConnection);
|
||
|
DPF5(100, "EFT: PIF %08x PIT %08x TPF %08x TPT %08x f %x",
|
||
|
pTopologyConnection->pPinInfoFrom,
|
||
|
pTopologyConnection->pPinInfoTo,
|
||
|
pTopologyConnection->pTopologyPinFrom,
|
||
|
pTopologyConnection->pTopologyPinTo,
|
||
|
fToDirection);
|
||
|
|
||
|
if(!fToDirection) {
|
||
|
Status = STATUS_DEAD_END;
|
||
|
goto exit;
|
||
|
}
|
||
|
if(IS_CONNECTION_TYPE(pTopologyConnection, FILTER)) {
|
||
|
|
||
|
if(pTopologyConnection->pPinInfoFrom != NULL) {
|
||
|
Assert(pTopologyConnection->pPinInfoFrom);
|
||
|
|
||
|
if(*ppLogicalFilterNode == NULL) {
|
||
|
|
||
|
Status = CLogicalFilterNode::Create(
|
||
|
ppLogicalFilterNode,
|
||
|
pTopologyConnection->pPinInfoFrom->pFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Status = AddPinNodes(
|
||
|
pTopologyConnection->pPinInfoFrom,
|
||
|
ppLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
DPF2(100, "EFT: add from PI %08x LFN %08x",
|
||
|
pTopologyConnection->pPinInfoFrom,
|
||
|
*ppLogicalFilterNode);
|
||
|
}
|
||
|
ASSERT(*ppLogicalFilterNode != NULL);
|
||
|
Assert(*ppLogicalFilterNode);
|
||
|
|
||
|
if(pTopologyConnection->pPinInfoTo != NULL) {
|
||
|
|
||
|
Status = AddPinNodes(
|
||
|
pTopologyConnection->pPinInfoTo,
|
||
|
ppLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
DPF2(100, "EFT: add to PI %08x LFN %08x",
|
||
|
pTopologyConnection->pPinInfoTo,
|
||
|
*ppLogicalFilterNode);
|
||
|
}
|
||
|
|
||
|
if(pTopologyConnection->pTopologyPinTo != NULL) {
|
||
|
Assert(pTopologyConnection->pTopologyPinTo);
|
||
|
pTopologyNode = pTopologyConnection->pTopologyPinTo->pTopologyNode;
|
||
|
Assert(pTopologyNode);
|
||
|
|
||
|
Status = (*ppLogicalFilterNode)->lstTopologyNode.AddList(
|
||
|
pTopologyNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if(IsEqualGUID(
|
||
|
&KSNODETYPE_ACOUSTIC_ECHO_CANCEL,
|
||
|
pTopologyNode->pguidType)) {
|
||
|
|
||
|
Assert(*ppLogicalFilterNode);
|
||
|
(*ppLogicalFilterNode)->SetType(FILTER_TYPE_AEC);
|
||
|
if(pTopologyConnection->pTopologyPinTo->ulPinNumber ==
|
||
|
KSNODEPIN_AEC_RENDER_IN) {
|
||
|
(*ppLogicalFilterNode)->SetRenderOnly();
|
||
|
}
|
||
|
else {
|
||
|
ASSERT(
|
||
|
pTopologyConnection->pTopologyPinTo->ulPinNumber ==
|
||
|
KSNODEPIN_AEC_CAPTURE_IN);
|
||
|
(*ppLogicalFilterNode)->SetCaptureOnly();
|
||
|
}
|
||
|
Status = (*ppLogicalFilterNode)->AddList(
|
||
|
&pTopologyNode->lstLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(pTopologyNode->lstLogicalFilterNode.IsLstEmpty()) {
|
||
|
Assert(*ppLogicalFilterNode);
|
||
|
|
||
|
Status = (*ppLogicalFilterNode)->AddList(
|
||
|
&pTopologyNode->lstLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
Status = SwitchLogicalFilterNodes(
|
||
|
(PLOGICAL_FILTER_NODE)
|
||
|
pTopologyNode->lstLogicalFilterNode.GetListFirstData(),
|
||
|
ppLogicalFilterNode);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
DPF2(100, "EFT: add to PI %08x LFN %08x",
|
||
|
pTopologyConnection->pPinInfoTo,
|
||
|
*ppLogicalFilterNode);
|
||
|
}
|
||
|
}
|
||
|
Status = pTopologyConnection->AddList(
|
||
|
&(*ppLogicalFilterNode)->lstTopologyConnection);
|
||
|
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
Trap();
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if(IS_CONNECTION_TYPE(pTopologyConnection, FILTER)) {
|
||
|
Status = STATUS_CONTINUE;
|
||
|
}
|
||
|
else {
|
||
|
Status = STATUS_DEAD_END;
|
||
|
}
|
||
|
exit:
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
CLogicalFilterNode::CreateAll(
|
||
|
PFILTER_NODE pFilterNode
|
||
|
)
|
||
|
{
|
||
|
PLOGICAL_FILTER_NODE pLogicalFilterNode;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
PPIN_INFO pPinInfo;
|
||
|
PPIN_NODE pPinNode;
|
||
|
|
||
|
DPF2(100, "CLFN::CreateAll: FN %08x %s",
|
||
|
pFilterNode,
|
||
|
pFilterNode->DumpName());
|
||
|
|
||
|
//
|
||
|
// Split up the filter into logical filter nodes.
|
||
|
//
|
||
|
FOR_EACH_LIST_ITEM(&pFilterNode->lstPinInfo, pPinInfo) {
|
||
|
|
||
|
pLogicalFilterNode = NULL;
|
||
|
Status = EnumerateTopology(
|
||
|
pPinInfo,
|
||
|
(TOP_PFN)EnumerateFilterTopology,
|
||
|
&pLogicalFilterNode);
|
||
|
|
||
|
if(Status == STATUS_CONTINUE) {
|
||
|
Status = STATUS_SUCCESS;
|
||
|
}
|
||
|
else {
|
||
|
if(!NT_SUCCESS(Status)) {
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
//
|
||
|
// Look at the pins of each LFN and determine if it could possibly
|
||
|
// be a capture or render filter (or both).
|
||
|
//
|
||
|
FOR_EACH_LIST_ITEM(
|
||
|
&pFilterNode->lstLogicalFilterNode,
|
||
|
pLogicalFilterNode) {
|
||
|
ULONG ulPossibleFlags;
|
||
|
|
||
|
ulPossibleFlags = 0;
|
||
|
pLogicalFilterNode->ulFlags |= LFN_FLAGS_REFLECT_DATARANGE;
|
||
|
FOR_EACH_LIST_ITEM(&pLogicalFilterNode->lstPinNode, pPinNode) {
|
||
|
|
||
|
// Don't care about the major format
|
||
|
if(!IsEqualGUID(
|
||
|
&pPinNode->pDataRange->SubFormat,
|
||
|
&KSDATAFORMAT_SUBTYPE_WILDCARD) ||
|
||
|
|
||
|
!IsEqualGUID(
|
||
|
&pPinNode->pDataRange->Specifier,
|
||
|
&KSDATAFORMAT_SPECIFIER_WILDCARD)) {
|
||
|
pLogicalFilterNode->ulFlags &= ~LFN_FLAGS_REFLECT_DATARANGE;
|
||
|
}
|
||
|
|
||
|
switch(pPinNode->pPinInfo->Communication) {
|
||
|
case KSPIN_COMMUNICATION_BOTH:
|
||
|
ulPossibleFlags |=
|
||
|
LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER;
|
||
|
break;
|
||
|
case KSPIN_COMMUNICATION_SOURCE:
|
||
|
switch(pPinNode->pPinInfo->DataFlow) {
|
||
|
case KSPIN_DATAFLOW_IN:
|
||
|
ulPossibleFlags |= LFN_FLAGS_CONNECT_CAPTURE;
|
||
|
break;
|
||
|
case KSPIN_DATAFLOW_OUT:
|
||
|
ulPossibleFlags |= LFN_FLAGS_CONNECT_RENDER;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case KSPIN_COMMUNICATION_SINK:
|
||
|
switch(pPinNode->pPinInfo->DataFlow) {
|
||
|
case KSPIN_DATAFLOW_IN:
|
||
|
ulPossibleFlags |= LFN_FLAGS_CONNECT_RENDER;
|
||
|
break;
|
||
|
case KSPIN_DATAFLOW_OUT:
|
||
|
ulPossibleFlags |= LFN_FLAGS_CONNECT_CAPTURE;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
if(ulPossibleFlags ==
|
||
|
(LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
|
||
|
pLogicalFilterNode->ulFlags =
|
||
|
(ulPossibleFlags & pLogicalFilterNode->GetFlags()) |
|
||
|
(pLogicalFilterNode->GetFlags() &
|
||
|
~(LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER));
|
||
|
|
||
|
} END_EACH_LIST_ITEM
|
||
|
exit:
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
|
||
|
ULONG nLogicalFilter = 0;
|
||
|
|
||
|
ENUMFUNC
|
||
|
CLogicalFilterNode::Dump(
|
||
|
)
|
||
|
{
|
||
|
Assert(this);
|
||
|
// .slv
|
||
|
if(ulDebugFlags & (DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_OBJECT)) {
|
||
|
dprintf("LFN: %08x FN %08x fulType %08x ulOrder %08x ulOverhead %08x\n",
|
||
|
this,
|
||
|
pFilterNode,
|
||
|
pFilterNode->GetType(),
|
||
|
ulOrder,
|
||
|
ulOverhead);
|
||
|
dprintf(" %s\n", pFilterNode->DumpName());
|
||
|
dprintf(" fulType: ");
|
||
|
DumpfulType(GetType());
|
||
|
dprintf("\n ulFlags: ");
|
||
|
if(ulFlags & LFN_FLAGS_CONNECT_CAPTURE) {
|
||
|
dprintf("CAPTURE ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_CONNECT_RENDER) {
|
||
|
dprintf("RENDER ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_CONNECT_NORMAL_TOPOLOGY) {
|
||
|
dprintf("NORMAL_TOPOLOGY ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_CONNECT_MIXER_TOPOLOGY) {
|
||
|
dprintf("MIXER_TOPOLOGY ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_TOP_DOWN) {
|
||
|
dprintf("TOP_DOWN ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_NO_BYPASS) {
|
||
|
dprintf("NO_BYPASS ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_NOT_SELECT) {
|
||
|
dprintf("NOT_SELECT ");
|
||
|
}
|
||
|
if(ulFlags & LFN_FLAGS_REFLECT_DATARANGE) {
|
||
|
dprintf("REFLECT_DATARANGE ");
|
||
|
}
|
||
|
dprintf("\n");
|
||
|
// .slvx
|
||
|
if(ulDebugFlags & DEBUG_FLAGS_DETAILS) {
|
||
|
dprintf(" lstPN: ");
|
||
|
lstPinNode.DumpAddress();
|
||
|
dprintf("\n lstTN: ");
|
||
|
lstTopologyNode.DumpAddress();
|
||
|
dprintf("\n lstTC: ");
|
||
|
lstTopologyConnection.DumpAddress();
|
||
|
dprintf("\n lstFNI: ");
|
||
|
lstFilterNodeInstance.DumpAddress();
|
||
|
dprintf("\n");
|
||
|
}
|
||
|
}
|
||
|
// .slp
|
||
|
if(ulDebugFlags & DEBUG_FLAGS_PIN) {
|
||
|
lstPinNode.Dump();
|
||
|
}
|
||
|
// .slt
|
||
|
if(ulDebugFlags & DEBUG_FLAGS_TOPOLOGY) {
|
||
|
lstTopologyNode.Dump();
|
||
|
// .sltx
|
||
|
if(ulDebugFlags & DEBUG_FLAGS_DETAILS) {
|
||
|
lstTopologyConnection.Dump();
|
||
|
}
|
||
|
}
|
||
|
if(ulDebugFlags &
|
||
|
(DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_PIN | DEBUG_FLAGS_TOPOLOGY)) {
|
||
|
dprintf("\n");
|
||
|
}
|
||
|
return(STATUS_CONTINUE);
|
||
|
}
|
||
|
|
||
|
#endif
|