2479 lines
64 KiB
C++
2479 lines
64 KiB
C++
// File: calib.cpp
|
||
|
||
#include "precomp.h"
|
||
#include "resource.h"
|
||
#include "WaveDev.h"
|
||
#include "dstest.h"
|
||
|
||
#include "avdefs.h"
|
||
#include <mmsystem.h>
|
||
#include <mixer.h>
|
||
#include <mperror.h>
|
||
#include <iacapapi.h>
|
||
#include <sehcall.h>
|
||
|
||
// Local includes
|
||
#include "ConfCpl.h"
|
||
#include "conf.h"
|
||
|
||
// Defined in wizard.cpp
|
||
extern UINT_PTR GetPageBeforeAudioWiz();
|
||
|
||
|
||
// move somewhere else
|
||
#define MAXNUMPAGES_INCALIBWIZ 7
|
||
#define WAVEDEVICE_OPENFAILED -1
|
||
#define MAXSTRINGSIZE 256
|
||
#define READFROM_REGISTRY -1
|
||
|
||
#define AUDIOWIZ_WARNING 1
|
||
#define AUDIOWIZ_ERROR 2
|
||
|
||
|
||
#define CALIB_CHECK 1
|
||
#define CALIB_PREPARE 2
|
||
|
||
#define CALIBERR_NO_MIXERS 1
|
||
#define CALIBERR_CANT_OPEN_WAVE_DEV 2
|
||
#define CALIBERR_CANT_SET_VOLUME 3
|
||
#define CALIBERR_USER_CANCEL 4
|
||
#define CALIBERR_MIXER_ERROR 6
|
||
#define CALIBERR_NO_MICROPHONE 7
|
||
#define CALIBERR_DEVICE_ERROR 8
|
||
|
||
|
||
#define ATW_PLAYFILE_SOUND TEXT("TestSnd.Wav")
|
||
|
||
|
||
#define CLIPPINGVOL 0x6000
|
||
#define DECREMENT_AMOUNT 0x800
|
||
#define DECREMENT_AMOUNT_LARGE 0x1200
|
||
#define SILENCE_THRESHOLD 0x800
|
||
// trackbar sets volume range from 0-65535, but only has 100 steps.
|
||
#define TB_VOL_INCREMENT 655
|
||
#define ATW_MSG_LENGTH 256
|
||
|
||
#define MIXER_VOLUME_MAX 0x0000ffff
|
||
#define MIXER_VOLUME_UNINITIALIZED 0xffffffff
|
||
|
||
#define WM_AUDIO_CLIPPING (WM_USER+21)
|
||
#define WM_AUDIOTHREAD_STOP (WM_USER+22)
|
||
#define WM_AUDIOTHREAD_ERROR (WM_USER+23)
|
||
#define WM_AUDIOTHREAD_SOUND (WM_USER+24)
|
||
|
||
// vu meter
|
||
#define RECTANGLE_WIDTH 10
|
||
#define RECTANGLE_LEADING 1
|
||
#define MAX_VOLUME 32768
|
||
#define MAX_VOLUME_NORMALIZED 256
|
||
|
||
#define SHABS(x) (((x) > 0) ? (x) : (WORD)(-(x)))
|
||
|
||
typedef struct _power_struct
|
||
{
|
||
DWORD dwMin;
|
||
DWORD dwMax;
|
||
DWORD dwAvg;
|
||
LONG lDcComponent;
|
||
} AUDIO_POWER;
|
||
|
||
#define SAMPLE_SIZE 2 // 16 bit samples
|
||
|
||
typedef struct _ERRWIZINFO{
|
||
UINT uType;
|
||
UINT uButtonOptions;
|
||
UINT uNextWizId;
|
||
UINT uBackWizId;
|
||
UINT uErrTitleId;
|
||
UINT uErrTextId;
|
||
}ERRWIZINFO, *PERRWIZINFO;
|
||
|
||
|
||
typedef struct _calib_wavein
|
||
{
|
||
HWND hVUMeter;
|
||
DWORD nErrorTextId;
|
||
HWND hDlg;
|
||
UINT uWaveInDevId;
|
||
HANDLE hEvent; // signal to parent after creating msg queue
|
||
} CALIB_DISPLAY, *PCALIBDISPLAY;
|
||
|
||
|
||
typedef struct _AUDIOWIZINFO{
|
||
UINT uFlags;
|
||
UINT uOptions;
|
||
UINT uWaveInDevId;
|
||
UINT uWaveOutDevId;
|
||
BOOL iSetAgc;
|
||
UINT uChanged; //set in the wizard.
|
||
UINT uCalibratedVol;
|
||
UINT uSpeakerVol;
|
||
UINT uSoundCardCaps;
|
||
UINT uTypBandWidth;
|
||
TCHAR szWaveInDevName[MAXPNAMELEN];
|
||
TCHAR szWaveOutDevName[MAXPNAMELEN];
|
||
MIXVOLUME uPreCalibMainVol; // record volume
|
||
MIXVOLUME uPreCalibSubVol; // microphone volume
|
||
MIXVOLUME uPreCalibSpkVol; // speaker/wave volume
|
||
UINT uOldWaveInDevId;
|
||
UINT uOldWaveOutDevId;
|
||
TCHAR szOldWaveInDevName[MAXPNAMELEN];
|
||
TCHAR szOldWaveOutDevName[MAXPNAMELEN];
|
||
ERRWIZINFO ErrWizInfo;
|
||
|
||
DWORD dwWizButtons;
|
||
}AUDIOWIZINFO, *PAUDIOWIZINFO;
|
||
|
||
|
||
|
||
class WaveBufferList
|
||
{
|
||
BYTE *m_aBytes;
|
||
|
||
DWORD m_dwBuffers;
|
||
DWORD m_dwSize;
|
||
|
||
public:
|
||
WaveBufferList(DWORD dwBuffers, DWORD dwSize);
|
||
~WaveBufferList();
|
||
BYTE *GetBuffer(DWORD dwIndex);
|
||
};
|
||
|
||
|
||
|
||
WaveBufferList::WaveBufferList(DWORD dwBuffers, DWORD dwSize) :
|
||
m_aBytes(NULL),
|
||
m_dwBuffers(dwBuffers),
|
||
m_dwSize(dwSize)
|
||
{
|
||
if ((m_dwBuffers > 0) && (m_dwSize > 0))
|
||
{
|
||
m_aBytes = new BYTE[m_dwBuffers*m_dwSize];
|
||
}
|
||
}
|
||
|
||
|
||
BYTE *WaveBufferList::GetBuffer(DWORD dwIndex)
|
||
{
|
||
if ((dwIndex < m_dwBuffers) && (m_aBytes))
|
||
{
|
||
return m_aBytes + dwIndex*m_dwSize;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
WaveBufferList::~WaveBufferList()
|
||
{
|
||
if (m_aBytes)
|
||
delete [] m_aBytes;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//------------------------ Prototype Definitions -------------------------
|
||
BOOL GetAudioWizardPages(UINT uOptions, UINT uDevId,
|
||
LPPROPSHEETPAGE *plpPropSheetPages, LPUINT lpuNumPages);
|
||
void ReleaseAudioWizardPages(LPPROPSHEETPAGE lpPropSheetPages, PWIZCONFIG pWizConfig,
|
||
PAUDIOWIZOUTPUT pAudioWizOut);
|
||
INT_PTR CallAudioCalibWizard(HWND hwndOwner, UINT uOptions,
|
||
UINT uDevId,PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc);
|
||
|
||
static INT_PTR IntCreateAudioCalibWizard(HWND hwndOwner, UINT uOptions, UINT uDevId,
|
||
PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc);
|
||
|
||
INT_PTR APIENTRY DetSoundCardWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibWiz0( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibWiz1( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibWiz2( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibWiz3( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibWiz4( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
INT_PTR APIENTRY AudioCalibErrWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||
|
||
static void SaveAudioWizChanges(PAUDIOWIZINFO pawInfo);
|
||
static UINT GetSoundCardCaps(UINT uWaveInDevId,UINT uWaveOutDevId, HWND hwnd);
|
||
static UINT CheckForFullDuplex(UINT uWaveInDevId,UINT uWaveOutDevId);
|
||
static UINT CheckForAgc(UINT uWaveInDevId);
|
||
static UINT GetWaveDeviceFromWaveMapper(UINT uNumWaveDevId, UINT uInOrOut);
|
||
static UINT CheckForWaveDeviceSupport(UINT uWaveDevId, UINT uInOrOut);
|
||
|
||
static void ProcessCalibError(UINT uCalibErr, PAUDIOWIZINFO pawInfo);
|
||
static DWORD ComputePower(SHORT *wBuffer, DWORD dwNumSamples, AUDIO_POWER *pAudioPower);
|
||
static BOOL StartAGC(CMixerDevice *pMixer, BOOL iSetAgc, UINT uSoundCardCaps);
|
||
static void PaintVUMeter (HWND hwnd, DWORD dwVolume);
|
||
|
||
static DWORD CALLBACK CalibrateTalking(PVOID);
|
||
BOOL IntGetAudioWizardPages(UINT uOptions, UINT uDevId,
|
||
LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig,
|
||
LPUINT lpuNumPages, INT iSetAgc);
|
||
|
||
///////////////////////
|
||
|
||
static const BYTE g_VUTable[] = {
|
||
0, 1, 2, 3, 4, 5, 6, 7,
|
||
8, 23, 30, 35, 39, 43, 46, 49,
|
||
52, 55, 57, 60, 62, 64, 66, 68,
|
||
70, 72, 74, 76, 78, 80, 81, 83,
|
||
85, 86, 88, 89, 91, 92, 94, 95,
|
||
97, 98, 99, 101, 102, 103, 105, 106,
|
||
107, 108, 110, 111, 112, 113, 114, 115,
|
||
117, 118, 119, 120, 121, 122, 123, 124,
|
||
125, 126, 127, 128, 129, 130, 132, 132,
|
||
133, 134, 135, 136, 137, 138, 139, 140,
|
||
141, 142, 143, 144, 145, 146, 147, 147,
|
||
148, 149, 150, 151, 152, 153, 154, 154,
|
||
155, 156, 157, 158, 159, 159, 160, 161,
|
||
162, 163, 163, 164, 165, 166, 167, 167,
|
||
168, 169, 170, 170, 171, 172, 173, 173,
|
||
174, 175, 176, 176, 177, 178, 179, 179,
|
||
180, 181, 181, 182, 183, 184, 184, 185,
|
||
186, 186, 187, 188, 188, 189, 190, 190,
|
||
191, 192, 192, 193, 194, 194, 195, 196,
|
||
196, 197, 198, 198, 199, 200, 200, 201,
|
||
202, 202, 203, 204, 204, 205, 205, 206,
|
||
207, 207, 208, 209, 209, 210, 210, 211,
|
||
212, 212, 213, 213, 214, 215, 215, 216,
|
||
216, 217, 218, 218, 219, 219, 220, 221,
|
||
221, 222, 222, 223, 223, 224, 225, 225,
|
||
226, 226, 227, 227, 228, 229, 229, 230,
|
||
230, 231, 231, 232, 232, 233, 234, 234,
|
||
235, 235, 236, 236, 237, 237, 238, 238,
|
||
239, 239, 240, 241, 241, 242, 242, 243,
|
||
243, 244, 244, 245, 245, 246, 246, 247,
|
||
247, 248, 248, 249, 249, 250, 250, 251,
|
||
251, 252, 252, 253, 253, 254, 254, 255
|
||
};
|
||
|
||
|
||
//functions
|
||
BOOL GetAudioWizardPages(UINT uOptions, UINT uDevId,
|
||
LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig, LPUINT lpuNumPages)
|
||
{
|
||
return IntGetAudioWizardPages(uOptions, uDevId,
|
||
plpPropSheetPages, plpWizConfig,
|
||
lpuNumPages, READFROM_REGISTRY);
|
||
}
|
||
|
||
BOOL IntGetAudioWizardPages(UINT uOptions, UINT uDevId,
|
||
LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig,
|
||
LPUINT lpuNumPages, INT iSetAgc)
|
||
{
|
||
LPPROPSHEETPAGE psp;
|
||
UINT uNumPages = 0;
|
||
PWIZCONFIG pWizConfig;
|
||
PAUDIOWIZINFO pawInfo;
|
||
LPSTR szTemp;
|
||
RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
|
||
|
||
*plpPropSheetPages = NULL;
|
||
*plpWizConfig = NULL;
|
||
|
||
psp = (LPPROPSHEETPAGE) LocalAlloc(LPTR, MAXNUMPAGES_INCALIBWIZ * sizeof(PROPSHEETPAGE));
|
||
if (NULL == psp)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
pWizConfig = (PWIZCONFIG) LocalAlloc(LPTR, sizeof(AUDIOWIZINFO) + sizeof(WIZCONFIG));
|
||
if (NULL == pWizConfig)
|
||
{
|
||
LocalFree(psp);
|
||
return FALSE;
|
||
}
|
||
pWizConfig->fCancel = FALSE;
|
||
pWizConfig->uFlags = HIWORD(uOptions);
|
||
pWizConfig->dwCustomDataSize = sizeof(AUDIOWIZINFO);
|
||
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
pawInfo->uOptions = LOWORD(uOptions);
|
||
pawInfo->uWaveInDevId = uDevId;
|
||
pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
|
||
pawInfo->iSetAgc = iSetAgc;
|
||
|
||
pawInfo->uOldWaveInDevId = re.GetNumber(REGVAL_WAVEINDEVICEID,WAVE_MAPPER);
|
||
szTemp = re.GetString(REGVAL_WAVEINDEVICENAME);
|
||
if (szTemp)
|
||
lstrcpy(pawInfo->szOldWaveInDevName, szTemp);
|
||
|
||
pawInfo->uOldWaveOutDevId = re.GetNumber(REGVAL_WAVEOUTDEVICEID,WAVE_MAPPER);
|
||
szTemp = re.GetString(REGVAL_WAVEOUTDEVICENAME);
|
||
if (szTemp)
|
||
lstrcpy(pawInfo->szOldWaveOutDevName, szTemp);
|
||
|
||
pawInfo->uCalibratedVol = re.GetNumber(REGVAL_LASTCALIBRATEDVOL, 0xFFFFFFFF);
|
||
|
||
pawInfo->uPreCalibSpkVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // playback
|
||
pawInfo->uPreCalibSpkVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // playback
|
||
|
||
pawInfo->uPreCalibMainVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // recording
|
||
pawInfo->uPreCalibMainVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // recording
|
||
|
||
pawInfo->uPreCalibSubVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // microphone
|
||
pawInfo->uPreCalibSubVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // microphone
|
||
|
||
if (!waveInGetNumDevs() || !waveOutGetNumDevs())
|
||
pawInfo->uSoundCardCaps = SOUNDCARD_NONE;
|
||
else
|
||
pawInfo->uSoundCardCaps = SOUNDCARD_PRESENT;
|
||
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_DETSOUNDCARDWIZ,
|
||
DetSoundCardWiz,(LPARAM)pWizConfig);
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ0,
|
||
AudioCalibWiz0, (LPARAM)pWizConfig);
|
||
if ((RUNDUE_CARDCHANGE == pawInfo->uOptions) ||
|
||
(RUNDUE_NEVERBEFORE == pawInfo->uOptions) ||
|
||
(RUNDUE_USERINVOKED == pawInfo->uOptions))
|
||
{
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ1,
|
||
AudioCalibWiz1,(LPARAM)pWizConfig);
|
||
}
|
||
else
|
||
{
|
||
//the old wavein and wave out device will remain
|
||
pawInfo->uWaveInDevId = pawInfo->uOldWaveInDevId;
|
||
pawInfo->uWaveOutDevId = pawInfo->uOldWaveOutDevId;
|
||
lstrcpy(pawInfo->szWaveInDevName,pawInfo->szOldWaveOutDevName);
|
||
lstrcpy(pawInfo->szWaveOutDevName,pawInfo->szOldWaveOutDevName);
|
||
}
|
||
|
||
// For each of the pages that I need, fill in a PROPSHEETPAGE structure.
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ2,
|
||
AudioCalibWiz2, (LPARAM)pWizConfig);
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ3,
|
||
AudioCalibWiz3, (LPARAM)pWizConfig);
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ4,
|
||
AudioCalibWiz4, (LPARAM)pWizConfig);
|
||
FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBERRWIZ,
|
||
AudioCalibErrWiz, (LPARAM)pWizConfig);
|
||
|
||
// The number of pages in this wizard.
|
||
*lpuNumPages = uNumPages;
|
||
*plpPropSheetPages = (LPPROPSHEETPAGE) psp;
|
||
*plpWizConfig = pWizConfig;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void ReleaseAudioWizardPages(LPPROPSHEETPAGE lpPropSheetPages,
|
||
PWIZCONFIG pWizConfig, PAUDIOWIZOUTPUT pAudioWizOut)
|
||
{
|
||
PAUDIOWIZINFO pawInfo;
|
||
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
|
||
if (pAudioWizOut)
|
||
{
|
||
pAudioWizOut->uValid = pawInfo->uChanged;//whatever is set in the wizard is valid
|
||
pAudioWizOut->uSoundCardCaps = pawInfo->uSoundCardCaps;
|
||
pAudioWizOut->uCalibratedVol = pawInfo->uCalibratedVol;
|
||
pAudioWizOut->uTypBandWidth = pawInfo->uTypBandWidth;
|
||
pAudioWizOut->uWaveInDevId = pawInfo->uWaveInDevId;
|
||
pAudioWizOut->uWaveOutDevId = pawInfo->uWaveOutDevId;
|
||
lstrcpy(pAudioWizOut->szWaveInDevName,pawInfo->szWaveInDevName);
|
||
lstrcpy(pAudioWizOut->szWaveOutDevName,pawInfo->szWaveOutDevName);
|
||
|
||
|
||
//the ui needs to read the changed values and call nac methods for
|
||
//the changes below
|
||
pAudioWizOut->uChanged = AUDIOWIZ_NOCHANGES;
|
||
if ((pawInfo->uChanged & SOUNDCARD_CHANGED) &&
|
||
((pawInfo->uWaveInDevId != pawInfo->uOldWaveInDevId) ||
|
||
(pawInfo->uWaveOutDevId != pawInfo->uOldWaveOutDevId) ||
|
||
lstrcmp(pawInfo->szWaveInDevName,pawInfo->szOldWaveInDevName) ||
|
||
lstrcmp(pawInfo->szWaveOutDevName,pawInfo->szOldWaveOutDevName)))
|
||
{
|
||
pAudioWizOut->uChanged |= SOUNDCARD_CHANGED;
|
||
pAudioWizOut->uChanged |= SOUNDCARDCAPS_CHANGED;
|
||
|
||
}
|
||
}
|
||
|
||
LocalFree(pWizConfig);
|
||
LocalFree(lpPropSheetPages);
|
||
|
||
}
|
||
|
||
INT_PTR CallAudioCalibWizard(HWND hwndOwner, UINT uOptions,
|
||
UINT uDevId,PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc)
|
||
{
|
||
//agc values are provided
|
||
return(IntCreateAudioCalibWizard(hwndOwner, uOptions, uDevId, pAudioWizOut, iSetAgc));
|
||
|
||
}
|
||
|
||
VOID CmdAudioCalibWizard(HWND hwnd)
|
||
{
|
||
AUDIOWIZOUTPUT awo;
|
||
INT_PTR nRet = IntCreateAudioCalibWizard(
|
||
hwnd,
|
||
RUNDUE_USERINVOKED,
|
||
WAVE_MAPPER,
|
||
&awo,
|
||
READFROM_REGISTRY);
|
||
|
||
if ((nRet > 0) && (awo.uChanged & SOUNDCARD_CHANGED))
|
||
{
|
||
::HandleConfSettingsChange(CSETTING_L_AUDIODEVICE);
|
||
}
|
||
}
|
||
|
||
INT_PTR IntCreateAudioCalibWizard(HWND hwndOwner, UINT uOptions,
|
||
UINT uDevId, PAUDIOWIZOUTPUT pAudioWizOut, INT iSetAgc)
|
||
{
|
||
LPPROPSHEETPAGE ppsp;
|
||
UINT uNumPages;
|
||
PWIZCONFIG pWizConfig;
|
||
|
||
if (!IntGetAudioWizardPages(uOptions, uDevId,
|
||
&ppsp, &pWizConfig, &uNumPages, iSetAgc))
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
PROPSHEETHEADER psh;
|
||
InitStruct(&psh);
|
||
|
||
// Specify that this is a wizard property sheet with no Apply Now button.
|
||
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
|
||
psh.hwndParent = hwndOwner;
|
||
|
||
// Use page captions.
|
||
ASSERT(NULL == psh.pszCaption);
|
||
ASSERT(0 == psh.nStartPage);
|
||
|
||
psh.nPages = uNumPages;
|
||
psh.ppsp = ppsp;
|
||
|
||
// Create and run the wizard.
|
||
INT_PTR iRet = PropertySheet(&psh);
|
||
|
||
ReleaseAudioWizardPages(ppsp, pWizConfig, pAudioWizOut);
|
||
|
||
return iRet;
|
||
}
|
||
|
||
void SaveAudioWizChanges(PAUDIOWIZINFO pawInfo)
|
||
{
|
||
RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
|
||
|
||
if (pawInfo->uChanged & SOUNDCARDCAPS_CHANGED)
|
||
{
|
||
re.SetValue ( REGVAL_SOUNDCARDCAPS, pawInfo->uSoundCardCaps);
|
||
re.SetValue ( REGVAL_FULLDUPLEX, ISSOUNDCARDFULLDUPLEX(pawInfo->uSoundCardCaps) ? FULLDUPLEX_ENABLED : FULLDUPLEX_DISABLED);
|
||
|
||
if (!ISDIRECTSOUNDAVAILABLE(pawInfo->uSoundCardCaps))
|
||
{
|
||
re.SetValue(REGVAL_DIRECTSOUND, (ULONG)DSOUND_USER_DISABLED);
|
||
}
|
||
}
|
||
|
||
if (pawInfo->uChanged & CALIBVOL_CHANGED)
|
||
{
|
||
re.SetValue ( REGVAL_CALIBRATEDVOL, pawInfo->uCalibratedVol);
|
||
re.SetValue ( REGVAL_LASTCALIBRATEDVOL, pawInfo->uCalibratedVol);
|
||
}
|
||
if (pawInfo->uChanged & SOUNDCARD_CHANGED)
|
||
{
|
||
re.SetValue (REGVAL_WAVEINDEVICEID, pawInfo->uWaveInDevId);
|
||
re.SetValue (REGVAL_WAVEINDEVICENAME, pawInfo->szWaveInDevName);
|
||
re.SetValue (REGVAL_WAVEOUTDEVICEID, pawInfo->uWaveOutDevId);
|
||
re.SetValue (REGVAL_WAVEOUTDEVICENAME, pawInfo->szWaveOutDevName);
|
||
}
|
||
|
||
if (pawInfo->uChanged & SPEAKERVOL_CHANGED)
|
||
{
|
||
re.SetValue (REGVAL_SPEAKERVOL, pawInfo->uSpeakerVol);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
INT_PTR APIENTRY DetSoundCardWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
|
||
switch (message) {
|
||
case WM_INITDIALOG:
|
||
// Save the PROPSHEETPAGE information.
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
if (g_fSilentWizard)
|
||
{
|
||
HideWizard(GetParent(hDlg));
|
||
}
|
||
|
||
return (TRUE);
|
||
|
||
case WM_NOTIFY:
|
||
switch (((NMHDR FAR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
{
|
||
if (pawInfo->uSoundCardCaps != SOUNDCARD_NONE)
|
||
{
|
||
// Skip this page; go to IDD_AUDIOCALIBWIZ0;
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
|
||
// Initialize the controls.
|
||
DWORD dwWizButtons = PSWIZB_FINISH;
|
||
if (pWizConfig->uFlags & STARTWITH_BACK)
|
||
dwWizButtons |= PSWIZB_BACK;
|
||
PropSheet_SetWizButtons(GetParent(hDlg), dwWizButtons );
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case PSN_WIZNEXT:
|
||
// Due to bug in ComCtl32 don't allow next
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
|
||
case PSN_WIZBACK:
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!(pWizConfig->uFlags & STARTWITH_BACK))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
UINT_PTR iPrev = GetPageBeforeAudioWiz();
|
||
ASSERT( iPrev );
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, iPrev);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
|
||
case PSN_WIZFINISH:
|
||
{
|
||
RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
|
||
re.SetValue ( REGVAL_SOUNDCARDCAPS, pawInfo->uSoundCardCaps);
|
||
break;
|
||
}
|
||
|
||
case PSN_RESET:
|
||
pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
INT_PTR APIENTRY AudioCalibWiz0( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
|
||
switch (message) {
|
||
case WM_INITDIALOG:
|
||
// Save the PROPSHEETPAGE information.
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
return TRUE;
|
||
|
||
case WM_NOTIFY:
|
||
switch (((NMHDR FAR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
{
|
||
// Initialize the controls.
|
||
DWORD dwWizButtons = PSWIZB_NEXT;
|
||
if (pWizConfig->uFlags & STARTWITH_BACK)
|
||
dwWizButtons |= PSWIZB_BACK;
|
||
PropSheet_SetWizButtons(GetParent(hDlg), dwWizButtons );
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case PSN_WIZBACK:
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!(pWizConfig->uFlags & STARTWITH_BACK))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
if (pawInfo->uSoundCardCaps != SOUNDCARD_NONE)
|
||
{
|
||
// don't go to the DetSoundCard page...
|
||
UINT_PTR iPrev = GetPageBeforeAudioWiz();
|
||
ASSERT( iPrev );
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, iPrev);
|
||
return TRUE;
|
||
}
|
||
|
||
break;
|
||
|
||
case PSN_RESET:
|
||
pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
|
||
INT_PTR APIENTRY AudioCalibWiz1( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
UINT uSoundCardCaps;
|
||
int nIndex;
|
||
HWND hwndCB;
|
||
|
||
switch (message)
|
||
{
|
||
case WM_INITDIALOG:
|
||
{
|
||
WAVEINCAPS wiCaps;
|
||
WAVEOUTCAPS woCaps;
|
||
LPSTR lpszTemp;
|
||
UINT uWaveDevId;
|
||
UINT uWaveDevRealId;
|
||
UINT uDevCnt;
|
||
UINT uCnt;
|
||
UINT uDevID;
|
||
|
||
// Save the PROPSHEETPAGE information.
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
|
||
//we come to this page only if a sound card is present.
|
||
|
||
// If we end up with WAVE_MAPPER, this means that this is the first time we run this code
|
||
pawInfo->uWaveInDevId = uWaveDevRealId = uWaveDevId = pawInfo->uOldWaveInDevId;
|
||
uDevCnt = waveInGetNumDevs();
|
||
lstrcpy(pawInfo->szWaveInDevName, lpszTemp = pawInfo->szOldWaveInDevName);
|
||
|
||
//add the device to the drop down list
|
||
hwndCB = GetDlgItem(hDlg, IDC_WAVEIN);
|
||
for (uDevID = 0, uCnt = uDevCnt; 0 != uCnt; uDevID++, uCnt--)
|
||
{
|
||
if ((waveInGetDevCaps(uDevID, &wiCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) &&
|
||
(CheckForWaveDeviceSupport(uDevID, 0)))
|
||
{
|
||
nIndex = ComboBox_AddString(hwndCB, wiCaps.szPname);
|
||
ComboBox_SetItemData(hwndCB, nIndex, uDevID);
|
||
|
||
//if a device hasnt been chosen previously, then set the default device to the
|
||
//zeroth one
|
||
if (uWaveDevId == WAVE_MAPPER)
|
||
{
|
||
if (uDevCnt <= 1)
|
||
uWaveDevRealId = uDevID;
|
||
else
|
||
if ((uWaveDevRealId == WAVE_MAPPER) && (uDevCnt == uCnt))
|
||
uWaveDevRealId = GetWaveDeviceFromWaveMapper(uCnt, 0);
|
||
if (uDevID == uWaveDevRealId)
|
||
{
|
||
ComboBox_SetCurSel(hwndCB, nIndex);
|
||
pawInfo->uWaveInDevId = uDevID;
|
||
lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((0 == nIndex) || (!lstrcmp(wiCaps.szPname, lpszTemp)))
|
||
{
|
||
ComboBox_SetCurSel(hwndCB, nIndex);
|
||
pawInfo->uWaveInDevId = uDevID;
|
||
lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// TEMPORARY 1.0 stuff because this would require too much rewrite:
|
||
// In case no device was added to the combo box, let's put the first one in
|
||
// even though we know it will never work.
|
||
if ((0 == ComboBox_GetCount(hwndCB)) || (uWaveDevRealId == WAVE_MAPPER))
|
||
{
|
||
waveInGetDevCaps(0,&wiCaps, sizeof(WAVEINCAPS));
|
||
if (0 == ComboBox_GetCount(hwndCB))
|
||
{
|
||
ComboBox_AddString(hwndCB, wiCaps.szPname);
|
||
ComboBox_SetItemData(hwndCB, 0, 0);
|
||
}
|
||
ComboBox_SetCurSel(hwndCB, 0);
|
||
pawInfo->uWaveInDevId = 0;
|
||
lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
|
||
}
|
||
|
||
// If we end up with WAVE_MAPPER, this means that this is the first time we run this code
|
||
pawInfo->uWaveOutDevId = uWaveDevRealId = uWaveDevId = pawInfo->uOldWaveOutDevId;
|
||
uDevCnt = waveOutGetNumDevs();
|
||
lstrcpy(pawInfo->szWaveOutDevName, lpszTemp = pawInfo->szOldWaveOutDevName);
|
||
|
||
//add the device to the drop down list
|
||
hwndCB = GetDlgItem(hDlg, IDC_WAVEOUT);
|
||
for (uDevID = 0, uCnt = uDevCnt; 0 != uCnt; uDevID++, uCnt--)
|
||
{
|
||
if ((waveOutGetDevCaps(uDevID, &woCaps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) &&
|
||
(CheckForWaveDeviceSupport(uDevID, 1)))
|
||
{
|
||
nIndex = ComboBox_AddString(hwndCB, woCaps.szPname);
|
||
ComboBox_SetItemData(hwndCB, nIndex, uDevID);
|
||
|
||
//if a device hasnt been chosen previously, then set the default device to the
|
||
//zeroth one
|
||
if (uWaveDevId == WAVE_MAPPER)
|
||
{
|
||
if (uDevCnt <= 1)
|
||
uWaveDevRealId = uDevID;
|
||
else
|
||
if ((uWaveDevRealId == WAVE_MAPPER) && (uDevCnt == uCnt))
|
||
uWaveDevRealId = GetWaveDeviceFromWaveMapper(uCnt, 1);
|
||
if (uDevID == uWaveDevRealId)
|
||
{
|
||
ComboBox_SetCurSel(hwndCB, nIndex);
|
||
pawInfo->uWaveOutDevId = uDevID;
|
||
lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if ((0 == nIndex) || (!lstrcmp(woCaps.szPname, lpszTemp)))
|
||
{
|
||
ComboBox_SetCurSel(hwndCB, nIndex);
|
||
pawInfo->uWaveOutDevId = uDevID;
|
||
lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// TEMPORARY 1.0 stuff because this would require too much rewrite:
|
||
// In case no device was added to the combo box, let's put the first one in
|
||
// even though we know it will never work.
|
||
if ((0 == ComboBox_GetCount(hwndCB)) || (uWaveDevRealId == WAVE_MAPPER))
|
||
{
|
||
waveOutGetDevCaps(0,&woCaps, sizeof(WAVEOUTCAPS));
|
||
if (0 == ComboBox_GetCount(hwndCB))
|
||
{
|
||
ComboBox_AddString(hwndCB, (LPARAM)woCaps.szPname);
|
||
ComboBox_SetItemData(hwndCB, 0, 0);
|
||
}
|
||
ComboBox_SetCurSel(hwndCB, 0);
|
||
pawInfo->uWaveOutDevId = 0;
|
||
lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
|
||
}
|
||
|
||
return (TRUE);
|
||
}
|
||
|
||
case WM_NOTIFY:
|
||
switch (((NMHDR FAR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
// Initialize the controls.
|
||
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if ((1 != ComboBox_GetCount(GetDlgItem(hDlg, IDC_WAVEIN))) ||
|
||
(1 != ComboBox_GetCount(GetDlgItem(hDlg, IDC_WAVEOUT))))
|
||
{
|
||
break;
|
||
}
|
||
// else fall through to next
|
||
}
|
||
|
||
case PSN_WIZNEXT:
|
||
// set settings in registry
|
||
//check the device
|
||
//get the new wavein device and its info
|
||
hwndCB = GetDlgItem(hDlg, IDC_WAVEIN);
|
||
nIndex = ComboBox_GetCurSel(hwndCB);
|
||
pawInfo->uWaveInDevId = (UINT)ComboBox_GetItemData(hwndCB, nIndex);
|
||
ComboBox_GetLBText(hwndCB, nIndex, pawInfo->szWaveInDevName);
|
||
|
||
//get the new waveout device and its info
|
||
hwndCB = GetDlgItem(hDlg, IDC_WAVEOUT);
|
||
nIndex = ComboBox_GetCurSel(hwndCB);
|
||
pawInfo->uWaveOutDevId = (UINT)ComboBox_GetItemData(hwndCB, nIndex);
|
||
ComboBox_GetLBText(hwndCB, nIndex, pawInfo->szWaveOutDevName);
|
||
|
||
uSoundCardCaps = GetSoundCardCaps(pawInfo->uWaveInDevId,pawInfo->uWaveOutDevId, hDlg);
|
||
|
||
//save it in the wizinfo struct for writing to registry
|
||
pawInfo->uSoundCardCaps = uSoundCardCaps;
|
||
|
||
pawInfo->uChanged |= SOUNDCARDCAPS_CHANGED;
|
||
pawInfo->uChanged |= SOUNDCARD_CHANGED;
|
||
|
||
if (PSN_SETACTIVE == ((NMHDR FAR *) lParam)->code)
|
||
{
|
||
// Skip this page;
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
|
||
case PSN_RESET:
|
||
{
|
||
pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
|
||
break;
|
||
}
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
// The WaveOut test page
|
||
INT_PTR WINAPI AudioCalibWiz2(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static CMixerDevice *pMixer = NULL;
|
||
static HWND hTrackBar;
|
||
DWORD dwTBPos;
|
||
MIXVOLUME dwNewVol;
|
||
static MIXVOLUME dwVol; // last set volume
|
||
BOOL fRet;
|
||
static BOOL fCanSetVolume = FALSE;
|
||
static waveOutDev *pWaveOut= NULL;
|
||
UINT uWaveOutDevId;
|
||
static PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
TCHAR szText[ATW_MSG_LENGTH];
|
||
MMRESULT mmr;
|
||
static fIsPlaying;
|
||
|
||
switch (msg)
|
||
{
|
||
case (WM_INITDIALOG):
|
||
{
|
||
pMixer = NULL;
|
||
hTrackBar = GetDlgItem(hDlg, IDC_ATW_SLIDER1);
|
||
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
|
||
break;
|
||
}
|
||
|
||
case (WM_NOTIFY):
|
||
{
|
||
switch (((NMHDR *)lParam)->code)
|
||
{
|
||
|
||
case PSN_SETACTIVE:
|
||
fIsPlaying = FALSE;
|
||
|
||
uWaveOutDevId = pawInfo->uWaveOutDevId;
|
||
|
||
pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, uWaveOutDevId, MIXER_OBJECTF_WAVEOUT);
|
||
if (pMixer)
|
||
{
|
||
SendMessage(hTrackBar, TBM_SETRANGE, TRUE, (LPARAM)MAKELONG(0, 100));
|
||
SendMessage(hTrackBar, TBM_SETTICFREQ, 10, 0);
|
||
SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 20);
|
||
SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 10);
|
||
|
||
pMixer->GetVolume(&dwVol);
|
||
fCanSetVolume = pMixer->SetVolume(&dwVol);
|
||
pMixer->UnMuteVolume();
|
||
|
||
// preserve the speaker volume so that it can be restored
|
||
// if the user presses cancel
|
||
|
||
if (pawInfo->uPreCalibSpkVol.leftVolume == MIXER_VOLUME_UNINITIALIZED)
|
||
{
|
||
pawInfo->uPreCalibSpkVol.leftVolume = dwVol.leftVolume;
|
||
}
|
||
|
||
if (pawInfo->uPreCalibSpkVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
|
||
{
|
||
pawInfo->uPreCalibSpkVol.rightVolume = dwVol.rightVolume;
|
||
}
|
||
|
||
}
|
||
else
|
||
fCanSetVolume = FALSE;
|
||
|
||
EnableWindow(GetDlgItem(hDlg, IDC_GROUP_VOLUME), fCanSetVolume);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_ATW_SLIDER1), fCanSetVolume);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_ATW_TEST), TRUE);
|
||
|
||
if (fCanSetVolume)
|
||
{
|
||
FLoadString(IDS_ATW_PLAYBACK, szText, CCHMAX(szText));
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
|
||
}
|
||
|
||
// if we can't get a mixer, then center the trackbar and disable
|
||
else
|
||
{
|
||
FLoadString(IDS_ATW_PLAYBACK_NOMIX, szText, CCHMAX(szText));
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, 50);
|
||
}
|
||
|
||
SetDlgItemText(hDlg, IDC_ATW_PLAYTEXT, szText);
|
||
SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, TEXT(""));
|
||
|
||
FLoadString(IDS_TESTBUTTON_TEXT, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
|
||
|
||
pWaveOut = new waveOutDev(uWaveOutDevId, hDlg);
|
||
if (pWaveOut == NULL)
|
||
{
|
||
ERROR_OUT(("AudioWiz2: Unable to create waveOutDev object"));
|
||
}
|
||
|
||
PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_NEXT);
|
||
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
||
return TRUE;
|
||
}
|
||
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
case PSN_WIZBACK:
|
||
case PSN_WIZFINISH:
|
||
case PSN_KILLACTIVE:
|
||
if ((fCanSetVolume) && (pMixer))
|
||
{
|
||
pMixer->GetVolume(&dwNewVol);
|
||
pawInfo->uSpeakerVol = max(dwNewVol.leftVolume , dwNewVol.rightVolume);
|
||
pawInfo->uChanged |= SPEAKERVOL_CHANGED;
|
||
}
|
||
|
||
if (pMixer)
|
||
{
|
||
delete pMixer;
|
||
pMixer = NULL;
|
||
}
|
||
|
||
if (pWaveOut)
|
||
{
|
||
delete pWaveOut;
|
||
pWaveOut = NULL;
|
||
}
|
||
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
|
||
break;
|
||
|
||
case PSN_RESET:
|
||
// psn_reset get's received even if user presses
|
||
// cancel on another dialog.
|
||
|
||
// restore speaker volume to what it was before the tuning wizard was launched
|
||
if (pawInfo->uPreCalibSpkVol.leftVolume <= MIXER_VOLUME_MAX || pawInfo->uPreCalibSpkVol.rightVolume <= MIXER_VOLUME_MAX)
|
||
{
|
||
if (pMixer == NULL)
|
||
{
|
||
pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveOutDevId, MIXER_OBJECTF_WAVEOUT);
|
||
}
|
||
if (pMixer)
|
||
{
|
||
pMixer->SetVolume(&pawInfo->uPreCalibSpkVol);
|
||
}
|
||
}
|
||
|
||
if (pMixer)
|
||
{
|
||
delete pMixer;
|
||
pMixer = NULL;
|
||
}
|
||
|
||
if (pWaveOut)
|
||
{
|
||
delete pWaveOut;
|
||
pWaveOut = NULL;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
case (WM_HSCROLL): // trackbar notification
|
||
{
|
||
dwTBPos = (DWORD)SendMessage(hTrackBar, TBM_GETPOS, 0, 0);
|
||
if (pMixer)
|
||
{
|
||
pMixer->GetVolume(&dwVol);
|
||
NewMixVolume(&dwNewVol, dwVol, (dwTBPos * TB_VOL_INCREMENT));
|
||
pMixer->SetVolume(&dwNewVol);
|
||
}
|
||
break;
|
||
}
|
||
|
||
|
||
// mixer notifications
|
||
case MM_MIXM_CONTROL_CHANGE:
|
||
case MM_MIXM_LINE_CHANGE:
|
||
{
|
||
if (pMixer)
|
||
{
|
||
|
||
fRet = pMixer->GetVolume(&dwNewVol);
|
||
|
||
if ((fRet) && (dwNewVol.leftVolume != dwVol.leftVolume || dwNewVol.rightVolume != dwVol.rightVolume))
|
||
{
|
||
dwVol = dwNewVol;
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
// when the PlayFile is done playing
|
||
case WOM_DONE:
|
||
{
|
||
if ((pWaveOut) && (fIsPlaying))
|
||
{
|
||
pWaveOut->PlayFile(ATW_PLAYFILE_SOUND);
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
|
||
case WM_COMMAND:
|
||
{
|
||
// if the device fails to open, then we
|
||
// display the error text
|
||
|
||
// if the WAV file fails to load, we simply disable the button
|
||
|
||
if (LOWORD(wParam) == IDC_BUTTON_ATW_TEST)
|
||
{
|
||
|
||
if (fIsPlaying == TRUE)
|
||
{
|
||
fIsPlaying = FALSE;
|
||
pWaveOut->Close();
|
||
FLoadString(IDS_TESTBUTTON_TEXT, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
|
||
break;
|
||
}
|
||
|
||
mmr = pWaveOut->PlayFile(ATW_PLAYFILE_SOUND);
|
||
|
||
if (mmr == MMSYSERR_ALLOCATED )
|
||
{
|
||
FLoadString(IDS_PLAYBACK_ERROR, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, szText);
|
||
}
|
||
|
||
else if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_ATW_TEST), FALSE);
|
||
FLoadString(IDS_PLAYBACK_ERROR2, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, szText);
|
||
}
|
||
|
||
else // mmr == MMSYSERR_NOERROR
|
||
{
|
||
SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, TEXT(""));
|
||
FLoadString(IDS_STOPBUTTON_TEXT, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
|
||
fIsPlaying = TRUE;
|
||
}
|
||
|
||
}
|
||
break;
|
||
}
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
// Microphone test page
|
||
INT_PTR WINAPI AudioCalibWiz3(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static HANDLE hThread = NULL;
|
||
static DWORD dwThreadID = 0;
|
||
static HANDLE hEvent = NULL;
|
||
static CMixerDevice *pMixer = NULL;
|
||
static HWND hTrackBar;
|
||
static DWORD dwMainVol;
|
||
static DWORD dwSubVol;
|
||
DWORD dwTBPos, dwNewMainVol, dwNewSubVol;
|
||
MIXVOLUME dwVol, dwNewVol;
|
||
BOOL fRet;
|
||
static BOOL fCanSetVolume=FALSE;
|
||
static CALIB_DISPLAY CalibDisplay;
|
||
static PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
static BOOL fSoundDetected;
|
||
const TCHAR *szEventName = _TEXT("CONF.EXE ATW Event Handle");
|
||
|
||
switch (msg)
|
||
{
|
||
case (WM_INITDIALOG):
|
||
{
|
||
hThread = NULL;
|
||
dwThreadID = NULL;
|
||
hTrackBar = GetDlgItem(hDlg, IDC_ATW_SLIDER2);
|
||
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
|
||
break;
|
||
}
|
||
|
||
case (WM_NOTIFY):
|
||
{
|
||
switch (((NMHDR *)lParam)->code)
|
||
{
|
||
|
||
case PSN_SETACTIVE:
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
||
return TRUE;
|
||
}
|
||
|
||
fCanSetVolume = TRUE;
|
||
fSoundDetected = FALSE;
|
||
|
||
pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveInDevId, MIXER_OBJECTF_WAVEIN);
|
||
if (pMixer)
|
||
{
|
||
SendMessage(hTrackBar, TBM_SETRANGE, TRUE, (LPARAM)MAKELONG(0, 100));
|
||
SendMessage(hTrackBar, TBM_SETTICFREQ, 10, 0);
|
||
SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 20);
|
||
SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 10);
|
||
|
||
// remember the volume in case the user presses cancel
|
||
if (pawInfo->uPreCalibMainVol.leftVolume == MIXER_VOLUME_UNINITIALIZED ||
|
||
pawInfo->uPreCalibMainVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
|
||
{
|
||
pMixer->GetMainVolume(&(pawInfo->uPreCalibMainVol));
|
||
}
|
||
if (pawInfo->uPreCalibSubVol.leftVolume == MIXER_VOLUME_UNINITIALIZED ||
|
||
pawInfo->uPreCalibSubVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
|
||
{
|
||
pMixer->GetSubVolume(&(pawInfo->uPreCalibSubVol));
|
||
}
|
||
|
||
MIXVOLUME mixVol = {-1, -1};
|
||
pMixer->GetVolume(&mixVol);
|
||
fCanSetVolume = pMixer->SetVolume(&mixVol);
|
||
dwSubVol = dwMainVol= 0xffff;
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, dwMainVol/TB_VOL_INCREMENT);
|
||
pMixer->EnableMicrophone();
|
||
pMixer->UnMuteVolume();
|
||
|
||
StartAGC(pMixer, pawInfo->iSetAgc, pawInfo->uSoundCardCaps);
|
||
}
|
||
|
||
// no mixer!
|
||
if (pMixer == NULL)
|
||
{
|
||
ProcessCalibError(CALIBERR_MIXER_ERROR, pawInfo);
|
||
}
|
||
|
||
// no microphone!
|
||
else if (fCanSetVolume == FALSE)
|
||
{
|
||
delete pMixer;
|
||
pMixer = NULL;
|
||
ProcessCalibError(CALIBERR_CANT_SET_VOLUME, pawInfo);
|
||
}
|
||
|
||
// process error
|
||
if ((pMixer == NULL) || (fCanSetVolume == FALSE))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_AUDIOCALIBERRWIZ);
|
||
return TRUE;
|
||
}
|
||
|
||
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
|
||
CalibDisplay.hDlg = hDlg;
|
||
CalibDisplay.hVUMeter = GetDlgItem(hDlg, IDC_VUMETER);
|
||
CalibDisplay.uWaveInDevId = pawInfo->uWaveInDevId;
|
||
|
||
ASSERT(hEvent == NULL);
|
||
|
||
// just create the same event twice (easier than using DuplicateHandle)
|
||
hEvent = CreateEvent(NULL, FALSE, FALSE, szEventName);
|
||
CalibDisplay.hEvent = CreateEvent(NULL, FALSE, FALSE, szEventName);
|
||
|
||
ASSERT(hThread == NULL);
|
||
hThread = NULL;
|
||
|
||
if (hEvent && (CalibDisplay.hEvent))
|
||
{
|
||
hThread = CreateThread(NULL, 0, CalibrateTalking, (LPVOID)(&CalibDisplay), 0, &dwThreadID);
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
if ((hEvent == NULL) || (CalibDisplay.hEvent == NULL))
|
||
{
|
||
ERROR_OUT(("ATW: Unable to create events for thread control!\r\n"));
|
||
}
|
||
else if (hThread == NULL)
|
||
{
|
||
ERROR_OUT(("ATW: Unable to create thread for recording loop!\r\n"));
|
||
}
|
||
#endif
|
||
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
case PSN_WIZBACK:
|
||
case PSN_WIZFINISH:
|
||
case PSN_KILLACTIVE:
|
||
if (hThread)
|
||
{
|
||
SetEvent(hEvent); // signal the thread to exit, thread will CloseHandle(hEvent)
|
||
|
||
// wait for the thread to exit, but
|
||
// but keep processing window messages
|
||
AtlWaitWithMessageLoop(hThread);
|
||
|
||
CloseHandle(hEvent);
|
||
CloseHandle(hThread);
|
||
hThread = NULL;
|
||
hEvent = NULL;
|
||
dwThreadID = 0;
|
||
}
|
||
|
||
|
||
// silent wizard get's set to max
|
||
if (g_fSilentWizard)
|
||
{
|
||
pawInfo->uChanged |= CALIBVOL_CHANGED;
|
||
pawInfo->uChanged = 0xffff;
|
||
}
|
||
|
||
else if ((fCanSetVolume) && (pMixer))
|
||
{
|
||
pawInfo->uChanged |= CALIBVOL_CHANGED;
|
||
pMixer->GetVolume(&dwVol);
|
||
pawInfo->uCalibratedVol = max (dwVol.leftVolume , dwVol.rightVolume);
|
||
}
|
||
|
||
if (pMixer)
|
||
{
|
||
delete pMixer;
|
||
pMixer = NULL;
|
||
}
|
||
|
||
// if we never got an indication back from the sound thread
|
||
// then the next page to be displayed is the "microphone" error page
|
||
// note the check for the silent wizard
|
||
if ((!g_fSilentWizard) && (fSoundDetected == FALSE) && (((NMHDR *)lParam)->code == PSN_WIZNEXT))
|
||
{
|
||
ProcessCalibError(CALIBERR_NO_MICROPHONE, pawInfo);
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_AUDIOCALIBERRWIZ);
|
||
}
|
||
|
||
else
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
|
||
break;
|
||
|
||
case PSN_RESET:
|
||
// psn_reset get's received even if user presses
|
||
// cancel on another dialog.
|
||
if (hThread)
|
||
{
|
||
SetEvent(hEvent); // signal thread to exit
|
||
|
||
AtlWaitWithMessageLoop(hThread);
|
||
|
||
CloseHandle(hEvent);
|
||
hEvent = NULL;
|
||
CloseHandle(hThread);
|
||
hThread = NULL;
|
||
dwThreadID = 0;
|
||
}
|
||
|
||
|
||
// restore recording/microphone volume to what it was before the tuning wizard was launched
|
||
if ( (pawInfo->uPreCalibMainVol.leftVolume <= MIXER_VOLUME_MAX && pawInfo->uPreCalibMainVol.rightVolume <= MIXER_VOLUME_MAX) ||
|
||
(pawInfo->uPreCalibSubVol.leftVolume <= MIXER_VOLUME_MAX && pawInfo->uPreCalibSubVol.rightVolume <= MIXER_VOLUME_MAX))
|
||
{
|
||
if (pMixer == NULL)
|
||
{
|
||
pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveInDevId, MIXER_OBJECTF_WAVEIN);
|
||
}
|
||
if (pMixer)
|
||
{
|
||
if (pawInfo->uPreCalibMainVol.leftVolume < MIXER_VOLUME_MAX || pawInfo->uPreCalibMainVol.rightVolume < MIXER_VOLUME_MAX)
|
||
{
|
||
pMixer->SetMainVolume(&pawInfo->uPreCalibMainVol);
|
||
}
|
||
|
||
if (pawInfo->uPreCalibSubVol.leftVolume < MIXER_VOLUME_MAX || pawInfo->uPreCalibSubVol.rightVolume < MIXER_VOLUME_MAX)
|
||
{
|
||
pMixer->SetSubVolume(&pawInfo->uPreCalibSubVol);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (pMixer)
|
||
{
|
||
delete pMixer;
|
||
pMixer = NULL;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
case (WM_HSCROLL): // trackbar notification
|
||
{
|
||
|
||
dwTBPos = (DWORD)SendMessage(hTrackBar, TBM_GETPOS, 0, 0);
|
||
if (pMixer)
|
||
{
|
||
pMixer->GetVolume(&dwVol);
|
||
NewMixVolume(&dwNewVol, dwVol, (dwTBPos * TB_VOL_INCREMENT));
|
||
pMixer->SetVolume(&dwNewVol);
|
||
|
||
}
|
||
break;
|
||
}
|
||
|
||
// notifications from the mixer
|
||
case MM_MIXM_CONTROL_CHANGE:
|
||
case MM_MIXM_LINE_CHANGE:
|
||
{
|
||
if (pMixer)
|
||
{
|
||
fRet = pMixer->GetMainVolume(&dwVol);
|
||
if ((fRet) && (dwVol.leftVolume != dwMainVol || dwVol.rightVolume != dwMainVol))
|
||
{
|
||
pMixer->SetSubVolume(&dwVol);
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
|
||
break;
|
||
}
|
||
|
||
MIXVOLUME subvol;
|
||
fRet = pMixer->GetSubVolume(&subvol);
|
||
if ((fRet) && (dwVol.leftVolume != subvol.leftVolume || dwVol.rightVolume !=subvol.rightVolume))
|
||
{
|
||
pMixer->SetMainVolume(&subvol);
|
||
SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(subvol.leftVolume , subvol.rightVolume)/TB_VOL_INCREMENT);
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
// calibration thread sends this message to indicate that the
|
||
// volume is too loud
|
||
case WM_AUDIO_CLIPPING:
|
||
{
|
||
if (pMixer)
|
||
{
|
||
pMixer->GetVolume(&dwVol);
|
||
if (dwVol.leftVolume > DECREMENT_AMOUNT || dwVol.rightVolume > DECREMENT_AMOUNT)
|
||
{
|
||
dwVol.leftVolume -=DECREMENT_AMOUNT;
|
||
dwVol.rightVolume -=DECREMENT_AMOUNT;
|
||
|
||
pMixer->SetVolume(&dwVol);
|
||
|
||
// fix for Videum driver
|
||
// check to see if the volume actually got lowered
|
||
// if it didn't, try a larger decrement
|
||
pMixer->GetVolume(&dwNewVol);
|
||
if ((dwNewVol.leftVolume == dwVol.leftVolume) && (dwVol.leftVolume >= DECREMENT_AMOUNT_LARGE) ||
|
||
(dwNewVol.rightVolume == dwVol.rightVolume) && (dwVol.rightVolume >= DECREMENT_AMOUNT_LARGE))
|
||
{
|
||
dwVol.leftVolume -=DECREMENT_AMOUNT_LARGE;
|
||
dwVol.rightVolume -=DECREMENT_AMOUNT_LARGE;
|
||
|
||
pMixer->SetVolume(&dwVol);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
// the recording thread is signaling back to us that there is
|
||
// a severe error. Assume the thread has exited
|
||
case WM_AUDIOTHREAD_ERROR:
|
||
{
|
||
ProcessCalibError(CALIBERR_DEVICE_ERROR, pawInfo);
|
||
PropSheet_SetCurSelByID(GetParent(hDlg), IDD_AUDIOCALIBERRWIZ);
|
||
break;
|
||
}
|
||
|
||
// The recording thread will send this message back to us
|
||
// at least once to indicate that the silence threshold was
|
||
// broken. Thus, the microphone is functional.
|
||
case WM_AUDIOTHREAD_SOUND:
|
||
{
|
||
fSoundDetected = TRUE;
|
||
break;
|
||
}
|
||
|
||
default:
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
INT_PTR APIENTRY AudioCalibWiz4( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
static PROPSHEETPAGE * ps;
|
||
static PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
|
||
switch (message) {
|
||
case WM_INITDIALOG:
|
||
{
|
||
|
||
// Save the PROPSHEETPAGE information.
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
return (TRUE);
|
||
}
|
||
|
||
case WM_NOTIFY:
|
||
switch (((NMHDR FAR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
{
|
||
// Initialize the controls.
|
||
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
|
||
if (g_fSilentWizard)
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case PSN_WIZNEXT:
|
||
// Due to bug in ComCtl32 don't allow next
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
|
||
case PSN_WIZFINISH:
|
||
SaveAudioWizChanges(pawInfo);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
INT_PTR APIENTRY AudioCalibErrWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
PROPSHEETPAGE * ps;
|
||
PWIZCONFIG pWizConfig;
|
||
static PAUDIOWIZINFO pawInfo;
|
||
TCHAR szTemp[MAXSTRINGSIZE];
|
||
LPTSTR pszIcon;
|
||
|
||
|
||
//WORD wCmdId;
|
||
|
||
switch (message) {
|
||
case WM_INITDIALOG:
|
||
{
|
||
// Save the PROPSHEETPAGE information.
|
||
ps = (PROPSHEETPAGE *)lParam;
|
||
pWizConfig = (PWIZCONFIG)ps->lParam;
|
||
pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
|
||
return (TRUE);
|
||
}
|
||
|
||
case WM_NOTIFY:
|
||
switch (((NMHDR FAR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
// initialize the controls.
|
||
|
||
// Show the error or warning icon
|
||
pszIcon = (((pawInfo->ErrWizInfo).uType == AUDIOWIZ_WARNING) ?
|
||
IDI_ASTERISK : IDI_EXCLAMATION);
|
||
|
||
// Set the wizard bitmap to the static control
|
||
::SendDlgItemMessage( hDlg,
|
||
IDC_ERRWIZICON,
|
||
STM_SETIMAGE,
|
||
IMAGE_ICON,
|
||
(LPARAM) ::LoadIcon(NULL, pszIcon));
|
||
|
||
//set the error title
|
||
if ((pawInfo->ErrWizInfo).uErrTitleId)
|
||
{
|
||
LoadString(GetInstanceHandle(),(pawInfo->ErrWizInfo).uErrTitleId,
|
||
szTemp, MAXSTRINGSIZE);
|
||
SetDlgItemText(hDlg, IDC_ERRTITLE, szTemp);
|
||
}
|
||
|
||
if ((pawInfo->ErrWizInfo).uErrTextId)
|
||
{
|
||
//show the error text
|
||
LoadString(GetInstanceHandle(),(pawInfo->ErrWizInfo).uErrTextId,
|
||
szTemp, MAXSTRINGSIZE);
|
||
SetDlgItemText(hDlg, IDC_ERRTEXT, szTemp);
|
||
}
|
||
|
||
PropSheet_SetWizButtons(GetParent(hDlg),
|
||
(pawInfo->ErrWizInfo).uButtonOptions );
|
||
|
||
if (g_fSilentWizard)
|
||
{
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_FINISH))
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
|
||
}
|
||
else
|
||
{
|
||
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_NEXT))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (pawInfo->ErrWizInfo).uNextWizId);
|
||
return TRUE;
|
||
|
||
case PSN_RESET:
|
||
pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
|
||
break;
|
||
|
||
case PSN_WIZFINISH:
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_FINISH))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
|
||
SaveAudioWizChanges(pawInfo);
|
||
break;
|
||
|
||
case PSN_WIZBACK:
|
||
// Due to bug in ComCtl32 check if button is enabled
|
||
if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_BACK))
|
||
{
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (pawInfo->ErrWizInfo).uBackWizId);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
void ProcessCalibError(UINT uCalibErr, PAUDIOWIZINFO pawInfo)
|
||
{
|
||
switch (uCalibErr)
|
||
{
|
||
case CALIBERR_CANT_SET_VOLUME:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_WARNING;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_NORECVOLCNTRL;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = 0;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
|
||
break;
|
||
|
||
case CALIBERR_NO_MIXERS:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = 0;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ1;
|
||
break;
|
||
|
||
case CALIBERR_MIXER_ERROR:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = 0;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
|
||
break;
|
||
|
||
case CALIBERR_CANT_OPEN_WAVE_DEV:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_CANTOPENWAVE;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_QUITPROGRAM;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_NEXT|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = IDD_AUDIOCALIBWIZ3;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ1;
|
||
break;
|
||
|
||
case CALIBERR_NO_MICROPHONE:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_WARNING;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_NO_MICROPHONE;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_NO_MICWARNING;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_NEXT|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = IDD_AUDIOCALIBWIZ4;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ3;
|
||
break;
|
||
|
||
default:
|
||
case CALIBERR_DEVICE_ERROR:
|
||
pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
|
||
pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
|
||
pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
|
||
pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
|
||
pawInfo->ErrWizInfo.uNextWizId = 0;
|
||
pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
|
||
break;
|
||
}
|
||
}
|
||
|
||
UINT GetSoundCardCaps(UINT uWaveInDevId, UINT uWaveOutDevId, HWND hwnd)
|
||
{
|
||
UINT uSoundCardCaps;
|
||
UINT uRet;
|
||
bool bFD = false;
|
||
UINT uDSCheck;
|
||
|
||
|
||
uSoundCardCaps = SOUNDCARD_PRESENT;
|
||
|
||
if ((uRet = CheckForFullDuplex(uWaveInDevId,uWaveOutDevId)) == SOUNDCARD_NONE)
|
||
{
|
||
//failed to open wave device
|
||
//SS:Error message ??
|
||
//all applications using the wave device should be closed
|
||
|
||
}
|
||
else if (uRet == SOUNDCARD_FULLDUPLEX)
|
||
{
|
||
uSoundCardCaps = uSoundCardCaps | SOUNDCARD_FULLDUPLEX;
|
||
bFD = true;
|
||
}
|
||
if ((uRet = CheckForAgc(uWaveInDevId)) == SOUNDCARD_NONE)
|
||
{
|
||
//mixer initialization failed
|
||
//SS: Error message
|
||
}
|
||
else if (uRet == SOUNDCARD_HAVEAGC)
|
||
uSoundCardCaps = uSoundCardCaps | SOUNDCARD_HAVEAGC;
|
||
|
||
|
||
uDSCheck = DirectSoundCheck(uWaveInDevId, uWaveOutDevId, hwnd);
|
||
if (uDSCheck & DS_FULLDUPLEX)
|
||
{
|
||
uSoundCardCaps = uSoundCardCaps | SOUNDCARD_DIRECTSOUND;
|
||
}
|
||
|
||
return(uSoundCardCaps);
|
||
}
|
||
|
||
UINT CheckForFullDuplex(UINT uWaveInDevId,UINT uWaveOutDevId)
|
||
{
|
||
HWAVEIN hWaveIn=NULL;
|
||
HWAVEOUT hWaveOut=NULL;
|
||
MMRESULT mmr;
|
||
UINT uRet = SOUNDCARD_NONE;
|
||
|
||
waveInDev waveIn(uWaveInDevId);
|
||
waveOutDev waveOut(uWaveOutDevId);
|
||
|
||
|
||
mmr = waveOut.Open();
|
||
if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
return SOUNDCARD_NONE;
|
||
}
|
||
|
||
mmr = waveIn.Open();
|
||
if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
return SOUNDCARD_PRESENT;
|
||
}
|
||
|
||
return SOUNDCARD_FULLDUPLEX;
|
||
|
||
// object destructors will close devices
|
||
}
|
||
|
||
UINT GetWaveDeviceFromWaveMapper(UINT uNumWaveDevId, UINT uInOrOut)
|
||
{
|
||
HWAVE hWave=NULL;
|
||
HWAVE hWaveMapper=NULL;
|
||
WAVEFORMATEX WaveFormatEx;
|
||
MMRESULT mmr;
|
||
UINT uDeviceId = (UINT)-1;
|
||
UINT i;
|
||
|
||
WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
|
||
WaveFormatEx.nChannels = 1;
|
||
WaveFormatEx.nSamplesPerSec = 8000;
|
||
WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
|
||
WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
|
||
WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
|
||
WaveFormatEx.cbSize = 0;
|
||
|
||
if (!uInOrOut)
|
||
{
|
||
#if 0
|
||
// First, make sure that none of the devices are already open
|
||
for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
|
||
{
|
||
if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
goto MyExit;
|
||
else
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
// This is probably an 8 bit board. Try again using 8 bit format
|
||
WaveFormatEx.nAvgBytesPerSec = 8000;
|
||
WaveFormatEx.nBlockAlign = 1;
|
||
WaveFormatEx.wBitsPerSample = 8;
|
||
if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
goto MyExit;
|
||
}
|
||
if (hWave)
|
||
{
|
||
waveInClose((HWAVEIN)hWave);
|
||
hWave = (HWAVE)NULL;
|
||
}
|
||
}
|
||
|
||
WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
|
||
WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
|
||
WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
|
||
#endif
|
||
// Open the wave in device using wave mapper
|
||
if (mmr = waveInOpen ((HWAVEIN *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
|
||
{
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
// This is probably an 8 bit board. Try again using 8 bit format
|
||
WaveFormatEx.nAvgBytesPerSec = 8000;
|
||
WaveFormatEx.nBlockAlign = 1;
|
||
WaveFormatEx.wBitsPerSample = 8;
|
||
if (mmr = waveInOpen ((HWAVEIN *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
|
||
goto MyExit;
|
||
}
|
||
else
|
||
goto MyExit;
|
||
}
|
||
|
||
// Now, look for the wave device that is already open
|
||
// that's the one wave mapper picked up
|
||
for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
|
||
{
|
||
if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
{
|
||
uDeviceId = i;
|
||
goto MyExit;
|
||
}
|
||
else
|
||
if (hWave)
|
||
{
|
||
waveInClose((HWAVEIN)hWave);
|
||
hWave = (HWAVE)NULL;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
#if 0
|
||
// First, make sure that none of the devices are already open
|
||
for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
|
||
{
|
||
if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
goto MyExit;
|
||
else
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
// This is probably an 8 bit board. Try again using 8 bit format
|
||
WaveFormatEx.nAvgBytesPerSec = 8000;
|
||
WaveFormatEx.nBlockAlign = 1;
|
||
WaveFormatEx.wBitsPerSample = 8;
|
||
if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
goto MyExit;
|
||
}
|
||
if (hWave)
|
||
{
|
||
waveOutClose((HWAVEOUT)hWave);
|
||
hWave = (HWAVE)NULL;
|
||
}
|
||
}
|
||
|
||
WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
|
||
WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
|
||
WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
|
||
#endif
|
||
// Open the wave in device using wave mapper
|
||
if (mmr = waveOutOpen ((HWAVEOUT *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
|
||
{
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
// This is probably an 8 bit board. Try again using 8 bit format
|
||
WaveFormatEx.nAvgBytesPerSec = 8000;
|
||
WaveFormatEx.nBlockAlign = 1;
|
||
WaveFormatEx.wBitsPerSample = 8;
|
||
if (mmr = waveOutOpen ((HWAVEOUT *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
|
||
goto MyExit;
|
||
}
|
||
else
|
||
goto MyExit;
|
||
}
|
||
|
||
// Now, look for the wave device that is already open
|
||
// that's the one wave mapper picked up
|
||
for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
|
||
{
|
||
if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
|
||
{
|
||
uDeviceId = i;
|
||
goto MyExit;
|
||
}
|
||
else
|
||
if (hWave)
|
||
{
|
||
waveOutClose((HWAVEOUT)hWave);
|
||
hWave = (HWAVE)NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
MyExit:
|
||
if (!uInOrOut)
|
||
{
|
||
if (hWave) waveInClose((HWAVEIN)hWave);
|
||
if (hWaveMapper) waveInClose((HWAVEIN)hWaveMapper);
|
||
}
|
||
else
|
||
{
|
||
if (hWave) waveOutClose((HWAVEOUT)hWave);
|
||
if (hWaveMapper) waveOutClose((HWAVEOUT)hWaveMapper);
|
||
}
|
||
|
||
return(uDeviceId);
|
||
}
|
||
|
||
UINT CheckForWaveDeviceSupport(UINT uWaveDevId, UINT uInOrOut)
|
||
{
|
||
MMRESULT mmr;
|
||
|
||
// querying isn't good enough, always directly open the device
|
||
// to see if it supports a given format
|
||
|
||
if (!uInOrOut)
|
||
{
|
||
waveInDev WaveIn(uWaveDevId);
|
||
|
||
if (uWaveDevId != WAVE_MAPPER)
|
||
WaveIn.AllowMapper(FALSE);
|
||
|
||
mmr = WaveIn.Open(8000,16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveIn.Open(8000,8);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveIn.Open(11025, 16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveIn.Open(22050, 16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveIn.Open(44100, 16);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
else // waveOut
|
||
{
|
||
waveOutDev WaveOut(uWaveDevId);
|
||
|
||
if (uWaveDevId != WAVE_MAPPER)
|
||
WaveOut.AllowMapper(FALSE);
|
||
|
||
mmr = WaveOut.Open(8000,16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveOut.Open(8000,8);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveOut.Open(11025, 16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveOut.Open(22050, 16);
|
||
if (mmr == WAVERR_BADFORMAT)
|
||
{
|
||
mmr = WaveOut.Open(44100, 16);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// go ahead and allow the device to pass if it's in use
|
||
if ((mmr == MMSYSERR_ALLOCATED) || (mmr == MMSYSERR_NOERROR))
|
||
return TRUE;
|
||
|
||
else
|
||
return FALSE;
|
||
|
||
// destructors for waveOut and waveIn will call Close()
|
||
}
|
||
|
||
UINT CheckForAgc(UINT uWaveInDevId)
|
||
{
|
||
|
||
CMixerDevice *pMixDev;
|
||
UINT uRet = SOUNDCARD_NONE;
|
||
BOOL fAgc;
|
||
|
||
pMixDev = CMixerDevice::GetMixerForWaveDevice(
|
||
NULL,
|
||
uWaveInDevId,
|
||
MIXER_OBJECTF_WAVEIN);
|
||
//SS: we need to correlate the uDevId to mixer id
|
||
if (pMixDev)
|
||
{
|
||
uRet = SOUNDCARD_PRESENT;
|
||
if (pMixDev->GetAGC(&fAgc))
|
||
uRet = SOUNDCARD_HAVEAGC;
|
||
|
||
delete pMixDev;
|
||
}
|
||
return (uRet);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// This function is here to allow the help system to invoke
|
||
// the wizard via rundll32
|
||
|
||
void WINAPI RunAudioWiz(HWND hwndStub, HINSTANCE hInst, LPSTR lpszCmdLine, int CmdShow )
|
||
{
|
||
IntCreateAudioCalibWizard(hwndStub, RUNDUE_USERINVOKED, WAVE_MAPPER,
|
||
NULL, READFROM_REGISTRY);
|
||
}
|
||
|
||
|
||
static void PaintVUMeter (HWND hwnd, DWORD dwVolume)
|
||
{
|
||
COLORREF RedColor = RGB(255,0,0);
|
||
COLORREF YellowColor = RGB(255,255,0);
|
||
COLORREF GreenColor = RGB(0,255,0);
|
||
static DWORD dwPrevVolume=0;
|
||
HBRUSH hRedBrush, hOldBrush, hYellowBrush, hGreenBrush;
|
||
HBRUSH hBlackBrush, hCurrentBrush;
|
||
HDC hdc;
|
||
RECT rect, rectDraw, invalidRect;
|
||
DWORD width, boxwidth, startPos=0;
|
||
DWORD nRect=0, yellowPos, redPos;
|
||
LONG lDiff, lDiffTrunc = (MAX_VOLUME_NORMALIZED/2);
|
||
|
||
|
||
// rect gets filled with the dimensions we are drawing into
|
||
if (FALSE == GetClientRect (hwnd, &rect))
|
||
{
|
||
return;
|
||
}
|
||
|
||
// we expect volume to be between 0-32768
|
||
if (dwVolume > MAX_VOLUME)
|
||
dwVolume = MAX_VOLUME;
|
||
|
||
// reduce from 15 bits to 8 // 0 <= dwVolume <= 256
|
||
dwVolume = dwVolume / 128;
|
||
|
||
// run it through the "normalizing" table. Special case: F(256)==256
|
||
if (dwVolume < MAX_VOLUME_NORMALIZED)
|
||
dwVolume = g_VUTable[dwVolume];
|
||
|
||
// visual aesthetic #1 - get rid of VU jerkiness
|
||
// if the volume changed by more than 1/2 since the last update
|
||
// only move the meter up half way
|
||
// exception: if volume is explicitly 0, then skip
|
||
lDiff = (LONG)dwVolume - (LONG)dwPrevVolume;
|
||
if ((dwVolume != 0) && ( (lDiff > (MAX_VOLUME_NORMALIZED/2))
|
||
|| (lDiff < -(MAX_VOLUME_NORMALIZED/2)) ))
|
||
dwVolume = dwVolume - (lDiff/2);
|
||
|
||
// minus 2 for the ending borders
|
||
// if Framed rectangles are used, drop the -2
|
||
boxwidth = rect.right - rect.left - 2;
|
||
width = (boxwidth * dwVolume)/ MAX_VOLUME_NORMALIZED;
|
||
|
||
// visual aesthetic #2 - to get rid of flicker
|
||
// if volume has increased since last time
|
||
// then there is no need to invalidate/update anything
|
||
// otherwise only clear everything to the right of the
|
||
// calculated "width". +/- 1 so the border doesn't get erased
|
||
if ((dwVolume < dwPrevVolume) || (dwVolume == 0))
|
||
{
|
||
invalidRect.left = rect.left + width - RECTANGLE_WIDTH;
|
||
if (invalidRect.left < rect.left)
|
||
invalidRect.left = rect.left;
|
||
invalidRect.right = rect.right - 1;
|
||
invalidRect.top = rect.top + 1;
|
||
invalidRect.bottom = rect.bottom - 1;
|
||
|
||
// these calls together erase the invalid region
|
||
InvalidateRect (hwnd, &invalidRect, TRUE);
|
||
UpdateWindow (hwnd);
|
||
}
|
||
|
||
hdc = GetDC (hwnd) ;
|
||
|
||
hRedBrush = CreateSolidBrush (RedColor) ;
|
||
hGreenBrush = CreateSolidBrush(GreenColor);
|
||
hYellowBrush = CreateSolidBrush(YellowColor);
|
||
|
||
hBlackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||
hOldBrush = (HBRUSH) SelectObject (hdc, hBlackBrush);
|
||
|
||
// draw the main
|
||
FrameRect(hdc, &rect, hBlackBrush);
|
||
|
||
yellowPos = boxwidth/2;
|
||
redPos = (boxwidth*3)/4;
|
||
|
||
SelectObject(hdc, hGreenBrush);
|
||
|
||
hCurrentBrush = hGreenBrush;
|
||
|
||
rectDraw.top = rect.top +1;
|
||
rectDraw.bottom = rect.bottom -1;
|
||
while ((startPos+RECTANGLE_WIDTH) < width)
|
||
{
|
||
rectDraw.left = rect.left + (RECTANGLE_WIDTH+RECTANGLE_LEADING)*nRect + 1;
|
||
rectDraw.right = rectDraw.left + RECTANGLE_WIDTH;
|
||
nRect++;
|
||
|
||
FillRect(hdc, &rectDraw, hCurrentBrush);
|
||
startPos += RECTANGLE_WIDTH+RECTANGLE_LEADING;
|
||
|
||
if (startPos > redPos)
|
||
hCurrentBrush = hRedBrush;
|
||
else if (startPos > yellowPos)
|
||
hCurrentBrush = hYellowBrush;
|
||
}
|
||
|
||
SelectObject (hdc, hOldBrush);
|
||
DeleteObject(hRedBrush);
|
||
DeleteObject(hYellowBrush);
|
||
DeleteObject(hGreenBrush);
|
||
ReleaseDC (hwnd, hdc) ;
|
||
|
||
dwPrevVolume = dwVolume;
|
||
return;
|
||
}
|
||
|
||
static DWORD ComputePower(SHORT *wBuffer, DWORD dwNumSamples, AUDIO_POWER *pAudioPower)
|
||
{
|
||
DWORD dwIndex, dwTotal;
|
||
LONG dcComponent;
|
||
SHORT val;
|
||
DWORD dwVal;
|
||
|
||
ZeroMemory(pAudioPower, sizeof(AUDIO_POWER));
|
||
pAudioPower->dwMin = MAX_VOLUME; // 32768
|
||
|
||
dwTotal = 0;
|
||
dcComponent = 0;
|
||
|
||
for (dwIndex = 0; dwIndex < dwNumSamples; dwIndex++)
|
||
{
|
||
val = wBuffer[dwIndex];
|
||
dwVal = SHABS(val);
|
||
dwTotal += dwVal;
|
||
dcComponent += val;
|
||
|
||
if (dwVal > pAudioPower->dwMax)
|
||
pAudioPower->dwMax = dwVal;
|
||
if (dwVal < pAudioPower->dwMin)
|
||
pAudioPower->dwMin = dwVal;
|
||
}
|
||
|
||
pAudioPower->lDcComponent = dcComponent / (LONG)dwNumSamples;
|
||
pAudioPower->dwAvg = dwTotal / dwNumSamples;
|
||
|
||
return pAudioPower->dwAvg;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
// given a pointer to a wave In device, and a list of WAVEHDR structs
|
||
// each wave header is prepared (if needed) and fed to wavein
|
||
MMRESULT PostFreeBuffers(waveInDev *pWaveInDev, WAVEHDR *aWaveHdrs, int numBuffers, DWORD *pdwCount)
|
||
{
|
||
int nIndex;
|
||
MMRESULT mmr=MMSYSERR_NOERROR;
|
||
bool bNeedToPrepare;
|
||
|
||
// first time through - the dwUser field of all wave headers
|
||
// will be zero. Just look a the first header in the list
|
||
// to figure this out.
|
||
|
||
if (numBuffers < 1)
|
||
{
|
||
ASSERT(false);
|
||
return MMSYSERR_ERROR;
|
||
}
|
||
|
||
bNeedToPrepare = (aWaveHdrs[0].dwUser == 0);
|
||
|
||
if (bNeedToPrepare)
|
||
{
|
||
for (nIndex = 0; nIndex < numBuffers; nIndex++)
|
||
{
|
||
mmr = pWaveInDev->PrepareHeader(&aWaveHdrs[nIndex]);
|
||
|
||
if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
return mmr;
|
||
}
|
||
|
||
// so that the code below works ok, just mark the done
|
||
// bit on the wave headers
|
||
|
||
aWaveHdrs[nIndex].dwFlags |= WHDR_DONE;
|
||
}
|
||
}
|
||
|
||
|
||
// for each wave header passed in that has the "done" bit set
|
||
// repost to wavein
|
||
|
||
for (nIndex = 0; nIndex < numBuffers; nIndex++)
|
||
{
|
||
if (aWaveHdrs[nIndex].dwFlags & WHDR_DONE)
|
||
{
|
||
aWaveHdrs[nIndex].dwFlags &= ~(WHDR_DONE | WHDR_INQUEUE);
|
||
aWaveHdrs[nIndex].dwFlags |= WHDR_PREPARED;
|
||
|
||
*pdwCount = (*pdwCount) + 1;
|
||
if (*pdwCount == 0)
|
||
*pdwCount++;
|
||
|
||
aWaveHdrs[nIndex].dwUser = *pdwCount;
|
||
|
||
mmr = pWaveInDev->Record(&aWaveHdrs[nIndex]);
|
||
}
|
||
}
|
||
|
||
return mmr;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
// scan the array of wave headers for "done" buffers
|
||
// return the most recently posted buffer (if any)
|
||
|
||
BYTE *GetLatestBuffer(WAVEHDR *aWaveHdrs, int numBuffers)
|
||
{
|
||
DWORD_PTR dwUserHigh=0;
|
||
int nIndexHigh=0;
|
||
int nIndex;
|
||
|
||
|
||
for (nIndex = 0; nIndex < numBuffers; nIndex++)
|
||
{
|
||
if (aWaveHdrs[nIndex].dwFlags & WHDR_DONE)
|
||
{
|
||
if (aWaveHdrs[nIndex].dwUser > dwUserHigh)
|
||
{
|
||
dwUserHigh = aWaveHdrs[nIndex].dwUser;
|
||
nIndexHigh = nIndex;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (dwUserHigh > 0)
|
||
{
|
||
return (BYTE*)(aWaveHdrs[nIndexHigh].lpData);
|
||
}
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
static DWORD CALLBACK CalibrateTalking(PVOID pVoid)
|
||
{
|
||
const int SIZE_WAVEIN_BUFFER = 1600; // 100ms @ 8khz, 16-bit
|
||
const int NUM_WAVEIN_BUFFERS = 5;
|
||
WaveBufferList waveList(NUM_WAVEIN_BUFFERS, SIZE_WAVEIN_BUFFER);
|
||
WAVEHDR aWaveHdrs[NUM_WAVEIN_BUFFERS];
|
||
|
||
HWND hVUMeter, hDlg;
|
||
HANDLE hEvent;
|
||
MMRESULT mmr;
|
||
DWORD dwPow, dwRet, dwExitCode=0;
|
||
AUDIO_POWER audioPower;
|
||
CALIB_DISPLAY *pCalibDisplay;
|
||
TCHAR szText[ATW_MSG_LENGTH];
|
||
BOOL fOpened = TRUE;
|
||
BOOL fSoundDetected = FALSE;
|
||
int nRecordCount = 0, nIndex;
|
||
DWORD dwBufferIndex = 1;
|
||
SHORT *buffer;
|
||
|
||
|
||
HANDLE hEventRecord = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
||
waveInDev waveIn(((CALIB_DISPLAY *)pVoid)->uWaveInDevId, hEventRecord);
|
||
|
||
pCalibDisplay = (CALIB_DISPLAY *)pVoid;
|
||
hVUMeter = pCalibDisplay->hVUMeter;
|
||
hDlg = pCalibDisplay->hDlg;
|
||
hEvent = pCalibDisplay->hEvent;
|
||
|
||
ASSERT(hEvent);
|
||
|
||
|
||
mmr = waveIn.Open(8000,16);
|
||
if (mmr == MMSYSERR_ALLOCATED)
|
||
{
|
||
FLoadString(IDS_RECORD_ERROR, szText, CCHMAX(szText));
|
||
SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, szText);
|
||
fOpened = FALSE;
|
||
}
|
||
|
||
else if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
|
||
CloseHandle(hEvent);
|
||
CloseHandle(hEventRecord);
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, "");
|
||
ResetEvent(hEventRecord);
|
||
}
|
||
|
||
|
||
// initialize the array of wavehdrs
|
||
for (nIndex=0; nIndex < NUM_WAVEIN_BUFFERS; nIndex++)
|
||
{
|
||
ZeroMemory(&aWaveHdrs[nIndex], sizeof(WAVEHDR));
|
||
aWaveHdrs[nIndex].lpData = (LPSTR)(waveList.GetBuffer(nIndex));
|
||
aWaveHdrs[nIndex].dwBufferLength = SIZE_WAVEIN_BUFFER;
|
||
}
|
||
|
||
|
||
while (1)
|
||
{
|
||
|
||
// is it time to exit ?
|
||
dwRet = WaitForSingleObject(hEvent, 0);
|
||
if (dwRet == WAIT_OBJECT_0)
|
||
{
|
||
dwExitCode = 0;
|
||
break;
|
||
}
|
||
|
||
// if we still haven't opened the device
|
||
// keep trying
|
||
|
||
if (fOpened == FALSE)
|
||
{
|
||
mmr = waveIn.Open(8000,16);
|
||
if (mmr == MMSYSERR_ALLOCATED)
|
||
{
|
||
PaintVUMeter(hVUMeter, 0); // draw a blank rectangle
|
||
Sleep(500);
|
||
continue;
|
||
}
|
||
|
||
if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
|
||
dwExitCode = (DWORD)(-1);
|
||
break;
|
||
}
|
||
|
||
// mmr == noerror
|
||
SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, TEXT(""));
|
||
fOpened = TRUE;
|
||
ResetEvent(hEventRecord);
|
||
}
|
||
|
||
// wave device is open at this point
|
||
|
||
mmr = PostFreeBuffers(&waveIn, aWaveHdrs, NUM_WAVEIN_BUFFERS, &dwBufferIndex);
|
||
if (mmr != MMSYSERR_NOERROR)
|
||
{
|
||
PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
|
||
dwExitCode = (DWORD) -1;
|
||
break;
|
||
}
|
||
|
||
WaitForSingleObject(hEventRecord, 5000);
|
||
ResetEvent(hEventRecord);
|
||
|
||
buffer = (SHORT*)GetLatestBuffer(aWaveHdrs, NUM_WAVEIN_BUFFERS);
|
||
|
||
if (buffer)
|
||
{
|
||
nRecordCount++;
|
||
|
||
dwPow = ComputePower(buffer, SIZE_WAVEIN_BUFFER/2, &audioPower);
|
||
|
||
// don't update the meter for the first 200ms.
|
||
// "noise" from opening the soundcard tends to show up
|
||
if (nRecordCount > 2)
|
||
{
|
||
PaintVUMeter(hVUMeter, audioPower.dwMax);
|
||
|
||
// signal back to the calling window (if it hasn't already),
|
||
// that the silence threshold was broken
|
||
if ((fSoundDetected == FALSE) && (audioPower.dwMax > SILENCE_THRESHOLD))
|
||
{
|
||
PostMessage(hDlg, WM_AUDIOTHREAD_SOUND, 0,0);
|
||
fSoundDetected = TRUE;
|
||
}
|
||
|
||
// check for clipping, post message back to parent thread/window
|
||
// so that it will adjust the volume
|
||
if (audioPower.dwMax > CLIPPINGVOL)
|
||
{
|
||
// should we use send message instead ?
|
||
PostMessage(hDlg, WM_AUDIO_CLIPPING,0,0);
|
||
}
|
||
}
|
||
else
|
||
PaintVUMeter(hVUMeter, 0);
|
||
|
||
}
|
||
}
|
||
|
||
waveIn.Reset();
|
||
|
||
for (nIndex = 0; nIndex < NUM_WAVEIN_BUFFERS; nIndex++)
|
||
{
|
||
waveIn.UnPrepareHeader(&aWaveHdrs[nIndex]);
|
||
}
|
||
|
||
waveIn.Close();
|
||
|
||
CloseHandle(hEvent);
|
||
CloseHandle(hEventRecord);
|
||
|
||
TRACE_OUT(("ATW: Recording Thread Exit\r\n"));
|
||
|
||
return dwExitCode;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
// Turns on AGC if needed
|
||
// parameter is whatever pawInfo->iSetAgc is.
|
||
// but it's probably been hardcoded to be READFROM_REGISTRY
|
||
static BOOL StartAGC(CMixerDevice *pMixer, BOOL iSetAgc, UINT uSoundCardCaps)
|
||
{
|
||
BOOL bSet, bRet;
|
||
|
||
if (iSetAgc == READFROM_REGISTRY)
|
||
{
|
||
if (DOESSOUNDCARDHAVEAGC(uSoundCardCaps))
|
||
{
|
||
RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
|
||
bSet = (BOOL)( re.GetNumber(REGVAL_AUTOGAIN,AUTOGAIN_ENABLED) == AUTOGAIN_ENABLED );
|
||
}
|
||
else
|
||
{
|
||
bSet = FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bSet = (iSetAgc != 0);
|
||
}
|
||
|
||
|
||
bRet = pMixer->SetAGC(bSet);
|
||
|
||
if (bSet == FALSE)
|
||
return FALSE;
|
||
|
||
return bRet;
|
||
|
||
}
|
||
|