Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

470 lines
12 KiB

//---------------------------------------------------------------------------
//
// Module: sbproctl.c
//
// Purpose: Sound Blaster Pro Mixer control interface for Sound blaster driver
//
//---------------------------------------------------------------------------
//
// Copyright (c) 1994 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "sound.h"
#include "sbpromix.h"
BOOLEAN SBPROSetADCVolume
(
PGLOBAL_DEVICE_INFO pGDI,
ULONG ControlId
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SBPROSetMute)
#pragma alloc_text(PAGE, SBPROSetVolume)
#pragma alloc_text(PAGE, SBPROSetSources)
#pragma alloc_text(PAGE, SBPROSetADCHardware)
#pragma alloc_text(PAGE, SBPROSetADCVolume)
#pragma alloc_text(PAGE, SBPROResetADCHardware)
#endif
#if DBG
static char *ControlNames[NumberOfControls] = {
"ControlLineoutVolume", // 0
"ControlLineoutMute", // 1
"ControlWaveInMux", // 2
"ControlVoiceInMux", // 3
"ControlLineoutAuxVolume", // 4
"ControlLineoutAuxMute", // 5
"ControlLineoutMidioutVolume", // 6
"ControlLineoutMidioutMute", // 7
"ControlLineoutInternalCDVolume", // 8
"ControlLineoutInternalCDMute", // 9
"ControlLineoutWaveoutVolume", // 10
"ControlLineoutWaveoutMute", // 11
"ControlLineoutWaveoutPeak", // 12
"ControlWaveInAuxVolume", // 13
"ControlWaveInAuxPeak", // 14
"ControlWaveInMicPeak", // 15
"ControlWaveInInternalCDVolume", // 16
"ControlWaveInInternalCDPeak", // 17
"ControlVoiceInAuxVolume", // 18
"ControlVoiceInAuxPeak", // 19
"ControlVoiceInMicPeak" // 20
};
#endif // DBG
//------------------------------------------------------------------------
// BOOLEAN SBPROSetVolume
//
// Description:
// Sets the audio volume for the specified control.
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
// Global device data
//
// ULONG ControlId
// Id of the control
//
// Return Value:
// TRUE
//
//------------------------------------------------------------------------
BOOLEAN SBPROSetVolume
(
PGLOBAL_DEVICE_INFO pGDI,
ULONG ControlId
)
{
UCHAR bNumStepsL, bNumStepsR, bDSPReg ;
PLOCAL_MIXER_CONTROL_INFO ControlInfo;
ControlInfo = &pGDI->LocalMixerData.ControlInfo[ControlId];
dprintf3(("SBPROSetVolume, Control ID = %s, Left = %u, Right = %u",
ControlNames[ControlId], ControlInfo->Data.v[0].u, ControlInfo->Data.v[1].u));
if (ControlId != ControlLineoutVolume) {
//
// If it's not an output line call SBPROSetADCVolume
//
if (SBPROLineInit[SBPROControlInit[ControlId].LineID].Destination
!= DestLineout) {
return SBPROSetADCVolume(pGDI, ControlId);
}
//
// If wave input is running we don't want to change the volume on lines
// which are switched to wave input because these lines have the input
// volume set
//
if (!SBPROMixerOutputFree(pGDI, SBPROControlInit[ControlId].LineID)) {
return TRUE;
}
}
//
// Convert to steps of 1.5dB attenuation for the DSP
//
bNumStepsL =
VolLinearToLog( ControlInfo->Data.v[0].u );
bNumStepsR =
VolLinearToLog( ControlInfo->Data.v[1].u );
// Bounding...
if (bNumStepsL > 0x07)
bNumStepsL = 0x07 ;
if (bNumStepsR > 0x07)
bNumStepsR = 0x07 ;
// Convert to levels for the SB mixer
bNumStepsL = (0x07 - bNumStepsL) << 5 ;
bNumStepsR = (0x07 - bNumStepsR) << 1 ;
//
// Check the associated mute... if set, mute the output.
//
ASSERT(SBPROControlInit[ControlId + 1].dwControlType ==
MIXERCONTROL_CONTROLTYPE_MUTE);
if (ControlInfo[1].Data.v[0].u) {
bNumStepsL = bNumStepsR = 0 ;
}
switch (ControlId)
{
case ControlLineoutAuxVolume:
bDSPReg = DSP_MIX_LINEVOLIDX;
break ;
case ControlLineoutWaveoutVolume:
//
// Only mess with DAC during playback
//
if (!WAVE_OUT_ACTIVE(&pGDI->WaveInfo)) {
return TRUE;
}
bDSPReg = DSP_MIX_VOICEVOLIDX ;
break ;
case ControlLineoutMidioutVolume:
bDSPReg = DSP_MIX_FMVOLIDX ;
break ;
case ControlLineoutInternalCDVolume:
bDSPReg = DSP_MIX_CDVOLIDX;
break ;
case ControlLineoutVolume:
bDSPReg = DSP_MIX_MSTRVOLIDX;
break ;
}
dprintf3(( "bNumStepsL = %02x, bNumStepsR = %02x", bNumStepsL, bNumStepsR )) ;
dspWriteMixer( pGDI, bDSPReg, (UCHAR)(bNumStepsL | bNumStepsR )) ;
return TRUE;
} // end of MixSetVolume()
//--------------------------------------------------------------------------
//
// MMRESULT SBPROSetMute
//
// Description:
// Sets/unsets the associated control's mute
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
// Global device data
//
// ULONG ControlId
// Id of the control
//
// Return Value:
// TRUE
//------------------------------------------------------------------------
BOOLEAN SBPROSetMute
(
PGLOBAL_DEVICE_INFO pGDI,
ULONG ControlId
)
{
PLOCAL_MIXER_CONTROL_INFO ControlInfo;
ControlInfo = &pGDI->LocalMixerData.ControlInfo[ControlId];
dprintf3(("MixSetMute, Control ID = %s, Value = %s",
ControlNames[ControlId], ControlInfo->Data.v[0].u ? "Mute" : "Unmute"));
//
// Force an update of the volume - this will cause the
// respective control to mute the hardware.
//
// NOTE that the mute controls are ALWAYS immediately after
// their respective volume control
//
ASSERT(SBPROControlInit[ControlId - 1].dwControlType ==
MIXERCONTROL_CONTROLTYPE_VOLUME);
return SBPROSetVolume( pGDI, ControlId - 1 ) ;
} // end of SBPROSetMute()
//--------------------------------------------------------------------------
//
// MMRESULT SBPROSetADCVolume
//
// Description:
// Sets the ADC volume
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
// Global device data
//
// ULONG ControlId
// Id of the control
//
// Return Value:
// TRUE
//------------------------------------------------------------------------
BOOLEAN SBPROSetADCVolume
(
PGLOBAL_DEVICE_INFO pGDI,
ULONG ControlId
)
{
SBPROSetADCHardware(pGDI);
return TRUE;
} // end of SBPROSetADCVolume()
//--------------------------------------------------------------------------
//
// MMRESULT SBPROResetADCHardware
//
// Description:
// Resets the line levels to DEST_LINEOUT settings.
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
//
// Return (MMRESULT):
// nothing
//
//--------------------------------------------------------------------------
VOID SBPROResetADCHardware(PGLOBAL_DEVICE_INFO pGDI)
{
dprintf3(( "SBPROResetADCHardware" ));
//
// Just set the volume - the code in SBPROSetVolume will now
// set the volumes correctly because input is no longer active
//
SBPROSetVolume(pGDI, ControlLineoutAuxVolume);
SBPROSetVolume(pGDI, ControlLineoutMidioutVolume);
SBPROSetVolume(pGDI, ControlLineoutInternalCDVolume);
} // SBPROResetADCHardware()
VOID Set3BitVolume(PGLOBAL_DEVICE_INFO pGDI, UCHAR Register, USHORT Left, USHORT Right)
{
UCHAR bLeft, bRight;
bLeft = VolLinearToLog(Left);
if (bLeft > 0x07) {
bLeft = 0x07;
}
bRight = VolLinearToLog(Right);
if (bRight > 0x07) {
bRight = 0x07;
}
dspWriteMixer(pGDI, Register,
(UCHAR)(((0x07 - bLeft) << 5) | ((0x07 - bRight) << 1)));
}
//--------------------------------------------------------------------------
//
// MMRESULT SBPROSetADCHardware
//
// Description:
// Sets the ADC hardware per selected wave-in device
// control settings.
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
//
// Return nothing
//
//--------------------------------------------------------------------------
VOID SBPROSetADCHardware(PGLOBAL_DEVICE_INFO pGDI)
{
UCHAR bSource;
UCHAR bNumStepsL, bNumStepsR, bGainL, bGainR, bValue ;
DWORD dwDest, dwAGCControlID, dwMixerControlID,
dwGainControlID, dwVolControlID ;
UINT i ;
dprintf3(( "SBPROSetADCHardware" )) ;
bSource = 0xFF;
if (WAVE_IN_ACTIVE(&pGDI->WaveInfo)) {
if (MixerLineSelected(&pGDI->LocalMixerData, ControlWaveInMux, DestWaveInSourceAux)) {
bSource = 0x06;
Set3BitVolume(
pGDI,
DSP_MIX_LINEVOLIDX,
pGDI->LocalMixerData.ControlInfo[ControlWaveInAuxVolume].Data.v[0].u,
pGDI->LocalMixerData.ControlInfo[ControlWaveInAuxVolume].Data.v[1].u);
} else
if (MixerLineSelected(&pGDI->LocalMixerData, ControlWaveInMux, DestWaveInSourceMic)) {
bSource = 0x00;
//
// No volume to set
//
} else
if (MixerLineSelected(&pGDI->LocalMixerData, ControlWaveInMux, DestWaveInSourceInternal)) {
bSource = 0x02;
Set3BitVolume(
pGDI,
DSP_MIX_CDVOLIDX,
pGDI->LocalMixerData.ControlInfo[ControlWaveInInternalCDVolume].Data.v[0].u,
pGDI->LocalMixerData.ControlInfo[ControlWaveInInternalCDVolume].Data.v[1].u);
}
} else {
if (VOICE_IN_ACTIVE(&pGDI->WaveInfo)) {
if (pGDI->LocalMixerData.ControlInfo[ControlVoiceInMux].Data.v[0].u ==
MUXINPUT_AUX1) {
bSource = 0x06;
Set3BitVolume(
pGDI,
DSP_MIX_LINEVOLIDX,
pGDI->LocalMixerData.ControlInfo[ControlWaveInAuxVolume].Data.v[0].u,
pGDI->LocalMixerData.ControlInfo[ControlWaveInAuxVolume].Data.v[1].u);
} else {
bSource = 0x00;
}
} else {
//
// Nothing to set
//
return;
}
}
ASSERT(bSource != 0xFF);
//
// Select input source
//
{
UCHAR InputSettingRegister;
InputSettingRegister = dspReadMixer(pGDI, INPUT_SETTING_REG);
InputSettingRegister &= ~0x06;
dspWriteMixer(pGDI, INPUT_SETTING_REG,
(UCHAR)(InputSettingRegister | bSource));
}
} // SBPROSetADCHardware()
//--------------------------------------------------------------------------
//
// MMRESULT SBPROSetMixerSources
//
// Description:
// Sets the mixer sources based on values stored during
// MxdSetControlDetails(). Does not update ADC hardware
// unless the associated destination is active.
//
// Parameters:
// PGLOBAL_DEVICE_INFO pGDI
// Global device data
//
// ULONG ControlId
// Id of the control
//
// Return Value:
// TRUE
//------------------------------------------------------------------------
BOOLEAN SBPROSetSources
(
PGLOBAL_DEVICE_INFO pGDI,
ULONG ControlId
)
{
switch (ControlId)
{
case ControlWaveInMux:
case ControlVoiceInMux:
// Don't touch if the hardware is not active...
// (SBPROSetADCHardware checks this)
SBPROSetADCHardware(pGDI);
break ;
default:
// Shouldn't get here...
ASSERT(FALSE);
break;
}
return TRUE;
} // SBPROSetMixerSources()