📄 prophnd.cpp
字号:
// impossible. If you would store the volume like sndvol gives it
// to you and you return it on a get, then the balance slider
// moves and stays at the position the user wanted it. However,
// if you return the actual volume the balance slider will jump
// back to the position that the HW can do (play with it to see
// how it works).
//
if (lLevel > lMaximum) lLevel = lMaximum;
if (lLevel < lMinimum) lLevel = lMinimum;
// First update the node cache.
if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
{
that->stNodeCache[NodeDef].bLeftValid = -1;
that->stNodeCache[NodeDef].lLeft = lLevel;
}
if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
{
that->stNodeCache[NodeDef].bRightValid = -1;
that->stNodeCache[NodeDef].lRight = lLevel;
}
//
// If we have a master mono, then we have to program the speaker
// volumes a little different.
// Check for master mono (surround or headphone present) and
// if one of the speaker volumes is requested.
//
if ((that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT)) &&
((NodeDef == NODE_VIRT_MASTERMONO_VOLUME) || (NodeDef == NODE_LFE_VOLUME) ||
(NodeDef == NODE_CENTER_VOLUME) || (NodeDef == NODE_FRONT_VOLUME) ||
(NodeDef == NODE_SURROUND_VOLUME) || (NodeDef == NODE_HPOUT_VOLUME)))
{
//
// For master mono we have to update all speaker volumes.
//
if (NodeDef == NODE_VIRT_MASTERMONO_VOLUME)
{
// Update all speaker volumes.
ntStatus = SetMultichannelVolume (that, NODE_FRONT_VOLUME);
if (that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
ntStatus = SetMultichannelVolume (that, NODE_HPOUT_VOLUME);
if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
ntStatus = SetMultichannelVolume (that, NODE_SURROUND_VOLUME);
if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
{
ntStatus = SetMultichannelVolume (that, NODE_CENTER_VOLUME);
ntStatus = SetMultichannelVolume (that, NODE_LFE_VOLUME);
}
}
else // update the individual speaker volume only.
{
ntStatus = SetMultichannelVolume (that, NodeDef);
}
}
else // This is for all other volumes (or no master mono present).
{
// calculate the dB.dB value.
// The nodes are calculated differently.
switch (NodeDef)
{
// for record controls we calculate it 'reverse'.
case NODE_VIRT_MASTER_INPUT_VOLUME1:
case NODE_VIRT_MASTER_INPUT_VOLUME2:
case NODE_VIRT_MASTER_INPUT_VOLUME3:
case NODE_VIRT_MASTER_INPUT_VOLUME4:
case NODE_VIRT_MASTER_INPUT_VOLUME5:
case NODE_VIRT_MASTER_INPUT_VOLUME6:
case NODE_VIRT_MASTER_INPUT_VOLUME7:
case NODE_VIRT_MASTER_INPUT_VOLUME8:
// read the wavein selector.
ntStatus = that->AdapterCommon->ReadCodecRegister (
that->AdapterCommon->GetNodeReg (NODE_WAVEIN_SELECT),
&wRegister);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// mask out every unused bit.
wRegister &= (that->AdapterCommon->GetNodeMask (
NODE_WAVEIN_SELECT) & AC97REG_MASK_RIGHT);
// check if the volume that we change belongs to the active
// (selected) virtual channel.
// Tricky: If the virtual nodes are not defined consecutively
// this comparision will fail.
if ((NodeDef - NODE_VIRT_MASTER_INPUT_VOLUME1) != wRegister)
return ntStatus;
// fall through for calculation.
case NODE_MICIN_VOLUME:
wRegister = (WORD)(((lLevel + uStep / 2) - lMinimum) / uStep);
break;
case NODE_VIRT_MONOOUT_VOLUME1:
case NODE_VIRT_MONOOUT_VOLUME2:
// read the monoout selector.
ntStatus = that->AdapterCommon->ReadCodecRegister (
that->AdapterCommon->GetNodeReg (NODE_MONOOUT_SELECT),
&wRegister);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// mask out every unused bit.
wRegister &= that->AdapterCommon->GetNodeMask (NODE_MONOOUT_SELECT);
// check if the volume that we change belongs to the active
// (selected) virtual channel.
// Note: Monout select is set if we want to prg. MIC (Volume2).
if ((!wRegister && (NodeDef == NODE_VIRT_MONOOUT_VOLUME2)) ||
(wRegister && (NodeDef == NODE_VIRT_MONOOUT_VOLUME1)))
return ntStatus;
// fall through for calculation.
default:
wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
break;
}
// Oops - NODE_PCBEEP_VOLUME doesn't use bit0. We have to adjust.
if (NodeDef == NODE_PCBEEP_VOLUME)
wRegister <<= 1;
// write the stuff (with mask!).
// Note: mono channels are 'master' here (see fake above).
// this makes sure that left and right channel is prg. for the virt.
// controls. On controls that only have the right channel, the left
// channel programming does nothing cause the mask will be zero.
if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
{
// write only left.
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
wRegister << 8,
that->AdapterCommon->GetNodeMask (NodeDef) & AC97REG_MASK_LEFT);
// immediately return on error
if (!NT_SUCCESS (ntStatus))
return ntStatus;
}
if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
{
// write only right.
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
wRegister,
that->AdapterCommon->GetNodeMask (NodeDef) & AC97REG_MASK_RIGHT);
// immediately return on error
if (!NT_SUCCESS (ntStatus))
return ntStatus;
}
// For the virtual controls, which are in front of a muxer, there
// is no mute control displayed. But we have a HW mute control, so
// what we do is enabling this mute when the user moves the slider
// down to the bottom and disabling it on every other position.
// We do this only for the "mono muxer", the recording mutes will
// never be muted.
// Tricky: Master input virtual controls must be defined consecutively.
if ((NodeDef >= NODE_VIRT_MASTER_INPUT_VOLUME1) &&
(NodeDef <= NODE_VIRT_MASTER_INPUT_VOLUME8))
{
// disable the mute; this only works because the mute and volume
// share the same register.
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
0, AC97REG_MASK_MUTE);
// Just in case.
that->UpdateRecordMute ();
}
if ((NodeDef == NODE_VIRT_MONOOUT_VOLUME1) ||
(NodeDef == NODE_VIRT_MONOOUT_VOLUME2))
{
// these are only mono controls so checking one entry is enough.
if ( that->stNodeCache[NodeDef].bLeftValid &&
(that->stNodeCache[NodeDef].lLeft <= lMinimum))
{
// set the mute; this only works because the mute and volume
// share the same register.
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
AC97REG_MASK_MUTE, AC97REG_MASK_MUTE);
}
else
{
// clear the mute; this only works because the mute and volume
// share the same register.
ntStatus = that->AdapterCommon->WriteCodecRegister (
that->AdapterCommon->GetNodeReg (NodeDef),
0, AC97REG_MASK_MUTE);
}
}
}
DOUT (DBG_PROPERTY, ("SET: %s(%s) -> 0x%x", NodeStrings[NodeDef],
channel==CHAN_LEFT ? "L" : channel==CHAN_RIGHT ? "R" : "M",
*Level));
// ntStatus was set with the read call! whatever this is, return it.
}
}
else
{
if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
{
ntStatus = BasicSupportHandler (PropertyRequest);
}
}
return ntStatus;
}
/*****************************************************************************
* CMiniportTopologyICH::PropertyHandler_Tone
*****************************************************************************
* Accesses a KSAUDIO_TONE property.
* This function (property handler) is called by portcls every time there is a
* get, set or basic support request for the node. The connection between the
* node type and the property handler is made in the automation table which is
* referenced when you register the node.
* We use this property handler for all tone controls displayed at the advanced
* property dialog in sndvol32 and the 3D controls displayed and exposed as
* normal volume controls.
*/
NTSTATUS CMiniportTopologyICH::PropertyHandler_Tone
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
{
PAGED_CODE ();
ASSERT (PropertyRequest);
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::PropertyHandler_Tone]"));
NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
TopoNodes NodeDef;
LONG lMinimum, lMaximum;
ULONG uStep;
// The major target is the object pointer to the topology miniport.
CMiniportTopologyICH *that =
(CMiniportTopologyICH *) PropertyRequest->MajorTarget;
ASSERT (that);
// validate node
if (PropertyRequest->Node == (ULONG)-1)
return ntStatus;
// do the appropriate action for the request.
// we should do a get or a set?
if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
(PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
{
// validate parameters
if ((PropertyRequest->InstanceSize < sizeof(LONG)) ||
(PropertyRequest->ValueSize < sizeof(LONG)))
return ntStatus;
// get the buffer
PLONG Level = (PLONG)PropertyRequest->Value;
// Switch on the node id. This is just for parameter checking.
// If something goes wrong, we will immideately return with
// ntStatus, which is STATUS_INVALID_PARAMETER.
switch(NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
{
case NODE_BASS:
// check type.
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_BASS)
return ntStatus;
break;
case NODE_TREBLE:
// check type.
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_TREBLE)
return ntStatus;
break;
case NODE_VIRT_3D_CENTER:
case NODE_VIRT_3D_DEPTH:
// check 3D control
if (!that->AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE)
&& (NodeDef == NODE_VIRT_3D_CENTER))
return ntStatus;
if (!that->AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE)
&& (NodeDef == NODE_VIRT_3D_DEPTH))
return ntStatus;
// check type
if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
return ntStatus;
// check channel
if (*(PLONG(PropertyRequest->Instance)) == CHAN_RIGHT)
return ntStatus;
break;
case NODE_INVALID:
default:
// Ooops
DOUT (DBG_ERROR, ("PropertyHandler_Tone: Invalid node requested."));
return ntStatus;
}
// Now, do some action!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -