|
|
// File: audioctl.cpp
#include "precomp.h"
#include "resource.h"
#include "audioctl.h"
#include "mixer.h"
#include "confpolicies.h"
CAudioControl::CAudioControl(HWND hwnd) : m_pRecMixer(NULL), m_pSpkMixer(NULL), m_fMicMuted(FALSE), m_fSpkMuted(FALSE), m_pChannelMic(NULL), m_pChannelSpk(NULL), m_pAudioEvent(NULL), m_dwRecordDevice(0), m_dwPlaybackDevice(0), m_dwSilenceLevel(DEFAULT_MICROPHONE_SENSITIVITY * 10), m_hwndParent(hwnd) { m_dwMicVolume.leftVolume = 0xFFFFFFFF, m_dwMicVolume.rightVolume = 0xFFFFFFFF; m_dwSpkVolume.leftVolume = 0xFFFFFFFF; m_dwSpkVolume.rightVolume = 0xFFFFFFFF; m_dwSpkVolumeOld.leftVolume = 0xFFFFFFFF; m_dwSpkVolumeOld.rightVolume = 0xFFFFFFFF;
LoadSettings(); OnDeviceChanged(); OnAGC_Changed(); OnSilenceLevelChanged(); }
CAudioControl::~CAudioControl() { SaveSettings();
// restore speaker volume
if (m_pSpkMixer && (m_dwSpkVolumeOld.leftVolume <= 0x0000ffff || m_dwSpkVolumeOld.rightVolume <= 0x0000ffff)) { m_pSpkMixer->SetVolume(&m_dwSpkVolumeOld); }
delete m_pRecMixer; delete m_pSpkMixer;
if (NULL != m_pChannelMic) { m_pChannelMic->Release(); } if (NULL != m_pChannelSpk) { m_pChannelSpk->Release(); } }
/****************************************************************************
* * CLASS: CAudioControl * * MEMBER: OnChannelChanged() * * PURPOSE: Tracks audio channel changes * ****************************************************************************/
void CAudioControl::OnChannelChanged(NM_CHANNEL_NOTIFY uNotify, INmChannel *pChannel) { INmChannelAudio* pChannelAudio; if (SUCCEEDED(pChannel->QueryInterface(IID_INmChannelAudio, (void**)&pChannelAudio))) { if (S_OK == pChannelAudio->IsActive()) { if (S_OK == pChannelAudio->IsIncoming()) { if (NULL == m_pChannelSpk) { m_pChannelSpk = pChannelAudio; m_pChannelSpk->AddRef(); m_pChannelSpk->SetProperty(NM_AUDPROP_PAUSE, m_fSpkMuted); m_pChannelSpk->SetProperty(NM_AUDPROP_WAVE_DEVICE, m_dwPlaybackDevice); } } else { if (NULL == m_pChannelMic) { m_pChannelMic = pChannelAudio; m_pChannelMic->AddRef(); m_pChannelMic->SetProperty(NM_AUDPROP_PAUSE, m_fMicMuted); m_pChannelMic->SetProperty(NM_AUDPROP_LEVEL, m_dwSilenceLevel); m_pChannelMic->SetProperty(NM_AUDPROP_WAVE_DEVICE, m_dwRecordDevice); m_pChannelMic->SetProperty(NM_AUDPROP_AUTOMIX, m_fAutoMix); } } } else { if (S_OK == pChannelAudio->IsIncoming()) { // were done with the speaker channel
if (pChannelAudio == m_pChannelSpk) { m_pChannelSpk->Release(); m_pChannelSpk = NULL; } } else { // were done with the speaker channel
if (pChannelAudio == m_pChannelMic) { m_pChannelMic->Release(); m_pChannelMic = NULL; } } } pChannelAudio->Release(); } }
/****************************************************************************
* * CLASS: CAudioControl * * MEMBER: RefreshMixer() * * PURPOSE: Refreshes all controls that are mixer dependent * ****************************************************************************/
void CAudioControl::RefreshMixer() { if (NULL != m_pSpkMixer) { MIXVOLUME dwVol; BOOL fValid; fValid = m_pSpkMixer->GetVolume(&dwVol);
if (fValid && (dwVol.leftVolume != m_dwSpkVolume.leftVolume || dwVol.rightVolume != m_dwSpkVolume.rightVolume)) { m_dwSpkVolume.leftVolume = dwVol.leftVolume; m_dwSpkVolume.rightVolume = dwVol.rightVolume;
if (NULL != m_pAudioEvent) { m_pAudioEvent->OnLevelChange(TRUE /* fSpeaker */, max(m_dwSpkVolume.leftVolume , m_dwSpkVolume.rightVolume)); } } } if (NULL != m_pRecMixer) { BOOL fChanged = FALSE; MIXVOLUME dwMainVol = {0,0}; BOOL fValidMain = m_pRecMixer->GetMainVolume(&dwMainVol); MIXVOLUME dwMicVol = {0,0}; BOOL fValidMic = m_pRecMixer->GetSubVolume(&dwMicVol); if (fValidMain && (m_dwMicVolume.leftVolume != dwMainVol.leftVolume || m_dwMicVolume.rightVolume != dwMainVol.rightVolume)) { m_dwMicVolume.leftVolume = dwMainVol.leftVolume; m_dwMicVolume.rightVolume = dwMainVol.rightVolume;
// Force the mic vol to equal the main vol
SetRecorderVolume(&dwMainVol); fChanged = TRUE; } else if (fValidMic && (m_dwMicVolume.leftVolume != dwMicVol.leftVolume || m_dwMicVolume.rightVolume != dwMicVol.rightVolume)) { m_dwMicVolume.leftVolume = dwMicVol.leftVolume; m_dwMicVolume.rightVolume = dwMicVol.rightVolume;
// Force the main vol to equal the mic vol
SetRecorderVolume(&dwMicVol); fChanged = TRUE; }
if (fChanged) { if (NULL != m_pAudioEvent) { m_pAudioEvent->OnLevelChange(FALSE /* fSpeaker */, max(m_dwMicVolume.leftVolume , m_dwMicVolume.rightVolume)); } } } }
/****************************************************************************
* * CLASS: CAudioControl * * MEMBER: MuteAudio(BOOL fSpeaker, BOOL fMute) * * PURPOSE: Internal routine to mute an audio device * ****************************************************************************/
VOID CAudioControl::MuteAudio(BOOL fSpeaker, BOOL fMute) { INmChannelAudio *pChannel; if (fSpeaker) { m_fSpkMuted = fMute; pChannel = m_pChannelSpk; } else { m_fMicMuted = fMute; pChannel = m_pChannelMic; }
if (NULL != pChannel) { pChannel->SetProperty(NM_AUDPROP_PAUSE, fMute); }
if (NULL != m_pAudioEvent) { m_pAudioEvent->OnMuteChange(fSpeaker, fMute); } }
/****************************************************************************
* * CLASS: CAudioControl * * MEMBER: GetAudioSignalLevel(BOOL fSpeaker) * * PURPOSE: Internal routine to get the audio signal level * ****************************************************************************/
DWORD CAudioControl::GetAudioSignalLevel(BOOL fSpeaker) { DWORD_PTR dwLevel = 0; INmChannelAudio *pChannel = fSpeaker ? m_pChannelSpk : m_pChannelMic;
if (NULL != pChannel) { pChannel->GetProperty(NM_AUDPROP_LEVEL, &dwLevel); }
return (DWORD)dwLevel; }
BOOL CAudioControl::CanSetRecorderVolume() { if (NULL != m_pRecMixer) { return m_pRecMixer->CanSetVolume(); } return FALSE; }
BOOL CAudioControl::CanSetSpeakerVolume() { if (NULL != m_pSpkMixer) { return m_pSpkMixer->CanSetVolume(); } return FALSE; }
void CAudioControl::SetRecorderVolume(MIXVOLUME * pdwVolume) { if (NULL != m_pRecMixer) { m_pRecMixer->SetVolume(pdwVolume); } }
void CAudioControl::SetSpeakerVolume(MIXVOLUME * pdwVolume) { if (NULL != m_pSpkMixer) { m_pSpkMixer->SetVolume(pdwVolume); } }
void CAudioControl::GetRecorderVolume(MIXVOLUME * pdwVolume) { if (NULL != m_pRecMixer) { m_pRecMixer->GetVolume(pdwVolume); } }
void CAudioControl::GetSpeakerVolume(MIXVOLUME * pdwVolume) { if (NULL != m_pSpkMixer) { m_pSpkMixer->GetVolume(pdwVolume); } }
void CAudioControl::SetRecorderVolume(DWORD dwVolume) { MIXVOLUME mixVol; MIXVOLUME mixNewVol;
GetRecorderVolume(&mixVol);
NewMixVolume(&mixNewVol, mixVol, dwVolume); SetRecorderVolume(&mixNewVol); }
void CAudioControl::SetSpeakerVolume(DWORD dwVolume) { MIXVOLUME mixVol; MIXVOLUME mixNewVol;
GetSpeakerVolume(&mixVol);
NewMixVolume(&mixNewVol, mixVol, dwVolume); SetSpeakerVolume(&mixNewVol);
}
void CAudioControl::OnDeviceChanged() { MIXVOLUME dwMicVolume; DWORD dwNewPlaybackDevice;
RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
dwNewPlaybackDevice = re.GetNumber(REGVAL_WAVEOUTDEVICEID, 0);
// restore the speaker setting before changing to the new device
// verify that we aren't changing to the same device
if (m_pSpkMixer && (m_dwSpkVolumeOld.leftVolume <= 0x0000ffff || m_dwSpkVolumeOld.rightVolume <= 0x0000ffff) && (m_dwPlaybackDevice != dwNewPlaybackDevice) ) { m_pSpkMixer->SetVolume(&m_dwSpkVolumeOld); }
// Initialize the proper record/playback devices:
delete m_pRecMixer; m_dwRecordDevice = re.GetNumber(REGVAL_WAVEINDEVICEID, 0); m_pRecMixer = CMixerDevice::GetMixerForWaveDevice( m_hwndParent, m_dwRecordDevice, MIXER_OBJECTF_WAVEIN);
delete m_pSpkMixer; m_dwPlaybackDevice = dwNewPlaybackDevice; m_pSpkMixer = CMixerDevice::GetMixerForWaveDevice( m_hwndParent, m_dwPlaybackDevice, MIXER_OBJECTF_WAVEOUT);
if (NULL != m_pChannelMic) { m_pChannelMic->SetProperty(NM_AUDPROP_WAVE_DEVICE, m_dwRecordDevice); }
if (NULL != m_pChannelSpk) { m_pChannelSpk->SetProperty(NM_AUDPROP_WAVE_DEVICE, m_dwPlaybackDevice); }
// restore the microphone setting from whatever it was in the tuning wizard
if (m_pRecMixer) { dwMicVolume.leftVolume = dwMicVolume.rightVolume = re.GetNumber(REGVAL_CALIBRATEDVOL, 0x00ff); m_pRecMixer->SetVolume(&dwMicVolume); }
// remember the old speaker volume
if (m_pSpkMixer) { m_pSpkMixer->GetVolume(&m_dwSpkVolumeOld); }
RefreshMixer(); }
void CAudioControl::OnAGC_Changed() { RegEntry reAudio( AUDIO_KEY, HKEY_CURRENT_USER );
BOOL fAgc = ( reAudio.GetNumber(REGVAL_AUTOGAIN,AUTOGAIN_ENABLED) == AUTOGAIN_ENABLED );
m_fAutoMix = (reAudio.GetNumber(REGVAL_AUTOMIX, AUTOMIX_ENABLED) == AUTOMIX_ENABLED);
if (NULL != m_pRecMixer) { m_pRecMixer->SetAGC(fAgc); }
if (NULL != m_pChannelMic) { m_pChannelMic->SetProperty(NM_AUDPROP_AUTOMIX, m_fAutoMix); } }
void CAudioControl::OnSilenceLevelChanged() { RegEntry reAudio( AUDIO_KEY, HKEY_CURRENT_USER );
if (MICROPHONE_AUTO_NO == reAudio.GetNumber(REGVAL_MICROPHONE_AUTO, MICROPHONE_AUTO_YES)) { // Use "manual" mode:
// BUGBUG - there is a mismatch in terminology between
// "sensitivity" and "threshhold", which reverses the
// sense of this value. A low threshhold implies a high
// sensitivity, etc.
// Reverse the sense of this value before setting the
// Nac value, and resolve the terminology problem later.
// PROP_SILENCE_LEVEL property is in units of 0.1%, so scale it.
m_dwSilenceLevel = (MAX_MICROPHONE_SENSITIVITY - reAudio.GetNumber(REGVAL_MICROPHONE_SENSITIVITY, DEFAULT_MICROPHONE_SENSITIVITY))*10; } else { // Use "automatic" mode: This is actually controlled by
// PROP_SILENCE_LEVEL. If at maximum (100%), then it is
// in "automatic" mode
m_dwSilenceLevel = 100*10; // remember units are 0.1%
}
if (NULL != m_pChannelMic) { m_pChannelMic->SetProperty(NM_AUDPROP_LEVEL, m_dwSilenceLevel); } }
BOOL CAudioControl::LoadSettings() { RegEntry reAudio( AUDIO_KEY, HKEY_CURRENT_USER );
m_fSpkMuted = reAudio.GetNumber(REGVAL_SPKMUTE, FALSE); m_fMicMuted = reAudio.GetNumber(REGVAL_RECMUTE, FALSE);
return TRUE; }
BOOL CAudioControl::SaveSettings() { RegEntry reAudio( AUDIO_KEY, HKEY_CURRENT_USER ); reAudio.SetValue(REGVAL_SPKMUTE, m_fSpkMuted); reAudio.SetValue(REGVAL_RECMUTE, m_fMicMuted);
//
// Check if the microphone got changed during this section
//
if(m_pRecMixer) { MIXVOLUME dwMicVol = {0,0}; m_pRecMixer->GetVolume(&dwMicVol);
DWORD oldVolume = reAudio.GetNumber(REGVAL_CALIBRATEDVOL, 0x00ff); DWORD newVolume = max(dwMicVol.leftVolume,dwMicVol.rightVolume); if(oldVolume != newVolume) { reAudio.SetValue(REGVAL_CALIBRATEDVOL, newVolume); } }
return TRUE; }
HRESULT CAudioControl::SetProperty(BOOL fSpeaker, NM_AUDPROP uID, ULONG_PTR uValue) { INmChannelAudio *pChannel = fSpeaker ? m_pChannelSpk : m_pChannelMic; if (NULL != pChannel) { return(pChannel->SetProperty(uID, uValue)); }
return(E_UNEXPECTED); }
HRESULT CAudioControl::GetProperty(BOOL fSpeaker, NM_AUDPROP uID, ULONG_PTR *puValue) { INmChannelAudio *pChannel = fSpeaker ? m_pChannelSpk : m_pChannelMic; if (NULL != pChannel) { return(pChannel->GetProperty(uID, puValue)); }
return(E_UNEXPECTED); }
|