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.

1306 lines
33 KiB

  1. // File: AudioCpl.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "avdefs.h"
  5. #include "ConfCpl.h"
  6. #include "help_ids.h"
  7. #include <ih323cc.h>
  8. #include <initguid.h>
  9. #include <nacguids.h>
  10. #include <auformats.h>
  11. #include "ConfPolicies.h"
  12. const int SLOW_CPU_MHZ = 110; // pentiums 110mhz - 180mhz are "slow"
  13. const int FAST_CPU_MHZ = 200; // fast machines are 200mhz and faster
  14. const int VERYFAST_CPU_MHZ = 500; // un-normalized, this will include 400 mhz PentIIs
  15. // 486 and slow pentium (<= 100 mhz) settings (VERY SLOW)
  16. const UINT CIF_RATE_VERYSLOW = 3;
  17. const UINT SQCIF_RATE_VERYSLOW = 7;
  18. const UINT QCIF_RATE_VERYSLOW = 7;
  19. // pentium 75mhz settings (SLOW)
  20. const UINT CIF_RATE_SLOW = 7;
  21. const UINT SQCIF_RATE_SLOW = 15;
  22. const UINT QCIF_RATE_SLOW = 15;
  23. // pentium 200mhz settings (FAST)
  24. const UINT CIF_RATE_FAST = 15;
  25. const UINT SQCIF_RATE_FAST = 30;
  26. const UINT QCIF_RATE_FAST = 30;
  27. const UINT CIF_RATE_VERYFAST = 30;
  28. typedef struct _CODECINFO
  29. {
  30. HINSTANCE hLib;
  31. IH323CallControl* lpIH323;
  32. UINT uNumFormats;
  33. PBASIC_AUDCAP_INFO pCodecCapList;
  34. PWORD pOldCodecOrderList;
  35. PWORD pCurCodecOrderList;
  36. LPAPPCAPPIF lpIAppCap;
  37. LPAPPVIDCAPPIF lpIVidAppCap;
  38. LPCAPSIF lpICapsCtl;
  39. } CODECINFO, *PCODECINFO;
  40. typedef struct
  41. {
  42. BOOL fManual;
  43. UINT uBandwidth;
  44. PCODECINFO pCodecInfo;
  45. } ADVCODEC, *PADVCODEC;
  46. //SS: the cpu utilization is bogus so for now hide it
  47. //#define CODEC_LV_NUM_COLUMNS 3
  48. #define CODEC_LV_MAX_COLUMNS 3
  49. #define CODEC_LV_NUM_COLUMNS 2
  50. #define MAGIC_CPU_DO_NOT_EXCEED_PERCENTAGE 50 //Don't use more than this % of the CPU for encoding
  51. //Also in nac\balance.cpp
  52. // given the bandwidth identifier (1-4) and the CPU megahertz, return
  53. // the actual bandwidth amount in bits/sec
  54. int GetBandwidthBits(int id, int megahertz)
  55. {
  56. int nBits=BW_144KBS_BITS;
  57. switch (id)
  58. {
  59. case BW_144KBS:
  60. nBits=BW_144KBS_BITS;
  61. break;
  62. case BW_288KBS:
  63. nBits=BW_288KBS_BITS;
  64. break;
  65. case BW_ISDN:
  66. nBits=BW_ISDN_BITS;
  67. break;
  68. case BW_MOREKBS: // LAN
  69. if (megahertz >= VERYFAST_CPU_MHZ)
  70. {
  71. nBits = BW_FASTLAN_BITS;
  72. }
  73. else
  74. {
  75. nBits = BW_SLOWLAN_BITS;
  76. }
  77. break;
  78. }
  79. return nBits;
  80. }
  81. // begin data types used for ChooseCodecByBw
  82. #define CODEC_DISABLED 99
  83. #define CODEC_UNKNOWN 98
  84. typedef struct _codecprefrow
  85. {
  86. WORD wFormatTag;
  87. WORD wOrder586;
  88. WORD wOrder486;
  89. WORD wMinBW;
  90. } CODECPREFROW;
  91. typedef CODECPREFROW CODECPREFTABLE[];
  92. // FORMAT NAME 586 Order 486 Order Minimum BW
  93. static const CODECPREFTABLE g_CodecPrefTable =
  94. {
  95. WAVE_FORMAT_MSG723, 1, CODEC_DISABLED, BW_144KBS,
  96. WAVE_FORMAT_LH_SB16, 2, 1, BW_288KBS,
  97. WAVE_FORMAT_LH_SB8, 3, 2, BW_144KBS,
  98. WAVE_FORMAT_LH_SB12, 4, 3, BW_144KBS,
  99. WAVE_FORMAT_MULAW, 5, 4, BW_ISDN,
  100. WAVE_FORMAT_ALAW, 6, 5, BW_ISDN,
  101. WAVE_FORMAT_ADPCM, 7, 6, BW_ISDN,
  102. WAVE_FORMAT_LH_CELP, 8, CODEC_DISABLED, BW_144KBS,
  103. WAVE_FORMAT_MSRT24, 9, 7, BW_144KBS
  104. };
  105. // end of stuff used by ChooseCodecByBw
  106. static const int g_ColHdrStrId[CODEC_LV_MAX_COLUMNS] =
  107. {
  108. IDS_CODECNAME,
  109. IDS_MAXBITRATE,
  110. IDS_CPUUTIL,
  111. };
  112. //prototypes
  113. INT_PTR CALLBACK AdvCodecDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  114. int CALLBACK CodecLVCompareProc (LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
  115. BOOL FillCodecListView(HWND hCB, PCODECINFO pCodecInfo);
  116. BOOL ChooseCodecByBw(UINT uBandWidthId, PCODECINFO pCodecInfo);
  117. void SortCodecs(PADVCODEC pAdvCodec, int nSelection);
  118. BOOL SetAppCodecPrefs(PCODECINFO pCodecInfo,UINT uBandwith);
  119. BOOL GetIAppCap(PCODECINFO pCodecInfo);
  120. BOOL GetAppCapFormats(PCODECINFO pCodecInfo);
  121. void FreeAppCapFormats(PCODECINFO pCodecInfo);
  122. void ReleaseIAppCap(PCODECINFO pCodecInfo);
  123. BOOL ApplyUserPrefs(PCODECINFO pCodecInfo, UINT uMaximumBandwidth);
  124. static const DWORD _rgHelpIdsAudio[] = {
  125. IDC_GENERAL_GROUP, IDH_AUDIO_GENERAL,
  126. IDC_FULLDUPLEX, IDH_AUDIO_FULL_DUPLEX,
  127. IDC_AUTOGAIN, IDH_AUDIO_AUTO_GAIN,
  128. IDC_AUTOMIX, IDH_AUDIO_AUTOMIXER,
  129. IDC_DIRECTSOUND, IDH_AUDIO_DIRECTSOUND,
  130. IDC_START_AUDIO_WIZ, IDH_AUDIO_TUNING_WIZARD,
  131. IDC_ADVANCEDCODEC, IDH_AUDIO_ADVANCED_CODEC_SETTINGS,
  132. IDC_MICSENSE_GROUP, IDH_AUDIO_MIC_SENSITIVITY,
  133. IDC_MICSENSE_AUTO, IDH_AUDIO_AUTO_SENSITIVITY,
  134. IDC_MICSENSE_MANUAL, IDH_AUDIO_MANUAL_SENSITIVITY,
  135. IDC_TRK_MIC, IDH_AUDIO_MANUAL_SENSITIVITY,
  136. 0, 0 // terminator
  137. };
  138. VOID InitAudioSettings(HWND hDlg, BOOL *pfFullDuplex, BOOL *pfAgc, BOOL *pfAutoMix, BOOL *pfDirectSound)
  139. {
  140. BOOL fFullDuplex = FALSE;
  141. BOOL fAgc = FALSE;
  142. BOOL fDirectSound;
  143. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  144. UINT uSoundCardCaps = re.GetNumber(REGVAL_SOUNDCARDCAPS,SOUNDCARD_NONE);
  145. ASSERT(ISSOUNDCARDPRESENT(uSoundCardCaps) && (!SysPol::NoAudio()));
  146. if (ISSOUNDCARDFULLDUPLEX(uSoundCardCaps) && ConfPolicies::IsFullDuplexAllowed())
  147. {
  148. ::EnableWindow(::GetDlgItem(hDlg, IDC_FULLDUPLEX), TRUE);
  149. // read settings from registry
  150. fFullDuplex = (BOOL)
  151. ( re.GetNumber(REGVAL_FULLDUPLEX,0) == FULLDUPLEX_ENABLED );
  152. }
  153. else
  154. {
  155. DisableControl(hDlg, IDC_FULLDUPLEX);
  156. }
  157. if (DOESSOUNDCARDHAVEAGC(uSoundCardCaps))
  158. {
  159. ::EnableWindow(::GetDlgItem(hDlg, IDC_AUTOGAIN), TRUE);
  160. // read settings from registry
  161. fAgc = (BOOL)
  162. ( re.GetNumber(REGVAL_AUTOGAIN,AUTOGAIN_ENABLED) == AUTOGAIN_ENABLED );
  163. }
  164. else
  165. {
  166. DisableControl(hDlg, IDC_AUTOGAIN);
  167. }
  168. *pfFullDuplex = fFullDuplex;
  169. // for automix and agc, don't try updating the check-mark if
  170. // NULL has been passed in
  171. if (pfAutoMix)
  172. {
  173. *pfAutoMix = (BOOL)(re.GetNumber(REGVAL_AUTOMIX, AUTOMIX_ENABLED) == AUTOMIX_ENABLED);
  174. SendDlgItemMessage(hDlg, IDC_AUTOMIX, BM_SETCHECK, *pfAutoMix, 0L);
  175. }
  176. if (pfAgc)
  177. {
  178. *pfAgc = fAgc;
  179. SendDlgItemMessage ( hDlg, IDC_AUTOGAIN, BM_SETCHECK, fAgc, 0L );
  180. }
  181. if (ISDIRECTSOUNDAVAILABLE(uSoundCardCaps))
  182. {
  183. RegEntry rePol(POLICIES_KEY, HKEY_CURRENT_USER);
  184. fDirectSound = (BOOL)(re.GetNumber(REGVAL_DIRECTSOUND, DSOUND_USER_DISABLED) == DSOUND_USER_ENABLED);
  185. ::EnableWindow(::GetDlgItem(hDlg, IDC_DIRECTSOUND),
  186. !rePol.GetNumber(REGVAL_POL_NOCHANGE_DIRECTSOUND, DEFAULT_POL_NOCHANGE_DIRECTSOUND));
  187. }
  188. else
  189. {
  190. fDirectSound = FALSE;
  191. ::EnableWindow(::GetDlgItem(hDlg, IDC_DIRECTSOUND), FALSE);
  192. SendDlgItemMessage(hDlg, IDC_DIRECTSOUND, BM_SETCHECK, FALSE, 0L);
  193. }
  194. // don't check the checkbox if the caller didn't pass in a var to be updated
  195. if (pfDirectSound)
  196. {
  197. *pfDirectSound = fDirectSound;
  198. SendDlgItemMessage(hDlg, IDC_DIRECTSOUND, BM_SETCHECK, *pfDirectSound, 0L);
  199. }
  200. // set the check boxes for those that are enabled
  201. SendDlgItemMessage ( hDlg, IDC_FULLDUPLEX,
  202. BM_SETCHECK, *pfFullDuplex, 0L );
  203. }
  204. INT_PTR APIENTRY AudioDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  205. {
  206. static PROPSHEETPAGE * ps;
  207. static UINT uOldCodecChoice;
  208. static UINT uNewCodecChoice;
  209. static BOOL fOldFullDuplex;
  210. static BOOL fOldAgc;
  211. static BOOL fOldAutoMic;
  212. static BOOL fOldAutoMix;
  213. static BOOL fOldDirectSound;
  214. static BOOL fOldH323GatewayEnabled;
  215. static UINT uOldMicSense;
  216. static CODECINFO CodecInfo;
  217. static BOOL bAdvDlg;
  218. switch (message) {
  219. case WM_INITDIALOG:
  220. {
  221. // Save the PROPSHEETPAGE information.
  222. ps = (PROPSHEETPAGE *)lParam;
  223. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  224. InitAudioSettings(hDlg, &fOldFullDuplex, &fOldAgc, &fOldAutoMix, &fOldDirectSound);
  225. //initialize the codecinfo structure, these will be set as and when needed
  226. ZeroMemory(&CodecInfo, sizeof(CodecInfo));
  227. uNewCodecChoice = uOldCodecChoice = re.GetNumber(REGVAL_CODECCHOICE, CODECCHOICE_AUTO);
  228. // Get Audio settings
  229. fOldAutoMic = (BOOL)
  230. ( re.GetNumber(REGVAL_MICROPHONE_AUTO,
  231. DEFAULT_MICROPHONE_AUTO) == MICROPHONE_AUTO_YES );
  232. SendDlgItemMessage ( hDlg,
  233. fOldAutoMic ? IDC_MICSENSE_AUTO : IDC_MICSENSE_MANUAL,
  234. BM_SETCHECK, TRUE, 0L );
  235. EnableWindow ( GetDlgItem ( hDlg, IDC_TRK_MIC ),
  236. (BOOL)SendDlgItemMessage ( hDlg, IDC_MICSENSE_MANUAL,
  237. BM_GETCHECK, 0,0));
  238. SendDlgItemMessage (hDlg, IDC_TRK_MIC, TBM_SETRANGE, FALSE,
  239. MAKELONG (MIN_MICROPHONE_SENSITIVITY,
  240. MAX_MICROPHONE_SENSITIVITY ));
  241. uOldMicSense = re.GetNumber ( REGVAL_MICROPHONE_SENSITIVITY,
  242. DEFAULT_MICROPHONE_SENSITIVITY );
  243. SendDlgItemMessage (hDlg, IDC_TRK_MIC, TBM_SETTICFREQ,
  244. ( MAX_MICROPHONE_SENSITIVITY - MIN_MICROPHONE_SENSITIVITY )
  245. / 10, 0 );
  246. SendDlgItemMessage (hDlg, IDC_TRK_MIC, TBM_SETPOS, TRUE,
  247. uOldMicSense );
  248. bAdvDlg = FALSE;
  249. return (TRUE);
  250. }
  251. case WM_NOTIFY:
  252. switch (((NMHDR FAR *) lParam)->code) {
  253. case PSN_APPLY:
  254. {
  255. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  256. BOOL fFullDuplex = SendDlgItemMessage
  257. (hDlg, IDC_FULLDUPLEX, BM_GETCHECK, 0, 0 ) ?
  258. FULLDUPLEX_ENABLED : FULLDUPLEX_DISABLED;
  259. BOOL fAgc = SendDlgItemMessage
  260. (hDlg, IDC_AUTOGAIN, BM_GETCHECK, 0, 0 ) ?
  261. AUTOGAIN_ENABLED : AUTOGAIN_DISABLED;
  262. BOOL fAutoMix = SendDlgItemMessage
  263. (hDlg, IDC_AUTOMIX, BM_GETCHECK, 0, 0) ?
  264. AUTOMIX_ENABLED : AUTOMIX_DISABLED;
  265. BOOL fDirectSound = SendDlgItemMessage
  266. (hDlg, IDC_DIRECTSOUND, BM_GETCHECK, 0, 0) ?
  267. DSOUND_USER_ENABLED : DSOUND_USER_DISABLED;
  268. if ( fFullDuplex != fOldFullDuplex )
  269. {
  270. re.SetValue ( REGVAL_FULLDUPLEX, fFullDuplex );
  271. g_dwChangedSettings |= CSETTING_L_FULLDUPLEX;
  272. }
  273. if ( fAgc != fOldAgc )
  274. {
  275. re.SetValue ( REGVAL_AUTOGAIN, fAgc );
  276. g_dwChangedSettings |= CSETTING_L_AGC;
  277. }
  278. // use same flag bit as agc as for automix
  279. // since this automix and agc may evenutally
  280. // get combined into 1 ui choice
  281. if (fAutoMix != fOldAutoMix)
  282. {
  283. re.SetValue(REGVAL_AUTOMIX, fAutoMix);
  284. g_dwChangedSettings |= CSETTING_L_AGC;
  285. }
  286. if (fDirectSound != fOldDirectSound)
  287. {
  288. re.SetValue(REGVAL_DIRECTSOUND, fDirectSound);
  289. g_dwChangedSettings |= CSETTING_L_DIRECTSOUND;
  290. }
  291. UINT uBandWidth = re.GetNumber(REGVAL_TYPICALBANDWIDTH,BW_DEFAULT);
  292. // if the advanced dialog has not been accessed,
  293. // then there is nothing to changes as far as the
  294. // codecs go
  295. if (bAdvDlg)
  296. {
  297. if (uNewCodecChoice == CODECCHOICE_AUTO)
  298. {
  299. //apply heuristics and apply the prefs to registry
  300. ChooseCodecByBw(uBandWidth, &CodecInfo);
  301. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  302. }
  303. else
  304. {
  305. for (int i = 0; i < (int)CodecInfo.uNumFormats &&
  306. CodecInfo.pCodecCapList; i++)
  307. {
  308. if (CodecInfo.pCodecCapList[i].wSortIndex !=
  309. CodecInfo.pOldCodecOrderList[i])
  310. {
  311. // oder has changed, save the new order
  312. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  313. break;
  314. }
  315. }
  316. }
  317. }
  318. FreeAppCapFormats(&CodecInfo);
  319. // Handle the Trackbar controls:
  320. BOOL fAutoMic = (BOOL)SendDlgItemMessage ( hDlg, IDC_MICSENSE_AUTO,
  321. BM_GETCHECK, 0, 0 );
  322. if ( fAutoMic != fOldAutoMic ) {
  323. g_dwChangedSettings |= CSETTING_L_AUTOMIC;
  324. re.SetValue ( REGVAL_MICROPHONE_AUTO, fAutoMic ?
  325. MICROPHONE_AUTO_YES : MICROPHONE_AUTO_NO );
  326. }
  327. UINT uMicSense = (UINT)SendDlgItemMessage( hDlg, IDC_TRK_MIC,
  328. TBM_GETPOS, 0, 0 );
  329. if ( uMicSense != uOldMicSense ) {
  330. g_dwChangedSettings |= CSETTING_L_MICSENSITIVITY;
  331. re.SetValue ( REGVAL_MICROPHONE_SENSITIVITY, uMicSense);
  332. }
  333. break;
  334. }
  335. case PSN_RESET:
  336. //reset the codec choice in the registry if it has changed
  337. if (uNewCodecChoice != uOldCodecChoice)
  338. {
  339. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  340. re.SetValue(REGVAL_CODECCHOICE, uOldCodecChoice);
  341. }
  342. //free the capformats if allocated
  343. FreeAppCapFormats(&CodecInfo);
  344. break;
  345. }
  346. break;
  347. case WM_COMMAND:
  348. switch (GET_WM_COMMAND_ID (wParam, lParam))
  349. {
  350. case IDC_START_AUDIO_WIZ:
  351. {
  352. AUDIOWIZOUTPUT AwOutput;
  353. BOOL fFullDuplex, fAgc, fDirectSound, fCurrentDS;
  354. if (::FIsConferenceActive())
  355. {
  356. ConfMsgBox(hDlg,
  357. (LPCTSTR)IDS_NOAUDIOTUNING);
  358. break;
  359. }
  360. fAgc = SendDlgItemMessage
  361. (hDlg, IDC_AUTOGAIN, BM_GETCHECK, 0, 0 ) ?
  362. AUTOGAIN_ENABLED : AUTOGAIN_DISABLED;
  363. //SS:note the calibrated value can get out of sync
  364. //need a warning
  365. CallAudioCalibWizard(hDlg,RUNDUE_USERINVOKED,WAVE_MAPPER,&AwOutput,(INT)fAgc);
  366. if (AwOutput.uChanged & SOUNDCARD_CHANGED)
  367. g_dwChangedSettings |= CSETTING_L_AUDIODEVICE;
  368. // wizard can change duplex, and agc availability, and DirectSound
  369. // don't pass in AGC and AUTOMIX pointers, because we don't want
  370. // the checkboxes to revet back to what they were initialized at.
  371. InitAudioSettings(hDlg, &fFullDuplex, NULL, NULL, NULL);
  372. break;
  373. }
  374. case IDC_ADVANCEDCODEC:
  375. {
  376. RegEntry re( AUDIO_KEY, HKEY_CURRENT_USER );
  377. //SS ::: get the cap formats,
  378. //this will retrieve the codec caps if not allready rerieved
  379. if (GetAppCapFormats(&CodecInfo))
  380. {
  381. ADVCODEC AdvCodec;
  382. AdvCodec.fManual = (uNewCodecChoice == CODECCHOICE_MANUAL);
  383. AdvCodec.uBandwidth = re.GetNumber(REGVAL_TYPICALBANDWIDTH, BW_DEFAULT);
  384. AdvCodec.pCodecInfo = &CodecInfo;
  385. if ((DialogBoxParam(GetInstanceHandle(),MAKEINTRESOURCE(IDD_ADVANCEDCODEC),hDlg,AdvCodecDlgProc,
  386. (LPARAM)&AdvCodec)) == IDCANCEL)
  387. {
  388. //the dialog box changes it in place so current settings need to be restored into
  389. //update the pcodecinfo sort order from the previous current settings
  390. for (int i = 0; i < (int)CodecInfo.uNumFormats; i++)
  391. (CodecInfo.pCodecCapList[i]).wSortIndex = CodecInfo.pCurCodecOrderList[i];
  392. }
  393. else
  394. {
  395. uNewCodecChoice = (AdvCodec.fManual ?
  396. CODECCHOICE_MANUAL : CODECCHOICE_AUTO);
  397. re.SetValue(REGVAL_CODECCHOICE, uNewCodecChoice);
  398. //else update the current
  399. for (int i = 0; i < (int)CodecInfo.uNumFormats; i++)
  400. CodecInfo.pCurCodecOrderList[i] = (CodecInfo.pCodecCapList[i]).wSortIndex;
  401. bAdvDlg = TRUE;
  402. }
  403. }
  404. break;
  405. }
  406. case IDC_MICSENSE_AUTO:
  407. case IDC_MICSENSE_MANUAL:
  408. EnableWindow ( GetDlgItem ( hDlg, IDC_TRK_MIC ),
  409. (BOOL)SendDlgItemMessage ( hDlg, IDC_MICSENSE_MANUAL,
  410. BM_GETCHECK, 0,0));
  411. break;
  412. default:
  413. break;
  414. }
  415. break;
  416. case WM_CONTEXTMENU:
  417. DoHelpWhatsThis(wParam, _rgHelpIdsAudio);
  418. break;
  419. case WM_HELP:
  420. DoHelp(lParam, _rgHelpIdsAudio);
  421. break;
  422. }
  423. return (FALSE);
  424. }
  425. static const DWORD aAdvCodecHelpIds[] = {
  426. IDC_CODECMANUAL, IDH_AUDIO_MANUAL_CODEC_SETTINGS,
  427. IDC_COMBO_CODEC, IDH_ADVCOMP_CODECS,
  428. IDC_CODECDEFAULT, IDH_ADVCOMP_DEFAULTS,
  429. IDC_CODECLISTLABEL, IDH_ADVCOMP_CODECS,
  430. 0, 0 // terminator
  431. };
  432. INT_PTR CALLBACK AdvCodecDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  433. {
  434. static PADVCODEC pAdvCodec = NULL;
  435. static nCodecSelection=0;
  436. WORD wCmdId;
  437. switch(uMsg)
  438. {
  439. case WM_INITDIALOG:
  440. //get the list of codecs
  441. pAdvCodec = (PADVCODEC)lParam;
  442. ASSERT(pAdvCodec);
  443. SendDlgItemMessage ( hDlg, IDC_CODECMANUAL,
  444. BM_SETCHECK, pAdvCodec->fManual, 0L );
  445. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_CODEC), pAdvCodec->fManual);
  446. if (!pAdvCodec->fManual)
  447. {
  448. ChooseCodecByBw(pAdvCodec->uBandwidth, pAdvCodec->pCodecInfo);
  449. }
  450. //fill the list box;
  451. FillCodecListView(GetDlgItem(hDlg, IDC_COMBO_CODEC),
  452. pAdvCodec->pCodecInfo);
  453. if (pAdvCodec->fManual)
  454. {
  455. nCodecSelection = (int)SendMessage((HWND)lParam, CB_GETCURSEL, 0,0);
  456. // convert index of combo box choice to index in capability list
  457. nCodecSelection = (int)SendMessage((HWND)lParam, CB_GETITEMDATA, nCodecSelection,0);
  458. }
  459. return(TRUE);
  460. case WM_CONTEXTMENU:
  461. DoHelpWhatsThis(wParam, aAdvCodecHelpIds);
  462. break;
  463. case WM_HELP:
  464. DoHelp(lParam, aAdvCodecHelpIds);
  465. break;
  466. case WM_COMMAND:
  467. wCmdId = GET_WM_COMMAND_ID (wParam, lParam); // LOWORD (uParam)
  468. switch (wCmdId)
  469. {
  470. case IDOK:
  471. if (pAdvCodec->fManual)
  472. {
  473. nCodecSelection = (int)SendDlgItemMessage(hDlg, IDC_COMBO_CODEC, CB_GETCURSEL, 0,0);
  474. nCodecSelection = (int)SendDlgItemMessage(hDlg, IDC_COMBO_CODEC, CB_GETITEMDATA, nCodecSelection,0);
  475. SortCodecs(pAdvCodec, nCodecSelection);
  476. }
  477. EndDialog (hDlg, IDOK);
  478. return(TRUE);
  479. case IDCANCEL:
  480. EndDialog(hDlg, IDCANCEL);
  481. return(TRUE);
  482. case IDC_CODECMANUAL:
  483. pAdvCodec->fManual = (BOOL)SendDlgItemMessage ( hDlg, IDC_CODECMANUAL,
  484. BM_GETCHECK, 0,0);
  485. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_CODEC), pAdvCodec->fManual);
  486. if (pAdvCodec->fManual)
  487. {
  488. break;
  489. }
  490. else
  491. {
  492. ChooseCodecByBw(pAdvCodec->uBandwidth, pAdvCodec->pCodecInfo);
  493. FillCodecListView(GetDlgItem(hDlg, IDC_COMBO_CODEC),
  494. pAdvCodec->pCodecInfo);
  495. }
  496. break;
  497. } // WM_COMMAND
  498. default:
  499. return FALSE;
  500. }
  501. return (FALSE);
  502. }
  503. BOOL FillCodecListView(HWND hCB, PCODECINFO pCodecInfo)
  504. {
  505. PBASIC_AUDCAP_INFO pCurCodecCap;
  506. UINT uIndex, uTotal, uItemIndex;
  507. UINT uSortTop, uSortTopIndex;
  508. SendMessage(hCB, CB_RESETCONTENT,0,0); // erase all items in CB
  509. uSortTopIndex = 0;
  510. uTotal = pCodecInfo->uNumFormats;
  511. uSortTop = uTotal-1;
  512. for (uIndex = 0; uIndex < uTotal; uIndex++)
  513. {
  514. pCurCodecCap = &(pCodecInfo->pCodecCapList[uIndex]);
  515. if ((!pCurCodecCap->bRecvEnabled) && (!pCurCodecCap->bSendEnabled))
  516. {
  517. continue;
  518. }
  519. uItemIndex = (UINT)SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)(pCurCodecCap->szFormat));
  520. SendMessage(hCB, CB_SETITEMDATA, uItemIndex, uIndex);
  521. if (pCurCodecCap->wSortIndex < uSortTop)
  522. {
  523. uSortTop = pCurCodecCap->wSortIndex;
  524. uSortTopIndex = uItemIndex;
  525. }
  526. }
  527. SendMessage(hCB, CB_SETCURSEL, uSortTopIndex, 0);
  528. return TRUE;
  529. }
  530. void SortCodecs(PADVCODEC pAdvCodec, int nSelection)
  531. {
  532. PBASIC_AUDCAP_INFO pDefaultCodec, pSelectedCodec, pCodec;
  533. WORD wSortOrderBest, wSortOrderSelected;
  534. UINT uIndex;
  535. if (!pAdvCodec->fManual)
  536. return;
  537. if ((nSelection < 0) || ((UINT)nSelection > (pAdvCodec->pCodecInfo->uNumFormats)))
  538. {
  539. return;
  540. }
  541. ChooseCodecByBw(pAdvCodec->uBandwidth, pAdvCodec->pCodecInfo);
  542. // this is the codec the user selected
  543. pSelectedCodec = &(pAdvCodec->pCodecInfo->pCodecCapList[nSelection]);
  544. // all codecs that have a sort index less than the selected codec
  545. // get moved down one
  546. for (uIndex = 0; uIndex < pAdvCodec->pCodecInfo->uNumFormats; uIndex++)
  547. {
  548. pCodec = &(pAdvCodec->pCodecInfo->pCodecCapList[uIndex]);
  549. if (pCodec->wSortIndex < pSelectedCodec->wSortIndex)
  550. {
  551. pCodec->wSortIndex = pCodec->wSortIndex + 1;
  552. }
  553. }
  554. pSelectedCodec->wSortIndex = 0;
  555. }
  556. #define SQCIF 0x1
  557. #define QCIF 0x2
  558. #define CIF 0x4
  559. #define UNKNOWN 0x8
  560. #define get_format(s) (s == Small ? SQCIF : (s == Medium ? QCIF: (s == Large ? CIF : UNKNOWN)))
  561. BOOL SetAppCodecPrefs(PCODECINFO pCodecInfo,UINT uBandwidth)
  562. {
  563. BOOL fRet = FALSE;
  564. HRESULT hr;
  565. DWORD dwcFormats,dwcFormatsReturned;
  566. BASIC_VIDCAP_INFO *pvidcaps = NULL;
  567. UINT dwBitsPerSec,x;
  568. int iFamily,format, nNormalizedSpeed;
  569. int nCifIncrease;
  570. DWORD dwSysPolBandwidth;
  571. // frame rates initialized to 486/P60 settings
  572. UINT uRateCIF=CIF_RATE_VERYSLOW, uRateQCIF=QCIF_RATE_VERYSLOW, uRateSQCIF=SQCIF_RATE_VERYSLOW;
  573. if (!pCodecInfo->lpIAppCap)
  574. {
  575. if (!GetIAppCap(pCodecInfo))
  576. goto MyExit;
  577. }
  578. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->ApplyAppFormatPrefs(pCodecInfo->pCodecCapList,
  579. pCodecInfo->uNumFormats))))
  580. goto MyExit;
  581. //Set the BW to something sane
  582. #ifdef _M_IX86
  583. GetNormalizedCPUSpeed (&nNormalizedSpeed,&iFamily);
  584. #else
  585. //BUGBUG, setting things really high, otherwise,
  586. iFamily=6;
  587. nNormalizedSpeed=300;
  588. #endif
  589. dwBitsPerSec = GetBandwidthBits(uBandwidth,nNormalizedSpeed);
  590. dwSysPolBandwidth = SysPol::GetMaximumBandwidth();
  591. // apply bandwidth policy key if the user's setting is set to
  592. // a LAN speed
  593. if ((dwSysPolBandwidth > 0) && (dwBitsPerSec >= BW_SLOWLAN_BITS))
  594. {
  595. dwBitsPerSec = dwSysPolBandwidth;
  596. }
  597. if ((iFamily >= 5) && (nNormalizedSpeed >= SLOW_CPU_MHZ))
  598. {
  599. // normal pentiums (75mhz - 180mhz)
  600. if (nNormalizedSpeed < FAST_CPU_MHZ)
  601. {
  602. uRateCIF = CIF_RATE_SLOW;
  603. uRateQCIF = QCIF_RATE_SLOW;
  604. uRateSQCIF= SQCIF_RATE_SLOW;
  605. }
  606. // pentiums between 200-350 mhz
  607. else if (nNormalizedSpeed < VERYFAST_CPU_MHZ)
  608. {
  609. uRateCIF = CIF_RATE_FAST;
  610. uRateQCIF = QCIF_RATE_FAST;
  611. uRateSQCIF = SQCIF_RATE_FAST;
  612. }
  613. // really fast pentiums (400mhz and greater)
  614. else
  615. {
  616. // it would be better if we could scale between 15 and 30 frames/sec
  617. // depending on the CPU speed. But H.245 doesn't have any values
  618. // between 15 and 30. (See definition of Minimum Picture Interval)
  619. // So for now, 30 frames per sec CIF for all 400mhz and faster machines
  620. uRateCIF = CIF_RATE_VERYFAST;
  621. uRateQCIF = QCIF_RATE_FAST;
  622. uRateSQCIF = SQCIF_RATE_FAST;
  623. }
  624. }
  625. // Get the number of BASIC_VIDCAP_INFO structures available
  626. if (pCodecInfo->lpIVidAppCap->GetNumFormats((UINT*)&dwcFormats) != S_OK)
  627. goto MyExit;
  628. if (dwcFormats > 0)
  629. {
  630. // Allocate some memory to hold the list in
  631. if (!(pvidcaps = (BASIC_VIDCAP_INFO*)LocalAlloc(LPTR,dwcFormats * sizeof (BASIC_VIDCAP_INFO))))
  632. goto MyExit;
  633. // Get the list
  634. if (pCodecInfo->lpIVidAppCap->EnumFormats(pvidcaps, dwcFormats * sizeof (BASIC_VIDCAP_INFO),
  635. (UINT*)&dwcFormatsReturned) != S_OK)
  636. goto MyExit;
  637. //Setup the Bandwitdh, and the frame rate (according to philf's #s)
  638. for (x=0;x<dwcFormatsReturned;x++)
  639. {
  640. // If the codec is "hardware accelerated" (0 for cpu usage), then we assume
  641. // that the maximum bitrate is whatever is specified at install
  642. // time.
  643. pvidcaps[x].uMaxBitrate=dwBitsPerSec;
  644. if (pvidcaps[x].wCPUUtilizationEncode == 0)
  645. {
  646. // hardware acceleration - don't change the frame rate
  647. continue;
  648. }
  649. format=get_format (pvidcaps[x].enumVideoSize);
  650. //Which format
  651. switch (format)
  652. {
  653. case SQCIF:
  654. pvidcaps[x].uFrameRate=uRateSQCIF;
  655. break;
  656. case QCIF:
  657. pvidcaps[x].uFrameRate=uRateQCIF;
  658. break;
  659. case CIF:
  660. pvidcaps[x].uFrameRate=uRateCIF;
  661. break;
  662. default:
  663. WARNING_OUT(("Incorrect Frame size discovered\r\n"));
  664. pvidcaps[x].uFrameRate=uRateCIF;
  665. }
  666. }
  667. }
  668. // Ok, now submit this list
  669. if (pCodecInfo->lpIVidAppCap->ApplyAppFormatPrefs(pvidcaps, dwcFormats) != S_OK)
  670. goto MyExit;
  671. // Free the memory, we're done
  672. LocalFree(pvidcaps);
  673. // Set the bandwidth limit, which rebuilds capability sets
  674. hr = pCodecInfo->lpIH323->SetMaxPPBandwidth(dwBitsPerSec);
  675. fRet = !FAILED(hr);
  676. MyExit:
  677. return (fRet);
  678. }
  679. BOOL GetIAppCap(PCODECINFO pCodecInfo)
  680. {
  681. BOOL fRet=TRUE;
  682. HRESULT hr;
  683. if (pCodecInfo->lpIAppCap && pCodecInfo->lpIVidAppCap && pCodecInfo->lpICapsCtl)
  684. return TRUE;
  685. if(NULL == pCodecInfo->lpIH323)
  686. {
  687. IH323CallControl *pIH323 = NULL;
  688. pCodecInfo->hLib = ::NmLoadLibrary(H323DLL,FALSE);
  689. if ((pCodecInfo->hLib) == NULL)
  690. {
  691. WARNING_OUT(("NmLoadLibrary(H323DLL) failed"));
  692. return FALSE;
  693. }
  694. CREATEH323CC pfnCreateH323 = (CREATEH323CC) ::GetProcAddress(pCodecInfo->hLib, SZ_FNCREATEH323CC);
  695. if (pfnCreateH323 == NULL)
  696. {
  697. ERROR_OUT(("GetProcAddress(CreateH323) failed"));
  698. return FALSE;
  699. }
  700. hr = pfnCreateH323(&pIH323, FALSE, 0);
  701. if (FAILED(hr))
  702. {
  703. ERROR_OUT(("CreateH323 failed, hr=0x%lx", hr));
  704. return FALSE;
  705. }
  706. pCodecInfo->lpIH323 = pIH323;
  707. }
  708. else
  709. {
  710. // going to Release() later, so AddRef()
  711. pCodecInfo->lpIH323->AddRef();
  712. }
  713. if(!pCodecInfo->lpIAppCap)
  714. {
  715. hr = pCodecInfo->lpIH323->QueryInterface(IID_IAppAudioCap, (void **)&(pCodecInfo->lpIAppCap));
  716. if (FAILED(hr))
  717. {
  718. fRet=FALSE;
  719. goto MyExit;
  720. }
  721. }
  722. if(!pCodecInfo->lpIVidAppCap)
  723. {
  724. hr = pCodecInfo->lpIH323->QueryInterface(IID_IAppVidCap, (void **)&(pCodecInfo->lpIVidAppCap));
  725. if (FAILED(hr))
  726. {
  727. fRet=FALSE;
  728. goto MyExit;
  729. }
  730. }
  731. if(!pCodecInfo->lpICapsCtl)
  732. {
  733. hr = pCodecInfo->lpIH323->QueryInterface(IID_IDualPubCap, (void **)&(pCodecInfo->lpICapsCtl));
  734. if (FAILED(hr))
  735. {
  736. fRet=FALSE;
  737. goto MyExit;
  738. }
  739. }
  740. MyExit:
  741. if (!fRet)
  742. {
  743. ReleaseIAppCap(pCodecInfo);
  744. }
  745. return (fRet);
  746. }
  747. BOOL GetAppCapFormats(PCODECINFO pCodecInfo)
  748. {
  749. BOOL fRet = FALSE;
  750. UINT uNumFormats = 0;
  751. HRESULT hr;
  752. int i;
  753. if (pCodecInfo->pCodecCapList)
  754. return TRUE;
  755. if (!pCodecInfo->lpIAppCap)
  756. {
  757. if (!GetIAppCap(pCodecInfo))
  758. goto MyExit;
  759. }
  760. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->GetNumFormats(&uNumFormats))))
  761. goto MyExit;
  762. if (!uNumFormats)
  763. goto MyExit;
  764. if (!(pCodecInfo->pCodecCapList = (PBASIC_AUDCAP_INFO)LocalAlloc
  765. (LPTR,uNumFormats * sizeof(BASIC_AUDCAP_INFO))))
  766. goto MyExit;
  767. if (!(pCodecInfo->pOldCodecOrderList = (PWORD)LocalAlloc
  768. (LPTR,uNumFormats * sizeof(WORD))))
  769. goto MyExit;
  770. if (!(pCodecInfo->pCurCodecOrderList = (PWORD)LocalAlloc
  771. (LPTR,uNumFormats * sizeof(WORD))))
  772. goto MyExit;
  773. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->EnumFormats(pCodecInfo->pCodecCapList,
  774. uNumFormats * sizeof(BASIC_AUDCAP_INFO), &(pCodecInfo->uNumFormats)))))
  775. {
  776. //free the memory
  777. LocalFree(pCodecInfo->pCodecCapList);
  778. pCodecInfo->pCodecCapList = NULL;
  779. LocalFree(pCodecInfo->pOldCodecOrderList);
  780. pCodecInfo->pOldCodecOrderList = NULL;
  781. LocalFree(pCodecInfo->pCurCodecOrderList);
  782. pCodecInfo->pCurCodecOrderList = NULL;
  783. pCodecInfo->uNumFormats = 0;
  784. goto MyExit;
  785. }
  786. // initialize the old and the current state
  787. for (i=0; i<(int)pCodecInfo->uNumFormats;i++)
  788. {
  789. pCodecInfo->pCurCodecOrderList[i] = pCodecInfo->pCodecCapList[i].wSortIndex;
  790. pCodecInfo->pOldCodecOrderList[i] = pCodecInfo->pCodecCapList[i].wSortIndex;
  791. //SS:hack if we dont have the average, use the max as average
  792. if (!(pCodecInfo->pCodecCapList[i].uAvgBitrate))
  793. pCodecInfo->pCodecCapList[i].uAvgBitrate = pCodecInfo->pCodecCapList[i].uMaxBitrate;
  794. }
  795. fRet = TRUE;
  796. MyExit:
  797. if (!fRet)
  798. {
  799. FreeAppCapFormats(pCodecInfo);
  800. }
  801. return (fRet);
  802. }
  803. void FreeAppCapFormats(PCODECINFO pCodecInfo)
  804. {
  805. if (pCodecInfo->pCodecCapList)
  806. {
  807. LocalFree(pCodecInfo->pCodecCapList);
  808. pCodecInfo->pCodecCapList = NULL;
  809. pCodecInfo->uNumFormats = 0;
  810. }
  811. if (pCodecInfo->pOldCodecOrderList)
  812. {
  813. LocalFree(pCodecInfo->pOldCodecOrderList);
  814. pCodecInfo->pOldCodecOrderList = NULL;
  815. }
  816. if (pCodecInfo->pCurCodecOrderList)
  817. {
  818. LocalFree(pCodecInfo->pCurCodecOrderList);
  819. pCodecInfo->pCurCodecOrderList = NULL;
  820. }
  821. ReleaseIAppCap(pCodecInfo);
  822. }
  823. void ReleaseIAppCap(PCODECINFO pCodecInfo)
  824. {
  825. if(pCodecInfo->lpIAppCap)
  826. {
  827. pCodecInfo->lpIAppCap->Release();
  828. pCodecInfo->lpIAppCap = NULL;
  829. }
  830. if(pCodecInfo->lpIVidAppCap)
  831. {
  832. pCodecInfo->lpIVidAppCap->Release();
  833. pCodecInfo->lpIVidAppCap = NULL;
  834. }
  835. if(pCodecInfo->lpICapsCtl)
  836. {
  837. pCodecInfo->lpICapsCtl->Release();
  838. pCodecInfo->lpICapsCtl = NULL;
  839. }
  840. if(pCodecInfo->lpIH323)
  841. {
  842. pCodecInfo->lpIH323->Release();
  843. pCodecInfo->lpIH323 = NULL;
  844. }
  845. if (pCodecInfo->hLib)
  846. {
  847. FreeLibrary(pCodecInfo->hLib);
  848. pCodecInfo->hLib = NULL;
  849. }
  850. }
  851. static void IsCodecDisabled(WORD wFormatTag, int cpu_family,
  852. UINT uBandwidthID, BOOL *pbSendEnabled, BOOL *pbRecvEnabled)
  853. {
  854. int index;
  855. int size = sizeof(g_CodecPrefTable)/sizeof(CODECPREFROW);
  856. for (index = 0; index < size; index++)
  857. {
  858. if (g_CodecPrefTable[index].wFormatTag == wFormatTag)
  859. {
  860. // does bandwidth limit the use of this codec ?
  861. if (uBandwidthID < g_CodecPrefTable[index].wMinBW)
  862. {
  863. *pbSendEnabled = FALSE;
  864. *pbRecvEnabled = FALSE;
  865. return;
  866. }
  867. *pbRecvEnabled = TRUE; // all codecs can decode on 486
  868. if ((cpu_family <= 4) &&
  869. (CODEC_DISABLED == g_CodecPrefTable[index].wOrder486))
  870. {
  871. *pbSendEnabled = FALSE;
  872. }
  873. // otherwise, the codec can be used for sending and receiving
  874. else
  875. {
  876. *pbSendEnabled = TRUE;
  877. }
  878. return;
  879. }
  880. }
  881. WARNING_OUT(("Audiocpl.cpp:IsCodecDisabled - Unknown Codec!"));
  882. // it may be unknown, but enable it anyway
  883. *pbSendEnabled = TRUE;
  884. *pbRecvEnabled = TRUE;
  885. return;
  886. }
  887. static int GetCodecPrefOrder(WORD wFormatTag, int cpu_family)
  888. {
  889. int index;
  890. int size = sizeof(g_CodecPrefTable)/sizeof(CODECPREFROW);
  891. for (index = 0; index < size; index++)
  892. {
  893. if (g_CodecPrefTable[index].wFormatTag == wFormatTag)
  894. {
  895. if (cpu_family > 4)
  896. {
  897. return g_CodecPrefTable[index].wOrder586;
  898. }
  899. else
  900. {
  901. return g_CodecPrefTable[index].wOrder486;
  902. }
  903. }
  904. }
  905. WARNING_OUT(("Audiocpl.cpp:GetCodecPrefOrder - Unknown Codec!"));
  906. // this will put the codec at the bottom of the list
  907. return CODEC_UNKNOWN;
  908. }
  909. // called by the sort routine that is within ChooseCodecByBW()
  910. // returns -1 if v1 is more prefered. +1 if v2 is more preferred over
  911. // v1. Returns 0 on tie.
  912. static int codec_compare(const void *v1, const void *v2, int nCpuFamily)
  913. {
  914. PBASIC_AUDCAP_INFO pCap1, pCap2;
  915. pCap1 = (PBASIC_AUDCAP_INFO)v1;
  916. pCap2 = (PBASIC_AUDCAP_INFO)v2;
  917. int pref1, pref2;
  918. // get preference order
  919. // if we can't send with this codec, we compare it as disabled
  920. // so that it appears on the bottom of the Codec Selection UI list
  921. if (pCap1->bSendEnabled == TRUE)
  922. pref1 = GetCodecPrefOrder(pCap1->wFormatTag, nCpuFamily);
  923. else
  924. pref1 = CODEC_DISABLED;
  925. if (pCap2->bSendEnabled == TRUE)
  926. pref2 = GetCodecPrefOrder(pCap2->wFormatTag, nCpuFamily);
  927. else
  928. pref2 = CODEC_DISABLED;
  929. if (pref1 < pref2)
  930. return -1;
  931. if (pref1 > pref2)
  932. return 1;
  933. // pref1==pref2
  934. // special case, G723.1 has two formats. Higher bitrate is prefered
  935. if (pCap1->wFormatTag == WAVE_FORMAT_MSG723)
  936. {
  937. if (pCap1->uMaxBitrate < pCap2->uMaxBitrate)
  938. return 1;
  939. else
  940. return -1;
  941. }
  942. return 0;
  943. }
  944. BOOL ChooseCodecByBw(UINT uBandWidthId, PCODECINFO pCodecInfo)
  945. {
  946. PBASIC_AUDCAP_INFO pCodecCapList; // list of capabilities
  947. #ifdef _M_IX86
  948. int nNormalizedSpeed;
  949. #endif
  950. int nFamily;
  951. UINT uNumFormats, uNumDisabled = 0;
  952. UINT index;
  953. BOOL bSendEnabled, bRecvEnabled, bCompletelySorted;
  954. int *OrderList, ret, temp;
  955. //Fill out the PCodecInfo Structure
  956. if (!GetAppCapFormats(pCodecInfo))
  957. return FALSE;
  958. if (NULL == pCodecInfo->pCodecCapList)
  959. return FALSE;
  960. pCodecCapList = pCodecInfo->pCodecCapList;
  961. uNumFormats = pCodecInfo->uNumFormats;
  962. // figure out what type of CPU we have
  963. #ifdef _M_IX86
  964. GetNormalizedCPUSpeed (&nNormalizedSpeed,&nFamily);
  965. // A Pentium with FP emumalation is assumed to be a 486
  966. if (TRUE == IsFloatingPointEmulated())
  967. {
  968. nFamily = 4;
  969. }
  970. #else
  971. // assume a DEC Alpha is a really fast pentium
  972. nFamily=5;
  973. #endif
  974. // scan once to see which codecs should be disabled
  975. for (index=0; index < uNumFormats; index++)
  976. {
  977. IsCodecDisabled(pCodecCapList[index].wFormatTag,
  978. nFamily,uBandWidthId, &bSendEnabled, &bRecvEnabled);
  979. pCodecCapList[index].bSendEnabled = bSendEnabled;
  980. pCodecCapList[index].bRecvEnabled = bRecvEnabled;
  981. }
  982. // sort the capability list based on the preference table
  983. OrderList = (int *)LocalAlloc(LPTR, sizeof(int)*uNumFormats);
  984. if (OrderList == NULL)
  985. return FALSE;
  986. for (index = 0; index < uNumFormats; index++)
  987. {
  988. OrderList[index] = index;
  989. }
  990. // bubble sort routine
  991. do
  992. {
  993. bCompletelySorted = TRUE;
  994. for (index=0; index < (uNumFormats-1); index++)
  995. {
  996. ret = codec_compare(&pCodecCapList[OrderList[index]],
  997. &pCodecCapList[OrderList[index+1]], nFamily);
  998. if (ret > 0)
  999. {
  1000. // swap
  1001. temp = OrderList[index];
  1002. OrderList[index] = OrderList[index+1];
  1003. OrderList[index+1] = temp;
  1004. bCompletelySorted = FALSE;
  1005. }
  1006. }
  1007. } while (bCompletelySorted == FALSE);
  1008. // set the selection index from the result of the sort
  1009. for (index = 0; index < uNumFormats; index++)
  1010. {
  1011. pCodecCapList[OrderList[index]].wSortIndex = (WORD)index;
  1012. }
  1013. LocalFree(OrderList);
  1014. return TRUE;
  1015. }
  1016. // this is called by the audio tuning wizard
  1017. VOID SaveDefaultCodecSettings(UINT uBandWidth)
  1018. {
  1019. CODECINFO CodecInfo;
  1020. ZeroMemory(&CodecInfo, sizeof(CodecInfo));
  1021. RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
  1022. re.SetValue(REGVAL_CODECCHOICE, CODECCHOICE_AUTO);
  1023. ChooseCodecByBw(uBandWidth, &CodecInfo);
  1024. //set the ordering
  1025. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  1026. FreeAppCapFormats(&CodecInfo);
  1027. }
  1028. // this is called by the general property page
  1029. VOID UpdateCodecSettings(UINT uBandWidth)
  1030. {
  1031. RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
  1032. if (re.GetNumber(REGVAL_CODECCHOICE, CODECCHOICE_AUTO) ==
  1033. CODECCHOICE_AUTO)
  1034. {
  1035. CODECINFO CodecInfo;
  1036. ZeroMemory(&CodecInfo, sizeof(CodecInfo));
  1037. ChooseCodecByBw(uBandWidth, &CodecInfo);
  1038. //set the ordering
  1039. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  1040. FreeAppCapFormats(&CodecInfo);
  1041. }
  1042. }