Source code of Windows XP (NT5)
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.

2478 lines
64 KiB

  1. // File: calib.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "WaveDev.h"
  5. #include "dstest.h"
  6. #include "avdefs.h"
  7. #include <mmsystem.h>
  8. #include <mixer.h>
  9. #include <mperror.h>
  10. #include <iacapapi.h>
  11. #include <sehcall.h>
  12. // Local includes
  13. #include "ConfCpl.h"
  14. #include "conf.h"
  15. // Defined in wizard.cpp
  16. extern UINT_PTR GetPageBeforeAudioWiz();
  17. // move somewhere else
  18. #define MAXNUMPAGES_INCALIBWIZ 7
  19. #define WAVEDEVICE_OPENFAILED -1
  20. #define MAXSTRINGSIZE 256
  21. #define READFROM_REGISTRY -1
  22. #define AUDIOWIZ_WARNING 1
  23. #define AUDIOWIZ_ERROR 2
  24. #define CALIB_CHECK 1
  25. #define CALIB_PREPARE 2
  26. #define CALIBERR_NO_MIXERS 1
  27. #define CALIBERR_CANT_OPEN_WAVE_DEV 2
  28. #define CALIBERR_CANT_SET_VOLUME 3
  29. #define CALIBERR_USER_CANCEL 4
  30. #define CALIBERR_MIXER_ERROR 6
  31. #define CALIBERR_NO_MICROPHONE 7
  32. #define CALIBERR_DEVICE_ERROR 8
  33. #define ATW_PLAYFILE_SOUND TEXT("TestSnd.Wav")
  34. #define CLIPPINGVOL 0x6000
  35. #define DECREMENT_AMOUNT 0x800
  36. #define DECREMENT_AMOUNT_LARGE 0x1200
  37. #define SILENCE_THRESHOLD 0x800
  38. // trackbar sets volume range from 0-65535, but only has 100 steps.
  39. #define TB_VOL_INCREMENT 655
  40. #define ATW_MSG_LENGTH 256
  41. #define MIXER_VOLUME_MAX 0x0000ffff
  42. #define MIXER_VOLUME_UNINITIALIZED 0xffffffff
  43. #define WM_AUDIO_CLIPPING (WM_USER+21)
  44. #define WM_AUDIOTHREAD_STOP (WM_USER+22)
  45. #define WM_AUDIOTHREAD_ERROR (WM_USER+23)
  46. #define WM_AUDIOTHREAD_SOUND (WM_USER+24)
  47. // vu meter
  48. #define RECTANGLE_WIDTH 10
  49. #define RECTANGLE_LEADING 1
  50. #define MAX_VOLUME 32768
  51. #define MAX_VOLUME_NORMALIZED 256
  52. #define SHABS(x) (((x) > 0) ? (x) : (WORD)(-(x)))
  53. typedef struct _power_struct
  54. {
  55. DWORD dwMin;
  56. DWORD dwMax;
  57. DWORD dwAvg;
  58. LONG lDcComponent;
  59. } AUDIO_POWER;
  60. #define SAMPLE_SIZE 2 // 16 bit samples
  61. typedef struct _ERRWIZINFO{
  62. UINT uType;
  63. UINT uButtonOptions;
  64. UINT uNextWizId;
  65. UINT uBackWizId;
  66. UINT uErrTitleId;
  67. UINT uErrTextId;
  68. }ERRWIZINFO, *PERRWIZINFO;
  69. typedef struct _calib_wavein
  70. {
  71. HWND hVUMeter;
  72. DWORD nErrorTextId;
  73. HWND hDlg;
  74. UINT uWaveInDevId;
  75. HANDLE hEvent; // signal to parent after creating msg queue
  76. } CALIB_DISPLAY, *PCALIBDISPLAY;
  77. typedef struct _AUDIOWIZINFO{
  78. UINT uFlags;
  79. UINT uOptions;
  80. UINT uWaveInDevId;
  81. UINT uWaveOutDevId;
  82. BOOL iSetAgc;
  83. UINT uChanged; //set in the wizard.
  84. UINT uCalibratedVol;
  85. UINT uSpeakerVol;
  86. UINT uSoundCardCaps;
  87. UINT uTypBandWidth;
  88. TCHAR szWaveInDevName[MAXPNAMELEN];
  89. TCHAR szWaveOutDevName[MAXPNAMELEN];
  90. MIXVOLUME uPreCalibMainVol; // record volume
  91. MIXVOLUME uPreCalibSubVol; // microphone volume
  92. MIXVOLUME uPreCalibSpkVol; // speaker/wave volume
  93. UINT uOldWaveInDevId;
  94. UINT uOldWaveOutDevId;
  95. TCHAR szOldWaveInDevName[MAXPNAMELEN];
  96. TCHAR szOldWaveOutDevName[MAXPNAMELEN];
  97. ERRWIZINFO ErrWizInfo;
  98. DWORD dwWizButtons;
  99. }AUDIOWIZINFO, *PAUDIOWIZINFO;
  100. class WaveBufferList
  101. {
  102. BYTE *m_aBytes;
  103. DWORD m_dwBuffers;
  104. DWORD m_dwSize;
  105. public:
  106. WaveBufferList(DWORD dwBuffers, DWORD dwSize);
  107. ~WaveBufferList();
  108. BYTE *GetBuffer(DWORD dwIndex);
  109. };
  110. WaveBufferList::WaveBufferList(DWORD dwBuffers, DWORD dwSize) :
  111. m_aBytes(NULL),
  112. m_dwBuffers(dwBuffers),
  113. m_dwSize(dwSize)
  114. {
  115. if ((m_dwBuffers > 0) && (m_dwSize > 0))
  116. {
  117. m_aBytes = new BYTE[m_dwBuffers*m_dwSize];
  118. }
  119. }
  120. BYTE *WaveBufferList::GetBuffer(DWORD dwIndex)
  121. {
  122. if ((dwIndex < m_dwBuffers) && (m_aBytes))
  123. {
  124. return m_aBytes + dwIndex*m_dwSize;
  125. }
  126. return NULL;
  127. }
  128. WaveBufferList::~WaveBufferList()
  129. {
  130. if (m_aBytes)
  131. delete [] m_aBytes;
  132. }
  133. //------------------------ Prototype Definitions -------------------------
  134. BOOL GetAudioWizardPages(UINT uOptions, UINT uDevId,
  135. LPPROPSHEETPAGE *plpPropSheetPages, LPUINT lpuNumPages);
  136. void ReleaseAudioWizardPages(LPPROPSHEETPAGE lpPropSheetPages, PWIZCONFIG pWizConfig,
  137. PAUDIOWIZOUTPUT pAudioWizOut);
  138. INT_PTR CallAudioCalibWizard(HWND hwndOwner, UINT uOptions,
  139. UINT uDevId,PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc);
  140. static INT_PTR IntCreateAudioCalibWizard(HWND hwndOwner, UINT uOptions, UINT uDevId,
  141. PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc);
  142. INT_PTR APIENTRY DetSoundCardWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  143. INT_PTR APIENTRY AudioCalibWiz0( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  144. INT_PTR APIENTRY AudioCalibWiz1( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  145. INT_PTR APIENTRY AudioCalibWiz2( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  146. INT_PTR APIENTRY AudioCalibWiz3( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  147. INT_PTR APIENTRY AudioCalibWiz4( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  148. INT_PTR APIENTRY AudioCalibErrWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  149. static void SaveAudioWizChanges(PAUDIOWIZINFO pawInfo);
  150. static UINT GetSoundCardCaps(UINT uWaveInDevId,UINT uWaveOutDevId, HWND hwnd);
  151. static UINT CheckForFullDuplex(UINT uWaveInDevId,UINT uWaveOutDevId);
  152. static UINT CheckForAgc(UINT uWaveInDevId);
  153. static UINT GetWaveDeviceFromWaveMapper(UINT uNumWaveDevId, UINT uInOrOut);
  154. static UINT CheckForWaveDeviceSupport(UINT uWaveDevId, UINT uInOrOut);
  155. static void ProcessCalibError(UINT uCalibErr, PAUDIOWIZINFO pawInfo);
  156. static DWORD ComputePower(SHORT *wBuffer, DWORD dwNumSamples, AUDIO_POWER *pAudioPower);
  157. static BOOL StartAGC(CMixerDevice *pMixer, BOOL iSetAgc, UINT uSoundCardCaps);
  158. static void PaintVUMeter (HWND hwnd, DWORD dwVolume);
  159. static DWORD CALLBACK CalibrateTalking(PVOID);
  160. BOOL IntGetAudioWizardPages(UINT uOptions, UINT uDevId,
  161. LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig,
  162. LPUINT lpuNumPages, INT iSetAgc);
  163. ///////////////////////
  164. static const BYTE g_VUTable[] = {
  165. 0, 1, 2, 3, 4, 5, 6, 7,
  166. 8, 23, 30, 35, 39, 43, 46, 49,
  167. 52, 55, 57, 60, 62, 64, 66, 68,
  168. 70, 72, 74, 76, 78, 80, 81, 83,
  169. 85, 86, 88, 89, 91, 92, 94, 95,
  170. 97, 98, 99, 101, 102, 103, 105, 106,
  171. 107, 108, 110, 111, 112, 113, 114, 115,
  172. 117, 118, 119, 120, 121, 122, 123, 124,
  173. 125, 126, 127, 128, 129, 130, 132, 132,
  174. 133, 134, 135, 136, 137, 138, 139, 140,
  175. 141, 142, 143, 144, 145, 146, 147, 147,
  176. 148, 149, 150, 151, 152, 153, 154, 154,
  177. 155, 156, 157, 158, 159, 159, 160, 161,
  178. 162, 163, 163, 164, 165, 166, 167, 167,
  179. 168, 169, 170, 170, 171, 172, 173, 173,
  180. 174, 175, 176, 176, 177, 178, 179, 179,
  181. 180, 181, 181, 182, 183, 184, 184, 185,
  182. 186, 186, 187, 188, 188, 189, 190, 190,
  183. 191, 192, 192, 193, 194, 194, 195, 196,
  184. 196, 197, 198, 198, 199, 200, 200, 201,
  185. 202, 202, 203, 204, 204, 205, 205, 206,
  186. 207, 207, 208, 209, 209, 210, 210, 211,
  187. 212, 212, 213, 213, 214, 215, 215, 216,
  188. 216, 217, 218, 218, 219, 219, 220, 221,
  189. 221, 222, 222, 223, 223, 224, 225, 225,
  190. 226, 226, 227, 227, 228, 229, 229, 230,
  191. 230, 231, 231, 232, 232, 233, 234, 234,
  192. 235, 235, 236, 236, 237, 237, 238, 238,
  193. 239, 239, 240, 241, 241, 242, 242, 243,
  194. 243, 244, 244, 245, 245, 246, 246, 247,
  195. 247, 248, 248, 249, 249, 250, 250, 251,
  196. 251, 252, 252, 253, 253, 254, 254, 255
  197. };
  198. //functions
  199. BOOL GetAudioWizardPages(UINT uOptions, UINT uDevId,
  200. LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig, LPUINT lpuNumPages)
  201. {
  202. return IntGetAudioWizardPages(uOptions, uDevId,
  203. plpPropSheetPages, plpWizConfig,
  204. lpuNumPages, READFROM_REGISTRY);
  205. }
  206. BOOL IntGetAudioWizardPages(UINT uOptions, UINT uDevId,
  207. LPPROPSHEETPAGE *plpPropSheetPages, PWIZCONFIG *plpWizConfig,
  208. LPUINT lpuNumPages, INT iSetAgc)
  209. {
  210. LPPROPSHEETPAGE psp;
  211. UINT uNumPages = 0;
  212. PWIZCONFIG pWizConfig;
  213. PAUDIOWIZINFO pawInfo;
  214. LPSTR szTemp;
  215. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  216. *plpPropSheetPages = NULL;
  217. *plpWizConfig = NULL;
  218. psp = (LPPROPSHEETPAGE) LocalAlloc(LPTR, MAXNUMPAGES_INCALIBWIZ * sizeof(PROPSHEETPAGE));
  219. if (NULL == psp)
  220. {
  221. return FALSE;
  222. }
  223. pWizConfig = (PWIZCONFIG) LocalAlloc(LPTR, sizeof(AUDIOWIZINFO) + sizeof(WIZCONFIG));
  224. if (NULL == pWizConfig)
  225. {
  226. LocalFree(psp);
  227. return FALSE;
  228. }
  229. pWizConfig->fCancel = FALSE;
  230. pWizConfig->uFlags = HIWORD(uOptions);
  231. pWizConfig->dwCustomDataSize = sizeof(AUDIOWIZINFO);
  232. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  233. pawInfo->uOptions = LOWORD(uOptions);
  234. pawInfo->uWaveInDevId = uDevId;
  235. pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
  236. pawInfo->iSetAgc = iSetAgc;
  237. pawInfo->uOldWaveInDevId = re.GetNumber(REGVAL_WAVEINDEVICEID,WAVE_MAPPER);
  238. szTemp = re.GetString(REGVAL_WAVEINDEVICENAME);
  239. if (szTemp)
  240. lstrcpy(pawInfo->szOldWaveInDevName, szTemp);
  241. pawInfo->uOldWaveOutDevId = re.GetNumber(REGVAL_WAVEOUTDEVICEID,WAVE_MAPPER);
  242. szTemp = re.GetString(REGVAL_WAVEOUTDEVICENAME);
  243. if (szTemp)
  244. lstrcpy(pawInfo->szOldWaveOutDevName, szTemp);
  245. pawInfo->uCalibratedVol = re.GetNumber(REGVAL_LASTCALIBRATEDVOL, 0xFFFFFFFF);
  246. pawInfo->uPreCalibSpkVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // playback
  247. pawInfo->uPreCalibSpkVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // playback
  248. pawInfo->uPreCalibMainVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // recording
  249. pawInfo->uPreCalibMainVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // recording
  250. pawInfo->uPreCalibSubVol.leftVolume = MIXER_VOLUME_UNINITIALIZED; // microphone
  251. pawInfo->uPreCalibSubVol.rightVolume = MIXER_VOLUME_UNINITIALIZED; // microphone
  252. if (!waveInGetNumDevs() || !waveOutGetNumDevs())
  253. pawInfo->uSoundCardCaps = SOUNDCARD_NONE;
  254. else
  255. pawInfo->uSoundCardCaps = SOUNDCARD_PRESENT;
  256. FillInPropertyPage(&psp[uNumPages++], IDD_DETSOUNDCARDWIZ,
  257. DetSoundCardWiz,(LPARAM)pWizConfig);
  258. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ0,
  259. AudioCalibWiz0, (LPARAM)pWizConfig);
  260. if ((RUNDUE_CARDCHANGE == pawInfo->uOptions) ||
  261. (RUNDUE_NEVERBEFORE == pawInfo->uOptions) ||
  262. (RUNDUE_USERINVOKED == pawInfo->uOptions))
  263. {
  264. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ1,
  265. AudioCalibWiz1,(LPARAM)pWizConfig);
  266. }
  267. else
  268. {
  269. //the old wavein and wave out device will remain
  270. pawInfo->uWaveInDevId = pawInfo->uOldWaveInDevId;
  271. pawInfo->uWaveOutDevId = pawInfo->uOldWaveOutDevId;
  272. lstrcpy(pawInfo->szWaveInDevName,pawInfo->szOldWaveOutDevName);
  273. lstrcpy(pawInfo->szWaveOutDevName,pawInfo->szOldWaveOutDevName);
  274. }
  275. // For each of the pages that I need, fill in a PROPSHEETPAGE structure.
  276. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ2,
  277. AudioCalibWiz2, (LPARAM)pWizConfig);
  278. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ3,
  279. AudioCalibWiz3, (LPARAM)pWizConfig);
  280. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBWIZ4,
  281. AudioCalibWiz4, (LPARAM)pWizConfig);
  282. FillInPropertyPage(&psp[uNumPages++], IDD_AUDIOCALIBERRWIZ,
  283. AudioCalibErrWiz, (LPARAM)pWizConfig);
  284. // The number of pages in this wizard.
  285. *lpuNumPages = uNumPages;
  286. *plpPropSheetPages = (LPPROPSHEETPAGE) psp;
  287. *plpWizConfig = pWizConfig;
  288. return TRUE;
  289. }
  290. void ReleaseAudioWizardPages(LPPROPSHEETPAGE lpPropSheetPages,
  291. PWIZCONFIG pWizConfig, PAUDIOWIZOUTPUT pAudioWizOut)
  292. {
  293. PAUDIOWIZINFO pawInfo;
  294. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  295. if (pAudioWizOut)
  296. {
  297. pAudioWizOut->uValid = pawInfo->uChanged;//whatever is set in the wizard is valid
  298. pAudioWizOut->uSoundCardCaps = pawInfo->uSoundCardCaps;
  299. pAudioWizOut->uCalibratedVol = pawInfo->uCalibratedVol;
  300. pAudioWizOut->uTypBandWidth = pawInfo->uTypBandWidth;
  301. pAudioWizOut->uWaveInDevId = pawInfo->uWaveInDevId;
  302. pAudioWizOut->uWaveOutDevId = pawInfo->uWaveOutDevId;
  303. lstrcpy(pAudioWizOut->szWaveInDevName,pawInfo->szWaveInDevName);
  304. lstrcpy(pAudioWizOut->szWaveOutDevName,pawInfo->szWaveOutDevName);
  305. //the ui needs to read the changed values and call nac methods for
  306. //the changes below
  307. pAudioWizOut->uChanged = AUDIOWIZ_NOCHANGES;
  308. if ((pawInfo->uChanged & SOUNDCARD_CHANGED) &&
  309. ((pawInfo->uWaveInDevId != pawInfo->uOldWaveInDevId) ||
  310. (pawInfo->uWaveOutDevId != pawInfo->uOldWaveOutDevId) ||
  311. lstrcmp(pawInfo->szWaveInDevName,pawInfo->szOldWaveInDevName) ||
  312. lstrcmp(pawInfo->szWaveOutDevName,pawInfo->szOldWaveOutDevName)))
  313. {
  314. pAudioWizOut->uChanged |= SOUNDCARD_CHANGED;
  315. pAudioWizOut->uChanged |= SOUNDCARDCAPS_CHANGED;
  316. }
  317. }
  318. LocalFree(pWizConfig);
  319. LocalFree(lpPropSheetPages);
  320. }
  321. INT_PTR CallAudioCalibWizard(HWND hwndOwner, UINT uOptions,
  322. UINT uDevId,PAUDIOWIZOUTPUT pAudioWizOut,INT iSetAgc)
  323. {
  324. //agc values are provided
  325. return(IntCreateAudioCalibWizard(hwndOwner, uOptions, uDevId, pAudioWizOut, iSetAgc));
  326. }
  327. VOID CmdAudioCalibWizard(HWND hwnd)
  328. {
  329. AUDIOWIZOUTPUT awo;
  330. INT_PTR nRet = IntCreateAudioCalibWizard(
  331. hwnd,
  332. RUNDUE_USERINVOKED,
  333. WAVE_MAPPER,
  334. &awo,
  335. READFROM_REGISTRY);
  336. if ((nRet > 0) && (awo.uChanged & SOUNDCARD_CHANGED))
  337. {
  338. ::HandleConfSettingsChange(CSETTING_L_AUDIODEVICE);
  339. }
  340. }
  341. INT_PTR IntCreateAudioCalibWizard(HWND hwndOwner, UINT uOptions,
  342. UINT uDevId, PAUDIOWIZOUTPUT pAudioWizOut, INT iSetAgc)
  343. {
  344. LPPROPSHEETPAGE ppsp;
  345. UINT uNumPages;
  346. PWIZCONFIG pWizConfig;
  347. if (!IntGetAudioWizardPages(uOptions, uDevId,
  348. &ppsp, &pWizConfig, &uNumPages, iSetAgc))
  349. {
  350. return -1;
  351. }
  352. PROPSHEETHEADER psh;
  353. InitStruct(&psh);
  354. // Specify that this is a wizard property sheet with no Apply Now button.
  355. psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
  356. psh.hwndParent = hwndOwner;
  357. // Use page captions.
  358. ASSERT(NULL == psh.pszCaption);
  359. ASSERT(0 == psh.nStartPage);
  360. psh.nPages = uNumPages;
  361. psh.ppsp = ppsp;
  362. // Create and run the wizard.
  363. INT_PTR iRet = PropertySheet(&psh);
  364. ReleaseAudioWizardPages(ppsp, pWizConfig, pAudioWizOut);
  365. return iRet;
  366. }
  367. void SaveAudioWizChanges(PAUDIOWIZINFO pawInfo)
  368. {
  369. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  370. if (pawInfo->uChanged & SOUNDCARDCAPS_CHANGED)
  371. {
  372. re.SetValue ( REGVAL_SOUNDCARDCAPS, pawInfo->uSoundCardCaps);
  373. re.SetValue ( REGVAL_FULLDUPLEX, ISSOUNDCARDFULLDUPLEX(pawInfo->uSoundCardCaps) ? FULLDUPLEX_ENABLED : FULLDUPLEX_DISABLED);
  374. if (!ISDIRECTSOUNDAVAILABLE(pawInfo->uSoundCardCaps))
  375. {
  376. re.SetValue(REGVAL_DIRECTSOUND, (ULONG)DSOUND_USER_DISABLED);
  377. }
  378. }
  379. if (pawInfo->uChanged & CALIBVOL_CHANGED)
  380. {
  381. re.SetValue ( REGVAL_CALIBRATEDVOL, pawInfo->uCalibratedVol);
  382. re.SetValue ( REGVAL_LASTCALIBRATEDVOL, pawInfo->uCalibratedVol);
  383. }
  384. if (pawInfo->uChanged & SOUNDCARD_CHANGED)
  385. {
  386. re.SetValue (REGVAL_WAVEINDEVICEID, pawInfo->uWaveInDevId);
  387. re.SetValue (REGVAL_WAVEINDEVICENAME, pawInfo->szWaveInDevName);
  388. re.SetValue (REGVAL_WAVEOUTDEVICEID, pawInfo->uWaveOutDevId);
  389. re.SetValue (REGVAL_WAVEOUTDEVICENAME, pawInfo->szWaveOutDevName);
  390. }
  391. if (pawInfo->uChanged & SPEAKERVOL_CHANGED)
  392. {
  393. re.SetValue (REGVAL_SPEAKERVOL, pawInfo->uSpeakerVol);
  394. }
  395. }
  396. INT_PTR APIENTRY DetSoundCardWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  397. {
  398. PROPSHEETPAGE * ps;
  399. static PWIZCONFIG pWizConfig;
  400. static PAUDIOWIZINFO pawInfo;
  401. switch (message) {
  402. case WM_INITDIALOG:
  403. // Save the PROPSHEETPAGE information.
  404. ps = (PROPSHEETPAGE *)lParam;
  405. pWizConfig = (PWIZCONFIG)ps->lParam;
  406. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  407. if (g_fSilentWizard)
  408. {
  409. HideWizard(GetParent(hDlg));
  410. }
  411. return (TRUE);
  412. case WM_NOTIFY:
  413. switch (((NMHDR FAR *) lParam)->code) {
  414. case PSN_SETACTIVE:
  415. {
  416. if (pawInfo->uSoundCardCaps != SOUNDCARD_NONE)
  417. {
  418. // Skip this page; go to IDD_AUDIOCALIBWIZ0;
  419. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  420. return TRUE;
  421. }
  422. // Initialize the controls.
  423. DWORD dwWizButtons = PSWIZB_FINISH;
  424. if (pWizConfig->uFlags & STARTWITH_BACK)
  425. dwWizButtons |= PSWIZB_BACK;
  426. PropSheet_SetWizButtons(GetParent(hDlg), dwWizButtons );
  427. if (g_fSilentWizard)
  428. {
  429. PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
  430. }
  431. break;
  432. }
  433. case PSN_WIZNEXT:
  434. // Due to bug in ComCtl32 don't allow next
  435. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  436. return TRUE;
  437. case PSN_WIZBACK:
  438. // Due to bug in ComCtl32 check if button is enabled
  439. if (!(pWizConfig->uFlags & STARTWITH_BACK))
  440. {
  441. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  442. return TRUE;
  443. }
  444. else
  445. {
  446. UINT_PTR iPrev = GetPageBeforeAudioWiz();
  447. ASSERT( iPrev );
  448. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, iPrev);
  449. return TRUE;
  450. }
  451. break;
  452. case PSN_WIZFINISH:
  453. {
  454. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  455. re.SetValue ( REGVAL_SOUNDCARDCAPS, pawInfo->uSoundCardCaps);
  456. break;
  457. }
  458. case PSN_RESET:
  459. pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
  460. break;
  461. default:
  462. break;
  463. }
  464. break;
  465. default:
  466. return FALSE;
  467. }
  468. return (FALSE);
  469. }
  470. INT_PTR APIENTRY AudioCalibWiz0( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  471. {
  472. PROPSHEETPAGE * ps;
  473. static PWIZCONFIG pWizConfig;
  474. static PAUDIOWIZINFO pawInfo;
  475. switch (message) {
  476. case WM_INITDIALOG:
  477. // Save the PROPSHEETPAGE information.
  478. ps = (PROPSHEETPAGE *)lParam;
  479. pWizConfig = (PWIZCONFIG)ps->lParam;
  480. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  481. return TRUE;
  482. case WM_NOTIFY:
  483. switch (((NMHDR FAR *) lParam)->code) {
  484. case PSN_SETACTIVE:
  485. {
  486. // Initialize the controls.
  487. DWORD dwWizButtons = PSWIZB_NEXT;
  488. if (pWizConfig->uFlags & STARTWITH_BACK)
  489. dwWizButtons |= PSWIZB_BACK;
  490. PropSheet_SetWizButtons(GetParent(hDlg), dwWizButtons );
  491. if (g_fSilentWizard)
  492. {
  493. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  494. }
  495. break;
  496. }
  497. case PSN_WIZBACK:
  498. // Due to bug in ComCtl32 check if button is enabled
  499. if (!(pWizConfig->uFlags & STARTWITH_BACK))
  500. {
  501. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  502. return TRUE;
  503. }
  504. if (pawInfo->uSoundCardCaps != SOUNDCARD_NONE)
  505. {
  506. // don't go to the DetSoundCard page...
  507. UINT_PTR iPrev = GetPageBeforeAudioWiz();
  508. ASSERT( iPrev );
  509. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, iPrev);
  510. return TRUE;
  511. }
  512. break;
  513. case PSN_RESET:
  514. pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
  515. break;
  516. default:
  517. break;
  518. }
  519. break;
  520. default:
  521. return FALSE;
  522. }
  523. return (FALSE);
  524. }
  525. INT_PTR APIENTRY AudioCalibWiz1( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  526. {
  527. static PROPSHEETPAGE * ps;
  528. static PWIZCONFIG pWizConfig;
  529. static PAUDIOWIZINFO pawInfo;
  530. UINT uSoundCardCaps;
  531. int nIndex;
  532. HWND hwndCB;
  533. switch (message)
  534. {
  535. case WM_INITDIALOG:
  536. {
  537. WAVEINCAPS wiCaps;
  538. WAVEOUTCAPS woCaps;
  539. LPSTR lpszTemp;
  540. UINT uWaveDevId;
  541. UINT uWaveDevRealId;
  542. UINT uDevCnt;
  543. UINT uCnt;
  544. UINT uDevID;
  545. // Save the PROPSHEETPAGE information.
  546. ps = (PROPSHEETPAGE *)lParam;
  547. pWizConfig = (PWIZCONFIG)ps->lParam;
  548. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  549. //we come to this page only if a sound card is present.
  550. // If we end up with WAVE_MAPPER, this means that this is the first time we run this code
  551. pawInfo->uWaveInDevId = uWaveDevRealId = uWaveDevId = pawInfo->uOldWaveInDevId;
  552. uDevCnt = waveInGetNumDevs();
  553. lstrcpy(pawInfo->szWaveInDevName, lpszTemp = pawInfo->szOldWaveInDevName);
  554. //add the device to the drop down list
  555. hwndCB = GetDlgItem(hDlg, IDC_WAVEIN);
  556. for (uDevID = 0, uCnt = uDevCnt; 0 != uCnt; uDevID++, uCnt--)
  557. {
  558. if ((waveInGetDevCaps(uDevID, &wiCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) &&
  559. (CheckForWaveDeviceSupport(uDevID, 0)))
  560. {
  561. nIndex = ComboBox_AddString(hwndCB, wiCaps.szPname);
  562. ComboBox_SetItemData(hwndCB, nIndex, uDevID);
  563. //if a device hasnt been chosen previously, then set the default device to the
  564. //zeroth one
  565. if (uWaveDevId == WAVE_MAPPER)
  566. {
  567. if (uDevCnt <= 1)
  568. uWaveDevRealId = uDevID;
  569. else
  570. if ((uWaveDevRealId == WAVE_MAPPER) && (uDevCnt == uCnt))
  571. uWaveDevRealId = GetWaveDeviceFromWaveMapper(uCnt, 0);
  572. if (uDevID == uWaveDevRealId)
  573. {
  574. ComboBox_SetCurSel(hwndCB, nIndex);
  575. pawInfo->uWaveInDevId = uDevID;
  576. lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
  577. }
  578. }
  579. else
  580. {
  581. if ((0 == nIndex) || (!lstrcmp(wiCaps.szPname, lpszTemp)))
  582. {
  583. ComboBox_SetCurSel(hwndCB, nIndex);
  584. pawInfo->uWaveInDevId = uDevID;
  585. lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
  586. }
  587. }
  588. }
  589. }
  590. // TEMPORARY 1.0 stuff because this would require too much rewrite:
  591. // In case no device was added to the combo box, let's put the first one in
  592. // even though we know it will never work.
  593. if ((0 == ComboBox_GetCount(hwndCB)) || (uWaveDevRealId == WAVE_MAPPER))
  594. {
  595. waveInGetDevCaps(0,&wiCaps, sizeof(WAVEINCAPS));
  596. if (0 == ComboBox_GetCount(hwndCB))
  597. {
  598. ComboBox_AddString(hwndCB, wiCaps.szPname);
  599. ComboBox_SetItemData(hwndCB, 0, 0);
  600. }
  601. ComboBox_SetCurSel(hwndCB, 0);
  602. pawInfo->uWaveInDevId = 0;
  603. lstrcpy(pawInfo->szWaveInDevName, wiCaps.szPname);
  604. }
  605. // If we end up with WAVE_MAPPER, this means that this is the first time we run this code
  606. pawInfo->uWaveOutDevId = uWaveDevRealId = uWaveDevId = pawInfo->uOldWaveOutDevId;
  607. uDevCnt = waveOutGetNumDevs();
  608. lstrcpy(pawInfo->szWaveOutDevName, lpszTemp = pawInfo->szOldWaveOutDevName);
  609. //add the device to the drop down list
  610. hwndCB = GetDlgItem(hDlg, IDC_WAVEOUT);
  611. for (uDevID = 0, uCnt = uDevCnt; 0 != uCnt; uDevID++, uCnt--)
  612. {
  613. if ((waveOutGetDevCaps(uDevID, &woCaps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) &&
  614. (CheckForWaveDeviceSupport(uDevID, 1)))
  615. {
  616. nIndex = ComboBox_AddString(hwndCB, woCaps.szPname);
  617. ComboBox_SetItemData(hwndCB, nIndex, uDevID);
  618. //if a device hasnt been chosen previously, then set the default device to the
  619. //zeroth one
  620. if (uWaveDevId == WAVE_MAPPER)
  621. {
  622. if (uDevCnt <= 1)
  623. uWaveDevRealId = uDevID;
  624. else
  625. if ((uWaveDevRealId == WAVE_MAPPER) && (uDevCnt == uCnt))
  626. uWaveDevRealId = GetWaveDeviceFromWaveMapper(uCnt, 1);
  627. if (uDevID == uWaveDevRealId)
  628. {
  629. ComboBox_SetCurSel(hwndCB, nIndex);
  630. pawInfo->uWaveOutDevId = uDevID;
  631. lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
  632. }
  633. }
  634. else
  635. {
  636. if ((0 == nIndex) || (!lstrcmp(woCaps.szPname, lpszTemp)))
  637. {
  638. ComboBox_SetCurSel(hwndCB, nIndex);
  639. pawInfo->uWaveOutDevId = uDevID;
  640. lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
  641. }
  642. }
  643. }
  644. }
  645. // TEMPORARY 1.0 stuff because this would require too much rewrite:
  646. // In case no device was added to the combo box, let's put the first one in
  647. // even though we know it will never work.
  648. if ((0 == ComboBox_GetCount(hwndCB)) || (uWaveDevRealId == WAVE_MAPPER))
  649. {
  650. waveOutGetDevCaps(0,&woCaps, sizeof(WAVEOUTCAPS));
  651. if (0 == ComboBox_GetCount(hwndCB))
  652. {
  653. ComboBox_AddString(hwndCB, (LPARAM)woCaps.szPname);
  654. ComboBox_SetItemData(hwndCB, 0, 0);
  655. }
  656. ComboBox_SetCurSel(hwndCB, 0);
  657. pawInfo->uWaveOutDevId = 0;
  658. lstrcpy(pawInfo->szWaveOutDevName, woCaps.szPname);
  659. }
  660. return (TRUE);
  661. }
  662. case WM_NOTIFY:
  663. switch (((NMHDR FAR *) lParam)->code) {
  664. case PSN_SETACTIVE:
  665. // Initialize the controls.
  666. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  667. if (g_fSilentWizard)
  668. {
  669. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  670. break;
  671. }
  672. else
  673. {
  674. if ((1 != ComboBox_GetCount(GetDlgItem(hDlg, IDC_WAVEIN))) ||
  675. (1 != ComboBox_GetCount(GetDlgItem(hDlg, IDC_WAVEOUT))))
  676. {
  677. break;
  678. }
  679. // else fall through to next
  680. }
  681. case PSN_WIZNEXT:
  682. // set settings in registry
  683. //check the device
  684. //get the new wavein device and its info
  685. hwndCB = GetDlgItem(hDlg, IDC_WAVEIN);
  686. nIndex = ComboBox_GetCurSel(hwndCB);
  687. pawInfo->uWaveInDevId = (UINT)ComboBox_GetItemData(hwndCB, nIndex);
  688. ComboBox_GetLBText(hwndCB, nIndex, pawInfo->szWaveInDevName);
  689. //get the new waveout device and its info
  690. hwndCB = GetDlgItem(hDlg, IDC_WAVEOUT);
  691. nIndex = ComboBox_GetCurSel(hwndCB);
  692. pawInfo->uWaveOutDevId = (UINT)ComboBox_GetItemData(hwndCB, nIndex);
  693. ComboBox_GetLBText(hwndCB, nIndex, pawInfo->szWaveOutDevName);
  694. uSoundCardCaps = GetSoundCardCaps(pawInfo->uWaveInDevId,pawInfo->uWaveOutDevId, hDlg);
  695. //save it in the wizinfo struct for writing to registry
  696. pawInfo->uSoundCardCaps = uSoundCardCaps;
  697. pawInfo->uChanged |= SOUNDCARDCAPS_CHANGED;
  698. pawInfo->uChanged |= SOUNDCARD_CHANGED;
  699. if (PSN_SETACTIVE == ((NMHDR FAR *) lParam)->code)
  700. {
  701. // Skip this page;
  702. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  703. return TRUE;
  704. }
  705. break;
  706. case PSN_RESET:
  707. {
  708. pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
  709. break;
  710. }
  711. default:
  712. break;
  713. }
  714. break;
  715. default:
  716. return FALSE;
  717. }
  718. return (FALSE);
  719. }
  720. // The WaveOut test page
  721. INT_PTR WINAPI AudioCalibWiz2(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  722. {
  723. static CMixerDevice *pMixer = NULL;
  724. static HWND hTrackBar;
  725. DWORD dwTBPos;
  726. MIXVOLUME dwNewVol;
  727. static MIXVOLUME dwVol; // last set volume
  728. BOOL fRet;
  729. static BOOL fCanSetVolume = FALSE;
  730. static waveOutDev *pWaveOut= NULL;
  731. UINT uWaveOutDevId;
  732. static PROPSHEETPAGE * ps;
  733. static PWIZCONFIG pWizConfig;
  734. static PAUDIOWIZINFO pawInfo;
  735. TCHAR szText[ATW_MSG_LENGTH];
  736. MMRESULT mmr;
  737. static fIsPlaying;
  738. switch (msg)
  739. {
  740. case (WM_INITDIALOG):
  741. {
  742. pMixer = NULL;
  743. hTrackBar = GetDlgItem(hDlg, IDC_ATW_SLIDER1);
  744. ps = (PROPSHEETPAGE *)lParam;
  745. pWizConfig = (PWIZCONFIG)ps->lParam;
  746. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  747. break;
  748. }
  749. case (WM_NOTIFY):
  750. {
  751. switch (((NMHDR *)lParam)->code)
  752. {
  753. case PSN_SETACTIVE:
  754. fIsPlaying = FALSE;
  755. uWaveOutDevId = pawInfo->uWaveOutDevId;
  756. pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, uWaveOutDevId, MIXER_OBJECTF_WAVEOUT);
  757. if (pMixer)
  758. {
  759. SendMessage(hTrackBar, TBM_SETRANGE, TRUE, (LPARAM)MAKELONG(0, 100));
  760. SendMessage(hTrackBar, TBM_SETTICFREQ, 10, 0);
  761. SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 20);
  762. SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 10);
  763. pMixer->GetVolume(&dwVol);
  764. fCanSetVolume = pMixer->SetVolume(&dwVol);
  765. pMixer->UnMuteVolume();
  766. // preserve the speaker volume so that it can be restored
  767. // if the user presses cancel
  768. if (pawInfo->uPreCalibSpkVol.leftVolume == MIXER_VOLUME_UNINITIALIZED)
  769. {
  770. pawInfo->uPreCalibSpkVol.leftVolume = dwVol.leftVolume;
  771. }
  772. if (pawInfo->uPreCalibSpkVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
  773. {
  774. pawInfo->uPreCalibSpkVol.rightVolume = dwVol.rightVolume;
  775. }
  776. }
  777. else
  778. fCanSetVolume = FALSE;
  779. EnableWindow(GetDlgItem(hDlg, IDC_GROUP_VOLUME), fCanSetVolume);
  780. EnableWindow(GetDlgItem(hDlg, IDC_ATW_SLIDER1), fCanSetVolume);
  781. EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_ATW_TEST), TRUE);
  782. if (fCanSetVolume)
  783. {
  784. FLoadString(IDS_ATW_PLAYBACK, szText, CCHMAX(szText));
  785. SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
  786. }
  787. // if we can't get a mixer, then center the trackbar and disable
  788. else
  789. {
  790. FLoadString(IDS_ATW_PLAYBACK_NOMIX, szText, CCHMAX(szText));
  791. SendMessage(hTrackBar, TBM_SETPOS, TRUE, 50);
  792. }
  793. SetDlgItemText(hDlg, IDC_ATW_PLAYTEXT, szText);
  794. SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, TEXT(""));
  795. FLoadString(IDS_TESTBUTTON_TEXT, szText, CCHMAX(szText));
  796. SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
  797. pWaveOut = new waveOutDev(uWaveOutDevId, hDlg);
  798. if (pWaveOut == NULL)
  799. {
  800. ERROR_OUT(("AudioWiz2: Unable to create waveOutDev object"));
  801. }
  802. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_NEXT);
  803. if (g_fSilentWizard)
  804. {
  805. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  806. return TRUE;
  807. }
  808. break;
  809. case PSN_WIZNEXT:
  810. case PSN_WIZBACK:
  811. case PSN_WIZFINISH:
  812. case PSN_KILLACTIVE:
  813. if ((fCanSetVolume) && (pMixer))
  814. {
  815. pMixer->GetVolume(&dwNewVol);
  816. pawInfo->uSpeakerVol = max(dwNewVol.leftVolume , dwNewVol.rightVolume);
  817. pawInfo->uChanged |= SPEAKERVOL_CHANGED;
  818. }
  819. if (pMixer)
  820. {
  821. delete pMixer;
  822. pMixer = NULL;
  823. }
  824. if (pWaveOut)
  825. {
  826. delete pWaveOut;
  827. pWaveOut = NULL;
  828. }
  829. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
  830. break;
  831. case PSN_RESET:
  832. // psn_reset get's received even if user presses
  833. // cancel on another dialog.
  834. // restore speaker volume to what it was before the tuning wizard was launched
  835. if (pawInfo->uPreCalibSpkVol.leftVolume <= MIXER_VOLUME_MAX || pawInfo->uPreCalibSpkVol.rightVolume <= MIXER_VOLUME_MAX)
  836. {
  837. if (pMixer == NULL)
  838. {
  839. pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveOutDevId, MIXER_OBJECTF_WAVEOUT);
  840. }
  841. if (pMixer)
  842. {
  843. pMixer->SetVolume(&pawInfo->uPreCalibSpkVol);
  844. }
  845. }
  846. if (pMixer)
  847. {
  848. delete pMixer;
  849. pMixer = NULL;
  850. }
  851. if (pWaveOut)
  852. {
  853. delete pWaveOut;
  854. pWaveOut = NULL;
  855. }
  856. break;
  857. default:
  858. return FALSE;
  859. }
  860. return TRUE;
  861. }
  862. case (WM_HSCROLL): // trackbar notification
  863. {
  864. dwTBPos = (DWORD)SendMessage(hTrackBar, TBM_GETPOS, 0, 0);
  865. if (pMixer)
  866. {
  867. pMixer->GetVolume(&dwVol);
  868. NewMixVolume(&dwNewVol, dwVol, (dwTBPos * TB_VOL_INCREMENT));
  869. pMixer->SetVolume(&dwNewVol);
  870. }
  871. break;
  872. }
  873. // mixer notifications
  874. case MM_MIXM_CONTROL_CHANGE:
  875. case MM_MIXM_LINE_CHANGE:
  876. {
  877. if (pMixer)
  878. {
  879. fRet = pMixer->GetVolume(&dwNewVol);
  880. if ((fRet) && (dwNewVol.leftVolume != dwVol.leftVolume || dwNewVol.rightVolume != dwVol.rightVolume))
  881. {
  882. dwVol = dwNewVol;
  883. SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
  884. break;
  885. }
  886. }
  887. break;
  888. }
  889. // when the PlayFile is done playing
  890. case WOM_DONE:
  891. {
  892. if ((pWaveOut) && (fIsPlaying))
  893. {
  894. pWaveOut->PlayFile(ATW_PLAYFILE_SOUND);
  895. }
  896. break;
  897. }
  898. case WM_COMMAND:
  899. {
  900. // if the device fails to open, then we
  901. // display the error text
  902. // if the WAV file fails to load, we simply disable the button
  903. if (LOWORD(wParam) == IDC_BUTTON_ATW_TEST)
  904. {
  905. if (fIsPlaying == TRUE)
  906. {
  907. fIsPlaying = FALSE;
  908. pWaveOut->Close();
  909. FLoadString(IDS_TESTBUTTON_TEXT, szText, CCHMAX(szText));
  910. SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
  911. break;
  912. }
  913. mmr = pWaveOut->PlayFile(ATW_PLAYFILE_SOUND);
  914. if (mmr == MMSYSERR_ALLOCATED )
  915. {
  916. FLoadString(IDS_PLAYBACK_ERROR, szText, CCHMAX(szText));
  917. SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, szText);
  918. }
  919. else if (mmr != MMSYSERR_NOERROR)
  920. {
  921. EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_ATW_TEST), FALSE);
  922. FLoadString(IDS_PLAYBACK_ERROR2, szText, CCHMAX(szText));
  923. SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, szText);
  924. }
  925. else // mmr == MMSYSERR_NOERROR
  926. {
  927. SetDlgItemText(hDlg, IDC_ATW_PLAYBACK_ERROR, TEXT(""));
  928. FLoadString(IDS_STOPBUTTON_TEXT, szText, CCHMAX(szText));
  929. SetDlgItemText(hDlg, IDC_BUTTON_ATW_TEST, szText);
  930. fIsPlaying = TRUE;
  931. }
  932. }
  933. break;
  934. }
  935. default:
  936. return FALSE;
  937. }
  938. return TRUE;
  939. }
  940. // Microphone test page
  941. INT_PTR WINAPI AudioCalibWiz3(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  942. {
  943. static HANDLE hThread = NULL;
  944. static DWORD dwThreadID = 0;
  945. static HANDLE hEvent = NULL;
  946. static CMixerDevice *pMixer = NULL;
  947. static HWND hTrackBar;
  948. static DWORD dwMainVol;
  949. static DWORD dwSubVol;
  950. DWORD dwTBPos, dwNewMainVol, dwNewSubVol;
  951. MIXVOLUME dwVol, dwNewVol;
  952. BOOL fRet;
  953. static BOOL fCanSetVolume=FALSE;
  954. static CALIB_DISPLAY CalibDisplay;
  955. static PROPSHEETPAGE * ps;
  956. static PWIZCONFIG pWizConfig;
  957. static PAUDIOWIZINFO pawInfo;
  958. static BOOL fSoundDetected;
  959. const TCHAR *szEventName = _TEXT("CONF.EXE ATW Event Handle");
  960. switch (msg)
  961. {
  962. case (WM_INITDIALOG):
  963. {
  964. hThread = NULL;
  965. dwThreadID = NULL;
  966. hTrackBar = GetDlgItem(hDlg, IDC_ATW_SLIDER2);
  967. ps = (PROPSHEETPAGE *)lParam;
  968. pWizConfig = (PWIZCONFIG)ps->lParam;
  969. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  970. break;
  971. }
  972. case (WM_NOTIFY):
  973. {
  974. switch (((NMHDR *)lParam)->code)
  975. {
  976. case PSN_SETACTIVE:
  977. if (g_fSilentWizard)
  978. {
  979. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  980. return TRUE;
  981. }
  982. fCanSetVolume = TRUE;
  983. fSoundDetected = FALSE;
  984. pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveInDevId, MIXER_OBJECTF_WAVEIN);
  985. if (pMixer)
  986. {
  987. SendMessage(hTrackBar, TBM_SETRANGE, TRUE, (LPARAM)MAKELONG(0, 100));
  988. SendMessage(hTrackBar, TBM_SETTICFREQ, 10, 0);
  989. SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 20);
  990. SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 10);
  991. // remember the volume in case the user presses cancel
  992. if (pawInfo->uPreCalibMainVol.leftVolume == MIXER_VOLUME_UNINITIALIZED ||
  993. pawInfo->uPreCalibMainVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
  994. {
  995. pMixer->GetMainVolume(&(pawInfo->uPreCalibMainVol));
  996. }
  997. if (pawInfo->uPreCalibSubVol.leftVolume == MIXER_VOLUME_UNINITIALIZED ||
  998. pawInfo->uPreCalibSubVol.rightVolume == MIXER_VOLUME_UNINITIALIZED)
  999. {
  1000. pMixer->GetSubVolume(&(pawInfo->uPreCalibSubVol));
  1001. }
  1002. MIXVOLUME mixVol = {-1, -1};
  1003. pMixer->GetVolume(&mixVol);
  1004. fCanSetVolume = pMixer->SetVolume(&mixVol);
  1005. dwSubVol = dwMainVol= 0xffff;
  1006. SendMessage(hTrackBar, TBM_SETPOS, TRUE, dwMainVol/TB_VOL_INCREMENT);
  1007. pMixer->EnableMicrophone();
  1008. pMixer->UnMuteVolume();
  1009. StartAGC(pMixer, pawInfo->iSetAgc, pawInfo->uSoundCardCaps);
  1010. }
  1011. // no mixer!
  1012. if (pMixer == NULL)
  1013. {
  1014. ProcessCalibError(CALIBERR_MIXER_ERROR, pawInfo);
  1015. }
  1016. // no microphone!
  1017. else if (fCanSetVolume == FALSE)
  1018. {
  1019. delete pMixer;
  1020. pMixer = NULL;
  1021. ProcessCalibError(CALIBERR_CANT_SET_VOLUME, pawInfo);
  1022. }
  1023. // process error
  1024. if ((pMixer == NULL) || (fCanSetVolume == FALSE))
  1025. {
  1026. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_AUDIOCALIBERRWIZ);
  1027. return TRUE;
  1028. }
  1029. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
  1030. CalibDisplay.hDlg = hDlg;
  1031. CalibDisplay.hVUMeter = GetDlgItem(hDlg, IDC_VUMETER);
  1032. CalibDisplay.uWaveInDevId = pawInfo->uWaveInDevId;
  1033. ASSERT(hEvent == NULL);
  1034. // just create the same event twice (easier than using DuplicateHandle)
  1035. hEvent = CreateEvent(NULL, FALSE, FALSE, szEventName);
  1036. CalibDisplay.hEvent = CreateEvent(NULL, FALSE, FALSE, szEventName);
  1037. ASSERT(hThread == NULL);
  1038. hThread = NULL;
  1039. if (hEvent && (CalibDisplay.hEvent))
  1040. {
  1041. hThread = CreateThread(NULL, 0, CalibrateTalking, (LPVOID)(&CalibDisplay), 0, &dwThreadID);
  1042. }
  1043. #ifdef DEBUG
  1044. if ((hEvent == NULL) || (CalibDisplay.hEvent == NULL))
  1045. {
  1046. ERROR_OUT(("ATW: Unable to create events for thread control!\r\n"));
  1047. }
  1048. else if (hThread == NULL)
  1049. {
  1050. ERROR_OUT(("ATW: Unable to create thread for recording loop!\r\n"));
  1051. }
  1052. #endif
  1053. break;
  1054. case PSN_WIZNEXT:
  1055. case PSN_WIZBACK:
  1056. case PSN_WIZFINISH:
  1057. case PSN_KILLACTIVE:
  1058. if (hThread)
  1059. {
  1060. SetEvent(hEvent); // signal the thread to exit, thread will CloseHandle(hEvent)
  1061. // wait for the thread to exit, but
  1062. // but keep processing window messages
  1063. AtlWaitWithMessageLoop(hThread);
  1064. CloseHandle(hEvent);
  1065. CloseHandle(hThread);
  1066. hThread = NULL;
  1067. hEvent = NULL;
  1068. dwThreadID = 0;
  1069. }
  1070. // silent wizard get's set to max
  1071. if (g_fSilentWizard)
  1072. {
  1073. pawInfo->uChanged |= CALIBVOL_CHANGED;
  1074. pawInfo->uChanged = 0xffff;
  1075. }
  1076. else if ((fCanSetVolume) && (pMixer))
  1077. {
  1078. pawInfo->uChanged |= CALIBVOL_CHANGED;
  1079. pMixer->GetVolume(&dwVol);
  1080. pawInfo->uCalibratedVol = max (dwVol.leftVolume , dwVol.rightVolume);
  1081. }
  1082. if (pMixer)
  1083. {
  1084. delete pMixer;
  1085. pMixer = NULL;
  1086. }
  1087. // if we never got an indication back from the sound thread
  1088. // then the next page to be displayed is the "microphone" error page
  1089. // note the check for the silent wizard
  1090. if ((!g_fSilentWizard) && (fSoundDetected == FALSE) && (((NMHDR *)lParam)->code == PSN_WIZNEXT))
  1091. {
  1092. ProcessCalibError(CALIBERR_NO_MICROPHONE, pawInfo);
  1093. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, IDD_AUDIOCALIBERRWIZ);
  1094. }
  1095. else
  1096. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
  1097. break;
  1098. case PSN_RESET:
  1099. // psn_reset get's received even if user presses
  1100. // cancel on another dialog.
  1101. if (hThread)
  1102. {
  1103. SetEvent(hEvent); // signal thread to exit
  1104. AtlWaitWithMessageLoop(hThread);
  1105. CloseHandle(hEvent);
  1106. hEvent = NULL;
  1107. CloseHandle(hThread);
  1108. hThread = NULL;
  1109. dwThreadID = 0;
  1110. }
  1111. // restore recording/microphone volume to what it was before the tuning wizard was launched
  1112. if ( (pawInfo->uPreCalibMainVol.leftVolume <= MIXER_VOLUME_MAX && pawInfo->uPreCalibMainVol.rightVolume <= MIXER_VOLUME_MAX) ||
  1113. (pawInfo->uPreCalibSubVol.leftVolume <= MIXER_VOLUME_MAX && pawInfo->uPreCalibSubVol.rightVolume <= MIXER_VOLUME_MAX))
  1114. {
  1115. if (pMixer == NULL)
  1116. {
  1117. pMixer = CMixerDevice::GetMixerForWaveDevice(hDlg, pawInfo->uWaveInDevId, MIXER_OBJECTF_WAVEIN);
  1118. }
  1119. if (pMixer)
  1120. {
  1121. if (pawInfo->uPreCalibMainVol.leftVolume < MIXER_VOLUME_MAX || pawInfo->uPreCalibMainVol.rightVolume < MIXER_VOLUME_MAX)
  1122. {
  1123. pMixer->SetMainVolume(&pawInfo->uPreCalibMainVol);
  1124. }
  1125. if (pawInfo->uPreCalibSubVol.leftVolume < MIXER_VOLUME_MAX || pawInfo->uPreCalibSubVol.rightVolume < MIXER_VOLUME_MAX)
  1126. {
  1127. pMixer->SetSubVolume(&pawInfo->uPreCalibSubVol);
  1128. }
  1129. }
  1130. }
  1131. if (pMixer)
  1132. {
  1133. delete pMixer;
  1134. pMixer = NULL;
  1135. }
  1136. break;
  1137. default:
  1138. return FALSE;
  1139. }
  1140. return TRUE;
  1141. }
  1142. case (WM_HSCROLL): // trackbar notification
  1143. {
  1144. dwTBPos = (DWORD)SendMessage(hTrackBar, TBM_GETPOS, 0, 0);
  1145. if (pMixer)
  1146. {
  1147. pMixer->GetVolume(&dwVol);
  1148. NewMixVolume(&dwNewVol, dwVol, (dwTBPos * TB_VOL_INCREMENT));
  1149. pMixer->SetVolume(&dwNewVol);
  1150. }
  1151. break;
  1152. }
  1153. // notifications from the mixer
  1154. case MM_MIXM_CONTROL_CHANGE:
  1155. case MM_MIXM_LINE_CHANGE:
  1156. {
  1157. if (pMixer)
  1158. {
  1159. fRet = pMixer->GetMainVolume(&dwVol);
  1160. if ((fRet) && (dwVol.leftVolume != dwMainVol || dwVol.rightVolume != dwMainVol))
  1161. {
  1162. pMixer->SetSubVolume(&dwVol);
  1163. SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(dwVol.leftVolume , dwVol.rightVolume)/TB_VOL_INCREMENT);
  1164. break;
  1165. }
  1166. MIXVOLUME subvol;
  1167. fRet = pMixer->GetSubVolume(&subvol);
  1168. if ((fRet) && (dwVol.leftVolume != subvol.leftVolume || dwVol.rightVolume !=subvol.rightVolume))
  1169. {
  1170. pMixer->SetMainVolume(&subvol);
  1171. SendMessage(hTrackBar, TBM_SETPOS, TRUE, max(subvol.leftVolume , subvol.rightVolume)/TB_VOL_INCREMENT);
  1172. break;
  1173. }
  1174. }
  1175. break;
  1176. }
  1177. // calibration thread sends this message to indicate that the
  1178. // volume is too loud
  1179. case WM_AUDIO_CLIPPING:
  1180. {
  1181. if (pMixer)
  1182. {
  1183. pMixer->GetVolume(&dwVol);
  1184. if (dwVol.leftVolume > DECREMENT_AMOUNT || dwVol.rightVolume > DECREMENT_AMOUNT)
  1185. {
  1186. dwVol.leftVolume -=DECREMENT_AMOUNT;
  1187. dwVol.rightVolume -=DECREMENT_AMOUNT;
  1188. pMixer->SetVolume(&dwVol);
  1189. // fix for Videum driver
  1190. // check to see if the volume actually got lowered
  1191. // if it didn't, try a larger decrement
  1192. pMixer->GetVolume(&dwNewVol);
  1193. if ((dwNewVol.leftVolume == dwVol.leftVolume) && (dwVol.leftVolume >= DECREMENT_AMOUNT_LARGE) ||
  1194. (dwNewVol.rightVolume == dwVol.rightVolume) && (dwVol.rightVolume >= DECREMENT_AMOUNT_LARGE))
  1195. {
  1196. dwVol.leftVolume -=DECREMENT_AMOUNT_LARGE;
  1197. dwVol.rightVolume -=DECREMENT_AMOUNT_LARGE;
  1198. pMixer->SetVolume(&dwVol);
  1199. }
  1200. }
  1201. }
  1202. break;
  1203. }
  1204. // the recording thread is signaling back to us that there is
  1205. // a severe error. Assume the thread has exited
  1206. case WM_AUDIOTHREAD_ERROR:
  1207. {
  1208. ProcessCalibError(CALIBERR_DEVICE_ERROR, pawInfo);
  1209. PropSheet_SetCurSelByID(GetParent(hDlg), IDD_AUDIOCALIBERRWIZ);
  1210. break;
  1211. }
  1212. // The recording thread will send this message back to us
  1213. // at least once to indicate that the silence threshold was
  1214. // broken. Thus, the microphone is functional.
  1215. case WM_AUDIOTHREAD_SOUND:
  1216. {
  1217. fSoundDetected = TRUE;
  1218. break;
  1219. }
  1220. default:
  1221. return FALSE;
  1222. }
  1223. return TRUE;
  1224. }
  1225. INT_PTR APIENTRY AudioCalibWiz4( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1226. {
  1227. static PROPSHEETPAGE * ps;
  1228. static PWIZCONFIG pWizConfig;
  1229. static PAUDIOWIZINFO pawInfo;
  1230. switch (message) {
  1231. case WM_INITDIALOG:
  1232. {
  1233. // Save the PROPSHEETPAGE information.
  1234. ps = (PROPSHEETPAGE *)lParam;
  1235. pWizConfig = (PWIZCONFIG)ps->lParam;
  1236. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  1237. return (TRUE);
  1238. }
  1239. case WM_NOTIFY:
  1240. switch (((NMHDR FAR *) lParam)->code) {
  1241. case PSN_SETACTIVE:
  1242. {
  1243. // Initialize the controls.
  1244. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
  1245. if (g_fSilentWizard)
  1246. {
  1247. PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
  1248. }
  1249. break;
  1250. }
  1251. case PSN_WIZNEXT:
  1252. // Due to bug in ComCtl32 don't allow next
  1253. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  1254. return TRUE;
  1255. case PSN_WIZFINISH:
  1256. SaveAudioWizChanges(pawInfo);
  1257. break;
  1258. }
  1259. break;
  1260. }
  1261. return (FALSE);
  1262. }
  1263. INT_PTR APIENTRY AudioCalibErrWiz( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1264. {
  1265. PROPSHEETPAGE * ps;
  1266. PWIZCONFIG pWizConfig;
  1267. static PAUDIOWIZINFO pawInfo;
  1268. TCHAR szTemp[MAXSTRINGSIZE];
  1269. LPTSTR pszIcon;
  1270. //WORD wCmdId;
  1271. switch (message) {
  1272. case WM_INITDIALOG:
  1273. {
  1274. // Save the PROPSHEETPAGE information.
  1275. ps = (PROPSHEETPAGE *)lParam;
  1276. pWizConfig = (PWIZCONFIG)ps->lParam;
  1277. pawInfo = (PAUDIOWIZINFO)pWizConfig->pCustomData;
  1278. return (TRUE);
  1279. }
  1280. case WM_NOTIFY:
  1281. switch (((NMHDR FAR *) lParam)->code) {
  1282. case PSN_SETACTIVE:
  1283. // initialize the controls.
  1284. // Show the error or warning icon
  1285. pszIcon = (((pawInfo->ErrWizInfo).uType == AUDIOWIZ_WARNING) ?
  1286. IDI_ASTERISK : IDI_EXCLAMATION);
  1287. // Set the wizard bitmap to the static control
  1288. ::SendDlgItemMessage( hDlg,
  1289. IDC_ERRWIZICON,
  1290. STM_SETIMAGE,
  1291. IMAGE_ICON,
  1292. (LPARAM) ::LoadIcon(NULL, pszIcon));
  1293. //set the error title
  1294. if ((pawInfo->ErrWizInfo).uErrTitleId)
  1295. {
  1296. LoadString(GetInstanceHandle(),(pawInfo->ErrWizInfo).uErrTitleId,
  1297. szTemp, MAXSTRINGSIZE);
  1298. SetDlgItemText(hDlg, IDC_ERRTITLE, szTemp);
  1299. }
  1300. if ((pawInfo->ErrWizInfo).uErrTextId)
  1301. {
  1302. //show the error text
  1303. LoadString(GetInstanceHandle(),(pawInfo->ErrWizInfo).uErrTextId,
  1304. szTemp, MAXSTRINGSIZE);
  1305. SetDlgItemText(hDlg, IDC_ERRTEXT, szTemp);
  1306. }
  1307. PropSheet_SetWizButtons(GetParent(hDlg),
  1308. (pawInfo->ErrWizInfo).uButtonOptions );
  1309. if (g_fSilentWizard)
  1310. {
  1311. // Due to bug in ComCtl32 check if button is enabled
  1312. if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_FINISH))
  1313. {
  1314. PropSheet_PressButton(GetParent(hDlg), PSBTN_FINISH);
  1315. }
  1316. else
  1317. {
  1318. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  1319. }
  1320. }
  1321. break;
  1322. case PSN_WIZNEXT:
  1323. // Due to bug in ComCtl32 check if button is enabled
  1324. if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_NEXT))
  1325. {
  1326. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  1327. return TRUE;
  1328. }
  1329. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (pawInfo->ErrWizInfo).uNextWizId);
  1330. return TRUE;
  1331. case PSN_RESET:
  1332. pawInfo->uChanged = AUDIOWIZ_NOCHANGES;
  1333. break;
  1334. case PSN_WIZFINISH:
  1335. // Due to bug in ComCtl32 check if button is enabled
  1336. if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_FINISH))
  1337. {
  1338. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  1339. return TRUE;
  1340. }
  1341. SaveAudioWizChanges(pawInfo);
  1342. break;
  1343. case PSN_WIZBACK:
  1344. // Due to bug in ComCtl32 check if button is enabled
  1345. if (!((pawInfo->ErrWizInfo).uButtonOptions & PSWIZB_BACK))
  1346. {
  1347. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
  1348. return TRUE;
  1349. }
  1350. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (pawInfo->ErrWizInfo).uBackWizId);
  1351. return TRUE;
  1352. }
  1353. break;
  1354. }
  1355. return (FALSE);
  1356. }
  1357. void ProcessCalibError(UINT uCalibErr, PAUDIOWIZINFO pawInfo)
  1358. {
  1359. switch (uCalibErr)
  1360. {
  1361. case CALIBERR_CANT_SET_VOLUME:
  1362. pawInfo->ErrWizInfo.uType = AUDIOWIZ_WARNING;
  1363. pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
  1364. pawInfo->ErrWizInfo.uErrTextId = IDS_NORECVOLCNTRL;
  1365. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
  1366. pawInfo->ErrWizInfo.uNextWizId = 0;
  1367. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
  1368. break;
  1369. case CALIBERR_NO_MIXERS:
  1370. pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
  1371. pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
  1372. pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
  1373. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
  1374. pawInfo->ErrWizInfo.uNextWizId = 0;
  1375. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ1;
  1376. break;
  1377. case CALIBERR_MIXER_ERROR:
  1378. pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
  1379. pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
  1380. pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
  1381. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
  1382. pawInfo->ErrWizInfo.uNextWizId = 0;
  1383. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
  1384. break;
  1385. case CALIBERR_CANT_OPEN_WAVE_DEV:
  1386. pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
  1387. pawInfo->ErrWizInfo.uErrTitleId = IDS_CANTOPENWAVE;
  1388. pawInfo->ErrWizInfo.uErrTextId = IDS_QUITPROGRAM;
  1389. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_NEXT|PSWIZB_BACK;
  1390. pawInfo->ErrWizInfo.uNextWizId = IDD_AUDIOCALIBWIZ3;
  1391. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ1;
  1392. break;
  1393. case CALIBERR_NO_MICROPHONE:
  1394. pawInfo->ErrWizInfo.uType = AUDIOWIZ_WARNING;
  1395. pawInfo->ErrWizInfo.uErrTitleId = IDS_NO_MICROPHONE;
  1396. pawInfo->ErrWizInfo.uErrTextId = IDS_NO_MICWARNING;
  1397. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_NEXT|PSWIZB_BACK;
  1398. pawInfo->ErrWizInfo.uNextWizId = IDD_AUDIOCALIBWIZ4;
  1399. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ3;
  1400. break;
  1401. default:
  1402. case CALIBERR_DEVICE_ERROR:
  1403. pawInfo->ErrWizInfo.uType = AUDIOWIZ_ERROR;
  1404. pawInfo->ErrWizInfo.uErrTitleId = IDS_UNSUPPORTEDCARD;
  1405. pawInfo->ErrWizInfo.uErrTextId = IDS_AUDIO_ERROR;
  1406. pawInfo->ErrWizInfo.uButtonOptions = PSWIZB_FINISH|PSWIZB_BACK;
  1407. pawInfo->ErrWizInfo.uNextWizId = 0;
  1408. pawInfo->ErrWizInfo.uBackWizId = IDD_AUDIOCALIBWIZ2;
  1409. break;
  1410. }
  1411. }
  1412. UINT GetSoundCardCaps(UINT uWaveInDevId, UINT uWaveOutDevId, HWND hwnd)
  1413. {
  1414. UINT uSoundCardCaps;
  1415. UINT uRet;
  1416. bool bFD = false;
  1417. UINT uDSCheck;
  1418. uSoundCardCaps = SOUNDCARD_PRESENT;
  1419. if ((uRet = CheckForFullDuplex(uWaveInDevId,uWaveOutDevId)) == SOUNDCARD_NONE)
  1420. {
  1421. //failed to open wave device
  1422. //SS:Error message ??
  1423. //all applications using the wave device should be closed
  1424. }
  1425. else if (uRet == SOUNDCARD_FULLDUPLEX)
  1426. {
  1427. uSoundCardCaps = uSoundCardCaps | SOUNDCARD_FULLDUPLEX;
  1428. bFD = true;
  1429. }
  1430. if ((uRet = CheckForAgc(uWaveInDevId)) == SOUNDCARD_NONE)
  1431. {
  1432. //mixer initialization failed
  1433. //SS: Error message
  1434. }
  1435. else if (uRet == SOUNDCARD_HAVEAGC)
  1436. uSoundCardCaps = uSoundCardCaps | SOUNDCARD_HAVEAGC;
  1437. uDSCheck = DirectSoundCheck(uWaveInDevId, uWaveOutDevId, hwnd);
  1438. if (uDSCheck & DS_FULLDUPLEX)
  1439. {
  1440. uSoundCardCaps = uSoundCardCaps | SOUNDCARD_DIRECTSOUND;
  1441. }
  1442. return(uSoundCardCaps);
  1443. }
  1444. UINT CheckForFullDuplex(UINT uWaveInDevId,UINT uWaveOutDevId)
  1445. {
  1446. HWAVEIN hWaveIn=NULL;
  1447. HWAVEOUT hWaveOut=NULL;
  1448. MMRESULT mmr;
  1449. UINT uRet = SOUNDCARD_NONE;
  1450. waveInDev waveIn(uWaveInDevId);
  1451. waveOutDev waveOut(uWaveOutDevId);
  1452. mmr = waveOut.Open();
  1453. if (mmr != MMSYSERR_NOERROR)
  1454. {
  1455. return SOUNDCARD_NONE;
  1456. }
  1457. mmr = waveIn.Open();
  1458. if (mmr != MMSYSERR_NOERROR)
  1459. {
  1460. return SOUNDCARD_PRESENT;
  1461. }
  1462. return SOUNDCARD_FULLDUPLEX;
  1463. // object destructors will close devices
  1464. }
  1465. UINT GetWaveDeviceFromWaveMapper(UINT uNumWaveDevId, UINT uInOrOut)
  1466. {
  1467. HWAVE hWave=NULL;
  1468. HWAVE hWaveMapper=NULL;
  1469. WAVEFORMATEX WaveFormatEx;
  1470. MMRESULT mmr;
  1471. UINT uDeviceId = (UINT)-1;
  1472. UINT i;
  1473. WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
  1474. WaveFormatEx.nChannels = 1;
  1475. WaveFormatEx.nSamplesPerSec = 8000;
  1476. WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
  1477. WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
  1478. WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
  1479. WaveFormatEx.cbSize = 0;
  1480. if (!uInOrOut)
  1481. {
  1482. #if 0
  1483. // First, make sure that none of the devices are already open
  1484. for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
  1485. {
  1486. if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1487. goto MyExit;
  1488. else
  1489. if (mmr == WAVERR_BADFORMAT)
  1490. {
  1491. // This is probably an 8 bit board. Try again using 8 bit format
  1492. WaveFormatEx.nAvgBytesPerSec = 8000;
  1493. WaveFormatEx.nBlockAlign = 1;
  1494. WaveFormatEx.wBitsPerSample = 8;
  1495. if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1496. goto MyExit;
  1497. }
  1498. if (hWave)
  1499. {
  1500. waveInClose((HWAVEIN)hWave);
  1501. hWave = (HWAVE)NULL;
  1502. }
  1503. }
  1504. WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
  1505. WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
  1506. WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
  1507. #endif
  1508. // Open the wave in device using wave mapper
  1509. if (mmr = waveInOpen ((HWAVEIN *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
  1510. {
  1511. if (mmr == WAVERR_BADFORMAT)
  1512. {
  1513. // This is probably an 8 bit board. Try again using 8 bit format
  1514. WaveFormatEx.nAvgBytesPerSec = 8000;
  1515. WaveFormatEx.nBlockAlign = 1;
  1516. WaveFormatEx.wBitsPerSample = 8;
  1517. if (mmr = waveInOpen ((HWAVEIN *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
  1518. goto MyExit;
  1519. }
  1520. else
  1521. goto MyExit;
  1522. }
  1523. // Now, look for the wave device that is already open
  1524. // that's the one wave mapper picked up
  1525. for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
  1526. {
  1527. if ((mmr = waveInOpen ((HWAVEIN *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1528. {
  1529. uDeviceId = i;
  1530. goto MyExit;
  1531. }
  1532. else
  1533. if (hWave)
  1534. {
  1535. waveInClose((HWAVEIN)hWave);
  1536. hWave = (HWAVE)NULL;
  1537. }
  1538. }
  1539. }
  1540. else
  1541. {
  1542. #if 0
  1543. // First, make sure that none of the devices are already open
  1544. for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
  1545. {
  1546. if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1547. goto MyExit;
  1548. else
  1549. if (mmr == WAVERR_BADFORMAT)
  1550. {
  1551. // This is probably an 8 bit board. Try again using 8 bit format
  1552. WaveFormatEx.nAvgBytesPerSec = 8000;
  1553. WaveFormatEx.nBlockAlign = 1;
  1554. WaveFormatEx.wBitsPerSample = 8;
  1555. if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1556. goto MyExit;
  1557. }
  1558. if (hWave)
  1559. {
  1560. waveOutClose((HWAVEOUT)hWave);
  1561. hWave = (HWAVE)NULL;
  1562. }
  1563. }
  1564. WaveFormatEx.nAvgBytesPerSec = 8000*SAMPLE_SIZE;
  1565. WaveFormatEx.nBlockAlign = SAMPLE_SIZE;
  1566. WaveFormatEx.wBitsPerSample = SAMPLE_SIZE*8;
  1567. #endif
  1568. // Open the wave in device using wave mapper
  1569. if (mmr = waveOutOpen ((HWAVEOUT *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
  1570. {
  1571. if (mmr == WAVERR_BADFORMAT)
  1572. {
  1573. // This is probably an 8 bit board. Try again using 8 bit format
  1574. WaveFormatEx.nAvgBytesPerSec = 8000;
  1575. WaveFormatEx.nBlockAlign = 1;
  1576. WaveFormatEx.wBitsPerSample = 8;
  1577. if (mmr = waveOutOpen ((HWAVEOUT *) &hWaveMapper, WAVE_MAPPER, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL))
  1578. goto MyExit;
  1579. }
  1580. else
  1581. goto MyExit;
  1582. }
  1583. // Now, look for the wave device that is already open
  1584. // that's the one wave mapper picked up
  1585. for (i=0; i<uNumWaveDevId; i++, hWave=NULL)
  1586. {
  1587. if ((mmr = waveOutOpen ((HWAVEOUT *) &hWave, i, (WAVEFORMATEX *) &WaveFormatEx, 0, 0, CALLBACK_NULL)) == MMSYSERR_ALLOCATED)
  1588. {
  1589. uDeviceId = i;
  1590. goto MyExit;
  1591. }
  1592. else
  1593. if (hWave)
  1594. {
  1595. waveOutClose((HWAVEOUT)hWave);
  1596. hWave = (HWAVE)NULL;
  1597. }
  1598. }
  1599. }
  1600. MyExit:
  1601. if (!uInOrOut)
  1602. {
  1603. if (hWave) waveInClose((HWAVEIN)hWave);
  1604. if (hWaveMapper) waveInClose((HWAVEIN)hWaveMapper);
  1605. }
  1606. else
  1607. {
  1608. if (hWave) waveOutClose((HWAVEOUT)hWave);
  1609. if (hWaveMapper) waveOutClose((HWAVEOUT)hWaveMapper);
  1610. }
  1611. return(uDeviceId);
  1612. }
  1613. UINT CheckForWaveDeviceSupport(UINT uWaveDevId, UINT uInOrOut)
  1614. {
  1615. MMRESULT mmr;
  1616. // querying isn't good enough, always directly open the device
  1617. // to see if it supports a given format
  1618. if (!uInOrOut)
  1619. {
  1620. waveInDev WaveIn(uWaveDevId);
  1621. if (uWaveDevId != WAVE_MAPPER)
  1622. WaveIn.AllowMapper(FALSE);
  1623. mmr = WaveIn.Open(8000,16);
  1624. if (mmr == WAVERR_BADFORMAT)
  1625. {
  1626. mmr = WaveIn.Open(8000,8);
  1627. if (mmr == WAVERR_BADFORMAT)
  1628. {
  1629. mmr = WaveIn.Open(11025, 16);
  1630. if (mmr == WAVERR_BADFORMAT)
  1631. {
  1632. mmr = WaveIn.Open(22050, 16);
  1633. if (mmr == WAVERR_BADFORMAT)
  1634. {
  1635. mmr = WaveIn.Open(44100, 16);
  1636. }
  1637. }
  1638. }
  1639. }
  1640. }
  1641. else // waveOut
  1642. {
  1643. waveOutDev WaveOut(uWaveDevId);
  1644. if (uWaveDevId != WAVE_MAPPER)
  1645. WaveOut.AllowMapper(FALSE);
  1646. mmr = WaveOut.Open(8000,16);
  1647. if (mmr == WAVERR_BADFORMAT)
  1648. {
  1649. mmr = WaveOut.Open(8000,8);
  1650. if (mmr == WAVERR_BADFORMAT)
  1651. {
  1652. mmr = WaveOut.Open(11025, 16);
  1653. if (mmr == WAVERR_BADFORMAT)
  1654. {
  1655. mmr = WaveOut.Open(22050, 16);
  1656. if (mmr == WAVERR_BADFORMAT)
  1657. {
  1658. mmr = WaveOut.Open(44100, 16);
  1659. }
  1660. }
  1661. }
  1662. }
  1663. }
  1664. // go ahead and allow the device to pass if it's in use
  1665. if ((mmr == MMSYSERR_ALLOCATED) || (mmr == MMSYSERR_NOERROR))
  1666. return TRUE;
  1667. else
  1668. return FALSE;
  1669. // destructors for waveOut and waveIn will call Close()
  1670. }
  1671. UINT CheckForAgc(UINT uWaveInDevId)
  1672. {
  1673. CMixerDevice *pMixDev;
  1674. UINT uRet = SOUNDCARD_NONE;
  1675. BOOL fAgc;
  1676. pMixDev = CMixerDevice::GetMixerForWaveDevice(
  1677. NULL,
  1678. uWaveInDevId,
  1679. MIXER_OBJECTF_WAVEIN);
  1680. //SS: we need to correlate the uDevId to mixer id
  1681. if (pMixDev)
  1682. {
  1683. uRet = SOUNDCARD_PRESENT;
  1684. if (pMixDev->GetAGC(&fAgc))
  1685. uRet = SOUNDCARD_HAVEAGC;
  1686. delete pMixDev;
  1687. }
  1688. return (uRet);
  1689. }
  1690. // This function is here to allow the help system to invoke
  1691. // the wizard via rundll32
  1692. void WINAPI RunAudioWiz(HWND hwndStub, HINSTANCE hInst, LPSTR lpszCmdLine, int CmdShow )
  1693. {
  1694. IntCreateAudioCalibWizard(hwndStub, RUNDUE_USERINVOKED, WAVE_MAPPER,
  1695. NULL, READFROM_REGISTRY);
  1696. }
  1697. static void PaintVUMeter (HWND hwnd, DWORD dwVolume)
  1698. {
  1699. COLORREF RedColor = RGB(255,0,0);
  1700. COLORREF YellowColor = RGB(255,255,0);
  1701. COLORREF GreenColor = RGB(0,255,0);
  1702. static DWORD dwPrevVolume=0;
  1703. HBRUSH hRedBrush, hOldBrush, hYellowBrush, hGreenBrush;
  1704. HBRUSH hBlackBrush, hCurrentBrush;
  1705. HDC hdc;
  1706. RECT rect, rectDraw, invalidRect;
  1707. DWORD width, boxwidth, startPos=0;
  1708. DWORD nRect=0, yellowPos, redPos;
  1709. LONG lDiff, lDiffTrunc = (MAX_VOLUME_NORMALIZED/2);
  1710. // rect gets filled with the dimensions we are drawing into
  1711. if (FALSE == GetClientRect (hwnd, &rect))
  1712. {
  1713. return;
  1714. }
  1715. // we expect volume to be between 0-32768
  1716. if (dwVolume > MAX_VOLUME)
  1717. dwVolume = MAX_VOLUME;
  1718. // reduce from 15 bits to 8 // 0 <= dwVolume <= 256
  1719. dwVolume = dwVolume / 128;
  1720. // run it through the "normalizing" table. Special case: F(256)==256
  1721. if (dwVolume < MAX_VOLUME_NORMALIZED)
  1722. dwVolume = g_VUTable[dwVolume];
  1723. // visual aesthetic #1 - get rid of VU jerkiness
  1724. // if the volume changed by more than 1/2 since the last update
  1725. // only move the meter up half way
  1726. // exception: if volume is explicitly 0, then skip
  1727. lDiff = (LONG)dwVolume - (LONG)dwPrevVolume;
  1728. if ((dwVolume != 0) && ( (lDiff > (MAX_VOLUME_NORMALIZED/2))
  1729. || (lDiff < -(MAX_VOLUME_NORMALIZED/2)) ))
  1730. dwVolume = dwVolume - (lDiff/2);
  1731. // minus 2 for the ending borders
  1732. // if Framed rectangles are used, drop the -2
  1733. boxwidth = rect.right - rect.left - 2;
  1734. width = (boxwidth * dwVolume)/ MAX_VOLUME_NORMALIZED;
  1735. // visual aesthetic #2 - to get rid of flicker
  1736. // if volume has increased since last time
  1737. // then there is no need to invalidate/update anything
  1738. // otherwise only clear everything to the right of the
  1739. // calculated "width". +/- 1 so the border doesn't get erased
  1740. if ((dwVolume < dwPrevVolume) || (dwVolume == 0))
  1741. {
  1742. invalidRect.left = rect.left + width - RECTANGLE_WIDTH;
  1743. if (invalidRect.left < rect.left)
  1744. invalidRect.left = rect.left;
  1745. invalidRect.right = rect.right - 1;
  1746. invalidRect.top = rect.top + 1;
  1747. invalidRect.bottom = rect.bottom - 1;
  1748. // these calls together erase the invalid region
  1749. InvalidateRect (hwnd, &invalidRect, TRUE);
  1750. UpdateWindow (hwnd);
  1751. }
  1752. hdc = GetDC (hwnd) ;
  1753. hRedBrush = CreateSolidBrush (RedColor) ;
  1754. hGreenBrush = CreateSolidBrush(GreenColor);
  1755. hYellowBrush = CreateSolidBrush(YellowColor);
  1756. hBlackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
  1757. hOldBrush = (HBRUSH) SelectObject (hdc, hBlackBrush);
  1758. // draw the main
  1759. FrameRect(hdc, &rect, hBlackBrush);
  1760. yellowPos = boxwidth/2;
  1761. redPos = (boxwidth*3)/4;
  1762. SelectObject(hdc, hGreenBrush);
  1763. hCurrentBrush = hGreenBrush;
  1764. rectDraw.top = rect.top +1;
  1765. rectDraw.bottom = rect.bottom -1;
  1766. while ((startPos+RECTANGLE_WIDTH) < width)
  1767. {
  1768. rectDraw.left = rect.left + (RECTANGLE_WIDTH+RECTANGLE_LEADING)*nRect + 1;
  1769. rectDraw.right = rectDraw.left + RECTANGLE_WIDTH;
  1770. nRect++;
  1771. FillRect(hdc, &rectDraw, hCurrentBrush);
  1772. startPos += RECTANGLE_WIDTH+RECTANGLE_LEADING;
  1773. if (startPos > redPos)
  1774. hCurrentBrush = hRedBrush;
  1775. else if (startPos > yellowPos)
  1776. hCurrentBrush = hYellowBrush;
  1777. }
  1778. SelectObject (hdc, hOldBrush);
  1779. DeleteObject(hRedBrush);
  1780. DeleteObject(hYellowBrush);
  1781. DeleteObject(hGreenBrush);
  1782. ReleaseDC (hwnd, hdc) ;
  1783. dwPrevVolume = dwVolume;
  1784. return;
  1785. }
  1786. static DWORD ComputePower(SHORT *wBuffer, DWORD dwNumSamples, AUDIO_POWER *pAudioPower)
  1787. {
  1788. DWORD dwIndex, dwTotal;
  1789. LONG dcComponent;
  1790. SHORT val;
  1791. DWORD dwVal;
  1792. ZeroMemory(pAudioPower, sizeof(AUDIO_POWER));
  1793. pAudioPower->dwMin = MAX_VOLUME; // 32768
  1794. dwTotal = 0;
  1795. dcComponent = 0;
  1796. for (dwIndex = 0; dwIndex < dwNumSamples; dwIndex++)
  1797. {
  1798. val = wBuffer[dwIndex];
  1799. dwVal = SHABS(val);
  1800. dwTotal += dwVal;
  1801. dcComponent += val;
  1802. if (dwVal > pAudioPower->dwMax)
  1803. pAudioPower->dwMax = dwVal;
  1804. if (dwVal < pAudioPower->dwMin)
  1805. pAudioPower->dwMin = dwVal;
  1806. }
  1807. pAudioPower->lDcComponent = dcComponent / (LONG)dwNumSamples;
  1808. pAudioPower->dwAvg = dwTotal / dwNumSamples;
  1809. return pAudioPower->dwAvg;
  1810. }
  1811. // given a pointer to a wave In device, and a list of WAVEHDR structs
  1812. // each wave header is prepared (if needed) and fed to wavein
  1813. MMRESULT PostFreeBuffers(waveInDev *pWaveInDev, WAVEHDR *aWaveHdrs, int numBuffers, DWORD *pdwCount)
  1814. {
  1815. int nIndex;
  1816. MMRESULT mmr=MMSYSERR_NOERROR;
  1817. bool bNeedToPrepare;
  1818. // first time through - the dwUser field of all wave headers
  1819. // will be zero. Just look a the first header in the list
  1820. // to figure this out.
  1821. if (numBuffers < 1)
  1822. {
  1823. ASSERT(false);
  1824. return MMSYSERR_ERROR;
  1825. }
  1826. bNeedToPrepare = (aWaveHdrs[0].dwUser == 0);
  1827. if (bNeedToPrepare)
  1828. {
  1829. for (nIndex = 0; nIndex < numBuffers; nIndex++)
  1830. {
  1831. mmr = pWaveInDev->PrepareHeader(&aWaveHdrs[nIndex]);
  1832. if (mmr != MMSYSERR_NOERROR)
  1833. {
  1834. return mmr;
  1835. }
  1836. // so that the code below works ok, just mark the done
  1837. // bit on the wave headers
  1838. aWaveHdrs[nIndex].dwFlags |= WHDR_DONE;
  1839. }
  1840. }
  1841. // for each wave header passed in that has the "done" bit set
  1842. // repost to wavein
  1843. for (nIndex = 0; nIndex < numBuffers; nIndex++)
  1844. {
  1845. if (aWaveHdrs[nIndex].dwFlags & WHDR_DONE)
  1846. {
  1847. aWaveHdrs[nIndex].dwFlags &= ~(WHDR_DONE | WHDR_INQUEUE);
  1848. aWaveHdrs[nIndex].dwFlags |= WHDR_PREPARED;
  1849. *pdwCount = (*pdwCount) + 1;
  1850. if (*pdwCount == 0)
  1851. *pdwCount++;
  1852. aWaveHdrs[nIndex].dwUser = *pdwCount;
  1853. mmr = pWaveInDev->Record(&aWaveHdrs[nIndex]);
  1854. }
  1855. }
  1856. return mmr;
  1857. }
  1858. // scan the array of wave headers for "done" buffers
  1859. // return the most recently posted buffer (if any)
  1860. BYTE *GetLatestBuffer(WAVEHDR *aWaveHdrs, int numBuffers)
  1861. {
  1862. DWORD_PTR dwUserHigh=0;
  1863. int nIndexHigh=0;
  1864. int nIndex;
  1865. for (nIndex = 0; nIndex < numBuffers; nIndex++)
  1866. {
  1867. if (aWaveHdrs[nIndex].dwFlags & WHDR_DONE)
  1868. {
  1869. if (aWaveHdrs[nIndex].dwUser > dwUserHigh)
  1870. {
  1871. dwUserHigh = aWaveHdrs[nIndex].dwUser;
  1872. nIndexHigh = nIndex;
  1873. }
  1874. }
  1875. }
  1876. if (dwUserHigh > 0)
  1877. {
  1878. return (BYTE*)(aWaveHdrs[nIndexHigh].lpData);
  1879. }
  1880. return NULL;
  1881. }
  1882. static DWORD CALLBACK CalibrateTalking(PVOID pVoid)
  1883. {
  1884. const int SIZE_WAVEIN_BUFFER = 1600; // 100ms @ 8khz, 16-bit
  1885. const int NUM_WAVEIN_BUFFERS = 5;
  1886. WaveBufferList waveList(NUM_WAVEIN_BUFFERS, SIZE_WAVEIN_BUFFER);
  1887. WAVEHDR aWaveHdrs[NUM_WAVEIN_BUFFERS];
  1888. HWND hVUMeter, hDlg;
  1889. HANDLE hEvent;
  1890. MMRESULT mmr;
  1891. DWORD dwPow, dwRet, dwExitCode=0;
  1892. AUDIO_POWER audioPower;
  1893. CALIB_DISPLAY *pCalibDisplay;
  1894. TCHAR szText[ATW_MSG_LENGTH];
  1895. BOOL fOpened = TRUE;
  1896. BOOL fSoundDetected = FALSE;
  1897. int nRecordCount = 0, nIndex;
  1898. DWORD dwBufferIndex = 1;
  1899. SHORT *buffer;
  1900. HANDLE hEventRecord = CreateEvent(NULL, TRUE, FALSE, NULL);
  1901. waveInDev waveIn(((CALIB_DISPLAY *)pVoid)->uWaveInDevId, hEventRecord);
  1902. pCalibDisplay = (CALIB_DISPLAY *)pVoid;
  1903. hVUMeter = pCalibDisplay->hVUMeter;
  1904. hDlg = pCalibDisplay->hDlg;
  1905. hEvent = pCalibDisplay->hEvent;
  1906. ASSERT(hEvent);
  1907. mmr = waveIn.Open(8000,16);
  1908. if (mmr == MMSYSERR_ALLOCATED)
  1909. {
  1910. FLoadString(IDS_RECORD_ERROR, szText, CCHMAX(szText));
  1911. SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, szText);
  1912. fOpened = FALSE;
  1913. }
  1914. else if (mmr != MMSYSERR_NOERROR)
  1915. {
  1916. PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
  1917. CloseHandle(hEvent);
  1918. CloseHandle(hEventRecord);
  1919. return -1;
  1920. }
  1921. else
  1922. {
  1923. SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, "");
  1924. ResetEvent(hEventRecord);
  1925. }
  1926. // initialize the array of wavehdrs
  1927. for (nIndex=0; nIndex < NUM_WAVEIN_BUFFERS; nIndex++)
  1928. {
  1929. ZeroMemory(&aWaveHdrs[nIndex], sizeof(WAVEHDR));
  1930. aWaveHdrs[nIndex].lpData = (LPSTR)(waveList.GetBuffer(nIndex));
  1931. aWaveHdrs[nIndex].dwBufferLength = SIZE_WAVEIN_BUFFER;
  1932. }
  1933. while (1)
  1934. {
  1935. // is it time to exit ?
  1936. dwRet = WaitForSingleObject(hEvent, 0);
  1937. if (dwRet == WAIT_OBJECT_0)
  1938. {
  1939. dwExitCode = 0;
  1940. break;
  1941. }
  1942. // if we still haven't opened the device
  1943. // keep trying
  1944. if (fOpened == FALSE)
  1945. {
  1946. mmr = waveIn.Open(8000,16);
  1947. if (mmr == MMSYSERR_ALLOCATED)
  1948. {
  1949. PaintVUMeter(hVUMeter, 0); // draw a blank rectangle
  1950. Sleep(500);
  1951. continue;
  1952. }
  1953. if (mmr != MMSYSERR_NOERROR)
  1954. {
  1955. PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
  1956. dwExitCode = (DWORD)(-1);
  1957. break;
  1958. }
  1959. // mmr == noerror
  1960. SetDlgItemText(hDlg, IDC_ATW_RECORD_ERROR, TEXT(""));
  1961. fOpened = TRUE;
  1962. ResetEvent(hEventRecord);
  1963. }
  1964. // wave device is open at this point
  1965. mmr = PostFreeBuffers(&waveIn, aWaveHdrs, NUM_WAVEIN_BUFFERS, &dwBufferIndex);
  1966. if (mmr != MMSYSERR_NOERROR)
  1967. {
  1968. PostMessage(hDlg, WM_AUDIOTHREAD_ERROR, 0, 0);
  1969. dwExitCode = (DWORD) -1;
  1970. break;
  1971. }
  1972. WaitForSingleObject(hEventRecord, 5000);
  1973. ResetEvent(hEventRecord);
  1974. buffer = (SHORT*)GetLatestBuffer(aWaveHdrs, NUM_WAVEIN_BUFFERS);
  1975. if (buffer)
  1976. {
  1977. nRecordCount++;
  1978. dwPow = ComputePower(buffer, SIZE_WAVEIN_BUFFER/2, &audioPower);
  1979. // don't update the meter for the first 200ms.
  1980. // "noise" from opening the soundcard tends to show up
  1981. if (nRecordCount > 2)
  1982. {
  1983. PaintVUMeter(hVUMeter, audioPower.dwMax);
  1984. // signal back to the calling window (if it hasn't already),
  1985. // that the silence threshold was broken
  1986. if ((fSoundDetected == FALSE) && (audioPower.dwMax > SILENCE_THRESHOLD))
  1987. {
  1988. PostMessage(hDlg, WM_AUDIOTHREAD_SOUND, 0,0);
  1989. fSoundDetected = TRUE;
  1990. }
  1991. // check for clipping, post message back to parent thread/window
  1992. // so that it will adjust the volume
  1993. if (audioPower.dwMax > CLIPPINGVOL)
  1994. {
  1995. // should we use send message instead ?
  1996. PostMessage(hDlg, WM_AUDIO_CLIPPING,0,0);
  1997. }
  1998. }
  1999. else
  2000. PaintVUMeter(hVUMeter, 0);
  2001. }
  2002. }
  2003. waveIn.Reset();
  2004. for (nIndex = 0; nIndex < NUM_WAVEIN_BUFFERS; nIndex++)
  2005. {
  2006. waveIn.UnPrepareHeader(&aWaveHdrs[nIndex]);
  2007. }
  2008. waveIn.Close();
  2009. CloseHandle(hEvent);
  2010. CloseHandle(hEventRecord);
  2011. TRACE_OUT(("ATW: Recording Thread Exit\r\n"));
  2012. return dwExitCode;
  2013. }
  2014. // Turns on AGC if needed
  2015. // parameter is whatever pawInfo->iSetAgc is.
  2016. // but it's probably been hardcoded to be READFROM_REGISTRY
  2017. static BOOL StartAGC(CMixerDevice *pMixer, BOOL iSetAgc, UINT uSoundCardCaps)
  2018. {
  2019. BOOL bSet, bRet;
  2020. if (iSetAgc == READFROM_REGISTRY)
  2021. {
  2022. if (DOESSOUNDCARDHAVEAGC(uSoundCardCaps))
  2023. {
  2024. RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
  2025. bSet = (BOOL)( re.GetNumber(REGVAL_AUTOGAIN,AUTOGAIN_ENABLED) == AUTOGAIN_ENABLED );
  2026. }
  2027. else
  2028. {
  2029. bSet = FALSE;
  2030. }
  2031. }
  2032. else
  2033. {
  2034. bSet = (iSetAgc != 0);
  2035. }
  2036. bRet = pMixer->SetAGC(bSet);
  2037. if (bSet == FALSE)
  2038. return FALSE;
  2039. return bRet;
  2040. }
  2041.