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.

967 lines
31 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) 1992-1998 Microsoft Corporation
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // config.c
  13. //
  14. // Description:
  15. // IMA ADPCM codec 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 MaxRTXxcodeSetting.
  30. //
  31. // These parameters may be set in the registry, using the imaadpcm 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. // Note: The configuration dialog is only compiled into the code if the
  39. // IMAADPCM_USECONFIG symbol is defined. This is designed to make it
  40. // easy to remove the dialog box completely for certain platforms,
  41. // such as MIPS and Alpha under Windows NT.
  42. //
  43. //==========================================================================;
  44. #include <windows.h>
  45. #include <windowsx.h>
  46. #include <mmsystem.h>
  47. #include <mmreg.h>
  48. #include <msacm.h>
  49. #include <msacmdrv.h>
  50. #include "muldiv32.h"
  51. #include "codec.h"
  52. #include "imaadpcm.h"
  53. #include "debug.h"
  54. #ifdef WIN32
  55. #include <tchar.h>
  56. #else
  57. #define _tcstoul strtoul
  58. #define _tcsncpy _fstrncpy
  59. #endif
  60. #include <string.h>
  61. #include <stdlib.h>
  62. #ifndef WIN32
  63. #error Win16 support has been dropped from this codec! Compile for Win32.
  64. #endif
  65. #ifdef IMAADPCM_USECONFIG
  66. //
  67. // Strings required to access configuration information in the registry.
  68. //
  69. const TCHAR BCODE gszMaxRTEncodeSetting[] = TEXT("MaxRTEncodeSetting");
  70. const TCHAR BCODE gszMaxRTDecodeSetting[] = TEXT("MaxRTDecodeSetting");
  71. const TCHAR BCODE gszPercentCPU[] = TEXT("PercentCPU");
  72. const TCHAR gszMultimediaKey[] = TEXT("Software\\Microsoft\\Multimedia\\");
  73. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  74. //
  75. // Be careful changing the following!
  76. //
  77. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  78. //
  79. // Data required to access the dialog box help.
  80. //
  81. // Note that you must write your own help file for your codec, even if
  82. // the configuration dialog box looks identical. If you use the file
  83. // listed here, then the title will say "IMA ADPCM" or something.
  84. //
  85. // Note: the number HELPCONTEXT_IMAADPCM must be unique in the file
  86. // gszHelpFilename, and the number must defined in the [MAP]
  87. // section of the .hpj help project file. Then the .rtf file
  88. // will reference that number (using the keyword defined in
  89. // the .hpj file). Then when we call WinHelp with the number,
  90. // WinHelp will go to the right help entry.
  91. //
  92. const TCHAR BCODE gszHelpFilename[] = TEXT("audiocdc.hlp");
  93. #define HELPCONTEXT_IMAADPCM 1001
  94. #define IDH_AUDIOCDC_COMPRESSION 100
  95. #define IDH_AUDIOCDC_DECOMPRESSION 200
  96. #define IDH_AUDIOCDC_AUTOCONFIGURE 300
  97. static int aKeyWordIds[] = {
  98. IDC_COMBO_MAXRTENCODE, IDH_AUDIOCDC_COMPRESSION,
  99. IDC_STATIC_COMPRESS, IDH_AUDIOCDC_COMPRESSION,
  100. IDC_COMBO_MAXRTDECODE, IDH_AUDIOCDC_DECOMPRESSION,
  101. IDC_STATIC_DECOMPRESS, IDH_AUDIOCDC_DECOMPRESSION,
  102. IDC_BTN_AUTOCONFIG, IDH_AUDIOCDC_AUTOCONFIGURE,
  103. 0, 0
  104. };
  105. //==========================================================================;
  106. //
  107. //
  108. //
  109. //
  110. //==========================================================================;
  111. //--------------------------------------------------------------------------;
  112. //
  113. // VOID configWriteConfiguration
  114. //
  115. // Description:
  116. //
  117. // This routine writes the configuration data in PDI to the registry.
  118. // This consists of the max real-time Encode and Decode settings.
  119. //
  120. // Arguments:
  121. // PDRIVERINSTANCE pdi
  122. //
  123. // Return (VOID): None.
  124. //
  125. //--------------------------------------------------------------------------;
  126. VOID configWriteConfiguration
  127. (
  128. PDRIVERINSTANCE pdi
  129. )
  130. {
  131. DWORD dw;
  132. if( NULL != pdi->hkey )
  133. {
  134. dw = (DWORD)pdi->nConfigMaxRTEncodeSetting;
  135. (void)RegSetValueEx( pdi->hkey, (LPTSTR)gszMaxRTEncodeSetting, 0,
  136. REG_DWORD, (LPBYTE)&dw, sizeof(DWORD) );
  137. dw = (DWORD)pdi->nConfigMaxRTDecodeSetting;
  138. (void)RegSetValueEx( pdi->hkey, (LPTSTR)gszMaxRTDecodeSetting, 0,
  139. REG_DWORD, (LPBYTE)&dw, sizeof(DWORD) );
  140. }
  141. }
  142. //--------------------------------------------------------------------------;
  143. //
  144. // DWORD dwReadRegistryDefault
  145. //
  146. // Description:
  147. //
  148. // This routine reads a given value from the registry, and returns a
  149. // default value if the read is not successful.
  150. //
  151. // Arguments:
  152. // HKEY hkey: Registry key to read from.
  153. // LPTSTR lpszEntry:
  154. // DWORD dwDefault:
  155. //
  156. // Return (DWORD):
  157. //
  158. //--------------------------------------------------------------------------;
  159. INLINE DWORD dwReadRegistryDefault
  160. (
  161. HKEY hkey,
  162. LPTSTR lpszEntry,
  163. DWORD dwDefault
  164. )
  165. {
  166. DWORD dwType = (DWORD)~REG_DWORD; // Init to anything but REG_DWORD.
  167. DWORD cbSize = sizeof(DWORD);
  168. DWORD dwRet;
  169. LONG lError;
  170. ASSERT( NULL != hkey );
  171. ASSERT( NULL != lpszEntry );
  172. lError = RegQueryValueEx( hkey,
  173. lpszEntry,
  174. NULL,
  175. &dwType,
  176. (LPBYTE)&dwRet,
  177. &cbSize );
  178. if( ERROR_SUCCESS != lError || REG_DWORD != dwType )
  179. dwRet = dwDefault;
  180. return dwRet;
  181. }
  182. //--------------------------------------------------------------------------;
  183. //
  184. // VOID configSetDefaults
  185. //
  186. // Description:
  187. //
  188. // This routine sets the configuration parameters to their default
  189. // values.
  190. //
  191. // Arguments:
  192. // PDRIVERINSTANCE pdi:
  193. //
  194. //--------------------------------------------------------------------------;
  195. VOID configSetDefaults
  196. (
  197. PDRIVERINSTANCE pdi
  198. )
  199. {
  200. pdi->nConfigMaxRTEncodeSetting =
  201. IMAADPCM_CONFIG_DEFAULT_MAXRTENCODESETTING;
  202. pdi->nConfigMaxRTDecodeSetting =
  203. IMAADPCM_CONFIG_DEFAULT_MAXRTDECODESETTING;
  204. pdi->nConfigPercentCPU =
  205. IMAADPCM_CONFIG_DEFAULT_PERCENTCPU;
  206. }
  207. //--------------------------------------------------------------------------;
  208. //
  209. // UINT configAutoConfig
  210. //
  211. // Description:
  212. //
  213. // We will determine how much time it takes to encode and then decode
  214. // 2 seconds of data and use this to guess at the max sample
  215. // rate we can convert in real-time.
  216. //
  217. // The max is computed with essentially 100% of the CPU. Practically,
  218. // we won't have 100% of the CPU available. So we take a percentage
  219. // of the computed max and use that as the max in the config dialog.
  220. //
  221. // The percentage that we use can be set in the ini file imaadpcm
  222. // section by PercentCPU=xx.
  223. //
  224. //
  225. // Arguments:
  226. // HWND hwnd:
  227. //
  228. // Return (UINT): String identifier (IDS) of error message, or zero if
  229. // the call succeeded.
  230. //
  231. //--------------------------------------------------------------------------;
  232. UINT FNLOCAL configAutoConfig
  233. (
  234. PDRIVERINSTANCE pdi,
  235. UINT *pnEncodeSetting,
  236. UINT *pnDecodeSetting
  237. )
  238. {
  239. LPPCMWAVEFORMAT pwfPCM = NULL;
  240. LPIMAADPCMWAVEFORMAT pwfADPCM = NULL;
  241. LPACMDRVFORMATSUGGEST padfs = NULL;
  242. LPACMDRVSTREAMINSTANCE padsi = NULL;
  243. LPACMDRVSTREAMHEADER padsh = NULL;
  244. LPACMDRVSTREAMSIZE padss = NULL;
  245. PSTREAMINSTANCE psi = NULL;
  246. LPBYTE pBufPCM;
  247. LPBYTE pBufADPCM;
  248. DWORD cbPCM;
  249. DWORD cbADPCM;
  250. DWORD dwEncodeTime;
  251. DWORD dwDecodeTime;
  252. DWORD dwStartTime;
  253. DWORD dwMaxEncodeRate;
  254. DWORD dwMaxDecodeRate;
  255. UINT nConfig;
  256. UINT uIDS;
  257. HCURSOR hCursorSave;
  258. //
  259. // We divide by this!
  260. //
  261. ASSERT( 0 != pdi->nConfigPercentCPU );
  262. uIDS = 0; // No errors yet - this is our "success" return.
  263. //
  264. // This function may take a while. Set hour glass cursor
  265. //
  266. hCursorSave = SetCursor(LoadCursor(NULL, IDC_WAIT));
  267. //
  268. // Set up the input PCM wave format structure.
  269. //
  270. pwfPCM = (LPPCMWAVEFORMAT)GlobalAllocPtr( GPTR, sizeof(*pwfPCM) );
  271. if( NULL == pwfPCM )
  272. {
  273. uIDS = IDS_ERROR_NOMEM;
  274. goto errReturn;
  275. }
  276. pwfPCM->wf.wFormatTag = WAVE_FORMAT_PCM; // Mono 16-bit!!!
  277. pwfPCM->wf.nChannels = 1;
  278. pwfPCM->wf.nSamplesPerSec = 8000;
  279. pwfPCM->wf.nBlockAlign = 2;
  280. pwfPCM->wBitsPerSample = 16;
  281. pwfPCM->wf.nAvgBytesPerSec = pwfPCM->wf.nSamplesPerSec *
  282. pwfPCM->wf.nBlockAlign;
  283. //
  284. // Get this driver to suggest a format to convert to. Note: we may
  285. // want to constrain the suggestion partly, depending on the
  286. // capabilities of the codec. We should always choose the most
  287. // complex conversion if there are several possibilities.
  288. //
  289. padfs = (LPACMDRVFORMATSUGGEST)GlobalAllocPtr( GPTR, sizeof(*padfs) );
  290. pwfADPCM = (LPIMAADPCMWAVEFORMAT)GlobalAllocPtr( GPTR, sizeof(*pwfADPCM) );
  291. if( NULL == padfs || NULL == pwfADPCM )
  292. {
  293. uIDS = IDS_ERROR_NOMEM;
  294. goto errReturn;
  295. }
  296. padfs->cbStruct = sizeof(*padfs);
  297. padfs->fdwSuggest = 0; // Default everything.
  298. padfs->pwfxSrc = (LPWAVEFORMATEX)pwfPCM;
  299. padfs->cbwfxSrc = sizeof(*pwfPCM);
  300. padfs->pwfxDst = (LPWAVEFORMATEX)pwfADPCM;
  301. padfs->cbwfxDst = sizeof(*pwfADPCM);
  302. (void)acmdFormatSuggest( pdi, padfs ); // This will always work, right?
  303. //
  304. // Set stream instance data. Note: we assume that the members that
  305. // we don't set here never actually get used. Make sure that this
  306. // is really true!
  307. //
  308. padsi = (LPACMDRVSTREAMINSTANCE)GlobalAllocPtr( GPTR, sizeof(*padsi) );
  309. psi = (PSTREAMINSTANCE)LocalAlloc( LPTR, sizeof(*psi) );
  310. if( NULL == padsi || NULL == psi )
  311. {
  312. uIDS = IDS_ERROR_NOMEM;
  313. goto errReturn;
  314. }
  315. // Make sure that psi->fnConvert matches the PCM format in pwfPCM!!!
  316. psi->fnConvert = imaadpcmEncode4Bit_M16;
  317. psi->fdwConfig = pdi->fdwConfig;
  318. psi->nStepIndexL = 0;
  319. psi->nStepIndexR = 0;
  320. // Make sure that no other members of padsi are used!!!
  321. padsi->cbStruct = sizeof(*padsi);
  322. padsi->pwfxSrc = (LPWAVEFORMATEX)pwfPCM;
  323. padsi->pwfxDst = (LPWAVEFORMATEX)pwfADPCM;
  324. padsi->dwDriver = (DWORD_PTR)psi;
  325. //
  326. // Now, get the driver to tell us how much space is required for the
  327. // destination buffer.
  328. //
  329. cbPCM = IMAADPCM_CONFIGTESTTIME * pwfPCM->wf.nAvgBytesPerSec;
  330. padss = (LPACMDRVSTREAMSIZE)GlobalAllocPtr( GPTR, sizeof(*padss) );
  331. if( NULL == padss )
  332. {
  333. uIDS = IDS_ERROR_NOMEM;
  334. goto errReturn;
  335. }
  336. padss->cbStruct = sizeof(padss);
  337. padss->fdwSize = ACM_STREAMSIZEF_SOURCE;
  338. padss->cbSrcLength = cbPCM;
  339. (void)acmdStreamSize( padsi, padss ); // This will always work, right?
  340. //
  341. // Allocate source and destination buffers. Note that we specifically
  342. // don't zero-initialize them, so that we will get random PCM data in
  343. // the PCM buffer.
  344. //
  345. cbADPCM = padss->cbDstLength;
  346. pBufPCM = (LPBYTE)GlobalAllocPtr( GMEM_FIXED, (UINT)cbPCM );
  347. pBufADPCM = (LPBYTE)GlobalAllocPtr( GMEM_FIXED, (UINT)cbADPCM );
  348. if( NULL == pBufPCM || NULL == pBufADPCM )
  349. {
  350. uIDS = IDS_ERROR_NOMEM;
  351. goto errReturn;
  352. }
  353. //
  354. // Now, tell the driver to convert our buffer and measure the time.
  355. // Note that we don't care what is in the source buffer, we only
  356. // care how long it takes.
  357. //
  358. padsh = (LPACMDRVSTREAMHEADER)GlobalAllocPtr( GPTR, sizeof(*padsh) );
  359. if( NULL == padsh )
  360. {
  361. uIDS = IDS_ERROR_NOMEM;
  362. goto errReturn;
  363. }
  364. // Make sure that no other members of padsh are used!!!
  365. padsh->cbStruct = sizeof(*padsh);
  366. padsh->pbSrc = pBufPCM;
  367. padsh->cbSrcLength = cbPCM;
  368. padsh->pbDst = pBufADPCM;
  369. padsh->cbDstLength = cbADPCM;
  370. padsh->fdwConvert = 0; // Should be 0 already, but...
  371. dwStartTime = timeGetTime();
  372. (void)acmdStreamConvert( pdi, padsi, padsh ); // Won't fail?!
  373. dwEncodeTime = timeGetTime() - dwStartTime;
  374. //
  375. // Now, we have an encoded IMA ADPCM buffer. Tell the driver to
  376. // convert it back to PCM, measuring the time. First we reset the
  377. // size of the ADPCM buffer to correspond with the buffer returned
  378. // by the convert. Then we zero out our structure buffers and reset
  379. // them for the new conversion. Note: we assume that the PCM buffer
  380. // is already large enough to handle the conversion.
  381. //
  382. cbADPCM = padsh->cbDstLengthUsed;
  383. #ifdef WIN32
  384. ZeroMemory( psi, sizeof(*psi) );
  385. ZeroMemory( padsi, sizeof(*padsi) );
  386. ZeroMemory( padsh, sizeof(*padsh) );
  387. #else
  388. _fmemset( psi, 0, sizeof(*psi) );
  389. _fmemset( padsi, 0, sizeof(*padsi) );
  390. _fmemset( padsh, 0, sizeof(*padsh) );
  391. #endif
  392. // Make sure that psi->fnConvert matches the format in pfwADPCM!!!
  393. psi->fnConvert = imaadpcmDecode4Bit_M16;
  394. psi->fdwConfig = pdi->fdwConfig;
  395. psi->nStepIndexL = 0;
  396. psi->nStepIndexR = 0;
  397. // Make sure that no other members of padsi are used!!!
  398. padsi->cbStruct = sizeof(*padsi);
  399. padsi->pwfxSrc = (LPWAVEFORMATEX)pwfADPCM;
  400. padsi->pwfxDst = (LPWAVEFORMATEX)pwfPCM;
  401. padsi->dwDriver = (DWORD_PTR)psi;
  402. // Make sure that no other members of padsh are used!!!
  403. padsh->cbStruct = sizeof(*padsh);
  404. padsh->pbSrc = pBufADPCM;
  405. padsh->cbSrcLength = cbADPCM;
  406. padsh->pbDst = pBufPCM;
  407. padsh->cbDstLength = cbPCM;
  408. padsh->fdwConvert = 0; // Should be 0 already, but...
  409. dwStartTime = timeGetTime();
  410. (void)acmdStreamConvert( pdi, padsi, padsh ); // Won't fail?!
  411. dwDecodeTime = timeGetTime() - dwStartTime;
  412. //
  413. // Now, figure out the max encode and decode rates implied by the
  414. // times required by the conversions.
  415. //
  416. if( dwEncodeTime == 0 )
  417. dwMaxEncodeRate = 0xFFFFFFFFL;
  418. else
  419. dwMaxEncodeRate = MulDiv32( pwfPCM->wf.nSamplesPerSec,
  420. 1000L * IMAADPCM_CONFIGTESTTIME,
  421. dwEncodeTime ) *
  422. pdi->nConfigPercentCPU / 100;
  423. if( dwDecodeTime == 0 )
  424. dwMaxDecodeRate = 0xFFFFFFFFL;
  425. else
  426. dwMaxDecodeRate = MulDiv32( pwfPCM->wf.nSamplesPerSec,
  427. 1000L * IMAADPCM_CONFIGTESTTIME,
  428. dwDecodeTime ) *
  429. pdi->nConfigPercentCPU / 100;
  430. DPF(1,"dwEncodeTime=%d, dwMaxEncodeRate=%d", dwEncodeTime,dwMaxEncodeRate);
  431. DPF(1,"dwDecodeTime=%d, dwMaxDecodeRate=%d", dwDecodeTime,dwMaxDecodeRate);
  432. //
  433. // Now set the configuration based on these values. We scan the
  434. // gaRateListFormat[] array looking at the dwMonoRate to determine
  435. // the appropriate setting.
  436. //
  437. // Encode.
  438. //
  439. nConfig = 0;
  440. while( gaRateListFormat[nConfig].dwMonoRate < dwMaxEncodeRate &&
  441. IMAADPCM_CONFIG_NUMSETTINGS > nConfig )
  442. {
  443. nConfig++;
  444. }
  445. *pnEncodeSetting = nConfig - 1; // We went too far.
  446. //
  447. // Decode.
  448. //
  449. nConfig = 0;
  450. while( gaRateListFormat[nConfig].dwMonoRate < dwMaxDecodeRate &&
  451. IMAADPCM_CONFIG_NUMSETTINGS > nConfig )
  452. {
  453. nConfig++;
  454. }
  455. *pnDecodeSetting = nConfig - 1; // We went too far.
  456. //
  457. // Free structure allocations and exit.
  458. //
  459. //
  460. errReturn:
  461. if( NULL != pwfPCM )
  462. GlobalFreePtr( pwfPCM );
  463. if( NULL != pwfADPCM )
  464. GlobalFreePtr( pwfADPCM );
  465. if( NULL != padfs )
  466. GlobalFreePtr( padfs );
  467. if( NULL != padsi )
  468. GlobalFreePtr( padsi );
  469. if( NULL != padsh )
  470. GlobalFreePtr( padsh );
  471. if( NULL != padss )
  472. GlobalFreePtr( padss );
  473. if( NULL != psi )
  474. LocalFree( (HLOCAL)psi );
  475. SetCursor( hCursorSave );
  476. return uIDS;
  477. }
  478. //==========================================================================;
  479. //
  480. //
  481. //
  482. //
  483. //==========================================================================;
  484. //--------------------------------------------------------------------------;
  485. //
  486. // INT_PTR acmdDlgProcConfigure
  487. //
  488. // Description:
  489. // This routine handles the configuration dialog box.
  490. //
  491. // Arguments:
  492. // HWND hwnd:
  493. //
  494. // UINT uMsg:
  495. //
  496. // WPARAM wParam:
  497. //
  498. // LPARAM lParam:
  499. //
  500. // Return (BOOL):
  501. //
  502. //
  503. // Note: In order to avoid using a static fHelpRunning flag which will
  504. // still be here after we exit, we allocate an fHelpRunning
  505. // variable in the DRIVERINSTANCE structure. This is purely to
  506. // avoid static variables (which force us to have a data segment
  507. // of 4K); the fHelpRunning is not used in any other procedures.
  508. //
  509. //--------------------------------------------------------------------------;
  510. INT_PTR FNWCALLBACK acmdDlgProcConfigure
  511. (
  512. HWND hwnd,
  513. UINT uMsg,
  514. WPARAM wParam,
  515. LPARAM lParam
  516. )
  517. {
  518. PDRIVERINSTANCE pdi;
  519. HWND hctrlEnc;
  520. HWND hctrlDec;
  521. UINT uCmdId;
  522. UINT u;
  523. int n;
  524. TCHAR szFormat[IMAADPCM_CONFIG_TEXTLEN];
  525. TCHAR szOutput[IMAADPCM_CONFIG_TEXTLEN];
  526. UINT nConfigMaxRTEncodeSetting;
  527. UINT nConfigMaxRTDecodeSetting;
  528. switch (uMsg)
  529. {
  530. case WM_INITDIALOG:
  531. pdi = (PDRIVERINSTANCE)(UINT_PTR)lParam;
  532. pdi->fHelpRunning = FALSE; // Used only in this procedure.
  533. #ifdef WIN4
  534. //
  535. // This driver is marked Windows Subsystem version 3.5 in order
  536. // that it be compatible with Daytona - however, that means that
  537. // Chicago will think it is a Win 3.1 application and give it
  538. // Win 3.1 default colors. This makes the config dialog look
  539. // white, whereas the Chicago default uses 3DFACE. This code
  540. // (and the CTLCOLOR messages) sets the colors explicitly.
  541. //
  542. pdi->hbrDialog = CreateSolidBrush( GetSysColor(COLOR_3DFACE) );
  543. #endif
  544. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  545. nConfigMaxRTEncodeSetting = pdi->nConfigMaxRTEncodeSetting;
  546. nConfigMaxRTDecodeSetting = pdi->nConfigMaxRTDecodeSetting;
  547. hctrlEnc = GetDlgItem(hwnd, IDC_COMBO_MAXRTENCODE);
  548. hctrlDec = GetDlgItem(hwnd, IDC_COMBO_MAXRTDECODE);
  549. for( u=0; u<IMAADPCM_CONFIG_NUMSETTINGS; u++ )
  550. {
  551. LoadString( pdi->hinst, gaRateListFormat[u].idsFormat,
  552. szFormat, SIZEOF(szFormat) );
  553. switch( gaRateListFormat[u].uFormatType )
  554. {
  555. case CONFIG_RLF_NONUMBER:
  556. lstrcpy( szOutput, szFormat );
  557. break;
  558. case CONFIG_RLF_MONOONLY:
  559. wsprintf( szOutput, szFormat,
  560. gaRateListFormat[u].dwMonoRate );
  561. break;
  562. case CONFIG_RLF_STEREOONLY:
  563. wsprintf( szOutput, szFormat,
  564. gaRateListFormat[u].dwMonoRate / 2 );
  565. break;
  566. case CONFIG_RLF_MONOSTEREO:
  567. wsprintf( szOutput, szFormat,
  568. gaRateListFormat[u].dwMonoRate,
  569. gaRateListFormat[u].dwMonoRate / 2 );
  570. break;
  571. }
  572. ComboBox_AddString(hctrlEnc, szOutput);
  573. ComboBox_AddString(hctrlDec, szOutput);
  574. }
  575. ComboBox_SetCurSel( hctrlEnc, nConfigMaxRTEncodeSetting );
  576. ComboBox_SetCurSel( hctrlDec, nConfigMaxRTDecodeSetting );
  577. return (TRUE);
  578. case WM_DESTROY:
  579. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  580. if (pdi->fHelpRunning)
  581. {
  582. WinHelp(hwnd, gszHelpFilename, HELP_QUIT, 0L);
  583. }
  584. #ifdef WIN4
  585. DeleteObject( pdi->hbrDialog );
  586. #endif
  587. //
  588. // Let dialog box process this message
  589. //
  590. //
  591. return (FALSE);
  592. #ifdef WIN4
  593. //
  594. // Handle CTLCOLOR messages to get the dialog boxes to the default
  595. // Chicago colors. See the INITDIALOG message, above.
  596. //
  597. case WM_CTLCOLORSTATIC:
  598. case WM_CTLCOLORDLG:
  599. case WM_CTLCOLORBTN:
  600. SetTextColor( (HDC)wParam, GetSysColor(COLOR_WINDOWTEXT) );
  601. SetBkColor( (HDC)wParam, GetSysColor(COLOR_3DFACE) );
  602. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  603. return (UINT_PTR)pdi->hbrDialog;
  604. #endif
  605. case WM_HELP:
  606. WinHelp(((LPHELPINFO)lParam)->hItemHandle, gszHelpFilename,
  607. HELP_WM_HELP, (ULONG_PTR)aKeyWordIds);
  608. return (TRUE);
  609. case WM_COMMAND:
  610. pdi = (PDRIVERINSTANCE)GetWindowLongPtr(hwnd, DWLP_USER);
  611. uCmdId = (UINT) wParam;
  612. switch (uCmdId)
  613. {
  614. case IDC_BTN_AUTOCONFIG:
  615. {
  616. UINT uErrorIDS;
  617. uErrorIDS = configAutoConfig( pdi,
  618. &nConfigMaxRTEncodeSetting,
  619. &nConfigMaxRTDecodeSetting );
  620. if( 0==uErrorIDS )
  621. {
  622. //
  623. // No error - set dialog box settings.
  624. //
  625. hctrlEnc = GetDlgItem( hwnd, IDC_COMBO_MAXRTENCODE );
  626. ComboBox_SetCurSel( hctrlEnc, nConfigMaxRTEncodeSetting );
  627. hctrlDec = GetDlgItem( hwnd, IDC_COMBO_MAXRTDECODE );
  628. ComboBox_SetCurSel( hctrlDec, nConfigMaxRTDecodeSetting );
  629. }
  630. else
  631. {
  632. //
  633. // Display error message.
  634. //
  635. TCHAR tstrErr[200];
  636. TCHAR tstrErrTitle[200];
  637. if (0 == LoadString(pdi->hinst, IDS_ERROR, tstrErrTitle, SIZEOF(tstrErrTitle)))
  638. break;
  639. if (0 == LoadString(pdi->hinst, uErrorIDS, tstrErr, SIZEOF(tstrErr)))
  640. break;
  641. MessageBox(hwnd, tstrErr, tstrErrTitle, MB_ICONEXCLAMATION | MB_OK);
  642. }
  643. }
  644. break;
  645. case IDOK:
  646. n = DRVCNF_CANCEL;
  647. //
  648. // RT Encode setting
  649. //
  650. hctrlEnc = GetDlgItem(hwnd, IDC_COMBO_MAXRTENCODE);
  651. nConfigMaxRTEncodeSetting = ComboBox_GetCurSel( hctrlEnc );
  652. if (nConfigMaxRTEncodeSetting != pdi->nConfigMaxRTEncodeSetting)
  653. {
  654. pdi->nConfigMaxRTEncodeSetting = nConfigMaxRTEncodeSetting;
  655. n = DRVCNF_OK;
  656. }
  657. //
  658. // RT Decode setting
  659. //
  660. hctrlDec = GetDlgItem(hwnd, IDC_COMBO_MAXRTDECODE);
  661. nConfigMaxRTDecodeSetting = ComboBox_GetCurSel( hctrlDec );
  662. if (nConfigMaxRTDecodeSetting != pdi->nConfigMaxRTDecodeSetting)
  663. {
  664. pdi->nConfigMaxRTDecodeSetting = nConfigMaxRTDecodeSetting;
  665. n = DRVCNF_OK;
  666. }
  667. //
  668. // If we changed something, write the data to the
  669. // registry.
  670. //
  671. if( DRVCNF_OK == n )
  672. {
  673. configWriteConfiguration( pdi );
  674. }
  675. EndDialog(hwnd, DRVCNF_OK);
  676. break;
  677. case IDCANCEL:
  678. EndDialog(hwnd, DRVCNF_CANCEL);
  679. break;
  680. case IDC_BTN_HELP:
  681. pdi->fHelpRunning = TRUE;
  682. WinHelp(hwnd, gszHelpFilename, HELP_CONTEXT, HELPCONTEXT_IMAADPCM);
  683. break;
  684. }
  685. return (TRUE);
  686. }
  687. return (FALSE);
  688. } // acmdDlgProcConfigure()
  689. //--------------------------------------------------------------------------;
  690. //
  691. // BOOL acmdDriverConfigInit
  692. //
  693. // Description:
  694. // This routine initializes the configuration parameters by reading them
  695. // from the registry. If there are no entries in the registry, this
  696. // codec auto-configures itself and writes the results to the registry.
  697. // If the auto-configure fails, or if we don't know our alias name,
  698. // then we set the configuration to default values.
  699. //
  700. // Arguments:
  701. // PDRIVERINSTANCE pdi:
  702. //
  703. // LPCTSTR pszAliasName:
  704. //
  705. // Return (BOOL):
  706. //
  707. //
  708. //--------------------------------------------------------------------------;
  709. BOOL FNGLOBAL acmdDriverConfigInit
  710. (
  711. PDRIVERINSTANCE pdi,
  712. LPCTSTR pszAliasName
  713. )
  714. {
  715. HKEY hkey;
  716. UINT nEncodeSetting;
  717. UINT nDecodeSetting;
  718. UINT uErrorIDS;
  719. //
  720. // If pszAliasName is NULL then just set all defaults
  721. //
  722. //
  723. if (NULL == pszAliasName)
  724. {
  725. DPF(2,"acmdDriverConfigInit: no alias name; using default settings.");
  726. configSetDefaults( pdi );
  727. return (TRUE);
  728. }
  729. //
  730. // If we haven't got an open hkey, then open it. Note that this routine
  731. // may be called more than once; on the second time, we should not
  732. // re-open the key.
  733. //
  734. if( NULL == pdi->hkey )
  735. {
  736. RegCreateKeyEx( IMAADPCM_CONFIG_DEFAULTKEY, gszMultimediaKey, 0,
  737. NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL );
  738. if( NULL != hkey )
  739. {
  740. ASSERT( NULL != pszAliasName );
  741. RegCreateKeyEx( hkey, pszAliasName, 0, NULL, 0,
  742. KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  743. NULL, &pdi->hkey, NULL );
  744. RegCloseKey( hkey );
  745. }
  746. }
  747. //
  748. // Read configuration data from registry.
  749. //
  750. if( NULL == pdi->hkey )
  751. {
  752. configSetDefaults( pdi );
  753. }
  754. else
  755. {
  756. pdi->nConfigMaxRTEncodeSetting =
  757. (UINT)dwReadRegistryDefault( pdi->hkey,
  758. (LPTSTR)gszMaxRTEncodeSetting,
  759. IMAADPCM_CONFIG_UNCONFIGURED );
  760. pdi->nConfigMaxRTDecodeSetting =
  761. (UINT)dwReadRegistryDefault( pdi->hkey,
  762. (LPTSTR)gszMaxRTDecodeSetting,
  763. IMAADPCM_CONFIG_UNCONFIGURED );
  764. pdi->nConfigPercentCPU =
  765. (UINT)dwReadRegistryDefault( pdi->hkey,
  766. (LPTSTR)gszPercentCPU,
  767. IMAADPCM_CONFIG_DEFAULT_PERCENTCPU );
  768. //
  769. // Check that nConfigPercentCPU is a valid value.
  770. //
  771. if( pdi->nConfigPercentCPU <= 0 )
  772. {
  773. pdi->nConfigPercentCPU = IMAADPCM_CONFIG_DEFAULT_PERCENTCPU;
  774. }
  775. }
  776. //
  777. // If either the encode or decode setting is out of range, then
  778. // we call the auto-configure routine and write out the results.
  779. // This should only happen the first time the codec is run.
  780. //
  781. if( IMAADPCM_CONFIG_NUMSETTINGS <= pdi->nConfigMaxRTEncodeSetting ||
  782. IMAADPCM_CONFIG_NUMSETTINGS <= pdi->nConfigMaxRTDecodeSetting )
  783. {
  784. DPF( 1, "acmdDriverConfigInit: performing initial auto-config." );
  785. uErrorIDS = configAutoConfig( pdi,
  786. &nEncodeSetting,
  787. &nDecodeSetting );
  788. if( 0 != uErrorIDS )
  789. {
  790. //
  791. // Error in auto-config. Use defaults instead.
  792. //
  793. nEncodeSetting = IMAADPCM_CONFIG_DEFAULT_MAXRTENCODESETTING;
  794. nDecodeSetting = IMAADPCM_CONFIG_DEFAULT_MAXRTDECODESETTING;
  795. }
  796. pdi->nConfigMaxRTEncodeSetting = nEncodeSetting;
  797. pdi->nConfigMaxRTDecodeSetting = nDecodeSetting;
  798. //
  799. // Always write the results to the registry, even if we hit an
  800. // error, so we won't hit the automatic auto-config next
  801. // time we run. One failure is enough!
  802. //
  803. configWriteConfiguration( pdi );
  804. }
  805. return (TRUE);
  806. } // acmdDriverConfigInit()
  807. #endif // IMAADPCM_USECONFIG