Leaked source code of windows server 2003
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.

1917 lines
54 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. //
  15. //==========================================================================;
  16. #include "mmcpl.h"
  17. #include <windowsx.h>
  18. #include <mmsystem.h>
  19. #include <dbt.h>
  20. #include <ks.h>
  21. #include <ksmedia.h>
  22. #include <mmddkp.h>
  23. #include <mmreg.h>
  24. #include <msacm.h>
  25. #include <msacmdrv.h>
  26. #include <msacmdlg.h>
  27. #include <stdlib.h>
  28. #include "gfxui.h"
  29. #include "drivers.h"
  30. #include "advaudio.h"
  31. #include "roland.h"
  32. #include <objbase.h>
  33. #include <setupapi.h>
  34. #include <cfgmgr32.h>
  35. #include <initguid.h>
  36. #include <devguid.h>
  37. #define WM_ACMMAP_ACM_NOTIFY (WM_USER + 100)
  38. #include <memory.h>
  39. #include <commctrl.h>
  40. #include <prsht.h>
  41. #include <regstr.h>
  42. #include "trayvol.h"
  43. #include "utils.h"
  44. #include "medhelp.h"
  45. /*
  46. ***************************************************************
  47. * Defines
  48. ***************************************************************
  49. */
  50. #ifndef DRV_F_ADD
  51. #define DRV_F_ADD 0x00000000 // TODO: Should be in MMDDK.H
  52. #define DRV_F_REMOVE 0x00000001
  53. #define DRV_F_CHANGE 0x00000002
  54. #define DRV_F_PROP_INSTR 0x00000004
  55. #define DRV_F_NEWDEFAULTS 0x00000008
  56. #define DRV_F_PARAM_IS_DEVNODE 0x10000000
  57. #endif
  58. #ifndef ACMHELPMSGCONTEXTMENU // TODO: Should
  59. #define ACMHELPMSGCONTEXTMENU TEXT("acmchoose_contextmenu") // be in MSACM.H
  60. #define ACMHELPMSGCONTEXTHELP TEXT("acmchoose_contexthelp")
  61. #endif
  62. #ifndef ACMFORMATCHOOSE_STYLEF_CONTEXTHELP // TODO: Should be in MSACM.H
  63. #define ACMFORMATCHOOSE_STYLEF_CONTEXTHELP 0x00000080L
  64. #endif
  65. /*
  66. ***************************************************************
  67. * Globals
  68. ***************************************************************
  69. */
  70. BOOL gfLoadedACM;
  71. UINT giDevChange = 0;
  72. WNDPROC gfnPSProc = NULL;
  73. HWND ghDlg;
  74. /*
  75. ***************************************************************
  76. * Typedefs
  77. ***************************************************************
  78. */
  79. typedef struct tACMDRIVERSETTINGS
  80. {
  81. HACMDRIVERID hadid;
  82. DWORD fdwSupport;
  83. DWORD dwPriority;
  84. } ACMDRIVERSETTINGS, FAR *LPACMDRIVERSETTINGS;
  85. typedef struct _CplCodecInfo
  86. {
  87. TCHAR szDesc[128];
  88. ACMDRIVERSETTINGS ads;
  89. HICON hIcon;
  90. BOOL fMadeIcon;
  91. }CPLCODECINFO, * PCPLCODECINFO;
  92. /*
  93. ***************************************************************
  94. * File Globals
  95. ***************************************************************
  96. */
  97. static CONST TCHAR aszFormatNumber[] = TEXT("%lu");
  98. //
  99. // These hold Window Message IDs for the two messages sent from the
  100. // Customize dialog (acmFormatChoose) for context-sensitive help.
  101. //
  102. UINT guCustomizeContextMenu = WM_NULL;
  103. UINT guCustomizeContextHelp = WM_NULL;
  104. BOOL fHaveStartedAudioDialog = FALSE;
  105. /*
  106. ***************************************************************
  107. * extern
  108. ***************************************************************
  109. */
  110. //
  111. // this string variable must be large enough to hold the IDS_TXT_DISABLED
  112. // resource string.. for USA, this is '(disabled)'--which is 11 bytes
  113. // including the NULL terminator.
  114. //
  115. TCHAR gszDevEnabled[256];
  116. TCHAR gszDevDisabled[256];
  117. /*
  118. ***************************************************************
  119. * Prototypes
  120. ***************************************************************
  121. */
  122. BOOL PASCAL DoACMPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  123. BOOL PASCAL DoAudioCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  124. BOOL PASCAL CustomizeDialog(HWND hDlg, LPTSTR szNewFormat, DWORD cbSize);
  125. void DoAdvancedSetup(HWND hwnd);
  126. void WAVEOUTInit(HWND hDlg, PAUDIODLGINFO pai);
  127. void WAVEINInit(HWND hDlg, PAUDIODLGINFO pai);
  128. PCPLCODECINFO acmFindCodecInfo (WORD, WORD);
  129. BOOL CALLBACK acmFindCodecInfoCallback (HACMDRIVERID, DWORD_PTR, DWORD);
  130. void acmFreeCodecInfo (PCPLCODECINFO);
  131. UINT acmCountCodecs (void);
  132. BOOL CALLBACK acmCountCodecsEnum (HACMDRIVERID, DWORD_PTR, DWORD);
  133. #ifndef ACM_DRIVERREMOVEF_UNINSTALL
  134. #define ACM_DRIVERREMOVEF_UNINSTALL 0x00000001L
  135. #endif
  136. /*
  137. ***************************************************************
  138. ***************************************************************
  139. */
  140. void acmDeleteCodec (WORD wMid, WORD wPid)
  141. {
  142. PCPLCODECINFO pci;
  143. if ((pci = acmFindCodecInfo (wMid, wPid)) != NULL)
  144. {
  145. acmDriverRemove (pci->ads.hadid, ACM_DRIVERREMOVEF_UNINSTALL);
  146. acmFreeCodecInfo (pci);
  147. }
  148. }
  149. //--------------------------------------------------------------------------;
  150. //
  151. // INT_PTR DlgProcACMAboutBox
  152. //
  153. // Description:
  154. //
  155. //
  156. // Arguments:
  157. //
  158. // Return (BOOL):
  159. //
  160. //
  161. // History:
  162. // 11/16/92 cjp [curtisp]
  163. //
  164. //--------------------------------------------------------------------------;
  165. INT_PTR CALLBACK DlgProcACMAboutBox
  166. (
  167. HWND hwnd,
  168. UINT uMsg,
  169. WPARAM wParam,
  170. LPARAM lParam
  171. )
  172. {
  173. TCHAR ach[80];
  174. TCHAR szFormat[80];
  175. LPACMDRIVERDETAILS padd;
  176. DWORD dw1;
  177. DWORD dw2;
  178. UINT uCmdId;
  179. switch (uMsg)
  180. {
  181. case WM_INITDIALOG:
  182. {
  183. padd = (LPACMDRIVERDETAILSW)lParam;
  184. if (NULL == padd)
  185. {
  186. DPF(0, "!DlgProcACMAboutBox: NULL driver details passed!");
  187. return (TRUE);
  188. }
  189. //
  190. // fill in all the static text controls with the long info
  191. // returned from the driver
  192. //
  193. LoadString(ghInstance, IDS_ABOUT_TITLE, szFormat, sizeof(szFormat)/sizeof(TCHAR));
  194. wsprintf(ach, szFormat, (LPTSTR)padd->szShortName);
  195. SetWindowText(hwnd, ach);
  196. //
  197. // if the driver supplies an icon, then use it..
  198. //
  199. if (NULL != padd->hicon)
  200. {
  201. Static_SetIcon(GetDlgItem(hwnd, IDD_ABOUT_ICON_DRIVER), padd->hicon);
  202. }
  203. SetDlgItemText(hwnd, IDD_ABOUT_TXT_DESCRIPTION, padd->szLongName);
  204. dw1 = padd->vdwACM;
  205. dw2 = padd->vdwDriver;
  206. LoadString(ghInstance, IDS_ABOUT_VERSION, szFormat, sizeof(szFormat)/sizeof(TCHAR));
  207. wsprintf(ach, szFormat, HIWORD(dw2) >> 8, (BYTE)HIWORD(dw2), HIWORD(dw1) >> 8, (BYTE)HIWORD(dw1));
  208. SetDlgItemText(hwnd,IDD_ABOUT_TXT_VERSION, ach);
  209. SetDlgItemText(hwnd, IDD_ABOUT_TXT_COPYRIGHT, padd->szCopyright);
  210. SetDlgItemText(hwnd, IDD_ABOUT_TXT_LICENSING, padd->szLicensing);
  211. SetDlgItemText(hwnd, IDD_ABOUT_TXT_FEATURES, padd->szFeatures);
  212. return (TRUE);
  213. }
  214. break;
  215. case WM_COMMAND:
  216. {
  217. uCmdId = GET_WM_COMMAND_ID(wParam,lParam);
  218. if ((uCmdId == IDOK) || (uCmdId == IDCANCEL))
  219. EndDialog(hwnd, wParam == uCmdId);
  220. return (TRUE);
  221. }
  222. break;
  223. }
  224. return (FALSE);
  225. } // DlgProcACMAboutBox()
  226. //--------------------------------------------------------------------------;
  227. //
  228. // void ControlAboutDriver
  229. //
  230. // Description:
  231. //
  232. //
  233. // Arguments:
  234. // HWND hwnd:
  235. //
  236. // LPACMDRIVERSETTINGS pads:
  237. //
  238. // Return (void):
  239. //
  240. // History:
  241. // 09/08/93 cjp [curtisp]
  242. //
  243. //--------------------------------------------------------------------------;
  244. STATIC void ControlAboutDriver
  245. (
  246. HWND hwnd,
  247. LPACMDRIVERSETTINGS pads
  248. )
  249. {
  250. PACMDRIVERDETAILSW padd;
  251. MMRESULT mmr;
  252. if (NULL == pads)
  253. {
  254. return;
  255. }
  256. //
  257. // if the driver returns MMSYSERR_NOTSUPPORTED, then we need to
  258. // display the info--otherwise, it supposedly displayed a dialog
  259. // (or had a critical error?)
  260. //
  261. mmr = (MMRESULT)acmDriverMessage((HACMDRIVER)pads->hadid, ACMDM_DRIVER_ABOUT, (LPARAM)hwnd, 0L);
  262. if ((MMRESULT)MMSYSERR_NOTSUPPORTED != mmr)
  263. {
  264. return;
  265. }
  266. //
  267. // alloc some zero-init'd memory to hold the about box info
  268. //
  269. padd = (PACMDRIVERDETAILS)LocalAlloc(LPTR, sizeof(*padd));
  270. if (NULL == padd)
  271. {
  272. DPF("!PACMDRIVERDETAILSA LocalAlloc failed");
  273. return;
  274. }
  275. //
  276. // get info and bring up a generic about box...
  277. //
  278. padd->cbStruct = sizeof(*padd);
  279. mmr = (MMRESULT)acmDriverDetails(pads->hadid, padd, 0L);
  280. if (MMSYSERR_NOERROR == mmr)
  281. {
  282. DialogBoxParam(ghInstance, MAKEINTRESOURCE(DLG_ABOUT_MSACM), hwnd, DlgProcACMAboutBox, (LPARAM)(LPVOID)padd);
  283. }
  284. LocalFree((HLOCAL)padd);
  285. } // ControlAboutDriver()
  286. //--------------------------------------------------------------------------;
  287. //
  288. // BOOL ControlConfigureDriver
  289. //
  290. // Description:
  291. //
  292. //
  293. // Arguments:
  294. // HWND hwnd:
  295. //
  296. // LPACMDRIVERSETTINGS pads:
  297. //
  298. // Return (BOOL):
  299. //
  300. // History:
  301. // 06/15/93 cjp [curtisp]
  302. //
  303. //--------------------------------------------------------------------------;
  304. STATIC BOOL ControlConfigureDriver
  305. (
  306. HWND hwnd,
  307. LPACMDRIVERSETTINGS pads
  308. )
  309. {
  310. if (NULL == pads)
  311. {
  312. return (FALSE);
  313. }
  314. if (acmDriverMessage((HACMDRIVER)pads->hadid,DRV_CONFIGURE,(LPARAM)hwnd,0L) == DRVCNF_RESTART)
  315. {
  316. DisplayMessage(hwnd, IDS_CHANGESAVED, IDS_RESTART, MB_OK);
  317. }
  318. return (TRUE);
  319. } // ControlConfigureDriver()
  320. STATIC void CommitCodecChanges(LPACMDRIVERSETTINGS pads)
  321. {
  322. MMRESULT mmr;
  323. BOOL fDisabled;
  324. DWORD fdwPriority;
  325. mmr = (MMRESULT)acmDriverPriority(NULL, 0L, ACM_DRIVERPRIORITYF_BEGIN);
  326. if (MMSYSERR_NOERROR != mmr)
  327. {
  328. DPF(0, "!ControlApplySettings: acmDriverPriority(end) failed! mmr=%u", mmr);
  329. return;
  330. }
  331. fDisabled = (0 != (ACMDRIVERDETAILS_SUPPORTF_DISABLED & pads->fdwSupport));
  332. fdwPriority = fDisabled ? ACM_DRIVERPRIORITYF_DISABLE : ACM_DRIVERPRIORITYF_ENABLE;
  333. mmr = (MMRESULT)acmDriverPriority(pads->hadid, pads->dwPriority, fdwPriority);
  334. if (MMSYSERR_NOERROR != mmr)
  335. {
  336. DPF(0, "!ControlApplySettings: acmDriverPriority(%.04Xh, %lu, %.08lXh) failed! mmr=%u",
  337. pads->hadid, pads->dwPriority, fdwPriority, mmr);
  338. }
  339. mmr = (MMRESULT)acmDriverPriority(NULL, 0L, ACM_DRIVERPRIORITYF_END);
  340. }
  341. const static DWORD aACMDlgHelpIds[] = { // Context Help IDs
  342. ID_DEV_SETTINGS, IDH_MMCPL_DEVPROP_SETTINGS,
  343. IDD_CPL_BTN_ABOUT, IDH_MMCPL_DEVPROP_ABOUT,
  344. IDC_ENABLE, IDH_MMCPL_DEVPROP_ENABLE,
  345. IDC_DISABLE, IDH_MMCPL_DEVPROP_DISABLE,
  346. IDC_DEV_ICON, NO_HELP,
  347. IDC_DEV_DESC, NO_HELP,
  348. IDC_DEV_STATUS, NO_HELP,
  349. IDD_PRIORITY_TXT_FROMTO, IDH_MMCPL_DEVPROP_CHANGE_PRI,
  350. IDD_PRIORITY_COMBO_PRIORITY, IDH_MMCPL_DEVPROP_CHANGE_PRI,
  351. 0, 0
  352. };
  353. INT_PTR CALLBACK ACMDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  354. {
  355. NMHDR FAR *lpnm;
  356. static PCPLCODECINFO pci = NULL;
  357. switch (uMsg)
  358. {
  359. case WM_NOTIFY:
  360. {
  361. lpnm = (NMHDR FAR *)lParam;
  362. switch(lpnm->code)
  363. {
  364. case PSN_KILLACTIVE:
  365. FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
  366. break;
  367. case PSN_APPLY:
  368. FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
  369. break;
  370. case PSN_SETACTIVE:
  371. //FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  372. break;
  373. case PSN_RESET:
  374. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  375. break;
  376. }
  377. }
  378. break;
  379. case WM_INITDIALOG:
  380. {
  381. HWND hwndS = GetDlgItem(hDlg, IDC_DEV_STATUS);
  382. LPARAM lpUser = ((LPPROPSHEETPAGE)lParam)->lParam;
  383. if ((pci = acmFindCodecInfo (LOWORD(lpUser), HIWORD(lpUser))) == NULL)
  384. {
  385. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  386. break;
  387. }
  388. acmMetrics((HACMOBJ)pci->ads.hadid, ACM_METRIC_DRIVER_PRIORITY, &(pci->ads.dwPriority));
  389. acmMetrics((HACMOBJ)pci->ads.hadid, ACM_METRIC_DRIVER_SUPPORT, &(pci->ads.fdwSupport));
  390. SendDlgItemMessage(hDlg, IDC_DEV_ICON, STM_SETICON, (WPARAM)pci->hIcon, 0L);
  391. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pci);
  392. SetWindowText(GetDlgItem(hDlg, IDC_DEV_DESC), pci->szDesc);
  393. LoadString (ghInstance, IDS_DEVENABLEDOK, gszDevEnabled, sizeof(gszDevEnabled)/sizeof(TCHAR));
  394. LoadString (ghInstance, IDS_DEVDISABLED, gszDevDisabled, sizeof(gszDevDisabled)/sizeof(TCHAR));
  395. if(pci->ads.fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED)
  396. {
  397. SetWindowText(hwndS, gszDevDisabled);
  398. CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_DISABLE);
  399. }
  400. else
  401. {
  402. SetWindowText(hwndS, gszDevEnabled);
  403. CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_ENABLE);
  404. }
  405. EnableWindow(GetDlgItem(hDlg, ID_DEV_SETTINGS), (MMRESULT)acmDriverMessage((HACMDRIVER)pci->ads.hadid,DRV_QUERYCONFIGURE,0,0));
  406. FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  407. }
  408. break;
  409. case WM_DESTROY:
  410. {
  411. FORWARD_WM_COMMAND(hDlg, ID_REBUILD, 0, 0, SendMessage);
  412. if (pci != NULL)
  413. {
  414. acmFreeCodecInfo (pci);
  415. pci = NULL;
  416. }
  417. }
  418. break;
  419. case WM_CONTEXTMENU:
  420. {
  421. WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR) (LPTSTR) aACMDlgHelpIds);
  422. return TRUE;
  423. }
  424. break;
  425. case WM_HELP:
  426. {
  427. LPHELPINFO lphi = (LPVOID) lParam;
  428. WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR) (LPTSTR) aACMDlgHelpIds);
  429. return TRUE;
  430. }
  431. break;
  432. case WM_COMMAND:
  433. {
  434. HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoACMPropCommand);
  435. }
  436. break;
  437. }
  438. return FALSE;
  439. }
  440. BOOL PASCAL DoACMPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  441. {
  442. PCPLCODECINFO pci;
  443. LPACMDRIVERSETTINGS pads;
  444. static int iPriority = 0;
  445. static BOOL fDisabled = TRUE;
  446. static BOOL fRebuild;
  447. HWND hwndS = GetDlgItem(hDlg, IDC_DEV_STATUS);
  448. if ((pci = (PCPLCODECINFO)GetWindowLongPtr(hDlg,DWLP_USER)) == NULL)
  449. {
  450. return FALSE;
  451. }
  452. pads = &(pci->ads);
  453. switch (id)
  454. {
  455. case ID_APPLY:
  456. {
  457. HWND hcb = GetDlgItem(hDlg, IDD_PRIORITY_COMBO_PRIORITY);
  458. if ((fDisabled != Button_GetCheck(GetDlgItem(hDlg, IDC_DISABLE))) || (iPriority != ComboBox_GetCurSel(hcb)+1))
  459. {
  460. pads->fdwSupport ^= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
  461. fDisabled = (0 != (pads->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED));
  462. iPriority = pads->dwPriority = ComboBox_GetCurSel(hcb)+1;
  463. CommitCodecChanges(pads);
  464. fRebuild = TRUE;
  465. }
  466. return TRUE;
  467. }
  468. case ID_REBUILD:
  469. {
  470. if (fRebuild && pci)
  471. {
  472. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)0);
  473. fRebuild = FALSE;
  474. }
  475. }
  476. break;
  477. case ID_INIT:
  478. {
  479. TCHAR achFromTo[80];
  480. TCHAR ach[80];
  481. HWND hcb;
  482. UINT u;
  483. UINT nCodecs;
  484. iPriority = (int)pads->dwPriority;
  485. fDisabled = (0 != (pads->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED));
  486. fRebuild = FALSE;
  487. LoadString(ghInstance, IDS_PRIORITY_FROMTO, achFromTo, sizeof(achFromTo)/sizeof(TCHAR));
  488. wsprintf(ach, achFromTo, iPriority);
  489. SetDlgItemText(hDlg, IDD_PRIORITY_TXT_FROMTO, ach);
  490. hcb = GetDlgItem(hDlg, IDD_PRIORITY_COMBO_PRIORITY);
  491. nCodecs = acmCountCodecs();
  492. for (u = 1; u <= (UINT)nCodecs; u++)
  493. {
  494. wsprintf(ach, aszFormatNumber, (DWORD)u);
  495. ComboBox_AddString(hcb, ach);
  496. }
  497. ComboBox_SetCurSel(hcb, iPriority - 1);
  498. }
  499. break;
  500. case IDD_PRIORITY_COMBO_PRIORITY:
  501. {
  502. switch (codeNotify)
  503. {
  504. case CBN_SELCHANGE:
  505. {
  506. PropSheet_Changed(GetParent(hDlg),hDlg);
  507. }
  508. break;
  509. }
  510. }
  511. break;
  512. case IDC_ENABLE:
  513. {
  514. SetWindowText(hwndS, gszDevEnabled);
  515. CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_ENABLE);
  516. PropSheet_Changed(GetParent(hDlg),hDlg);
  517. }
  518. break;
  519. case IDC_DISABLE:
  520. {
  521. SetWindowText(hwndS, gszDevDisabled);
  522. CheckRadioButton(hDlg, IDC_ENABLE, IDC_DISABLE, IDC_DISABLE);
  523. PropSheet_Changed(GetParent(hDlg),hDlg);
  524. }
  525. break;
  526. case ID_DEV_SETTINGS:
  527. {
  528. ControlConfigureDriver(hDlg, pads);
  529. }
  530. break;
  531. case IDD_CPL_BTN_ABOUT:
  532. {
  533. ControlAboutDriver(hDlg, pads);
  534. }
  535. break;
  536. }
  537. return FALSE;
  538. }
  539. ///////////////////////////////////////////////////////////////////////////////////
  540. ///////////////////////////////////////////////////////////////////////////////////
  541. ///////////////////////////////////////////////////////////////////////////////////
  542. ///////////////////////////////////////////////////////////////////////////////////
  543. ///////////////////////////////////////////////////////////////////////////////////
  544. ///////////////////////////////////////////////////////////////////////////////////
  545. ///////////////////////////////////////////////////////////////////////////////////
  546. ///////////////////////////////////////////////////////////////////////////////////
  547. ///////////////////////////////////////////////////////////////////////////////////
  548. ///////////////////////////////////////////////////////////////////////////////////////////
  549. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  550. ///////////////////////////////////////////////////////////////////////////////////////////
  551. DWORD GetWaveOutID(BOOL *pfPreferred)
  552. {
  553. MMRESULT mmr;
  554. DWORD_PTR dwWaveID = 0;
  555. DWORD dwFlags = 0;
  556. if (pfPreferred)
  557. {
  558. *pfPreferred = TRUE;
  559. }
  560. mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);
  561. if (!mmr && pfPreferred)
  562. {
  563. *pfPreferred = dwFlags & 0x00000001;
  564. }
  565. return(DWORD)(dwWaveID);
  566. }
  567. ///////////////////////////////////////////////////////////////////////////////////////////
  568. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  569. ///////////////////////////////////////////////////////////////////////////////////////////
  570. void SetWaveOutID(DWORD dwWaveID, BOOL fPrefOnly)
  571. {
  572. MMRESULT mmr;
  573. DWORD dwParam1, dwParam2;
  574. DWORD dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;
  575. mmr = waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, dwFlags);
  576. }
  577. ///////////////////////////////////////////////////////////////////////////////////////////
  578. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  579. ///////////////////////////////////////////////////////////////////////////////////////////
  580. DWORD GetWaveInID(BOOL *pfPreferred)
  581. {
  582. MMRESULT mmr;
  583. DWORD_PTR dwWaveID = 0;
  584. DWORD dwFlags = 0;
  585. if (pfPreferred)
  586. {
  587. *pfPreferred = TRUE;
  588. }
  589. mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);
  590. if (!mmr && pfPreferred)
  591. {
  592. *pfPreferred = dwFlags & 0x00000001;
  593. }
  594. return(DWORD)(dwWaveID);
  595. }
  596. ///////////////////////////////////////////////////////////////////////////////////////////
  597. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  598. ///////////////////////////////////////////////////////////////////////////////////////////
  599. void SetWaveInID(DWORD dwWaveID, BOOL fPrefOnly)
  600. {
  601. MMRESULT mmr;
  602. DWORD dwParam1, dwParam2;
  603. DWORD dwFlags = fPrefOnly ? 0x00000001 : 0x00000000;
  604. mmr = waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, dwFlags);
  605. }
  606. ///////////////////////////////////////////////////////////////////////////////////////////
  607. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  608. ///////////////////////////////////////////////////////////////////////////////////////////
  609. DWORD GetMIDIOutID(void)
  610. {
  611. MMRESULT mmr;
  612. DWORD dwWaveID;
  613. DWORD dwFlags = 0;
  614. mmr = midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &dwWaveID, (DWORD_PTR) &dwFlags);
  615. return(dwWaveID);
  616. }
  617. ///////////////////////////////////////////////////////////////////////////////////////////
  618. // Microsoft Confidential - DO NOT COPY THIS METHOD INTO ANY APPLICATION, THIS MEANS YOU!!!
  619. ///////////////////////////////////////////////////////////////////////////////////////////
  620. void SetMIDIOutID(DWORD dwWaveID)
  621. {
  622. MMRESULT mmr;
  623. DWORD dwParam1, dwParam2;
  624. mmr = midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_PREFERRED_SET, dwWaveID, 0);
  625. }
  626. void GetPrefInfo(PAUDIODLGINFO pai, HWND hDlg )
  627. {
  628. MMRESULT mmr;
  629. // Load WaveOut Info
  630. pai->cNumOutDevs = waveOutGetNumDevs();
  631. pai->uPrefOut = GetWaveOutID(&pai->fPrefOnly);
  632. // Load WaveIn Info
  633. pai->cNumInDevs = waveInGetNumDevs();
  634. pai->uPrefIn = GetWaveInID(NULL);
  635. // Load MIDI Out info
  636. pai->cNumMIDIOutDevs = midiOutGetNumDevs();
  637. pai->uPrefMIDIOut = GetMIDIOutID();
  638. }
  639. STATIC void EnablePlayVolCtrls(HWND hDlg, BOOL fEnable)
  640. {
  641. EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_SNDVOL) , fEnable);
  642. EnableWindow( GetDlgItem(hDlg, IDC_PLAYBACK_ADVSETUP) , fEnable);
  643. }
  644. STATIC void EnableRecVolCtrls(HWND hDlg, BOOL fEnable, BOOL fControl)
  645. {
  646. EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_RECVOL) , fEnable);
  647. EnableWindow( GetDlgItem(hDlg, IDC_RECORD_ADVSETUP) , fControl);
  648. }
  649. STATIC void EnableMIDIVolCtrls(HWND hDlg, BOOL fEnable)
  650. {
  651. EnableWindow( GetDlgItem(hDlg, IDC_LAUNCH_MUSICVOL) , fEnable);
  652. }
  653. STATIC void SetDeviceOut(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
  654. {
  655. BOOL fEnabled = FALSE;
  656. HMIXER hMixer = NULL;
  657. UINT uMixID;
  658. pai->uPrefOut = uID; // New device, lets setup buttons for this device
  659. if(MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefOut), &uMixID, MIXER_OBJECTF_WAVEOUT))
  660. {
  661. if(MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
  662. {
  663. fEnabled = TRUE;
  664. mixerClose(hMixer);
  665. }
  666. }
  667. EnablePlayVolCtrls(hDlg, fEnabled);
  668. }
  669. DWORD CountInputs(DWORD dwMixID)
  670. {
  671. MIXERCAPS mc;
  672. MMRESULT mmr;
  673. DWORD dwCount = 0;
  674. mmr = mixerGetDevCaps(dwMixID, &mc, sizeof(mc));
  675. if (mmr == MMSYSERR_NOERROR)
  676. {
  677. MIXERLINE mlDst;
  678. DWORD dwDestination;
  679. DWORD cDestinations;
  680. cDestinations = mc.cDestinations;
  681. for (dwDestination = 0; dwDestination < cDestinations; dwDestination++)
  682. {
  683. mlDst.cbStruct = sizeof ( mlDst );
  684. mlDst.dwDestination = dwDestination;
  685. if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_DESTINATION ) == MMSYSERR_NOERROR)
  686. {
  687. if (mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_WAVEIN || // needs to be a likely output destination
  688. mlDst.dwComponentType == (DWORD)MIXERLINE_COMPONENTTYPE_DST_VOICEIN)
  689. {
  690. DWORD cConnections = mlDst.cConnections;
  691. dwCount += mlDst.cControls;
  692. if (cConnections)
  693. {
  694. DWORD dwSource;
  695. for (dwSource = 0; dwSource < cConnections; dwSource++)
  696. {
  697. mlDst.dwDestination = dwDestination;
  698. mlDst.dwSource = dwSource;
  699. if (mixerGetLineInfo(HMIXEROBJ_INDEX(dwMixID), &mlDst, MIXER_GETLINEINFOF_SOURCE ) == MMSYSERR_NOERROR)
  700. {
  701. dwCount += mlDst.cControls;
  702. }
  703. }
  704. }
  705. }
  706. }
  707. }
  708. }
  709. return(dwCount);
  710. }
  711. STATIC void SetDeviceIn(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
  712. {
  713. BOOL fEnabled = FALSE;
  714. BOOL fControl = FALSE;
  715. HMIXER hMixer = NULL;
  716. UINT uMixID;
  717. pai->uPrefIn = uID; // New device, lets setup buttons for this device
  718. if( (MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefIn),&uMixID, MIXER_OBJECTF_WAVEIN)))
  719. {
  720. if( MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
  721. {
  722. if (CountInputs(uMixID))
  723. {
  724. fEnabled = TRUE;
  725. // If the capture device is not GFX capable, then there are no tabs to display
  726. fControl = GFXUI_CheckDevice(uMixID, GFXTYPE_CAPTURE);
  727. }
  728. mixerClose(hMixer);
  729. }
  730. }
  731. EnableRecVolCtrls(hDlg, fEnabled, fControl);
  732. }
  733. STATIC void SetMIDIDeviceOut(PAUDIODLGINFO pai, UINT uID, HWND hDlg)
  734. {
  735. BOOL fEnabled = FALSE;
  736. HMIXER hMixer = NULL;
  737. UINT uMixID;
  738. MIDIOUTCAPS moc;
  739. MMRESULT mmr;
  740. UINT mid;
  741. pai->uPrefMIDIOut = uID; // New device, lets setup buttons for this device
  742. if(MMSYSERR_NOERROR == mixerGetID(HMIXEROBJ_INDEX(pai->uPrefMIDIOut), &uMixID, MIXER_OBJECTF_MIDIOUT))
  743. {
  744. if(MMSYSERR_NOERROR == mixerOpen(&hMixer, uMixID, 0L, 0L, 0L))
  745. {
  746. fEnabled = TRUE;
  747. mixerClose(hMixer);
  748. }
  749. }
  750. EnableMIDIVolCtrls(hDlg, fEnabled);
  751. fEnabled = FALSE;
  752. mmr = midiOutGetDevCaps(pai->uPrefMIDIOut, &moc, sizeof(moc));
  753. if (MMSYSERR_NOERROR == mmr)
  754. {
  755. if ((moc.wMid == MM_MICROSOFT) && (moc.wPid == MM_MSFT_WDMAUDIO_MIDIOUT) && (moc.wTechnology == MOD_SWSYNTH))
  756. {
  757. fEnabled = TRUE;
  758. }
  759. }
  760. EnableWindow( GetDlgItem(hDlg, IDC_MUSIC_ABOUT) , fEnabled);
  761. }
  762. STDAPI_(void) DoRolandAbout(HWND hWnd)
  763. {
  764. UINT uWaveID = 0;
  765. if (GetWaveID(&uWaveID) != (MMRESULT)MMSYSERR_ERROR)
  766. {
  767. WAVEOUTCAPS woc;
  768. if (waveOutGetDevCaps(uWaveID, &woc, sizeof(woc)) == MMSYSERR_NOERROR)
  769. {
  770. RolandProp(hWnd, ghInstance, woc.szPname);
  771. }
  772. }
  773. }
  774. STATIC void SetPrefInfo(PAUDIODLGINFO pai, HWND hDlg )
  775. {
  776. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
  777. HWND hwndCBRec = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
  778. HWND hwndCBMIDI = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
  779. HKEY hkeyAcm;
  780. UINT item, deviceID;
  781. TCHAR szPref[MAXSTR];
  782. pai->fPrefOnly = Button_GetCheck(GetDlgItem(hDlg, IDC_AUDIO_PREF));
  783. item = (UINT)ComboBox_GetCurSel(hwndCBPlay);
  784. if (item != CB_ERR)
  785. {
  786. deviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);
  787. if(deviceID != pai->uPrefOut) // Make sure device changed
  788. {
  789. SetDeviceOut(pai, deviceID, hDlg); // Configure controls for this device
  790. }
  791. }
  792. item = (UINT)ComboBox_GetCurSel(hwndCBRec);
  793. if (item != CB_ERR)
  794. {
  795. deviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);
  796. if( deviceID != pai->uPrefIn ) // Make sure device changed
  797. {
  798. SetDeviceIn(pai, deviceID, hDlg); // Configure controls for this device
  799. }
  800. }
  801. item = (UINT)ComboBox_GetCurSel(hwndCBMIDI);
  802. if (item != CB_ERR)
  803. {
  804. deviceID = (UINT)ComboBox_GetItemData(hwndCBMIDI, item);
  805. if(deviceID != pai->uPrefMIDIOut) // Make sure device changed
  806. {
  807. SetMIDIDeviceOut(pai, deviceID, hDlg); // Configure controls for this device
  808. }
  809. }
  810. SetWaveOutID(pai->uPrefOut, pai->fPrefOnly);
  811. SetWaveInID(pai->uPrefIn, pai->fPrefOnly);
  812. SetMIDIOutID(pai->uPrefMIDIOut);
  813. WAVEOUTInit(hDlg, pai);
  814. WAVEINInit(hDlg, pai);
  815. // MIDI Devices are not remapped...
  816. }
  817. STATIC void MSACM_NotifyMapper(void)
  818. {
  819. waveOutMessage(HWAVEOUT_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
  820. waveInMessage(HWAVEIN_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
  821. midiOutMessage(HMIDIOUT_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, DRV_F_NEWDEFAULTS);
  822. }
  823. STATIC void WAVEOUTInit(HWND hDlg, PAUDIODLGINFO pai)
  824. {
  825. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
  826. MMRESULT mr;
  827. UINT device;
  828. TCHAR szNoAudio[128];
  829. szNoAudio[0] = TEXT('\0');
  830. ComboBox_ResetContent(hwndCBPlay);
  831. if (pai->cNumOutDevs == 0)
  832. {
  833. LoadString (ghInstance, IDS_NOAUDIOPLAY, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
  834. ComboBox_AddString(hwndCBPlay, szNoAudio);
  835. ComboBox_SetItemData(hwndCBPlay, 0, (LPARAM)-1);
  836. ComboBox_SetCurSel(hwndCBPlay, 0);
  837. EnableWindow( hwndCBPlay, FALSE );
  838. EnablePlayVolCtrls(hDlg, FALSE);
  839. }
  840. else
  841. {
  842. EnableWindow( hwndCBPlay, TRUE );
  843. for (device = 0; device < pai->cNumOutDevs; device++)
  844. {
  845. WAVEOUTCAPS woc;
  846. int newItem;
  847. woc.szPname[0] = TEXT('\0');
  848. if (waveOutGetDevCapsW(device, &woc, sizeof(woc)))
  849. {
  850. continue;
  851. }
  852. woc.szPname[sizeof(woc.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');
  853. newItem = ComboBox_AddString(hwndCBPlay, woc.szPname);
  854. if (newItem != CB_ERR && newItem != CB_ERRSPACE)
  855. {
  856. ComboBox_SetItemData(hwndCBPlay, newItem, (LPARAM)device);
  857. if (device == pai->uPrefOut)
  858. {
  859. ComboBox_SetCurSel(hwndCBPlay, newItem);
  860. SetDeviceOut(pai, device, hDlg);
  861. }
  862. }
  863. }
  864. }
  865. }
  866. STATIC void WAVEINInit(HWND hDlg, PAUDIODLGINFO pai)
  867. {
  868. HWND hwndCBRec = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
  869. MMRESULT mr;
  870. UINT device;
  871. TCHAR szNoAudio[128];
  872. ComboBox_ResetContent(hwndCBRec);
  873. if (pai->cNumInDevs == 0)
  874. {
  875. LoadString (ghInstance, IDS_NOAUDIOREC, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
  876. ComboBox_AddString(hwndCBRec, szNoAudio);
  877. ComboBox_SetItemData(hwndCBRec, 0, (LPARAM)-1);
  878. ComboBox_SetCurSel(hwndCBRec, 0);
  879. EnableWindow( hwndCBRec, FALSE );
  880. EnableRecVolCtrls(hDlg, FALSE, FALSE);
  881. }
  882. else
  883. {
  884. EnableWindow( hwndCBRec, TRUE );
  885. for (device = 0; device < pai->cNumInDevs; device++)
  886. {
  887. WAVEINCAPSW wic;
  888. int newItem;
  889. wic.szPname[0] = TEXT('\0');
  890. if (waveInGetDevCapsW(device, &wic, sizeof(wic)))
  891. {
  892. continue;
  893. }
  894. wic.szPname[sizeof(wic.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');
  895. newItem = ComboBox_AddString(hwndCBRec, wic.szPname);
  896. if (newItem != CB_ERR && newItem != CB_ERRSPACE)
  897. {
  898. ComboBox_SetItemData(hwndCBRec, newItem, (LPARAM)device);
  899. if (device == pai->uPrefIn)
  900. {
  901. ComboBox_SetCurSel(hwndCBRec, newItem);
  902. SetDeviceIn(pai, device, hDlg);
  903. }
  904. }
  905. }
  906. }
  907. }
  908. STATIC void MIDIInit(HWND hDlg, PAUDIODLGINFO pai)
  909. {
  910. HWND hwnd = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
  911. MMRESULT mr;
  912. UINT device;
  913. TCHAR szNoAudio[128];
  914. ComboBox_ResetContent(hwnd);
  915. szNoAudio[0] = TEXT('\0');
  916. EnableWindow( GetDlgItem(hDlg, IDC_MUSIC_ABOUT) , FALSE);
  917. if (pai->cNumMIDIOutDevs == 0)
  918. {
  919. LoadString (ghInstance, IDS_NOMIDIPLAY, szNoAudio, sizeof(szNoAudio)/sizeof(TCHAR));
  920. ComboBox_AddString(hwnd, szNoAudio);
  921. ComboBox_SetItemData(hwnd, 0, (LPARAM)-1);
  922. ComboBox_SetCurSel(hwnd, 0);
  923. EnableWindow( hwnd, FALSE );
  924. EnableMIDIVolCtrls(hDlg, FALSE);
  925. }
  926. else
  927. {
  928. EnableWindow( hwnd, TRUE );
  929. for (device = 0; device < pai->cNumMIDIOutDevs; device++)
  930. {
  931. MIDIOUTCAPS moc;
  932. int newItem;
  933. moc.szPname[0] = TEXT('\0');
  934. if (midiOutGetDevCapsW(device, &moc, sizeof(moc)))
  935. {
  936. continue;
  937. }
  938. moc.szPname[sizeof(moc.szPname)/sizeof(TCHAR) - 1] = TEXT('\0');
  939. newItem = ComboBox_AddString(hwnd, moc.szPname);
  940. if (newItem != CB_ERR && newItem != CB_ERRSPACE)
  941. {
  942. ComboBox_SetItemData(hwnd, newItem, (LPARAM)device);
  943. if (device == pai->uPrefMIDIOut)
  944. {
  945. ComboBox_SetCurSel(hwnd, newItem);
  946. SetMIDIDeviceOut(pai, device, hDlg);
  947. }
  948. }
  949. }
  950. }
  951. }
  952. STATIC void AudioDlgInit(HWND hDlg)
  953. {
  954. PAUDIODLGINFO pai = (PAUDIODLGINFO)LocalAlloc(LPTR, sizeof(AUDIODLGINFO));
  955. if (!pai) return;
  956. //
  957. // Register context-sensitive help messages from the Customize dialog.
  958. //
  959. guCustomizeContextMenu = RegisterWindowMessage( ACMHELPMSGCONTEXTMENU );
  960. guCustomizeContextHelp = RegisterWindowMessage( ACMHELPMSGCONTEXTHELP );
  961. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pai);
  962. GetPrefInfo(pai, hDlg);
  963. CheckDlgButton(hDlg, IDC_AUDIO_PREF, pai->fPrefOnly);
  964. WAVEOUTInit(hDlg, pai);
  965. WAVEINInit(hDlg, pai);
  966. MIDIInit(hDlg, pai);
  967. if (!(pai->cNumInDevs || pai->cNumOutDevs || pai->cNumMIDIOutDevs))
  968. {
  969. CheckDlgButton(hDlg, IDC_AUDIO_PREF, FALSE);
  970. EnableWindow(GetDlgItem(hDlg, IDC_AUDIO_PREF), FALSE);
  971. }
  972. }
  973. const static DWORD aAudioHelpIds[] = { // Context Help IDs
  974. IDC_GROUPBOX, IDH_COMM_GROUPBOX,
  975. IDI_SPEAKERICON, IDH_COMM_GROUPBOX,
  976. IDC_ICON_6, IDH_COMM_GROUPBOX,
  977. IDC_TEXT_4, IDH_AUDIO_PLAY_PREFER_DEV,
  978. IDC_AUDIO_CB_PLAY, IDH_AUDIO_PLAY_PREFER_DEV,
  979. IDC_LAUNCH_SNDVOL, IDH_AUDIO_PLAY_VOL,
  980. IDC_PLAYBACK_ADVSETUP, IDH_ADV_AUDIO_PLAY_PROP,
  981. IDC_GROUPBOX_2, IDH_COMM_GROUPBOX,
  982. IDI_RECORDICON, IDH_COMM_GROUPBOX,
  983. IDC_ICON_7, IDH_COMM_GROUPBOX,
  984. IDC_TEXT_8, IDH_AUDIO_REC_PREFER_DEV,
  985. IDC_AUDIO_CB_REC, IDH_AUDIO_REC_PREFER_DEV,
  986. IDC_LAUNCH_RECVOL, IDH_AUDIO_REC_VOL,
  987. IDC_RECORD_ADVSETUP, IDH_ADV_AUDIO_REC_PROP,
  988. IDC_GROUPBOX_3, IDH_COMM_GROUPBOX,
  989. IDI_MUSICICON, IDH_COMM_GROUPBOX,
  990. IDC_ICON_8, IDH_COMM_GROUPBOX,
  991. IDC_TEXT_9, IDH_MIDI_SINGLE_INST_BUTTON,
  992. IDC_MUSIC_CB_PLAY, IDH_MIDI_SINGLE_INST_BUTTON,
  993. IDC_LAUNCH_MUSICVOL, IDH_AUDIO_MIDI_VOL,
  994. IDC_MUSIC_ABOUT, IDH_ABOUT,
  995. IDC_AUDIO_PREF, IDH_AUDIO_USE_PREF_ONLY,
  996. 0, 0
  997. };
  998. const static DWORD aCustomizeHelpIds[] = {
  999. IDD_ACMFORMATCHOOSE_CMB_FORMAT, IDH_AUDIO_CUST_ATTRIB,
  1000. IDD_ACMFORMATCHOOSE_CMB_FORMATTAG, IDH_AUDIO_CUST_FORMAT,
  1001. IDD_ACMFORMATCHOOSE_CMB_CUSTOM, IDH_AUDIO_CUST_NAME,
  1002. IDD_ACMFORMATCHOOSE_BTN_DELNAME, IDH_AUDIO_CUST_REMOVE,
  1003. IDD_ACMFORMATCHOOSE_BTN_SETNAME, IDH_AUDIO_CUST_SAVEAS,
  1004. 0, 0
  1005. };
  1006. void WinMMDeviceChange(HWND hDlg)
  1007. {
  1008. PAUDIODLGINFO pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1009. // MSACM_NotifyMapper();
  1010. GetPrefInfo(pai, hDlg);
  1011. CheckDlgButton(hDlg, IDC_AUDIO_PREF, pai->fPrefOnly);
  1012. WAVEOUTInit(hDlg, pai);
  1013. WAVEINInit(hDlg, pai);
  1014. MIDIInit(hDlg, pai);
  1015. if (!(pai->cNumInDevs || pai->cNumOutDevs || pai->cNumMIDIOutDevs))
  1016. {
  1017. CheckDlgButton(hDlg, IDC_AUDIO_PREF, FALSE);
  1018. EnableWindow(GetDlgItem(hDlg, IDC_AUDIO_PREF), FALSE);
  1019. }
  1020. }
  1021. LRESULT CALLBACK AudioTabProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  1022. {
  1023. if (iMsg == giDevChange)
  1024. {
  1025. WinMMDeviceChange(ghDlg);
  1026. }
  1027. return CallWindowProc(gfnPSProc,hwnd,iMsg,wParam,lParam);
  1028. }
  1029. void InitDeviceChange(HWND hDlg)
  1030. {
  1031. gfnPSProc = (WNDPROC) SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LONG_PTR)AudioTabProc);
  1032. giDevChange = RegisterWindowMessage(TEXT("winmm_devicechange"));
  1033. }
  1034. void UninitDeviceChange(HWND hDlg)
  1035. {
  1036. SetWindowLongPtr(GetParent(hDlg),GWLP_WNDPROC,(LONG_PTR)gfnPSProc);
  1037. }
  1038. BOOL CALLBACK AudioDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
  1039. LPARAM lParam)
  1040. {
  1041. NMHDR FAR *lpnm;
  1042. PAUDIODLGINFO pai;
  1043. switch (uMsg)
  1044. {
  1045. case WM_NOTIFY:
  1046. {
  1047. lpnm = (NMHDR FAR *)lParam;
  1048. switch(lpnm->code)
  1049. {
  1050. case PSN_KILLACTIVE:
  1051. FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
  1052. break;
  1053. case PSN_APPLY:
  1054. FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
  1055. break;
  1056. case PSN_SETACTIVE:
  1057. FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  1058. break;
  1059. case PSN_RESET:
  1060. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  1061. break;
  1062. }
  1063. }
  1064. break;
  1065. case WM_INITDIALOG:
  1066. {
  1067. ghDlg = hDlg;
  1068. InitDeviceChange(hDlg);
  1069. if (!gfLoadedACM)
  1070. {
  1071. if (LoadACM())
  1072. {
  1073. gfLoadedACM = TRUE;
  1074. }
  1075. else
  1076. {
  1077. DPF("****Load ACM failed**\r\n");
  1078. ASSERT(FALSE);
  1079. ErrorBox(hDlg, IDS_CANTLOADACM, NULL);
  1080. ExitThread(0);
  1081. }
  1082. }
  1083. AudioDlgInit(hDlg);
  1084. }
  1085. break;
  1086. case WM_DESTROY:
  1087. {
  1088. UninitDeviceChange(hDlg);
  1089. pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1090. LocalFree((HLOCAL)pai);
  1091. if (gfLoadedACM)
  1092. {
  1093. if (!FreeACM())
  1094. {
  1095. DPF("****Free ACM failed**\r\n");
  1096. ASSERT(FALSE);
  1097. }
  1098. gfLoadedACM = FALSE;
  1099. }
  1100. }
  1101. break;
  1102. case WM_CONTEXTMENU:
  1103. {
  1104. WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR) (LPTSTR) aAudioHelpIds);
  1105. return TRUE;
  1106. }
  1107. break;
  1108. case WM_HELP:
  1109. {
  1110. LPHELPINFO lphi = (LPVOID) lParam;
  1111. WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR) (LPTSTR) aAudioHelpIds);
  1112. return TRUE;
  1113. }
  1114. break;
  1115. case WM_COMMAND:
  1116. {
  1117. HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoAudioCommand);
  1118. }
  1119. break;
  1120. default:
  1121. {
  1122. //
  1123. // Handle context-sensitive help messages from Customize dlg.
  1124. //
  1125. if( uMsg == guCustomizeContextMenu )
  1126. {
  1127. WinHelp( (HWND)wParam, NULL, HELP_CONTEXTMENU, (UINT_PTR)(LPTSTR)aCustomizeHelpIds );
  1128. }
  1129. else if( uMsg == guCustomizeContextHelp )
  1130. {
  1131. WinHelp( ((LPHELPINFO)lParam)->hItemHandle, NULL, HELP_WM_HELP, (UINT_PTR)(LPTSTR)aCustomizeHelpIds);
  1132. }
  1133. }
  1134. break;
  1135. }
  1136. return FALSE;
  1137. }
  1138. void ErrorMsgBox(HWND hDlg, UINT uTitle, UINT uMessage)
  1139. {
  1140. TCHAR szMsg[MAXSTR];
  1141. TCHAR szTitle[MAXSTR];
  1142. LoadString(ghInstance, IDS_ERROR_TITLE, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  1143. LoadString(ghInstance, IDS_ERROR_NOSNDVOL, szMsg, sizeof(szMsg)/sizeof(TCHAR));
  1144. MessageBox(hDlg, szMsg,szTitle,MB_OK);
  1145. }
  1146. void LaunchPlaybackVolume(HWND hDlg)
  1147. {
  1148. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
  1149. UINT item;
  1150. item = (UINT)ComboBox_GetCurSel(hwndCBPlay);
  1151. if (item != CB_ERR)
  1152. {
  1153. TCHAR szCmd[MAXSTR];
  1154. UINT uDeviceID;
  1155. MMRESULT mmr;
  1156. STARTUPINFO si;
  1157. PROCESS_INFORMATION pi;
  1158. memset(&si, 0, sizeof(si));
  1159. si.cb = sizeof(si);
  1160. si.wShowWindow = SW_SHOW;
  1161. si.dwFlags = STARTF_USESHOWWINDOW;
  1162. uDeviceID = (UINT)ComboBox_GetItemData(hwndCBPlay, item);
  1163. mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEOUT);
  1164. if (mmr == MMSYSERR_NOERROR)
  1165. {
  1166. wsprintf(szCmd,TEXT("sndvol32.exe -D %d"),uDeviceID);
  1167. if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  1168. {
  1169. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
  1170. }
  1171. }
  1172. else
  1173. {
  1174. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
  1175. }
  1176. }
  1177. }
  1178. void LaunchRecordVolume(HWND hDlg)
  1179. {
  1180. HWND hwndCBRec = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
  1181. UINT item;
  1182. item = (UINT)ComboBox_GetCurSel(hwndCBRec);
  1183. if (item != CB_ERR)
  1184. {
  1185. TCHAR szCmd[MAXSTR];
  1186. UINT uDeviceID;
  1187. MMRESULT mmr;
  1188. STARTUPINFO si;
  1189. PROCESS_INFORMATION pi;
  1190. memset(&si, 0, sizeof(si));
  1191. si.cb = sizeof(si);
  1192. si.wShowWindow = SW_SHOW;
  1193. si.dwFlags = STARTF_USESHOWWINDOW;
  1194. uDeviceID = (UINT)ComboBox_GetItemData(hwndCBRec, item);
  1195. mmr = mixerGetID(HMIXEROBJ_INDEX(uDeviceID), &uDeviceID, MIXER_OBJECTF_WAVEIN);
  1196. if (mmr == MMSYSERR_NOERROR)
  1197. {
  1198. wsprintf(szCmd,TEXT("sndvol32.exe -R -D %d"),uDeviceID);
  1199. if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  1200. {
  1201. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
  1202. }
  1203. }
  1204. else
  1205. {
  1206. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
  1207. }
  1208. }
  1209. }
  1210. void LaunchMIDIVolume(HWND hDlg)
  1211. {
  1212. HWND hwndCBMIDI = GetDlgItem(hDlg, IDC_MUSIC_CB_PLAY);
  1213. UINT item;
  1214. item = (UINT)ComboBox_GetCurSel(hwndCBMIDI);
  1215. if (item != CB_ERR)
  1216. {
  1217. TCHAR szCmd[MAXSTR];
  1218. DWORD dwDeviceID;
  1219. MMRESULT mmr;
  1220. STARTUPINFO si;
  1221. PROCESS_INFORMATION pi;
  1222. memset(&si, 0, sizeof(si));
  1223. si.cb = sizeof(si);
  1224. si.wShowWindow = SW_SHOW;
  1225. si.dwFlags = STARTF_USESHOWWINDOW;
  1226. dwDeviceID = (UINT)ComboBox_GetItemData(hwndCBMIDI, item);
  1227. mmr = mixerGetID(HMIXEROBJ_INDEX(dwDeviceID), &dwDeviceID, MIXER_OBJECTF_MIDIOUT);
  1228. if (mmr == MMSYSERR_NOERROR)
  1229. {
  1230. wsprintf(szCmd,TEXT("sndvol32.exe -D %d"),dwDeviceID);
  1231. if (!CreateProcess(NULL,szCmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
  1232. {
  1233. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOSNDVOL);
  1234. }
  1235. }
  1236. else
  1237. {
  1238. ErrorMsgBox(hDlg,IDS_ERROR_TITLE,IDS_ERROR_NOMIXER);
  1239. }
  1240. }
  1241. }
  1242. BOOL PASCAL DoAudioCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  1243. {
  1244. PAUDIODLGINFO pai = (PAUDIODLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1245. if (!gfLoadedACM)
  1246. {
  1247. return FALSE;
  1248. }
  1249. switch (id)
  1250. {
  1251. case ID_APPLY:
  1252. {
  1253. SetPrefInfo(pai, hDlg);
  1254. }
  1255. break;
  1256. case IDC_AUDIO_CB_PLAY:
  1257. case IDC_AUDIO_CB_REC:
  1258. case IDC_MUSIC_CB_PLAY:
  1259. {
  1260. switch (codeNotify)
  1261. {
  1262. case CBN_SELCHANGE:
  1263. {
  1264. PropSheet_Changed(GetParent(hDlg),hDlg);
  1265. if ((id == IDC_AUDIO_CB_PLAY) || (id == IDC_AUDIO_CB_REC) || id == IDC_MUSIC_CB_PLAY)
  1266. {
  1267. int iIndex;
  1268. AUDIODLGINFO aiTmp;
  1269. PAUDIODLGINFO paiTmp = &aiTmp;
  1270. iIndex = ComboBox_GetCurSel(hwndCtl);
  1271. if (iIndex != CB_ERR)
  1272. {
  1273. if (id == IDC_AUDIO_CB_PLAY)
  1274. {
  1275. paiTmp->uPrefOut = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
  1276. SetDeviceOut(paiTmp, paiTmp->uPrefOut, hDlg);
  1277. }
  1278. else if (id == IDC_AUDIO_CB_REC)
  1279. {
  1280. paiTmp->uPrefIn = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
  1281. SetDeviceIn(paiTmp, paiTmp->uPrefIn, hDlg);
  1282. }
  1283. else if (id == IDC_MUSIC_CB_PLAY)
  1284. {
  1285. paiTmp->uPrefMIDIOut = (UINT)ComboBox_GetItemData(hwndCtl, iIndex);
  1286. SetMIDIDeviceOut(paiTmp, paiTmp->uPrefMIDIOut, hDlg);
  1287. }
  1288. }
  1289. }
  1290. }
  1291. break;
  1292. }
  1293. }
  1294. break;
  1295. case IDC_AUDIO_PREF:
  1296. {
  1297. PropSheet_Changed(GetParent(hDlg),hDlg);
  1298. }
  1299. break;
  1300. case IDC_MUSIC_ABOUT:
  1301. {
  1302. DoRolandAbout(hDlg);
  1303. }
  1304. break;
  1305. case IDC_LAUNCH_SNDVOL:
  1306. {
  1307. LaunchPlaybackVolume(hDlg);
  1308. }
  1309. break;
  1310. case IDC_LAUNCH_RECVOL:
  1311. {
  1312. LaunchRecordVolume(hDlg);
  1313. }
  1314. break;
  1315. case IDC_LAUNCH_MUSICVOL:
  1316. {
  1317. LaunchMIDIVolume(hDlg);
  1318. }
  1319. break;
  1320. case IDC_PLAYBACK_ADVSETUP:
  1321. {
  1322. HWND hwndCBPlay = GetDlgItem(hDlg, IDC_AUDIO_CB_PLAY);
  1323. DWORD dwDeviceID;
  1324. UINT u;
  1325. TCHAR szPrefOut[MAXSTR];
  1326. u = (UINT)ComboBox_GetCurSel(hwndCBPlay);
  1327. if (u != CB_ERR)
  1328. {
  1329. ComboBox_GetLBText(hwndCBPlay, u, (LPARAM)(LPVOID)szPrefOut);
  1330. dwDeviceID = (DWORD)ComboBox_GetItemData(hwndCBPlay, u);
  1331. AdvancedAudio(hDlg, ghInstance, gszWindowsHlp, dwDeviceID, szPrefOut, FALSE);
  1332. }
  1333. }
  1334. break;
  1335. case IDC_RECORD_ADVSETUP:
  1336. {
  1337. HWND hwndCBRec = GetDlgItem(hDlg, IDC_AUDIO_CB_REC);
  1338. DWORD dwDeviceID;
  1339. UINT u;
  1340. TCHAR szPrefIn[MAXSTR];
  1341. u = (UINT)ComboBox_GetCurSel(hwndCBRec);
  1342. if (u != CB_ERR)
  1343. {
  1344. ComboBox_GetLBText(hwndCBRec, u, (LPARAM)(LPVOID)szPrefIn);
  1345. dwDeviceID = (DWORD)ComboBox_GetItemData(hwndCBRec, u);
  1346. AdvancedAudio(hDlg, ghInstance, gszWindowsHlp, dwDeviceID, szPrefIn, TRUE);
  1347. }
  1348. }
  1349. break;
  1350. }
  1351. return FALSE;
  1352. }
  1353. BOOL PASCAL CustomizeDialog(HWND hDlg, LPTSTR szNewFormat, DWORD cbSize)
  1354. {
  1355. BOOL fRet = FALSE; // assume the worse
  1356. ACMFORMATCHOOSE cwf;
  1357. LRESULT lr;
  1358. DWORD dwMaxFormatSize;
  1359. PWAVEFORMATEX spWaveFormat;
  1360. TCHAR szCustomize[64];
  1361. lr = acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,(LPVOID)&dwMaxFormatSize);
  1362. if (lr != 0)
  1363. {
  1364. goto CustomizeOut;
  1365. }
  1366. /* This LocalAlloc is freed in WAVE.C: DestroyWave() */
  1367. spWaveFormat = (PWAVEFORMATEX)LocalAlloc(LPTR, (UINT)dwMaxFormatSize);
  1368. _fmemset(&cwf, 0, sizeof(cwf));
  1369. LoadString(ghInstance, IDS_CUSTOMIZE, szCustomize, sizeof(szCustomize)/sizeof(TCHAR));
  1370. cwf.cbStruct = sizeof(cwf);
  1371. cwf.hwndOwner = hDlg;
  1372. cwf.fdwStyle = ACMFORMATCHOOSE_STYLEF_CONTEXTHELP;
  1373. cwf.fdwEnum = ACM_FORMATENUMF_INPUT;
  1374. cwf.pszTitle = (LPTSTR)szCustomize;
  1375. cwf.pwfx = (LPWAVEFORMATEX)spWaveFormat;
  1376. cwf.cbwfx = dwMaxFormatSize;
  1377. cwf.pszName = szNewFormat;
  1378. cwf.cchName = cbSize;
  1379. lr = acmFormatChooseW(&cwf);
  1380. if (lr == MMSYSERR_NOERROR)
  1381. {
  1382. fRet = TRUE;
  1383. }
  1384. #ifdef DEBUG
  1385. else
  1386. {
  1387. TCHAR a[200];
  1388. wsprintf(a,TEXT("MSACMCPL: acmFormatChoose failed (lr=%u).\n"),lr);
  1389. OutputDebugString(a);
  1390. }
  1391. #endif
  1392. CustomizeOut:
  1393. return fRet; // return our result
  1394. } /* NewSndDialog() */
  1395. ///////////////////////////////////////////////////////////////////////////////
  1396. void acmFreeCodecInfo (PCPLCODECINFO pcci)
  1397. {
  1398. if (pcci->fMadeIcon && pcci->hIcon)
  1399. {
  1400. DestroyIcon (pcci->hIcon);
  1401. pcci->hIcon = NULL;
  1402. pcci->fMadeIcon = FALSE;
  1403. }
  1404. LocalFree ((HANDLE)pcci);
  1405. }
  1406. typedef struct // FindCodecData
  1407. {
  1408. BOOL fFound;
  1409. ACMDRIVERDETAILSW add;
  1410. WORD wMid, wPid;
  1411. HACMDRIVERID hadid;
  1412. DWORD fdwSupport;
  1413. } FindCodecData;
  1414. PCPLCODECINFO acmFindCodecInfo (WORD wMidMatch, WORD wPidMatch)
  1415. {
  1416. MMRESULT mmr;
  1417. FindCodecData fcd;
  1418. PCPLCODECINFO pcci;
  1419. fcd.fFound = FALSE;
  1420. fcd.wMid = wMidMatch;
  1421. fcd.wPid = wPidMatch;
  1422. // fcd.add is filled in by acmFindCodecCallback during the following enum:
  1423. mmr = (MMRESULT)acmDriverEnum (acmFindCodecInfoCallback,
  1424. (DWORD_PTR)&fcd, // (data passed as arg2 to callback)
  1425. ACM_DRIVERENUMF_NOLOCAL |
  1426. ACM_DRIVERENUMF_DISABLED);
  1427. if (MMSYSERR_NOERROR != mmr)
  1428. {
  1429. return NULL;
  1430. }
  1431. if (!fcd.fFound)
  1432. {
  1433. return NULL;
  1434. }
  1435. // Congratulations--we found a matching ACM driver. Now
  1436. // we need to create a CPLCODECINFO structure to describe it,
  1437. // so the rest of the code in this file will work without
  1438. // mods. <<sigh>> A CPLCODECINFO structure doesn't have
  1439. // anything special--it's just a place to track info about
  1440. // an ACM driver. The most important thing is the HACMDRIVERID.
  1441. //
  1442. if ((pcci = (PCPLCODECINFO)LocalAlloc(LPTR, sizeof(CPLCODECINFO))) == NULL)
  1443. {
  1444. return NULL;
  1445. }
  1446. lstrcpy (pcci->szDesc, fcd.add.szLongName);
  1447. pcci->ads.hadid = fcd.hadid;
  1448. pcci->ads.fdwSupport = fcd.fdwSupport;
  1449. pcci->fMadeIcon = FALSE;
  1450. if ((pcci->hIcon = fcd.add.hicon) == NULL)
  1451. {
  1452. int cxIcon, cyIcon;
  1453. cxIcon = (int)GetSystemMetrics (SM_CXICON);
  1454. cyIcon = (int)GetSystemMetrics (SM_CYICON);
  1455. pcci->hIcon = LoadImage (myInstance,
  1456. MAKEINTRESOURCE( IDI_ACM ),
  1457. IMAGE_ICON, cxIcon, cyIcon, LR_DEFAULTCOLOR);
  1458. pcci->fMadeIcon = TRUE;
  1459. }
  1460. acmMetrics ((HACMOBJ)pcci->ads.hadid,
  1461. ACM_METRIC_DRIVER_PRIORITY,
  1462. &(pcci->ads.dwPriority));
  1463. return pcci;
  1464. }
  1465. BOOL CALLBACK acmFindCodecInfoCallback (HACMDRIVERID hadid,
  1466. DWORD_PTR dwUser,
  1467. DWORD fdwSupport)
  1468. {
  1469. FindCodecData *pfcd;
  1470. // dwUser is really a pointer to a FindCodecData
  1471. // structure, supplied by the guy who called acmDriverEnum.
  1472. //
  1473. if ((pfcd = (FindCodecData *)dwUser) == NULL)
  1474. {
  1475. return FALSE;
  1476. }
  1477. // No details? Try the next driver.
  1478. //
  1479. pfcd->add.cbStruct = sizeof(pfcd->add);
  1480. if (acmDriverDetailsW (hadid, &pfcd->add, 0L) != MMSYSERR_NOERROR)
  1481. {
  1482. return TRUE;
  1483. }
  1484. // Great. Now see if the driver we found matches
  1485. // pfcd->wMid/wPad; if so we're done, else keep searching.
  1486. //
  1487. if ((pfcd->wMid == pfcd->add.wMid) && (pfcd->wPid == pfcd->add.wPid) )
  1488. {
  1489. pfcd->hadid = hadid;
  1490. pfcd->fFound = TRUE;
  1491. pfcd->fdwSupport = fdwSupport;
  1492. return FALSE; // found it! leave pfcd->add intact and leave.
  1493. }
  1494. return TRUE; // not the right driver--keep looking
  1495. }
  1496. UINT acmCountCodecs (void)
  1497. {
  1498. MMRESULT mmr;
  1499. UINT nCodecs = 0;
  1500. mmr = (MMRESULT)acmDriverEnum (acmCountCodecsEnum,
  1501. (DWORD_PTR)&nCodecs,
  1502. ACM_DRIVERENUMF_NOLOCAL |
  1503. ACM_DRIVERENUMF_DISABLED);
  1504. if (MMSYSERR_NOERROR != mmr)
  1505. {
  1506. return 0;
  1507. }
  1508. return nCodecs;
  1509. }
  1510. BOOL CALLBACK acmCountCodecsEnum (HACMDRIVERID hadid,
  1511. DWORD_PTR dwUser,
  1512. DWORD fdwSupport)
  1513. {
  1514. UINT *pnCodecs;
  1515. // dwUser is really a pointer to a UINT being used to
  1516. // count the number of codecs we encounter.
  1517. //
  1518. if ((pnCodecs = (UINT *)dwUser) == NULL)
  1519. {
  1520. return FALSE;
  1521. }
  1522. ++ (*pnCodecs);
  1523. return TRUE; // keep counting
  1524. }