📄 miniport.cpp
字号:
// Gets the topology.
// Pass back appropriate descriptor, depending on whether volume node is needed.
// ==============================================================================
STDMETHODIMP_(NTSTATUS)
CMiniportMidiFM::
GetDescription
(
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
{
PAGED_CODE();
ASSERT(OutFilterDescriptor);
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiFM::GetDescription"));
if (m_volNodeNeeded)
{
*OutFilterDescriptor = &MiniportFilterWithVolDescriptor;
_DbgPrintF(DEBUGLVL_VERBOSE, ("Getting descriptor of new FM miniport with volume node"));
}
else
{
*OutFilterDescriptor = &MiniportFilterDescriptor;
}
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiStreamFM::NonDelegatingQueryInterface()
// Obtains an interface. This function works just like a COM QueryInterface
// call and is used if the object is not being aggregated.
// ==============================================================================
STDMETHODIMP_(NTSTATUS) CMiniportMidiStreamFM::NonDelegatingQueryInterface
(
REFIID Interface,
PVOID * Object
)
{
PAGED_CODE();
ASSERT(Object);
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamFM::NonDelegatingQueryInterface"));
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
{
*Object = PVOID(PUNKNOWN(PMINIPORT(this)));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniportMidiStream))
{
*Object = PVOID(PMINIPORTMIDISTREAM(this));
}
else
{
*Object = NULL;
}
if (*Object)
{
//
// We reference the interface for the caller.
//
PUNKNOWN(PMINIPORT(*Object))->AddRef();
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiStreamFM::~CMiniportMidiStreamFM()
// Destructor.
// ==============================================================================
CMiniportMidiStreamFM::~CMiniportMidiStreamFM
(
void
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamFM::~CMiniportMidiStreamFM"));
Opl3_AllNotesOff();
if (m_Miniport)
{
m_Miniport->m_fStreamExists = FALSE;
m_Miniport->Release();
}
}
#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiStreamFM::Init()
// Initializes a the miniport.
// ==============================================================================
NTSTATUS
CMiniportMidiStreamFM::
Init
(
IN CMiniportMidiFM * Miniport,
IN PUCHAR PortBase
)
{
PAGED_CODE();
ASSERT(Miniport);
ASSERT(PortBase);
int i;
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamFM::Init"));
//
// AddRef() is required because we are keeping this pointer.
//
m_Miniport = Miniport;
m_Miniport->AddRef();
m_PortBase = PortBase;
// init some members
m_dwCurTime = 1; /* for note on/off */
/* volume */
m_wSynthAttenL = 0; /* in 1.5dB steps */
m_wSynthAttenR = 0; /* in 1.5dB steps */
m_MinVolValue = 0xFFD0C000; // minimum -47.25(dB) * 0x10000
m_MaxVolValue = 0x00000000; // maximum 0 (dB) * 0x10000
m_VolStepDelta = 0x0000C000; // steps of 0.75 (dB) * 0x10000
m_SavedVolValue[CHAN_LEFT] = m_SavedVolValue[CHAN_RIGHT] = 0;
/* start attenuations at -3 dB, which is 90 MIDI level */
for (i = 0; i < NUMCHANNELS; i++)
{
m_bChanAtten[i] = 4;
m_bStereoMask[i] = 0xff;
};
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiStreamFM::SetState()
// Sets the transport state.
// ==============================================================================
STDMETHODIMP_(NTSTATUS)
CMiniportMidiStreamFM::
SetState
(
IN KSSTATE NewState
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamFM::SetState"));
NTSTATUS ntStatus = STATUS_SUCCESS;
switch (NewState)
{
case KSSTATE_STOP:
case KSSTATE_ACQUIRE:
case KSSTATE_PAUSE:
Opl3_AllNotesOff();
break;
case KSSTATE_RUN:
break;
}
return ntStatus;
}
#pragma code_seg("PAGE")
// ==============================================================================
// CMiniportMidiStreamFM::SetFormat()
// Sets the format.
// ==============================================================================
STDMETHODIMP_(NTSTATUS)
CMiniportMidiStreamFM::
SetFormat
(
IN PKSDATAFORMAT Format
)
{
PAGED_CODE();
ASSERT(Format);
_DbgPrintF(DEBUGLVL_VERBOSE,("CMiniportMidiStreamFM::SetFormat"));
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* BasicSupportHandler()
*****************************************************************************
* Assists in BASICSUPPORT accesses on level properties -
* this is declared as a friend method in the header file.
*/
static
NTSTATUS BasicSupportHandler
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
{
PAGED_CODE();
ASSERT(PropertyRequest);
_DbgPrintF(DEBUGLVL_VERBOSE, ("BasicSupportHandler"));
NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL;
if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
{
// if return buffer can hold a KSPROPERTY_DESCRIPTION, return it
PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
KSPROPERTY_TYPE_GET |
KSPROPERTY_TYPE_SET;
PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(KSPROPERTY_STEPPING_LONG);
PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
PropDesc->PropTypeSet.Id = VT_I4;
PropDesc->PropTypeSet.Flags = 0;
PropDesc->MembersListCount = 1;
PropDesc->Reserved = 0;
// if return buffer can also hold a range description, return it too
if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(KSPROPERTY_STEPPING_LONG)))
{
// fill in the members header
PKSPROPERTY_MEMBERSHEADER Members = PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
Members->MembersCount = 1;
Members->Flags = 0;
// fill in the stepped range
PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1);
switch (PropertyRequest->Node)
{
case eFMVolumeNode:
CMiniportMidiStreamFM *that = (CMiniportMidiStreamFM *)PropertyRequest->MinorTarget;
if (that)
{
Range->Bounds.SignedMinimum = that->m_MinVolValue;
Range->Bounds.SignedMaximum = that->m_MaxVolValue;
Range->SteppingDelta = that->m_VolStepDelta;
break;
}
else
{
return STATUS_INVALID_PARAMETER;
}
}
Range->Reserved = 0;
_DbgPrintF(DEBUGLVL_VERBOSE, ("---Node: %d Max: 0x%X Min: 0x%X Step: 0x%X",PropertyRequest->Node,
Range->Bounds.SignedMaximum,
Range->Bounds.SignedMinimum,
Range->SteppingDelta));
// set the return value size
PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(KSPROPERTY_STEPPING_LONG);
}
else
{
// set the return value size
PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
}
ntStatus = STATUS_SUCCESS;
}
else if (PropertyRequest->ValueSize >= sizeof(ULONG))
{
// if return buffer can hold a ULONG, return the access flags
PULONG AccessFlags = PULONG(PropertyRequest->Value);
*AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
KSPROPERTY_TYPE_GET |
KSPROPERTY_TYPE_SET;
// set the return value size
PropertyRequest->ValueSize = sizeof(ULONG);
ntStatus = STATUS_SUCCESS;
}
return ntStatus;
}
#pragma code_seg("PAGE")
/*****************************************************************************
* PropertyHandler_Level()
*****************************************************************************
* Accesses a KSAUDIO_LEVEL property.
*/
static
NTSTATUS PropertyHandler_Level
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
{
PAGED_CODE();
ASSERT(PropertyRequest);
_DbgPrintF(DEBUGLVL_VERBOSE,("PropertyHandler_Level"));
NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
LONG channel;
// validate node
if (PropertyRequest->Node == eFMVolumeNode)
{
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
{
// get the instance channel parameter
if (PropertyRequest->InstanceSize >= sizeof(LONG))
{
channel = *(PLONG(PropertyRequest->Instance));
// only support get requests on either mono/left(0) or right(1) channels
if ((channel == CHAN_LEFT) || (channel == CHAN_RIGHT))
{
// validate and get the output parameter
if (PropertyRequest->ValueSize >= sizeof(LONG))
{
PLONG Level = (PLONG)PropertyRequest->Value;
// check if volume property request
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_VOLUMELEVEL)
{
CMiniportMidiStreamFM *that = (CMiniportMidiStreamFM *)PropertyRequest->MinorTarget;
if (that)
{
*Level = that->GetFMAtten(channel);
PropertyRequest->ValueSize = sizeof(LONG);
ntStatus = STATUS_SUCCESS;
}
// if (!that) return STATUS_INVALID_PARAMETER
} // (PropertyItem->Id == KSPROPERTY_AUDIO_VOLUMELEVEL)
} // (ValueSize >= sizeof(LONG))
} // ((channel == CHAN_LEFT) || (channel == CHAN_RIGHT))
} // (InstanceSize >= sizeof(LONG))
} // (Verb & KSPROPERTY_TYPE_GET)
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
{
// get the instance channel parameter
if (PropertyRequest->InstanceSize >= sizeof(LONG))
{
channel = *(PLONG(PropertyRequest->Instance));
// only support get requests on either mono/left (0), right (1), or master (-1) channels
if ((channel == CHAN_LEFT) || (channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
{
// validate and get the input parameter
if (PropertyRequest->ValueSize == sizeof(LONG))
{
PLONG level = (PLONG)PropertyRequest->Value;
if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_VOLUMELEVEL)
{
CMiniportMidiStreamFM *that = (CMiniportMidiStreamFM *)PropertyRequest->MinorTarget;
if (that)
{
that->SetFMAtten(channel,*level);
ntStatus = STATUS_SUCCESS;
}
// if (!that) return STATUS_INVALID_PARAMETER
} // (PropertyItem->Id == KSPROPERTY_AUDIO_VOLUMELEVEL)
} // (ValueSize == sizeof(LONG))
} // ((channel == CHAN_LEFT) || (channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
} // (InstanceSize >= sizeof(LONG))
} // (Verb & KSPROPERTY_TYPE_SET)
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -