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.

1305 lines
32 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. uTotal = pCodecInfo->uNumFormats;
  510. uSortTop = uTotal-1;
  511. for (uIndex = 0; uIndex < uTotal; uIndex++)
  512. {
  513. pCurCodecCap = &(pCodecInfo->pCodecCapList[uIndex]);
  514. if ((!pCurCodecCap->bRecvEnabled) && (!pCurCodecCap->bSendEnabled))
  515. {
  516. continue;
  517. }
  518. uItemIndex = (UINT)SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)(pCurCodecCap->szFormat));
  519. SendMessage(hCB, CB_SETITEMDATA, uItemIndex, uIndex);
  520. if (pCurCodecCap->wSortIndex < uSortTop)
  521. {
  522. uSortTop = pCurCodecCap->wSortIndex;
  523. uSortTopIndex = uItemIndex;
  524. }
  525. }
  526. SendMessage(hCB, CB_SETCURSEL, uSortTopIndex, 0);
  527. return TRUE;
  528. }
  529. void SortCodecs(PADVCODEC pAdvCodec, int nSelection)
  530. {
  531. PBASIC_AUDCAP_INFO pDefaultCodec, pSelectedCodec, pCodec;
  532. WORD wSortOrderBest, wSortOrderSelected;
  533. UINT uIndex;
  534. if (!pAdvCodec->fManual)
  535. return;
  536. if ((nSelection < 0) || ((UINT)nSelection > (pAdvCodec->pCodecInfo->uNumFormats)))
  537. {
  538. return;
  539. }
  540. ChooseCodecByBw(pAdvCodec->uBandwidth, pAdvCodec->pCodecInfo);
  541. // this is the codec the user selected
  542. pSelectedCodec = &(pAdvCodec->pCodecInfo->pCodecCapList[nSelection]);
  543. // all codecs that have a sort index less than the selected codec
  544. // get moved down one
  545. for (uIndex = 0; uIndex < pAdvCodec->pCodecInfo->uNumFormats; uIndex++)
  546. {
  547. pCodec = &(pAdvCodec->pCodecInfo->pCodecCapList[uIndex]);
  548. if (pCodec->wSortIndex < pSelectedCodec->wSortIndex)
  549. {
  550. pCodec->wSortIndex = pCodec->wSortIndex + 1;
  551. }
  552. }
  553. pSelectedCodec->wSortIndex = 0;
  554. }
  555. #define SQCIF 0x1
  556. #define QCIF 0x2
  557. #define CIF 0x4
  558. #define UNKNOWN 0x8
  559. #define get_format(s) (s == Small ? SQCIF : (s == Medium ? QCIF: (s == Large ? CIF : UNKNOWN)))
  560. BOOL SetAppCodecPrefs(PCODECINFO pCodecInfo,UINT uBandwidth)
  561. {
  562. BOOL fRet = FALSE;
  563. HRESULT hr;
  564. DWORD dwcFormats,dwcFormatsReturned;
  565. BASIC_VIDCAP_INFO *pvidcaps = NULL;
  566. UINT dwBitsPerSec,x;
  567. int iFamily,format, nNormalizedSpeed;
  568. int nCifIncrease;
  569. DWORD dwSysPolBandwidth;
  570. // frame rates initialized to 486/P60 settings
  571. UINT uRateCIF=CIF_RATE_VERYSLOW, uRateQCIF=QCIF_RATE_VERYSLOW, uRateSQCIF=SQCIF_RATE_VERYSLOW;
  572. if (!pCodecInfo->lpIAppCap)
  573. {
  574. if (!GetIAppCap(pCodecInfo))
  575. goto MyExit;
  576. }
  577. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->ApplyAppFormatPrefs(pCodecInfo->pCodecCapList,
  578. pCodecInfo->uNumFormats))))
  579. goto MyExit;
  580. //Set the BW to something sane
  581. #ifdef _M_IX86
  582. GetNormalizedCPUSpeed (&nNormalizedSpeed,&iFamily);
  583. #else
  584. //BUGBUG, setting things really high, otherwise,
  585. iFamily=6;
  586. nNormalizedSpeed=300;
  587. #endif
  588. dwBitsPerSec = GetBandwidthBits(uBandwidth,nNormalizedSpeed);
  589. dwSysPolBandwidth = SysPol::GetMaximumBandwidth();
  590. // apply bandwidth policy key if the user's setting is set to
  591. // a LAN speed
  592. if ((dwSysPolBandwidth > 0) && (dwBitsPerSec >= BW_SLOWLAN_BITS))
  593. {
  594. dwBitsPerSec = dwSysPolBandwidth;
  595. }
  596. if ((iFamily >= 5) && (nNormalizedSpeed >= SLOW_CPU_MHZ))
  597. {
  598. // normal pentiums (75mhz - 180mhz)
  599. if (nNormalizedSpeed < FAST_CPU_MHZ)
  600. {
  601. uRateCIF = CIF_RATE_SLOW;
  602. uRateQCIF = QCIF_RATE_SLOW;
  603. uRateSQCIF= SQCIF_RATE_SLOW;
  604. }
  605. // pentiums between 200-350 mhz
  606. else if (nNormalizedSpeed < VERYFAST_CPU_MHZ)
  607. {
  608. uRateCIF = CIF_RATE_FAST;
  609. uRateQCIF = QCIF_RATE_FAST;
  610. uRateSQCIF = SQCIF_RATE_FAST;
  611. }
  612. // really fast pentiums (400mhz and greater)
  613. else
  614. {
  615. // it would be better if we could scale between 15 and 30 frames/sec
  616. // depending on the CPU speed. But H.245 doesn't have any values
  617. // between 15 and 30. (See definition of Minimum Picture Interval)
  618. // So for now, 30 frames per sec CIF for all 400mhz and faster machines
  619. uRateCIF = CIF_RATE_VERYFAST;
  620. uRateQCIF = QCIF_RATE_FAST;
  621. uRateSQCIF = SQCIF_RATE_FAST;
  622. }
  623. }
  624. // Get the number of BASIC_VIDCAP_INFO structures available
  625. if (pCodecInfo->lpIVidAppCap->GetNumFormats((UINT*)&dwcFormats) != S_OK)
  626. goto MyExit;
  627. if (dwcFormats > 0)
  628. {
  629. // Allocate some memory to hold the list in
  630. if (!(pvidcaps = (BASIC_VIDCAP_INFO*)LocalAlloc(LPTR,dwcFormats * sizeof (BASIC_VIDCAP_INFO))))
  631. goto MyExit;
  632. // Get the list
  633. if (pCodecInfo->lpIVidAppCap->EnumFormats(pvidcaps, dwcFormats * sizeof (BASIC_VIDCAP_INFO),
  634. (UINT*)&dwcFormatsReturned) != S_OK)
  635. goto MyExit;
  636. //Setup the Bandwitdh, and the frame rate (according to philf's #s)
  637. for (x=0;x<dwcFormatsReturned;x++)
  638. {
  639. // If the codec is "hardware accelerated" (0 for cpu usage), then we assume
  640. // that the maximum bitrate is whatever is specified at install
  641. // time.
  642. pvidcaps[x].uMaxBitrate=dwBitsPerSec;
  643. if (pvidcaps[x].wCPUUtilizationEncode == 0)
  644. {
  645. // hardware acceleration - don't change the frame rate
  646. continue;
  647. }
  648. format=get_format (pvidcaps[x].enumVideoSize);
  649. //Which format
  650. switch (format)
  651. {
  652. case SQCIF:
  653. pvidcaps[x].uFrameRate=uRateSQCIF;
  654. break;
  655. case QCIF:
  656. pvidcaps[x].uFrameRate=uRateQCIF;
  657. break;
  658. case CIF:
  659. pvidcaps[x].uFrameRate=uRateCIF;
  660. break;
  661. default:
  662. WARNING_OUT(("Incorrect Frame size discovered\r\n"));
  663. pvidcaps[x].uFrameRate=uRateCIF;
  664. }
  665. }
  666. }
  667. // Ok, now submit this list
  668. if (pCodecInfo->lpIVidAppCap->ApplyAppFormatPrefs(pvidcaps, dwcFormats) != S_OK)
  669. goto MyExit;
  670. // Free the memory, we're done
  671. LocalFree(pvidcaps);
  672. // Set the bandwidth limit, which rebuilds capability sets
  673. hr = pCodecInfo->lpIH323->SetMaxPPBandwidth(dwBitsPerSec);
  674. fRet = !FAILED(hr);
  675. MyExit:
  676. return (fRet);
  677. }
  678. BOOL GetIAppCap(PCODECINFO pCodecInfo)
  679. {
  680. BOOL fRet=TRUE;
  681. HRESULT hr;
  682. if (pCodecInfo->lpIAppCap && pCodecInfo->lpIVidAppCap && pCodecInfo->lpICapsCtl)
  683. return TRUE;
  684. if(NULL == pCodecInfo->lpIH323)
  685. {
  686. IH323CallControl *pIH323 = NULL;
  687. pCodecInfo->hLib = ::NmLoadLibrary(H323DLL);
  688. if ((pCodecInfo->hLib) == NULL)
  689. {
  690. WARNING_OUT(("LoadLibrary(H323DLL) failed"));
  691. return FALSE;
  692. }
  693. CREATEH323CC pfnCreateH323 = (CREATEH323CC) ::GetProcAddress(pCodecInfo->hLib, SZ_FNCREATEH323CC);
  694. if (pfnCreateH323 == NULL)
  695. {
  696. ERROR_OUT(("GetProcAddress(CreateH323) failed"));
  697. return FALSE;
  698. }
  699. hr = pfnCreateH323(&pIH323, FALSE, 0);
  700. if (FAILED(hr))
  701. {
  702. ERROR_OUT(("CreateH323 failed, hr=0x%lx", hr));
  703. return FALSE;
  704. }
  705. pCodecInfo->lpIH323 = pIH323;
  706. }
  707. else
  708. {
  709. // going to Release() later, so AddRef()
  710. pCodecInfo->lpIH323->AddRef();
  711. }
  712. if(!pCodecInfo->lpIAppCap)
  713. {
  714. hr = pCodecInfo->lpIH323->QueryInterface(IID_IAppAudioCap, (void **)&(pCodecInfo->lpIAppCap));
  715. if (FAILED(hr))
  716. {
  717. fRet=FALSE;
  718. goto MyExit;
  719. }
  720. }
  721. if(!pCodecInfo->lpIVidAppCap)
  722. {
  723. hr = pCodecInfo->lpIH323->QueryInterface(IID_IAppVidCap, (void **)&(pCodecInfo->lpIVidAppCap));
  724. if (FAILED(hr))
  725. {
  726. fRet=FALSE;
  727. goto MyExit;
  728. }
  729. }
  730. if(!pCodecInfo->lpICapsCtl)
  731. {
  732. hr = pCodecInfo->lpIH323->QueryInterface(IID_IDualPubCap, (void **)&(pCodecInfo->lpICapsCtl));
  733. if (FAILED(hr))
  734. {
  735. fRet=FALSE;
  736. goto MyExit;
  737. }
  738. }
  739. MyExit:
  740. if (!fRet)
  741. {
  742. ReleaseIAppCap(pCodecInfo);
  743. }
  744. return (fRet);
  745. }
  746. BOOL GetAppCapFormats(PCODECINFO pCodecInfo)
  747. {
  748. BOOL fRet = FALSE;
  749. UINT uNumFormats = 0;
  750. HRESULT hr;
  751. int i;
  752. if (pCodecInfo->pCodecCapList)
  753. return TRUE;
  754. if (!pCodecInfo->lpIAppCap)
  755. {
  756. if (!GetIAppCap(pCodecInfo))
  757. goto MyExit;
  758. }
  759. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->GetNumFormats(&uNumFormats))))
  760. goto MyExit;
  761. if (!uNumFormats)
  762. goto MyExit;
  763. if (!(pCodecInfo->pCodecCapList = (PBASIC_AUDCAP_INFO)LocalAlloc
  764. (LPTR,uNumFormats * sizeof(BASIC_AUDCAP_INFO))))
  765. goto MyExit;
  766. if (!(pCodecInfo->pOldCodecOrderList = (PWORD)LocalAlloc
  767. (LPTR,uNumFormats * sizeof(WORD))))
  768. goto MyExit;
  769. if (!(pCodecInfo->pCurCodecOrderList = (PWORD)LocalAlloc
  770. (LPTR,uNumFormats * sizeof(WORD))))
  771. goto MyExit;
  772. if (FAILED(hr = ((pCodecInfo->lpIAppCap)->EnumFormats(pCodecInfo->pCodecCapList,
  773. uNumFormats * sizeof(BASIC_AUDCAP_INFO), &(pCodecInfo->uNumFormats)))))
  774. {
  775. //free the memory
  776. LocalFree(pCodecInfo->pCodecCapList);
  777. pCodecInfo->pCodecCapList = NULL;
  778. LocalFree(pCodecInfo->pOldCodecOrderList);
  779. pCodecInfo->pOldCodecOrderList = NULL;
  780. LocalFree(pCodecInfo->pCurCodecOrderList);
  781. pCodecInfo->pCurCodecOrderList = NULL;
  782. pCodecInfo->uNumFormats = 0;
  783. goto MyExit;
  784. }
  785. // initialize the old and the current state
  786. for (i=0; i<(int)pCodecInfo->uNumFormats;i++)
  787. {
  788. pCodecInfo->pCurCodecOrderList[i] = pCodecInfo->pCodecCapList[i].wSortIndex;
  789. pCodecInfo->pOldCodecOrderList[i] = pCodecInfo->pCodecCapList[i].wSortIndex;
  790. //SS:hack if we dont have the average, use the max as average
  791. if (!(pCodecInfo->pCodecCapList[i].uAvgBitrate))
  792. pCodecInfo->pCodecCapList[i].uAvgBitrate = pCodecInfo->pCodecCapList[i].uMaxBitrate;
  793. }
  794. fRet = TRUE;
  795. MyExit:
  796. if (!fRet)
  797. {
  798. FreeAppCapFormats(pCodecInfo);
  799. }
  800. return (fRet);
  801. }
  802. void FreeAppCapFormats(PCODECINFO pCodecInfo)
  803. {
  804. if (pCodecInfo->pCodecCapList)
  805. {
  806. LocalFree(pCodecInfo->pCodecCapList);
  807. pCodecInfo->pCodecCapList = NULL;
  808. pCodecInfo->uNumFormats = 0;
  809. }
  810. if (pCodecInfo->pOldCodecOrderList)
  811. {
  812. LocalFree(pCodecInfo->pOldCodecOrderList);
  813. pCodecInfo->pOldCodecOrderList = NULL;
  814. }
  815. if (pCodecInfo->pCurCodecOrderList)
  816. {
  817. LocalFree(pCodecInfo->pCurCodecOrderList);
  818. pCodecInfo->pCurCodecOrderList = NULL;
  819. }
  820. ReleaseIAppCap(pCodecInfo);
  821. }
  822. void ReleaseIAppCap(PCODECINFO pCodecInfo)
  823. {
  824. if(pCodecInfo->lpIAppCap)
  825. {
  826. pCodecInfo->lpIAppCap->Release();
  827. pCodecInfo->lpIAppCap = NULL;
  828. }
  829. if(pCodecInfo->lpIVidAppCap)
  830. {
  831. pCodecInfo->lpIVidAppCap->Release();
  832. pCodecInfo->lpIVidAppCap = NULL;
  833. }
  834. if(pCodecInfo->lpICapsCtl)
  835. {
  836. pCodecInfo->lpICapsCtl->Release();
  837. pCodecInfo->lpICapsCtl = NULL;
  838. }
  839. if(pCodecInfo->lpIH323)
  840. {
  841. pCodecInfo->lpIH323->Release();
  842. pCodecInfo->lpIH323 = NULL;
  843. }
  844. if (pCodecInfo->hLib)
  845. {
  846. FreeLibrary(pCodecInfo->hLib);
  847. pCodecInfo->hLib = NULL;
  848. }
  849. }
  850. static void IsCodecDisabled(WORD wFormatTag, int cpu_family,
  851. UINT uBandwidthID, BOOL *pbSendEnabled, BOOL *pbRecvEnabled)
  852. {
  853. int index;
  854. int size = sizeof(g_CodecPrefTable)/sizeof(CODECPREFROW);
  855. for (index = 0; index < size; index++)
  856. {
  857. if (g_CodecPrefTable[index].wFormatTag == wFormatTag)
  858. {
  859. // does bandwidth limit the use of this codec ?
  860. if (uBandwidthID < g_CodecPrefTable[index].wMinBW)
  861. {
  862. *pbSendEnabled = FALSE;
  863. *pbRecvEnabled = FALSE;
  864. return;
  865. }
  866. *pbRecvEnabled = TRUE; // all codecs can decode on 486
  867. if ((cpu_family <= 4) &&
  868. (CODEC_DISABLED == g_CodecPrefTable[index].wOrder486))
  869. {
  870. *pbSendEnabled = FALSE;
  871. }
  872. // otherwise, the codec can be used for sending and receiving
  873. else
  874. {
  875. *pbSendEnabled = TRUE;
  876. }
  877. return;
  878. }
  879. }
  880. WARNING_OUT(("Audiocpl.cpp:IsCodecDisabled - Unknown Codec!"));
  881. // it may be unknown, but enable it anyway
  882. *pbSendEnabled = TRUE;
  883. *pbRecvEnabled = TRUE;
  884. return;
  885. }
  886. static int GetCodecPrefOrder(WORD wFormatTag, int cpu_family)
  887. {
  888. int index;
  889. int size = sizeof(g_CodecPrefTable)/sizeof(CODECPREFROW);
  890. for (index = 0; index < size; index++)
  891. {
  892. if (g_CodecPrefTable[index].wFormatTag == wFormatTag)
  893. {
  894. if (cpu_family > 4)
  895. {
  896. return g_CodecPrefTable[index].wOrder586;
  897. }
  898. else
  899. {
  900. return g_CodecPrefTable[index].wOrder486;
  901. }
  902. }
  903. }
  904. WARNING_OUT(("Audiocpl.cpp:GetCodecPrefOrder - Unknown Codec!"));
  905. // this will put the codec at the bottom of the list
  906. return CODEC_UNKNOWN;
  907. }
  908. // called by the sort routine that is within ChooseCodecByBW()
  909. // returns -1 if v1 is more prefered. +1 if v2 is more preferred over
  910. // v1. Returns 0 on tie.
  911. static int codec_compare(const void *v1, const void *v2, int nCpuFamily)
  912. {
  913. PBASIC_AUDCAP_INFO pCap1, pCap2;
  914. pCap1 = (PBASIC_AUDCAP_INFO)v1;
  915. pCap2 = (PBASIC_AUDCAP_INFO)v2;
  916. int pref1, pref2;
  917. // get preference order
  918. // if we can't send with this codec, we compare it as disabled
  919. // so that it appears on the bottom of the Codec Selection UI list
  920. if (pCap1->bSendEnabled == TRUE)
  921. pref1 = GetCodecPrefOrder(pCap1->wFormatTag, nCpuFamily);
  922. else
  923. pref1 = CODEC_DISABLED;
  924. if (pCap2->bSendEnabled == TRUE)
  925. pref2 = GetCodecPrefOrder(pCap2->wFormatTag, nCpuFamily);
  926. else
  927. pref2 = CODEC_DISABLED;
  928. if (pref1 < pref2)
  929. return -1;
  930. if (pref1 > pref2)
  931. return 1;
  932. // pref1==pref2
  933. // special case, G723.1 has two formats. Higher bitrate is prefered
  934. if (pCap1->wFormatTag == WAVE_FORMAT_MSG723)
  935. {
  936. if (pCap1->uMaxBitrate < pCap2->uMaxBitrate)
  937. return 1;
  938. else
  939. return -1;
  940. }
  941. return 0;
  942. }
  943. BOOL ChooseCodecByBw(UINT uBandWidthId, PCODECINFO pCodecInfo)
  944. {
  945. PBASIC_AUDCAP_INFO pCodecCapList; // list of capabilities
  946. #ifdef _M_IX86
  947. int nNormalizedSpeed;
  948. #endif
  949. int nFamily;
  950. UINT uNumFormats, uNumDisabled = 0;
  951. UINT index;
  952. BOOL bSendEnabled, bRecvEnabled, bCompletelySorted;
  953. int *OrderList, ret, temp;
  954. //Fill out the PCodecInfo Structure
  955. if (!GetAppCapFormats(pCodecInfo))
  956. return FALSE;
  957. if (NULL == pCodecInfo->pCodecCapList)
  958. return FALSE;
  959. pCodecCapList = pCodecInfo->pCodecCapList;
  960. uNumFormats = pCodecInfo->uNumFormats;
  961. // figure out what type of CPU we have
  962. #ifdef _M_IX86
  963. GetNormalizedCPUSpeed (&nNormalizedSpeed,&nFamily);
  964. // A Pentium with FP emumalation is assumed to be a 486
  965. if (TRUE == IsFloatingPointEmulated())
  966. {
  967. nFamily = 4;
  968. }
  969. #else
  970. // assume a DEC Alpha is a really fast pentium
  971. nFamily=5;
  972. #endif
  973. // scan once to see which codecs should be disabled
  974. for (index=0; index < uNumFormats; index++)
  975. {
  976. IsCodecDisabled(pCodecCapList[index].wFormatTag,
  977. nFamily,uBandWidthId, &bSendEnabled, &bRecvEnabled);
  978. pCodecCapList[index].bSendEnabled = bSendEnabled;
  979. pCodecCapList[index].bRecvEnabled = bRecvEnabled;
  980. }
  981. // sort the capability list based on the preference table
  982. OrderList = (int *)LocalAlloc(LPTR, sizeof(int)*uNumFormats);
  983. if (OrderList == NULL)
  984. return FALSE;
  985. for (index = 0; index < uNumFormats; index++)
  986. {
  987. OrderList[index] = index;
  988. }
  989. // bubble sort routine
  990. do
  991. {
  992. bCompletelySorted = TRUE;
  993. for (index=0; index < (uNumFormats-1); index++)
  994. {
  995. ret = codec_compare(&pCodecCapList[OrderList[index]],
  996. &pCodecCapList[OrderList[index+1]], nFamily);
  997. if (ret > 0)
  998. {
  999. // swap
  1000. temp = OrderList[index];
  1001. OrderList[index] = OrderList[index+1];
  1002. OrderList[index+1] = temp;
  1003. bCompletelySorted = FALSE;
  1004. }
  1005. }
  1006. } while (bCompletelySorted == FALSE);
  1007. // set the selection index from the result of the sort
  1008. for (index = 0; index < uNumFormats; index++)
  1009. {
  1010. pCodecCapList[OrderList[index]].wSortIndex = (WORD)index;
  1011. }
  1012. LocalFree(OrderList);
  1013. return TRUE;
  1014. }
  1015. // this is called by the audio tuning wizard
  1016. VOID SaveDefaultCodecSettings(UINT uBandWidth)
  1017. {
  1018. CODECINFO CodecInfo;
  1019. ZeroMemory(&CodecInfo, sizeof(CodecInfo));
  1020. RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
  1021. re.SetValue(REGVAL_CODECCHOICE, CODECCHOICE_AUTO);
  1022. ChooseCodecByBw(uBandWidth, &CodecInfo);
  1023. //set the ordering
  1024. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  1025. FreeAppCapFormats(&CodecInfo);
  1026. }
  1027. // this is called by the general property page
  1028. VOID UpdateCodecSettings(UINT uBandWidth)
  1029. {
  1030. RegEntry re(AUDIO_KEY, HKEY_CURRENT_USER);
  1031. if (re.GetNumber(REGVAL_CODECCHOICE, CODECCHOICE_AUTO) ==
  1032. CODECCHOICE_AUTO)
  1033. {
  1034. CODECINFO CodecInfo;
  1035. ZeroMemory(&CodecInfo, sizeof(CodecInfo));
  1036. ChooseCodecByBw(uBandWidth, &CodecInfo);
  1037. //set the ordering
  1038. SetAppCodecPrefs(&CodecInfo, uBandWidth);
  1039. FreeAppCapFormats(&CodecInfo);
  1040. }
  1041. }