297 lines
7.3 KiB
C++
297 lines
7.3 KiB
C++
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Module: pn.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"
|
|
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
|
|
CPinNode::CPinNode(
|
|
PPIN_INFO pPinInfo
|
|
)
|
|
{
|
|
Assert(pPinInfo);
|
|
this->pPinInfo = pPinInfo;
|
|
AddList(&pPinInfo->lstPinNode);
|
|
}
|
|
|
|
CPinNode::CPinNode(
|
|
PGRAPH_NODE pGraphNode,
|
|
PPIN_NODE pPinNode
|
|
)
|
|
{
|
|
this->pPinInfo = pPinNode->pPinInfo;
|
|
this->ulOverhead = pPinNode->GetOverhead();
|
|
this->pDataRange = pPinNode->pDataRange;
|
|
this->pInterface = pPinNode->pInterface;
|
|
this->pMedium = pPinNode->pMedium;
|
|
this->pLogicalFilterNode = pPinNode->pLogicalFilterNode;
|
|
AddList(&pGraphNode->lstPinNode);
|
|
}
|
|
|
|
NTSTATUS
|
|
CPinNode::CreateAll(
|
|
PPIN_INFO pPinInfo,
|
|
PDATARANGES pDataRanges,
|
|
PIDENTIFIERS pInterfaces,
|
|
PIDENTIFIERS pMediums
|
|
)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PKSDATARANGE pDataRange;
|
|
PPIN_NODE pPinNode;
|
|
ULONG d, i, m;
|
|
|
|
Assert(pPinInfo);
|
|
|
|
// Data Ranges loop
|
|
pDataRange = &pDataRanges->aDataRanges[0];
|
|
|
|
for(d = 0; d < pDataRanges->MultipleItem.Count; d++) {
|
|
|
|
if(IsEqualGUID(
|
|
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
|
|
&pDataRange->Specifier) ||
|
|
IsEqualGUID(
|
|
&KSDATAFORMAT_SPECIFIER_DSOUND,
|
|
&pDataRange->Specifier)) {
|
|
//
|
|
// Reject KSDATARANGE_AUDIO's that have the wrong size
|
|
//
|
|
if(pDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO)) {
|
|
DPF(5, "CPinNode::Create: KSDATARANGE_AUDIO wrong size");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Interfaces loop
|
|
for(i = 0; i < pInterfaces->MultipleItem.Count; i++) {
|
|
|
|
// Mediums loop
|
|
for(m = 0; m < pMediums->MultipleItem.Count; m++) {
|
|
|
|
pPinNode = new PIN_NODE(pPinInfo);
|
|
if(pPinNode == NULL) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
Trap();
|
|
goto exit;
|
|
}
|
|
if(pDataRanges != &DataRangesNull) {
|
|
pPinNode->pDataRange = pDataRange;
|
|
AssertAligned(pPinNode->pDataRange);
|
|
} else Trap();
|
|
if(pInterfaces != &IdentifiersNull) {
|
|
pPinNode->pInterface = &pInterfaces->aIdentifiers[i];
|
|
AssertAligned(pPinNode->pInterface);
|
|
}
|
|
if(pMediums != &IdentifiersNull) {
|
|
pPinNode->pMedium = &pMediums->aIdentifiers[m];
|
|
AssertAligned(pPinNode->pMedium);
|
|
} else Trap();
|
|
|
|
if(IsEqualGUID(
|
|
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
|
|
&pDataRange->Specifier) ||
|
|
IsEqualGUID(
|
|
&KSDATAFORMAT_SPECIFIER_DSOUND,
|
|
&pDataRange->Specifier)) {
|
|
//
|
|
// Puts in order based on SR, BPS and CHs,
|
|
// scaled down to 0 - 256
|
|
//
|
|
pPinNode->ulOverhead = 256 -
|
|
(( (((PKSDATARANGE_AUDIO)pDataRange)->
|
|
MaximumChannels > 6 ? 6 :
|
|
((PKSDATARANGE_AUDIO)pDataRange)->
|
|
MaximumChannels) *
|
|
((PKSDATARANGE_AUDIO)pDataRange)->
|
|
MaximumSampleFrequency *
|
|
((PKSDATARANGE_AUDIO)pDataRange)->
|
|
MaximumBitsPerSample) / ((96000 * 32 * 6)/256));
|
|
//
|
|
// Try the WaveFormatEx format first, then DSOUND
|
|
//
|
|
if(IsEqualGUID(
|
|
&KSDATAFORMAT_SPECIFIER_DSOUND,
|
|
&pDataRange->Specifier)) {
|
|
pPinNode->ulOverhead += 1;
|
|
}
|
|
}
|
|
else {
|
|
// Put in order that the filter had the data ranges
|
|
pPinNode->ulOverhead = d;
|
|
}
|
|
// Put in order that the filter had the interface/mediums
|
|
pPinNode->ulOverhead += (m << 16) + (i << 8);
|
|
}
|
|
}
|
|
// Get the pointer to the next data range
|
|
*((PUCHAR*)&pDataRange) += ((pDataRange->FormatSize +
|
|
FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT);
|
|
}
|
|
exit:
|
|
return(Status);
|
|
}
|
|
|
|
BOOL
|
|
CPinNode::ComparePins(
|
|
PPIN_NODE pPinNode2
|
|
)
|
|
{
|
|
PPIN_NODE pPinNode1 = this;
|
|
|
|
// Check if dataflow is compatible
|
|
switch(pPinNode1->pPinInfo->DataFlow) {
|
|
|
|
case KSPIN_DATAFLOW_IN:
|
|
switch(pPinNode2->pPinInfo->DataFlow) {
|
|
case KSPIN_DATAFLOW_OUT:
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: dataflow mismatch");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
case KSPIN_DATAFLOW_OUT:
|
|
switch(pPinNode2->pPinInfo->DataFlow) {
|
|
case KSPIN_DATAFLOW_IN:
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: dataflow mismatch");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Trap();
|
|
DPF(100, "ComparePins: dataflow mismatch");
|
|
return(FALSE);
|
|
}
|
|
|
|
// Check if communication type is compatible
|
|
switch(pPinNode1->pPinInfo->Communication) {
|
|
case KSPIN_COMMUNICATION_BOTH:
|
|
switch(pPinNode2->pPinInfo->Communication) {
|
|
case KSPIN_COMMUNICATION_BOTH:
|
|
case KSPIN_COMMUNICATION_SINK:
|
|
case KSPIN_COMMUNICATION_SOURCE:
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: comm mismatch");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
case KSPIN_COMMUNICATION_SOURCE:
|
|
switch(pPinNode2->pPinInfo->Communication) {
|
|
case KSPIN_COMMUNICATION_BOTH:
|
|
case KSPIN_COMMUNICATION_SINK:
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: comm mismatch");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
case KSPIN_COMMUNICATION_SINK:
|
|
switch(pPinNode2->pPinInfo->Communication) {
|
|
case KSPIN_COMMUNICATION_BOTH:
|
|
case KSPIN_COMMUNICATION_SOURCE:
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: comm mismatch");
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPF(100, "ComparePins: comm mismatch");
|
|
return(FALSE);
|
|
}
|
|
|
|
// Check if interface is the same
|
|
if(!CompareIdentifier(pPinNode1->pInterface, pPinNode2->pInterface)) {
|
|
DPF(100, "ComparePins: interface mismatch");
|
|
return(FALSE);
|
|
}
|
|
|
|
// Check if medium is the same
|
|
if(!CompareIdentifier(pPinNode1->pMedium, pPinNode2->pMedium)) {
|
|
Trap();
|
|
DPF(100, "ComparePins: medium mismatch");
|
|
return(FALSE);
|
|
}
|
|
|
|
// Check if data range is the same
|
|
if(!CompareDataRange(pPinNode1->pDataRange, pPinNode2->pDataRange)) {
|
|
DPF(100, "ComparePins: datarange mismatch");
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#ifdef DEBUG
|
|
|
|
ENUMFUNC
|
|
CPinNode::Dump(
|
|
)
|
|
{
|
|
Assert(this);
|
|
dprintf("PN: %08x PI %08x LFN %08x ulOverhead %08x #%d\n",
|
|
this,
|
|
pPinInfo,
|
|
pLogicalFilterNode,
|
|
ulOverhead,
|
|
pPinInfo->PinId);
|
|
dprintf(" Interface: %s\n", DbgIdentifier2Sz(pInterface));
|
|
dprintf(" Medium: %s\n", DbgIdentifier2Sz(pMedium));
|
|
if(pDataRange != NULL) {
|
|
dprintf(" MajorFormat: %s\n", DbgGuid2Sz(&pDataRange->MajorFormat));
|
|
dprintf(" SubFormat: %s\n", DbgGuid2Sz(&pDataRange->SubFormat));
|
|
dprintf(" Specifier: %s\n", DbgGuid2Sz(&pDataRange->Specifier));
|
|
DumpDataRangeAudio((PKSDATARANGE_AUDIO)pDataRange);
|
|
}
|
|
if(ulDebugFlags == DEBUG_FLAGS_OBJECT ||
|
|
ulDebugFlags & DEBUG_FLAGS_LOGICAL_FILTER) {
|
|
pPinInfo->Dump();
|
|
}
|
|
dprintf("\n");
|
|
return(STATUS_CONTINUE);
|
|
}
|
|
|
|
#endif
|
|
|
|
//---------------------------------------------------------------------------
|