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.
2480 lines
66 KiB
2480 lines
66 KiB
// 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 = 1;
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|