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.

959 lines
26 KiB

  1. //==========================================================================;
  2. //
  3. // cpl.c
  4. //
  5. // Copyright (c) 1991-1993 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Description:
  8. //
  9. //
  10. // History:
  11. // 07/94 VijR (Vij Rajarajan);
  12. //
  13. // 10/95 R Jernigan - removed link to Adv tab's treeview control
  14. // 09/99 tsharp - Ported back from W2K
  15. //
  16. //==========================================================================;
  17. #include "mmcpl.h"
  18. #include <windowsx.h>
  19. #include <mmsystem.h>
  20. #include <dbt.h>
  21. #include <ks.h>
  22. #include <ksmedia.h>
  23. #include <mmddkp.h>
  24. #include <mmreg.h>
  25. #include <msacm.h>
  26. #include <msacmdrv.h>
  27. #include <msacmdlg.h>
  28. #include <stdlib.h>
  29. #include "gfxui.h"
  30. #include "drivers.h"
  31. #include "advaudio.h"
  32. #include "roland.h"
  33. #include <objbase.h>
  34. #include <setupapi.h>
  35. #include <cfgmgr32.h>
  36. #include <initguid.h>
  37. #include <devguid.h>
  38. #define WM_ACMMAP_ACM_NOTIFY (WM_USER + 100)
  39. #include <memory.h>
  40. #include <commctrl.h>
  41. #include <prsht.h>
  42. #include <regstr.h>
  43. #include "trayvol.h"
  44. #include "utils.h"
  45. #include "medhelp.h"
  46. /****************************************************************************
  47. * WARNING - Hack Alert
  48. * The following declares are for DPLAY Voice
  49. ****************************************************************************/
  50. #define _FACDPV 0x15
  51. #define MAKE_DVHRESULT( code ) MAKE_HRESULT( 1, _FACDPV, code )
  52. #define DV_FULLDUPLEX MAKE_HRESULT( 0, _FACDPV, 5 )
  53. #define DV_HALFDUPLEX MAKE_HRESULT( 0, _FACDPV, 10 )
  54. #define DVERR_COMMANDALREADYPENDING MAKE_DVHRESULT( 371 )
  55. #define DVERR_SOUNDINITFAILURE MAKE_DVHRESULT( 372 )
  56. #define DVERR_USERCANCEL MAKE_DVHRESULT( 384 )
  57. // {D26AF734-208B-41da-8224-E0CE79810BE1}
  58. DEFINE_GUID(IID_IDirectPlayVoiceSetup,
  59. 0xd26af734, 0x208b, 0x41da, 0x82, 0x24, 0xe0, 0xce, 0x79, 0x81, 0xb, 0xe1);
  60. // {948CE83B-C4A2-44b3-99BF-279ED8DA7DF5}
  61. DEFINE_GUID(CLSID_DIRECTPLAYVOICE,
  62. 0x948ce83b, 0xc4a2, 0x44b3, 0x99, 0xbf, 0x27, 0x9e, 0xd8, 0xda, 0x7d, 0xf5);
  63. // {0F0F094B-B01C-4091-A14D-DD0CD807711A}
  64. DEFINE_GUID(CLSID_DirectPlayVoiceTest,
  65. 0xf0f094b, 0xb01c, 0x4091, 0xa1, 0x4d, 0xdd, 0xc, 0xd8, 0x7, 0x71, 0x1a);
  66. typedef struct IDirectPlayVoiceSetup FAR *LPDIRECTPLAYVOICESETUP, *PDIRECTPLAYVOICESETUP;
  67. #define DVFLAGS_WAVEIDS 0x80000000
  68. #define IDirectPlayVoiceSetup_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
  69. #define IDirectPlayVoiceSetup_AddRef(p) (p)->lpVtbl->AddRef(p)
  70. #define IDirectPlayVoiceSetup_Release(p) (p)->lpVtbl->Release(p)
  71. #define IDirectPlayVoiceSetup_CheckAudioSetup(p,a,b,c,d) (p)->lpVtbl->CheckAudioSetup(p,a,b,c,d)
  72. #undef INTERFACE
  73. #define INTERFACE IDirectPlayVoiceSetup
  74. DECLARE_INTERFACE_( IDirectPlayVoiceSetup, IUnknown )
  75. {
  76. /*** IUnknown methods ***/
  77. STDMETHOD(QueryInterface) (THIS_ REFIID riid, PVOID * ppvObj) PURE;
  78. STDMETHOD_(ULONG,AddRef) (THIS) PURE;
  79. STDMETHOD_(ULONG,Release) (THIS) PURE;
  80. /*** IDirectPlayVoiceSetup methods ***/
  81. STDMETHOD_(HRESULT, CheckAudioSetup) (THIS_ LPGUID, LPGUID, HWND, DWORD ) PURE;
  82. };
  83. /****************************************************************************
  84. * WARNING - Hack Alert End
  85. ****************************************************************************/
  86. /*
  87. ***************************************************************
  88. * Globals
  89. ***************************************************************
  90. */
  91. BOOL gfVocLoadedACM;
  92. BOOL gbVocSelectChanged = FALSE;
  93. BOOL gbVocCapPresent = FALSE;
  94. BOOL gbVocPlayPresent = FALSE;
  95. UINT giVocChange = 0;
  96. WNDPROC gfnVocPSProc = NULL;
  97. HWND ghVocDlg;
  98. /*
  99. ***************************************************************
  100. * Typedefs
  101. ***************************************************************
  102. */
  103. /*
  104. ***************************************************************
  105. * File Globals
  106. ***************************************************************
  107. */
  108. /*
  109. ***************************************************************
  110. * extern
  111. ***************************************************************
  112. */
  113. /*
  114. ***************************************************************
  115. * Prototypes
  116. ***************************************************************
  117. */
  118. BOOL PASCAL DoVocPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  119. BOOL PASCAL DoVoiceCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  120. void VOICEOUTInit(HWND hDlg, PAUDIODLGINFO paiVoc);
  121. void VOICECAPInit(HWND hDlg, PAUDIODLGINFO paiVoc);
  122. ///////////////////////////////////////////////////////////////////////////////////////////
  123. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  124. ///////////////////////////////////////////////////////////////////////////////////////////
  125. DWORD GetVoiceOutID(BOOL *pfPreferred)
  126. {
  127. MMRESULT mmr;
  128. DWORD dwWaveID;
  129. DWORD dwFlags = 0;
  130. if (pfPreferred)
  131. {
  132. *pfPreferred = TRUE;
  133. }
  134. mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);
  135. if (!mmr && pfPreferred)
  136. {
  137. *pfPreferred = dwFlags & 0x00000001;
  138. }
  139. return(dwWaveID);
  140. }
  141. ///////////////////////////////////////////////////////////////////////////////////////////
  142. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  143. ///////////////////////////////////////////////////////////////////////////////////////////
  144. BOOL SetVoiceOutID(DWORD dwWaveID, BOOL fPrefOnly)
  145. {
  146. MMRESULT mmr;
  147. DWORD dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;
  148. mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_SET, dwWaveID, dwFlags);
  149. return (!FAILED (mmr)); // TRUE;
  150. }
  151. ///////////////////////////////////////////////////////////////////////////////////////////
  152. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  153. ///////////////////////////////////////////////////////////////////////////////////////////
  154. DWORD GetVoiceCapID(BOOL *pfPreferred)
  155. {
  156. MMRESULT mmr;
  157. DWORD dwWaveID;
  158. DWORD dwFlags = 0;
  159. if (pfPreferred)
  160. {
  161. *pfPreferred = TRUE;
  162. }
  163. mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);
  164. if (!mmr && pfPreferred)
  165. {
  166. *pfPreferred = dwFlags & 0x00000001;
  167. }
  168. return(dwWaveID);
  169. }
  170. ///////////////////////////////////////////////////////////////////////////////////////////
  171. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  172. ///////////////////////////////////////////////////////////////////////////////////////////
  173. BOOL SetVoiceCapID(DWORD dwWaveID, BOOL fPrefOnly)
  174. {
  175. MMRESULT mmr;
  176. DWORD dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;
  177. mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_CONSOLEVOICECOM_SET, dwWaveID, dwFlags);
  178. return (!FAILED (mmr)); // TRUE;
  179. }
  180. void GetVocPrefInfo(PAUDIODLGINFO paiVoc, HWND hDlg )
  181. {
  182. // Load VoiceOut Info
  183. paiVoc->cNumOutDevs = waveOutGetNumDevs();
  184. paiVoc->uPrefOut = GetVoiceOutID(&paiVoc->fPrefOnly);
  185. // Load VoiceCap Info
  186. paiVoc->cNumInDevs = waveInGetNumDevs();
  187. paiVoc->uPrefIn = GetVoiceCapID(NULL);
  188. }
  189. STATIC void EnablePlayVoiceVolCtrls(HWND hDlg, BOOL fEnable)
  190. {
  191. EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_VOCVOL) , fEnable);
  192. EnableWindow( GetDlgItem(hDlg, IDC_PLAYBACK_ADVVOC) , fEnable);
  193. }
  194. STATIC void EnableRecVoiceVolCtrls(HWND hDlg, BOOL fEnable, BOOL fControl)
  195. {
  196. EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_CAPVOL) , fEnable);
  197. EnableWindow( GetDlgItem(hDlg, IDC_CAPTURE_ADVVOL) , fControl);
  198. }
  199. STATIC void SetVoiceOut(UINT uID, HWND hDlg)
  200. {
  201. BOOL fEnabled = FALSE;
  202. HMIXER hMixer = NULL;
  203. UINT uMixID;
  204. if(MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(uID), &uMixID, MIXER_OBJECTF_WAVEOUT))
  205. {
  206. if(MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
  207. {
  208. fEnabled = TRUE;
  209. mixerClose(hMixer);
  210. }
  211. }
  212. EnablePlayVoiceVolCtrls(hDlg, fEnabled);
  213. gbVocPlayPresent = fEnabled;
  214. }
  215. DWORD CountVocInputs(DWORD dwMixID)
  216. {
  217. MIXERCAPS mc;
  218. MMRESULT mmr;
  219. DWORD dwCount = 0;
  220. mmr = mixerGetDevCaps(dwMixID, &mc, sizeof(mc));
  221. if (mmr == MMSYSERR_NOERROR)
  222. {
  223. MIXERLINE mlDst;
  224. DWORD dwDestination;
  225. DWORD cDestinations;
  226. cDestinations = mc.cDestinations;
  227. for (dwDestination = 0; dwDestination < cDestinations; dwDestination++)
  228. {
  229. mlDst.cbStruct = sizeof ( mlDst );
  230. mlDst.dwDestination = dwDestination;
  231. if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_DESTINATION ) == MMSYSERR_NOERROR)
  232. {
  233. if (mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_WAVEIN || // needs to be a likely output destination
  234. mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_VOICEIN)
  235. {
  236. DWORD cConnections = mlDst.cConnections;
  237. dwCount += mlDst.cControls;
  238. if (cConnections)
  239. {
  240. DWORD dwSource;
  241. for (dwSource = 0; dwSource < cConnections; dwSource++)
  242. {
  243. mlDst.dwDestination = dwDestination;
  244. mlDst.dwSource = dwSource;
  245. if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_SOURCE ) == MMSYSERR_NOERROR)
  246. {
  247. dwCount += mlDst.cControls;
  248. }
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }
  255. return(dwCount);
  256. }
  257. STATIC void SetVoiceCap(UINT uID, HWND hDlg)
  258. {
  259. BOOL fEnabled = FALSE;
  260. BOOL fControl = FALSE;
  261. HMIXER hMixer = NULL;
  262. UINT uMixID;
  263. gbVocCapPresent = FALSE;
  264. if( (MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(uID),&uMixID, MIXER_OBJECTF_WAVEIN)))
  265. {
  266. if( MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
  267. {
  268. gbVocCapPresent = TRUE; // Even if the device has no inputs still enable test wizard
  269. if (CountVocInputs(uMixID))
  270. {
  271. fEnabled = TRUE;
  272. // If the capture device is not GFX capable, then there are no tabs to display
  273. fControl = GFXUI_CheckDevice(uMixID, GFXTYPE_CAPTURE);
  274. }
  275. mixerClose(hMixer);
  276. }
  277. }
  278. EnableRecVoiceVolCtrls(hDlg, fEnabled, fControl);
  279. }
  280. STATIC void SetVocPrefInfo(PAUDIODLGINFO paiVoc, HWND hDlg )
  281. {
  282. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_VOICE_CB_PLAY);
  283. HWND hwndCBRec = GetDlgItem(hDlg, IDC_VOICE_CB_REC);
  284. UINT item, deviceID;
  285. GetVocPrefInfo(paiVoc, hDlg);
  286. if (gbVocSelectChanged == TRUE)
  287. {
  288. gbVocSelectChanged = FALSE;
  289. item = (UINT)ComboBox_GetCurSel(hwndCBPlay);
  290. if (item != CB_ERR)
  291. {
  292. deviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);
  293. if(deviceID != paiVoc->uPrefOut) // Make sure device changed
  294. {
  295. if (SetVoiceOutID(deviceID, paiVoc->fPrefOnly))
  296. {
  297. paiVoc->uPrefOut = deviceID;
  298. }
  299. }
  300. }
  301. item = (UINT)ComboBox_GetCurSel(hwndCBRec);
  302. if (item != CB_ERR)
  303. {
  304. deviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);
  305. if( deviceID != paiVoc->uPrefIn ) // Make sure device changed
  306. {
  307. if (SetVoiceCapID(deviceID, paiVoc->fPrefOnly))
  308. {
  309. paiVoc->uPrefIn = deviceID;
  310. }
  311. }
  312. }
  313. }
  314. if (gbVocCapPresent && gbVocPlayPresent) EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , TRUE);
  315. // MIDI Devices are not remapped...
  316. }
  317. STATIC void VOICEOUTInit(HWND hDlg, PAUDIODLGINFO paiVoc)
  318. {
  319. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_VOICE_CB_PLAY);
  320. UINT device;
  321. TCHAR szNoVoice[128];
  322. szNoVoice[0] = TEXT('\0');
  323. GetVocPrefInfo(paiVoc, hDlg);
  324. ComboBox_ResetContent(hwndCBPlay);
  325. gbVocPlayPresent = FALSE;
  326. if (paiVoc->cNumOutDevs == 0)
  327. {
  328. LoadString (ghInstance, IDS_NOAUDIOPLAY, szNoVoice, sizeof(szNoVoice)/sizeof(TCHAR));
  329. ComboBox_AddString(hwndCBPlay, szNoVoice);
  330. ComboBox_SetItemData(hwndCBPlay, 0, (LPARAM)-1);
  331. ComboBox_SetCurSel(hwndCBPlay, 0);
  332. EnableWindow( hwndCBPlay, FALSE );
  333. EnablePlayVoiceVolCtrls(hDlg, FALSE);
  334. }
  335. else
  336. {
  337. EnableWindow( hwndCBPlay, TRUE );
  338. for (device = 0; device < paiVoc->cNumOutDevs; device++)
  339. {
  340. WAVEOUTCAPS woc;
  341. int newItem;
  342. woc.szPname[0] = TEXT('\0');
  343. if (waveOutGetDevCaps(device, &woc, sizeof(woc)))
  344. {
  345. continue;
  346. }
  347. woc.szPname[sizeof(woc.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');
  348. newItem = ComboBox_AddString(hwndCBPlay, woc.szPname);
  349. if (newItem != CB_ERR && newItem != CB_ERRSPACE)
  350. {
  351. ComboBox_SetItemData(hwndCBPlay, newItem, (LPARAM)device);
  352. if (device == paiVoc->uPrefOut)
  353. {
  354. ComboBox_SetCurSel(hwndCBPlay, newItem);
  355. SetVoiceOut(device, hDlg);
  356. }
  357. }
  358. }
  359. }
  360. }
  361. STATIC void VOICECAPInit(HWND hDlg, PAUDIODLGINFO paiVoc)
  362. {
  363. HWND hwndCBRec = GetDlgItem(hDlg, IDC_VOICE_CB_REC);
  364. UINT device;
  365. TCHAR szNoVoice[128];
  366. ComboBox_ResetContent(hwndCBRec);
  367. gbVocCapPresent = FALSE;
  368. if (paiVoc->cNumInDevs == 0)
  369. {
  370. LoadString (ghInstance, IDS_NOAUDIOREC, szNoVoice, sizeof(szNoVoice)/sizeof(TCHAR));
  371. ComboBox_AddString(hwndCBRec, szNoVoice);
  372. ComboBox_SetItemData(hwndCBRec, 0, (LPARAM)-1);
  373. ComboBox_SetCurSel(hwndCBRec, 0);
  374. EnableWindow( hwndCBRec, FALSE );
  375. EnableRecVoiceVolCtrls(hDlg, FALSE, FALSE);
  376. EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , FALSE);
  377. }
  378. else
  379. {
  380. EnableWindow( hwndCBRec, TRUE );
  381. for (device = 0; device < paiVoc->cNumInDevs; device++)
  382. {
  383. WAVEINCAPS wic;
  384. int newItem;
  385. wic.szPname[0] = TEXT('\0');
  386. if (waveInGetDevCaps(device, &wic, sizeof(wic)))
  387. {
  388. continue;
  389. }
  390. wic.szPname[sizeof(wic.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');
  391. newItem = ComboBox_AddString(hwndCBRec, wic.szPname);
  392. if (newItem != CB_ERR && newItem != CB_ERRSPACE)
  393. {
  394. ComboBox_SetItemData(hwndCBRec, newItem, (LPARAM)device);
  395. if (device == paiVoc->uPrefIn)
  396. {
  397. ComboBox_SetCurSel(hwndCBRec, newItem);
  398. SetVoiceCap(device, hDlg);
  399. }
  400. }
  401. }
  402. }
  403. }
  404. STATIC void VoiceDlgInit(HWND hDlg)
  405. {
  406. PAUDIODLGINFO paiVoc = (PAUDIODLGINFO)LocalAlloc(LPTR, sizeof(AUDIODLGINFO));
  407. if (!paiVoc) return;
  408. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)paiVoc);
  409. VOICEOUTInit(hDlg, paiVoc);
  410. VOICECAPInit(hDlg, paiVoc);
  411. if (gbVocCapPresent && gbVocPlayPresent) EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , TRUE);
  412. }
  413. const static DWORD aVoiceHelpIds[] = { // Context Help IDs
  414. IDC_GROUPBOX_VOC_1, IDH_COMM_GROUPBOX,
  415. IDC_VOICE_CB_PLAY, IDH_VOICE_SPEAKERICON,
  416. IDC_LAUNCH_VOCVOL, IDH_VOICE_LAUNCH_VOCVOL,
  417. IDC_PLAYBACK_ADVVOC, IDH_VOICE_PLAYBACK_ADVVOC,
  418. IDC_ICON_VOC_1, IDH_VOICE_SPEAKERICON,
  419. IDC_TEXT_32, NO_HELP,
  420. IDC_TEXT_VOC_1, IDH_VOICE_SPEAKERICON,
  421. IDC_TEXT_VOC_2, IDH_VOICE_RECORDICON,
  422. IDC_GROUPBOX_VOC_2, IDH_COMM_GROUPBOX,
  423. IDC_VOICE_CB_REC, IDH_VOICE_RECORDICON,
  424. IDC_LAUNCH_CAPVOL, IDH_VOICE_LAUNCH_CAPVOL,
  425. IDC_CAPTURE_ADVVOL, IDH_VOICE_CAPTURE_ADVVOL,
  426. IDC_ICON_VOC_2, IDH_VOICE_RECORDICON,
  427. IDC_ADVANCED_DIAG, IDH_VOICE_ADVANCED_TEST,
  428. 0, 0
  429. };
  430. void WinMMVoiceChange(HWND hDlg)
  431. {
  432. PAUDIODLGINFO paiVoc = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  433. VOICEOUTInit(hDlg, paiVoc);
  434. VOICECAPInit(hDlg, paiVoc);
  435. if (gbVocCapPresent && gbVocPlayPresent) EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , TRUE);
  436. }
  437. LRESULT CALLBACK VoiceTabProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  438. {
  439. if (iMsg == giVocChange)
  440. {
  441. WinMMVoiceChange(ghVocDlg);
  442. }
  443. return CallWindowProc(gfnVocPSProc,hwnd,iMsg,wParam,lParam);
  444. }
  445. void InitVoiceChange(HWND hDlg)
  446. {
  447. gfnVocPSProc = (WNDPROC) SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LPARAM)VoiceTabProc);
  448. giVocChange = RegisterWindowMessage(TEXT("winmm_devicechange"));
  449. }
  450. void UninitVoiceChange(HWND hDlg)
  451. {
  452. SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LPARAM)gfnVocPSProc);
  453. }
  454. BOOL CALLBACK VoiceDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
  455. LPARAM lParam)
  456. {
  457. NMHDR FAR *lpnm;
  458. PAUDIODLGINFO paiVoc;
  459. switch (uMsg)
  460. {
  461. case WM_NOTIFY:
  462. {
  463. lpnm = (NMHDR FAR *)lParam;
  464. switch(lpnm->code)
  465. {
  466. case PSN_KILLACTIVE:
  467. FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
  468. break;
  469. case PSN_APPLY:
  470. FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
  471. break;
  472. case PSN_SETACTIVE:
  473. FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  474. break;
  475. case PSN_RESET:
  476. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  477. break;
  478. }
  479. }
  480. break;
  481. case WM_INITDIALOG:
  482. {
  483. ghVocDlg = hDlg;
  484. gfVoiceTab = TRUE;
  485. InitVoiceChange(hDlg);
  486. if (!gfVocLoadedACM)
  487. {
  488. if (LoadACM())
  489. {
  490. gfVocLoadedACM = TRUE;
  491. }
  492. else
  493. {
  494. DPF("****Load ACM failed**\r\n");
  495. ASSERT(FALSE);
  496. ErrorBox(hDlg, IDS_CANTLOADACM, NULL);
  497. ExitThread(0);
  498. }
  499. }
  500. VoiceDlgInit(hDlg);
  501. }
  502. break;
  503. case WM_DESTROY:
  504. {
  505. UninitVoiceChange(hDlg);
  506. paiVoc = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  507. LocalFree((HLOCAL)paiVoc);
  508. if (gfVocLoadedACM)
  509. {
  510. if (!FreeACM())
  511. {
  512. DPF("****Free ACM failed**\r\n");
  513. ASSERT(FALSE);
  514. }
  515. gfVocLoadedACM = FALSE;
  516. }
  517. }
  518. break;
  519. case WM_CONTEXTMENU:
  520. {
  521. WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) aVoiceHelpIds);
  522. return TRUE;
  523. }
  524. break;
  525. case WM_HELP:
  526. {
  527. LPHELPINFO lphi = (LPVOID) lParam;
  528. WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aVoiceHelpIds);
  529. return TRUE;
  530. }
  531. break;
  532. case WM_COMMAND:
  533. {
  534. HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoVoiceCommand);
  535. }
  536. break;
  537. default:
  538. {
  539. }
  540. break;
  541. }
  542. return FALSE;
  543. }
  544. void ErrorVocMsgBox(HWND hDlg, UINT uTitle, UINT uMessage)
  545. {
  546. TCHAR szMsg[MAXSTR];
  547. TCHAR szTitle[MAXSTR];
  548. LoadString(ghInstance, uTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  549. LoadString(ghInstance, uMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR));
  550. MessageBox(hDlg, szMsg,szTitle,MB_OK);
  551. }
  552. void LaunchVocPlaybackVolume(HWND hDlg)
  553. {
  554. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_VOICE_CB_PLAY);
  555. UINT item;
  556. item = (UINT)ComboBox_GetCurSel(hwndCBPlay);
  557. if (item != CB_ERR)
  558. {
  559. TCHAR szCmd[MAXSTR];
  560. UINT uDeviceID;
  561. MMRESULT mmr;
  562. STARTUPINFO si;
  563. PROCESS_INFORMATION pi;
  564. memset(&si, 0, sizeof(si));
  565. si.cb = sizeof(si);
  566. si.wShowWindow = SW_SHOW;
  567. si.dwFlags = STARTF_USESHOWWINDOW;
  568. uDeviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);
  569. mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEOUT);
  570. if (mmr == MMSYSERR_NOERROR)
  571. {
  572. wsprintf(szCmd,TEXT("sndvol32.exe -D %d"),uDeviceID);
  573. if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  574. {
  575. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE,IDS_ERROR_NOVOCVOL);
  576. }
  577. }
  578. else
  579. {
  580. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE,IDS_ERROR_NOMIXER);
  581. }
  582. }
  583. }
  584. void LaunchCaptureVolume(HWND hDlg)
  585. {
  586. HWND hwndCBRec = GetDlgItem(hDlg, IDC_VOICE_CB_REC);
  587. UINT item;
  588. item = (UINT)ComboBox_GetCurSel(hwndCBRec);
  589. if (item != CB_ERR)
  590. {
  591. TCHAR szCmd[MAXSTR];
  592. UINT uDeviceID;
  593. MMRESULT mmr;
  594. STARTUPINFO si;
  595. PROCESS_INFORMATION pi;
  596. memset(&si, 0, sizeof(si));
  597. si.cb = sizeof(si);
  598. si.wShowWindow = SW_SHOW;
  599. si.dwFlags = STARTF_USESHOWWINDOW;
  600. uDeviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);
  601. mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEIN);
  602. if (mmr == MMSYSERR_NOERROR)
  603. {
  604. wsprintf(szCmd,TEXT("sndvol32.exe -R -D %d"),uDeviceID);
  605. if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  606. {
  607. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE,IDS_ERROR_NOVOCVOL);
  608. }
  609. }
  610. else
  611. {
  612. ErrorVocMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
  613. }
  614. }
  615. }
  616. void LaunchVoiceTest(HWND hDlg)
  617. {
  618. HRESULT hr;
  619. GUID guidCapture;
  620. GUID guidPlayback;
  621. UINT item;
  622. HWND hwndVocPlay = GetDlgItem(hDlg, IDC_VOICE_CB_PLAY);
  623. HWND hwndVocCap = GetDlgItem(hDlg, IDC_VOICE_CB_REC);
  624. LPDIRECTPLAYVOICESETUP lpdpvs;
  625. item = (UINT)ComboBox_GetCurSel(hwndVocPlay);
  626. if (item != CB_ERR)
  627. {
  628. guidPlayback.Data1 = item;
  629. }
  630. else
  631. {
  632. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE,IDS_ERROR_NOMIXER);
  633. return;
  634. }
  635. item = (UINT)ComboBox_GetCurSel(hwndVocCap);
  636. if (item != CB_ERR)
  637. {
  638. guidCapture.Data1 = item;
  639. }
  640. else
  641. {
  642. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE,IDS_ERROR_NOMIXER);
  643. return;
  644. }
  645. if (FAILED(CoInitialize(NULL))) return;
  646. if (FAILED(CoCreateInstance(&CLSID_DirectPlayVoiceTest, 0, CLSCTX_ALL, &IID_IDirectPlayVoiceSetup, (void**)&lpdpvs)))
  647. {
  648. CoUninitialize();
  649. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE, IDS_ERROR_NOVOCDIAG);
  650. return;
  651. }
  652. hr = IDirectPlayVoiceSetup_CheckAudioSetup(lpdpvs, &guidPlayback, &guidCapture, hDlg, DVFLAGS_WAVEIDS );
  653. if (FAILED(hr) && hr != DVERR_COMMANDALREADYPENDING && hr != DVERR_SOUNDINITFAILURE && hr != DVERR_USERCANCEL)
  654. {
  655. ErrorVocMsgBox(hDlg,IDS_ERROR_VOICE_TITLE, IDS_ERROR_NOVOCDIAG);
  656. }
  657. IDirectPlayVoiceSetup_Release(lpdpvs);
  658. CoUninitialize();
  659. }
  660. BOOL PASCAL DoVoiceCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  661. {
  662. PAUDIODLGINFO paiVoc = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  663. if (!gfVocLoadedACM)
  664. {
  665. return FALSE;
  666. }
  667. switch (id)
  668. {
  669. case ID_APPLY:
  670. {
  671. SetVocPrefInfo(paiVoc, hDlg);
  672. }
  673. break;
  674. case IDC_VOICE_CB_PLAY:
  675. case IDC_VOICE_CB_REC:
  676. {
  677. switch (codeNotify)
  678. {
  679. case CBN_SELCHANGE:
  680. {
  681. PropSheet_Changed(GetParent(hDlg),hDlg);
  682. if ((id == IDC_VOICE_CB_PLAY) || (id == IDC_VOICE_CB_REC))
  683. {
  684. int iIndex;
  685. iIndex = ComboBox_GetCurSel(hwndCtl);
  686. if (iIndex != CB_ERR)
  687. {
  688. gbVocSelectChanged = TRUE;
  689. if (id == IDC_VOICE_CB_REC)
  690. SetVoiceCap(iIndex, hDlg);
  691. if (id == IDC_VOICE_CB_PLAY)
  692. SetVoiceOut(iIndex, hDlg);
  693. if (gbVocCapPresent && gbVocPlayPresent)
  694. EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , TRUE);
  695. else
  696. EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_DIAG) , FALSE);
  697. }
  698. }
  699. }
  700. break;
  701. }
  702. }
  703. break;
  704. case IDC_ADVANCED_DIAG:
  705. {
  706. LaunchVoiceTest(hDlg);
  707. }
  708. break;
  709. case IDC_LAUNCH_VOCVOL:
  710. {
  711. LaunchVocPlaybackVolume(hDlg);
  712. }
  713. break;
  714. case IDC_LAUNCH_CAPVOL:
  715. {
  716. LaunchCaptureVolume(hDlg);
  717. }
  718. break;
  719. case IDC_PLAYBACK_ADVVOC:
  720. {
  721. HWND hwndVocPlay = GetDlgItem(hDlg, IDC_VOICE_CB_PLAY);
  722. DWORD dwDeviceID;
  723. UINT u;
  724. TCHAR szPrefOut[MAXSTR];
  725. u = (UINT)ComboBox_GetCurSel(hwndVocPlay);
  726. if (u != CB_ERR)
  727. {
  728. ComboBox_GetLBText(hwndVocPlay, u, (LPARAM)(LPVOID)szPrefOut);
  729. dwDeviceID = (DWORD)ComboBox_GetItemData(hwndVocPlay, u);
  730. AdvancedAudio(hDlg, ghInstance, gszWindowsHlp, dwDeviceID, szPrefOut, FALSE);
  731. }
  732. }
  733. break;
  734. case IDC_CAPTURE_ADVVOL:
  735. {
  736. HWND hwndVocCap = GetDlgItem(hDlg, IDC_VOICE_CB_REC);
  737. DWORD dwDeviceID;
  738. UINT u;
  739. TCHAR szPrefIn[MAXSTR];
  740. u = (UINT)ComboBox_GetCurSel(hwndVocCap);
  741. if (u != CB_ERR)
  742. {
  743. ComboBox_GetLBText(hwndVocCap, u, (LPARAM)(LPVOID)szPrefIn);
  744. dwDeviceID = (DWORD)ComboBox_GetItemData(hwndVocCap, u);
  745. AdvancedAudio(hDlg, ghInstance, gszWindowsHlp, dwDeviceID, szPrefIn, TRUE);
  746. }
  747. }
  748. break;
  749. }
  750. return FALSE;
  751. }