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.

916 lines
26 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1993-1999 Microsoft Corporation
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // config.c
  13. //
  14. // Description:
  15. // GSM 6.10 configuration init and dialog
  16. //
  17. //
  18. // The configuration parameters for this codec are:
  19. //
  20. // MaxRTEncodeSetting:
  21. // MaxRTDecodeSetting:
  22. // These determine the highest mono sample rate that
  23. // the codec will attempt to convert in real-time.
  24. //
  25. // PercentCPU:
  26. // This configuration parameter is not normally changed
  27. // by the user and is not presented in the config dialog.
  28. // This value affects the config dialog's 'Auto-Config'
  29. // calculation of MaxRTXxcodeSamplesPerSec.
  30. //
  31. // These parameters may be set in the registry, using the gsm610 subkey
  32. // (which corresponds to the alias name used for installation) under
  33. // the following key:
  34. //
  35. // HKEY_CURRENT_USER\Software\Microsoft\Multimedia
  36. //
  37. //==========================================================================;
  38. #include <windows.h>
  39. #include <windowsx.h>
  40. #include <mmsystem.h>
  41. #include <memory.h>
  42. #include <mmreg.h>
  43. #include <msacm.h>
  44. #include <msacmdrv.h>
  45. #include "codec.h"
  46. #include "gsm610.h"
  47. #include "debug.h"
  48. #ifdef WIN32
  49. #include <tchar.h>
  50. #else
  51. #define _tcstoul strtoul
  52. #define _tcsncpy _fstrncpy
  53. #endif
  54. #include <string.h>
  55. #include <stdlib.h>
  56. //
  57. // Strings required to access configuration information in the registry.
  58. //
  59. const TCHAR BCODE gszMaxRTEncodeSetting[] = TEXT("MaxRTEncodeSetting");
  60. const TCHAR BCODE gszMaxRTDecodeSetting[] = TEXT("MaxRTDecodeSetting");
  61. const TCHAR BCODE gszPercentCPU[] = TEXT("PercentCPU");
  62. const TCHAR gszMultimediaKey[] = TEXT("Software\\Microsoft\\Multimedia\\");
  63. #define MSGSM610_CONFIG_TEXTLEN 80
  64. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  65. //
  66. // Be careful changing the following!
  67. //
  68. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  69. //
  70. // Data required to access the dialog box help.
  71. //
  72. // Note that you must write your own help file for your codec, even if
  73. // the configuration dialog box looks identical. If you use the file
  74. // listed here, then the title will say "GSM 6.10" or something.
  75. //
  76. // Note: the number HELPCONTEXT_MSGSM610 must be unique in the file
  77. // gszHelpFilename, and the number must defined in the [MAP]
  78. // section of the .hpj help project file. Then the .rtf file
  79. // will reference that number (using the keyword defined in
  80. // the .hpj file). Then when we call WinHelp with the number,
  81. // WinHelp will go to the right help entry.
  82. //
  83. const TCHAR BCODE gszHelpFilename[] = TEXT("audiocdc.hlp");
  84. #define HELPCONTEXT_MSGSM610 1002
  85. #define IDH_AUDIOCDC_COMPRESSION 100
  86. #define IDH_AUDIOCDC_DECOMPRESSION 200
  87. #define IDH_AUDIOCDC_AUTOCONFIGURE 300
  88. static int aKeyWordIds[] = {
  89. IDC_COMBO_MAXRTENCODE, IDH_AUDIOCDC_COMPRESSION,
  90. IDC_STATIC_COMPRESS, IDH_AUDIOCDC_COMPRESSION,
  91. IDC_COMBO_MAXRTDECODE, IDH_AUDIOCDC_DECOMPRESSION,
  92. IDC_STATIC_DECOMPRESS, IDH_AUDIOCDC_DECOMPRESSION,
  93. IDC_BTN_AUTOCONFIG, IDH_AUDIOCDC_AUTOCONFIGURE,
  94. 0, 0
  95. };
  96. //==========================================================================;
  97. //
  98. //
  99. //
  100. //
  101. //==========================================================================;
  102. LPVOID FNLOCAL GlobalAllocLock(HGLOBAL far * ph, DWORD dwc)
  103. {
  104. *ph = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwc);
  105. if (NULL != *ph)
  106. return GlobalLock(*ph);
  107. else
  108. return NULL;
  109. }
  110. VOID FNLOCAL GlobalUnlockFree(LPVOID p, HGLOBAL h)
  111. {
  112. if (NULL != h)
  113. {
  114. if (NULL != p) GlobalUnlock(h);
  115. GlobalFree(h);
  116. }
  117. return;
  118. }
  119. //==========================================================================;
  120. //
  121. //
  122. //
  123. //
  124. //==========================================================================;
  125. //--------------------------------------------------------------------------;
  126. //
  127. // VOID configWriteConfiguration
  128. //
  129. // Description:
  130. //
  131. // This routine writes the configuration data in PDI to the registry.
  132. // This consists of the max real-time Encode and Decode settings.
  133. //
  134. // Arguments:
  135. // PDRIVERINSTANCE pdi
  136. //
  137. // Return (VOID): None.
  138. //
  139. //--------------------------------------------------------------------------;
  140. VOID configWriteConfiguration
  141. (
  142. PDRIVERINSTANCE pdi
  143. )
  144. {
  145. DWORD dw;
  146. if( NULL != pdi->hkey )
  147. {
  148. dw = (DWORD)pdi->nConfigMaxRTEncodeSetting;
  149. (void)RegSetValueEx( pdi->hkey, (LPTSTR)gszMaxRTEncodeSetting, 0,
  150. REG_DWORD, (LPBYTE)&dw, sizeof(DWORD) );
  151. dw = (DWORD)pdi->nConfigMaxRTDecodeSetting;
  152. (void)RegSetValueEx( pdi->hkey, (LPTSTR)gszMaxRTDecodeSetting, 0,
  153. REG_DWORD, (LPBYTE)&dw, sizeof(DWORD) );
  154. }
  155. }
  156. //--------------------------------------------------------------------------;
  157. //
  158. // DWORD dwReadRegistryDefault
  159. //
  160. // Description:
  161. //
  162. // This routine reads a given value from the registry, and returns a
  163. // default value if the read is not successful.
  164. //
  165. // Arguments:
  166. // HKEY hkey: Registry key to read from.
  167. // LPTSTR lpszEntry:
  168. // DWORD dwDefault:
  169. //
  170. // Return (DWORD):
  171. //
  172. //--------------------------------------------------------------------------;
  173. INLINE DWORD dwReadRegistryDefault
  174. (
  175. HKEY hkey,
  176. LPTSTR lpszEntry,
  177. DWORD dwDefault
  178. )
  179. {
  180. DWORD dwType = (DWORD)~REG_DWORD; // Init to anything but REG_DWORD.
  181. DWORD cbSize = sizeof(DWORD);
  182. DWORD dwRet;
  183. LONG lError;
  184. ASSERT( NULL != hkey );
  185. ASSERT( NULL != lpszEntry );
  186. lError = RegQueryValueEx( hkey,
  187. lpszEntry,
  188. NULL,
  189. &dwType,
  190. (LPBYTE)&dwRet,
  191. &cbSize );
  192. if( ERROR_SUCCESS != lError || REG_DWORD != dwType )
  193. dwRet = dwDefault;
  194. return dwRet;
  195. }
  196. //--------------------------------------------------------------------------;
  197. //
  198. // VOID configSetDefaults
  199. //
  200. // Description:
  201. //
  202. // This routine sets the configuration parameters to their default
  203. // values.
  204. //
  205. // Arguments:
  206. // PDRIVERINSTANCE pdi:
  207. //
  208. //--------------------------------------------------------------------------;
  209. VOID configSetDefaults
  210. (
  211. PDRIVERINSTANCE pdi
  212. )
  213. {
  214. pdi->nConfigMaxRTEncodeSetting =
  215. MSGSM610_CONFIG_DEFAULT_MAXRTENCODESETTING;
  216. pdi->nConfigMaxRTDecodeSetting =
  217. MSGSM610_CONFIG_DEFAULT_MAXRTDECODESETTING;
  218. pdi->nConfigPercentCPU =
  219. MSGSM610_CONFIG_DEFAULT_PERCENTCPU;
  220. }
  221. //--------------------------------------------------------------------------;
  222. //
  223. // UINT configAutoConfig
  224. //
  225. // Description:
  226. //
  227. // We will determine how much time it takes to encode and then decode
  228. // 2 seconds of data and use this to guess at the max sample
  229. // rate we can convert in real-time.
  230. //
  231. // The max is computed with essentially 100% of the CPU. Practically,
  232. // we won't have 100% of the CPU available. So we take a percentage
  233. // of the computed max and use that as the max in the config dialog.
  234. //
  235. // The percentage that we use can be set in the ini file gsm610
  236. // section by PercentCPU=xx.
  237. //
  238. //
  239. // Arguments:
  240. // HWND hwnd:
  241. //
  242. // Return (UINT): String identifier (IDS) of error message, or zero if
  243. // the call succeeded.
  244. //
  245. //--------------------------------------------------------------------------;
  246. UINT FNLOCAL configAutoConfig
  247. (
  248. PDRIVERINSTANCE pdi,
  249. UINT *pnEncodeSetting,
  250. UINT *pnDecodeSetting
  251. )
  252. {
  253. UINT nConfig;
  254. UINT uIDS;
  255. HCURSOR hCursorSave;
  256. PSTREAMINSTANCE psi;
  257. HGLOBAL hbPCM;
  258. HGLOBAL hbGSM;
  259. HGLOBAL hpcmwf;
  260. HGLOBAL hgsmwf;
  261. HGLOBAL hadsi;
  262. HGLOBAL hadsh;
  263. LPBYTE pbPCM, pbGSM;
  264. DWORD cbPCMLength, cbGSMLength;
  265. LPPCMWAVEFORMAT ppcmwf;
  266. LPGSM610WAVEFORMAT pgsmwf;
  267. LPACMDRVSTREAMINSTANCE padsi;
  268. LPACMDRVSTREAMHEADER padsh;
  269. DWORD dwTime;
  270. DWORD dwMaxRate;
  271. //
  272. // We divide by this!
  273. //
  274. ASSERT( 0 != pdi->nConfigPercentCPU );
  275. //
  276. // Init stuff that gets cleaned up at errReturn
  277. //
  278. //
  279. uIDS = 0;
  280. psi = NULL;
  281. hbPCM = NULL;
  282. hbGSM = NULL;
  283. hpcmwf = NULL;
  284. hgsmwf = NULL;
  285. hadsi = NULL;
  286. hadsh = NULL;
  287. pbPCM = NULL;
  288. pbGSM = NULL;
  289. ppcmwf = NULL;
  290. pgsmwf = NULL;
  291. padsi = NULL;
  292. padsh = NULL;
  293. //
  294. // This function may take a while. Set hour glass cursor
  295. //
  296. //
  297. hCursorSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  298. //
  299. // Allocate memory for all our structures
  300. //
  301. //
  302. psi = (PSTREAMINSTANCE)LocalAlloc(LPTR, sizeof(*psi));
  303. cbPCMLength = 2 * (8000 / 1 * 2);
  304. cbGSMLength = 2 * (8000 / 320 * 65);
  305. pbPCM = GlobalAllocLock(&hbPCM, cbPCMLength);
  306. pbGSM = GlobalAllocLock(&hbGSM, cbGSMLength);
  307. ppcmwf = GlobalAllocLock(&hpcmwf, sizeof(*ppcmwf));
  308. pgsmwf = GlobalAllocLock(&hgsmwf, sizeof(*pgsmwf));
  309. padsi = GlobalAllocLock(&hadsi, sizeof(*padsi));
  310. padsh = GlobalAllocLock(&hadsh, sizeof(*padsh));
  311. //
  312. // if we couldn't allocate some of the memory
  313. //
  314. //
  315. if ( (psi == NULL) ||
  316. (pbPCM == NULL) ||
  317. (pbGSM == NULL) ||
  318. (ppcmwf == NULL) ||
  319. (pgsmwf == NULL) ||
  320. (padsi == NULL) ||
  321. (padsh == NULL) )
  322. {
  323. uIDS = IDS_ERROR_NOMEM;
  324. goto errReturn;
  325. }
  326. //
  327. //
  328. //
  329. //
  330. // Fill in format structures for GSM 6.10 and PCM
  331. //
  332. //
  333. pgsmwf->wfx.wFormatTag = WAVE_FORMAT_GSM610;
  334. pgsmwf->wfx.nChannels = 1;
  335. pgsmwf->wfx.nSamplesPerSec = 8000;
  336. pgsmwf->wfx.nAvgBytesPerSec = 8000 / 320 * 65;
  337. pgsmwf->wfx.nBlockAlign = 65;
  338. pgsmwf->wfx.wBitsPerSample = 0;
  339. pgsmwf->wfx.cbSize = 0;
  340. pgsmwf->wSamplesPerBlock = 320;
  341. ppcmwf->wf.wFormatTag = WAVE_FORMAT_PCM;
  342. ppcmwf->wf.nChannels = 1;
  343. ppcmwf->wf.nSamplesPerSec = 8000;
  344. ppcmwf->wf.nAvgBytesPerSec = 8000 / 1 * 2;
  345. ppcmwf->wf.nBlockAlign = 2;
  346. ppcmwf->wBitsPerSample = 16;
  347. //
  348. // get the time, do encode, get the time. btw, we've never written
  349. // any data into our audio data buffers. we don't know what's in
  350. // them nor do we care. we just want to see how long it takes to
  351. // perform the conversion.
  352. //
  353. //
  354. dwTime = timeGetTime();
  355. padsi->cbStruct = sizeof(padsi);
  356. padsi->pwfxSrc = (LPWAVEFORMATEX) ppcmwf;
  357. padsi->pwfxDst = (LPWAVEFORMATEX) pgsmwf;
  358. padsi->dwDriver = (DWORD_PTR) psi;
  359. padsh->cbStruct = sizeof(padsh);
  360. padsh->pbSrc = pbPCM;
  361. padsh->cbSrcLength = cbPCMLength;
  362. padsh->pbDst = pbGSM;
  363. padsh->cbDstLength = cbGSMLength;
  364. padsh->fdwConvert = ACM_STREAMCONVERTF_BLOCKALIGN | ACM_STREAMCONVERTF_START;
  365. gsm610Encode(padsi, padsh);
  366. dwTime = timeGetTime() - dwTime;
  367. //
  368. // calculate what we might be able to do in real-time
  369. //
  370. //
  371. if (dwTime == 0)
  372. dwMaxRate = 0xFFFFFFFFL;
  373. else
  374. dwMaxRate = (1000L * 2L * ppcmwf->wf.nSamplesPerSec / dwTime);
  375. if ( (0xFFFFFFFFL / pdi->nConfigPercentCPU) >= dwMaxRate )
  376. dwMaxRate = dwMaxRate * pdi->nConfigPercentCPU / 100;
  377. if (dwMaxRate > 0xFFFFL)
  378. dwMaxRate = 0xFFFFL;
  379. DPF(1,"Encode dwMaxRate=%u", dwMaxRate);
  380. //
  381. // Now set the configuration based on dwMaxRate. We scan the
  382. // gaRateListFormat[] array looking at the dwMonoRate to determine
  383. // the appropriate setting.
  384. //
  385. nConfig = 0;
  386. while( gaRateListFormat[nConfig].dwMonoRate < dwMaxRate &&
  387. MSGSM610_CONFIG_NUMSETTINGS > nConfig )
  388. {
  389. nConfig++;
  390. }
  391. *pnEncodeSetting = nConfig - 1; // We went too far.
  392. //
  393. // get the time, do decode, get the time
  394. //
  395. //
  396. dwTime = timeGetTime();
  397. padsi->cbStruct = sizeof(*padsi);
  398. padsi->pwfxSrc = (LPWAVEFORMATEX) pgsmwf;
  399. padsi->pwfxDst = (LPWAVEFORMATEX) ppcmwf;
  400. padsi->dwDriver = (DWORD_PTR) psi;
  401. padsh->cbStruct = sizeof(*padsh);
  402. padsh->pbSrc = pbGSM;
  403. padsh->cbSrcLength = cbGSMLength;
  404. padsh->pbDst = pbPCM;
  405. padsh->cbDstLength = cbPCMLength;
  406. padsh->fdwConvert = ACM_STREAMCONVERTF_BLOCKALIGN | ACM_STREAMCONVERTF_START;
  407. gsm610Decode(padsi, padsh);
  408. dwTime = timeGetTime() - dwTime;
  409. //
  410. // calculate what we might be able to do in real-time
  411. //
  412. //
  413. if (dwTime == 0)
  414. dwMaxRate = 0xFFFFFFFFL;
  415. else
  416. dwMaxRate = (1000L * 2L * ppcmwf->wf.nSamplesPerSec / dwTime);
  417. if ( (0xFFFFFFFFL / pdi->nConfigPercentCPU) >= dwMaxRate )
  418. dwMaxRate = dwMaxRate * pdi->nConfigPercentCPU / 100;
  419. if (dwMaxRate > 0xFFFFL)
  420. dwMaxRate = 0xFFFFL;
  421. DPF(1,"Decode dwMaxRate=%u", dwMaxRate);
  422. //
  423. // Now set the configuration based on these values. We scan the
  424. // gaRateListFormat[] array looking at the dwMonoRate to determine
  425. // the appropriate setting.
  426. //
  427. nConfig = 0;
  428. while( gaRateListFormat[nConfig].dwMonoRate < dwMaxRate &&
  429. MSGSM610_CONFIG_NUMSETTINGS > nConfig )
  430. {
  431. nConfig++;
  432. }
  433. *pnDecodeSetting = nConfig - 1; // We went too far.
  434. //
  435. // Clean up
  436. //
  437. //
  438. errReturn:
  439. GlobalUnlockFree(padsh, hadsh);
  440. GlobalUnlockFree(padsi, hadsi);
  441. GlobalUnlockFree(ppcmwf, hpcmwf);
  442. GlobalUnlockFree(pgsmwf, hgsmwf);
  443. GlobalUnlockFree(pbPCM, hbPCM);
  444. GlobalUnlockFree(pbGSM, hbGSM);
  445. SetCursor(hCursorSave);
  446. return uIDS;
  447. }
  448. //==========================================================================;
  449. //
  450. //
  451. //
  452. //
  453. //==========================================================================;
  454. //--------------------------------------------------------------------------;
  455. //
  456. // BOOL acmdDlgProcConfigure
  457. //
  458. // Description:
  459. // This routine handles the configuration dialog box.
  460. //
  461. // Arguments:
  462. // HWND hwnd:
  463. //
  464. // UINT uMsg:
  465. //
  466. // WPARAM wParam:
  467. //
  468. // LPARAM lParam:
  469. //
  470. // Return (BOOL):
  471. //
  472. //
  473. // Note: In order to avoid using a static fHelpRunning flag which will
  474. // still be here after we exit, we allocate an fHelpRunning
  475. // variable in the DRIVERINSTANCE structure. This is purely to
  476. // avoid static variables (which force us to have a data segment
  477. // of 4K); the fHelpRunning is not used in any other procedures.
  478. //
  479. //--------------------------------------------------------------------------;
  480. INT_PTR FNWCALLBACK acmdDlgProcConfigure
  481. (
  482. HWND hwnd,
  483. UINT uMsg,
  484. WPARAM wParam,
  485. LPARAM lParam
  486. )
  487. {
  488. PDRIVERINSTANCE pdi;
  489. HWND hctrlEnc;
  490. HWND hctrlDec;
  491. UINT uCmdId;
  492. UINT u;
  493. int n;
  494. TCHAR szFormat[MSGSM610_CONFIG_TEXTLEN];
  495. TCHAR szOutput[MSGSM610_CONFIG_TEXTLEN];
  496. UINT nConfigMaxRTEncodeSetting;
  497. UINT nConfigMaxRTDecodeSetting;
  498. switch (uMsg)
  499. {
  500. case WM_INITDIALOG:
  501. pdi = (PDRIVERINSTANCE)lParam;
  502. pdi->fHelpRunning = FALSE; // Used only in this procedure.
  503. #ifdef WIN4
  504. //
  505. // This driver is marked Windows Subsystem version 3.5 in order
  506. // that it be compatible with Daytona - however, that means that
  507. // Chicago will think it is a Win 3.1 application and give it
  508. // Win 3.1 default colors. This makes the config dialog look
  509. // white, whereas the Chicago default uses 3DFACE. This code
  510. // (and the CTLCOLOR messages) sets the colors explicitly.
  511. //
  512. pdi->hbrDialog = CreateSolidBrush( GetSysColor(COLOR_3DFACE) );
  513. #endif
  514. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  515. nConfigMaxRTEncodeSetting = pdi->nConfigMaxRTEncodeSetting;
  516. nConfigMaxRTDecodeSetting = pdi->nConfigMaxRTDecodeSetting;
  517. hctrlEnc = GetDlgItem(hwnd, IDC_COMBO_MAXRTENCODE);
  518. hctrlDec = GetDlgItem(hwnd, IDC_COMBO_MAXRTDECODE);
  519. for( u=0; u<MSGSM610_CONFIG_NUMSETTINGS; u++ )
  520. {
  521. LoadString( pdi->hinst, gaRateListFormat[u].idsFormat,
  522. szFormat, SIZEOF(szFormat) );
  523. switch( gaRateListFormat[u].uFormatType )
  524. {
  525. case CONFIG_RLF_NONUMBER:
  526. lstrcpy( szOutput, szFormat );
  527. break;
  528. case CONFIG_RLF_MONOONLY:
  529. wsprintf( szOutput, szFormat,
  530. gaRateListFormat[u].dwMonoRate );
  531. break;
  532. }
  533. ComboBox_AddString(hctrlEnc, szOutput);
  534. ComboBox_AddString(hctrlDec, szOutput);
  535. }
  536. ComboBox_SetCurSel( hctrlEnc, nConfigMaxRTEncodeSetting );
  537. ComboBox_SetCurSel( hctrlDec, nConfigMaxRTDecodeSetting );
  538. return (TRUE);
  539. case WM_DESTROY:
  540. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  541. if (pdi->fHelpRunning)
  542. {
  543. WinHelp(hwnd, gszHelpFilename, HELP_QUIT, 0L);
  544. }
  545. #ifdef WIN4
  546. DeleteObject( pdi->hbrDialog );
  547. #endif
  548. //
  549. // Let dialog box process this message
  550. //
  551. //
  552. return (FALSE);
  553. #ifdef WIN4
  554. //
  555. // Handle CTLCOLOR messages to get the dialog boxes to the default
  556. // Chicago colors. See the INITDIALOG message, above.
  557. //
  558. case WM_CTLCOLORSTATIC:
  559. case WM_CTLCOLORDLG:
  560. case WM_CTLCOLORBTN:
  561. SetTextColor( (HDC)wParam, GetSysColor(COLOR_WINDOWTEXT) );
  562. SetBkColor( (HDC)wParam, GetSysColor(COLOR_3DFACE) );
  563. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  564. return (UINT_PTR)(pdi->hbrDialog);
  565. #endif
  566. case WM_HELP:
  567. WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszHelpFilename,
  568. HELP_WM_HELP, (ULONG_PTR)aKeyWordIds);
  569. return TRUE;
  570. case WM_COMMAND:
  571. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  572. uCmdId = (UINT) wParam;
  573. switch (uCmdId)
  574. {
  575. case IDC_BTN_AUTOCONFIG:
  576. {
  577. UINT uErrorIDS;
  578. uErrorIDS = configAutoConfig( pdi,
  579. &nConfigMaxRTEncodeSetting,
  580. &nConfigMaxRTDecodeSetting );
  581. if( 0==uErrorIDS )
  582. {
  583. //
  584. // No error - set dialog box settings.
  585. //
  586. hctrlEnc = GetDlgItem( hwnd, IDC_COMBO_MAXRTENCODE );
  587. ComboBox_SetCurSel( hctrlEnc, nConfigMaxRTEncodeSetting );
  588. hctrlDec = GetDlgItem( hwnd, IDC_COMBO_MAXRTDECODE );
  589. ComboBox_SetCurSel( hctrlDec, nConfigMaxRTDecodeSetting );
  590. }
  591. else
  592. {
  593. //
  594. // Display error message.
  595. //
  596. TCHAR tstrErr[200];
  597. TCHAR tstrErrTitle[200];
  598. if (0 == LoadString(pdi->hinst, IDS_ERROR, tstrErrTitle, SIZEOF(tstrErrTitle)))
  599. break;
  600. if (0 == LoadString(pdi->hinst, uErrorIDS, tstrErr, SIZEOF(tstrErr)))
  601. break;
  602. MessageBox(hwnd, tstrErr, tstrErrTitle, MB_ICONEXCLAMATION | MB_OK);
  603. }
  604. }
  605. break;
  606. case IDOK:
  607. n = DRVCNF_CANCEL;
  608. //
  609. // RT Encode setting
  610. //
  611. hctrlEnc = GetDlgItem(hwnd, IDC_COMBO_MAXRTENCODE);
  612. nConfigMaxRTEncodeSetting = ComboBox_GetCurSel( hctrlEnc );
  613. if (nConfigMaxRTEncodeSetting != pdi->nConfigMaxRTEncodeSetting)
  614. {
  615. pdi->nConfigMaxRTEncodeSetting = nConfigMaxRTEncodeSetting;
  616. n = DRVCNF_OK;
  617. }
  618. //
  619. // RT Decode setting
  620. //
  621. hctrlDec = GetDlgItem(hwnd, IDC_COMBO_MAXRTDECODE);
  622. nConfigMaxRTDecodeSetting = ComboBox_GetCurSel( hctrlDec );
  623. if (nConfigMaxRTDecodeSetting != pdi->nConfigMaxRTDecodeSetting)
  624. {
  625. pdi->nConfigMaxRTDecodeSetting = nConfigMaxRTDecodeSetting;
  626. n = DRVCNF_OK;
  627. }
  628. //
  629. // If we changed something, write the data to the
  630. // registry.
  631. //
  632. if( DRVCNF_OK == n )
  633. {
  634. configWriteConfiguration( pdi );
  635. }
  636. EndDialog(hwnd, DRVCNF_OK);
  637. break;
  638. case IDCANCEL:
  639. EndDialog(hwnd, DRVCNF_CANCEL);
  640. break;
  641. case IDC_BTN_HELP:
  642. pdi->fHelpRunning = TRUE;
  643. WinHelp(hwnd, gszHelpFilename, HELP_CONTEXT, HELPCONTEXT_MSGSM610);
  644. break;
  645. }
  646. return (TRUE);
  647. }
  648. return (FALSE);
  649. } // gsm610DlgProcConfigure()
  650. //--------------------------------------------------------------------------;
  651. //
  652. // BOOL acmdDriverConfigInit
  653. //
  654. // Description:
  655. // This routine initializes the configuration parameters by reading them
  656. // from the registry. If there are no entries in the registry, this
  657. // codec auto-configures itself and writes the results to the registry.
  658. // If the auto-configure fails, or if we don't know our alias name,
  659. // then we set the configuration to default values.
  660. //
  661. // Arguments:
  662. // PDRIVERINSTANCE pdi:
  663. //
  664. // LPCTSTR pszAliasName:
  665. //
  666. // Return (BOOL):
  667. //
  668. //
  669. //--------------------------------------------------------------------------;
  670. BOOL FNGLOBAL acmdDriverConfigInit
  671. (
  672. PDRIVERINSTANCE pdi,
  673. LPCTSTR pszAliasName
  674. )
  675. {
  676. HKEY hkey;
  677. UINT nEncodeSetting;
  678. UINT nDecodeSetting;
  679. UINT uErrorIDS;
  680. //
  681. // If pszAliasName is NULL then just set all defaults
  682. //
  683. //
  684. if (NULL == pszAliasName)
  685. {
  686. DPF(2,"acmdDriverConfigInit: no alias name; using default settings.");
  687. configSetDefaults( pdi );
  688. return (TRUE);
  689. }
  690. //
  691. // If we haven't got an open hkey, then open it. Note that this routine
  692. // may be called more than once; on the second time, we should not
  693. // re-open the key.
  694. //
  695. if( NULL == pdi->hkey )
  696. {
  697. RegCreateKeyEx( MSGSM610_CONFIG_DEFAULTKEY, gszMultimediaKey, 0,
  698. NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL );
  699. if( NULL != hkey )
  700. {
  701. ASSERT( NULL != pszAliasName );
  702. RegCreateKeyEx( hkey, pszAliasName, 0, NULL, 0,
  703. KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  704. NULL, &pdi->hkey, NULL );
  705. RegCloseKey( hkey );
  706. }
  707. }
  708. //
  709. // Read configuration data from registry.
  710. //
  711. if( NULL == pdi->hkey )
  712. {
  713. configSetDefaults( pdi );
  714. }
  715. else
  716. {
  717. pdi->nConfigMaxRTEncodeSetting =
  718. (UINT)dwReadRegistryDefault( pdi->hkey,
  719. (LPTSTR)gszMaxRTEncodeSetting,
  720. MSGSM610_CONFIG_UNCONFIGURED );
  721. pdi->nConfigMaxRTDecodeSetting =
  722. (UINT)dwReadRegistryDefault( pdi->hkey,
  723. (LPTSTR)gszMaxRTDecodeSetting,
  724. MSGSM610_CONFIG_UNCONFIGURED );
  725. pdi->nConfigPercentCPU =
  726. (UINT)dwReadRegistryDefault( pdi->hkey,
  727. (LPTSTR)gszPercentCPU,
  728. MSGSM610_CONFIG_DEFAULT_PERCENTCPU );
  729. //
  730. // Check that nConfigPercentCPU is a valid value.
  731. //
  732. if( pdi->nConfigPercentCPU <= 0 )
  733. {
  734. pdi->nConfigPercentCPU = MSGSM610_CONFIG_DEFAULT_PERCENTCPU;
  735. }
  736. }
  737. //
  738. // If either the encode or decode setting is out of range, then
  739. // we call the auto-configure routine and write out the results.
  740. // This should only happen the first time the codec is run.
  741. //
  742. if( MSGSM610_CONFIG_NUMSETTINGS <= pdi->nConfigMaxRTEncodeSetting ||
  743. MSGSM610_CONFIG_NUMSETTINGS <= pdi->nConfigMaxRTDecodeSetting )
  744. {
  745. DPF( 1, "acmdDriverConfigInit: performing initial auto-config." );
  746. uErrorIDS = configAutoConfig( pdi,
  747. &nEncodeSetting,
  748. &nDecodeSetting );
  749. if( 0 != uErrorIDS )
  750. {
  751. //
  752. // Error in auto-config. Use defaults instead.
  753. //
  754. nEncodeSetting = MSGSM610_CONFIG_DEFAULT_MAXRTENCODESETTING;
  755. nDecodeSetting = MSGSM610_CONFIG_DEFAULT_MAXRTDECODESETTING;
  756. }
  757. pdi->nConfigMaxRTEncodeSetting = nEncodeSetting;
  758. pdi->nConfigMaxRTDecodeSetting = nDecodeSetting;
  759. //
  760. // Always write the results to the registry, even if we hit an
  761. // error, so we won't hit the automatic auto-config next
  762. // time we run. One failure is enough!
  763. //
  764. configWriteConfiguration( pdi );
  765. }
  766. return (TRUE);
  767. } // acmdDriverConfigInit()