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.

1964 lines
64 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 - 1995 Microsoft Corporation. All Rights Reserved.
  9. *
  10. **************************************************************************/
  11. /****************************************************************************
  12. *
  13. * dialogs.c: Dialog box processing
  14. *
  15. * Vidcap32 Source code
  16. *
  17. ***************************************************************************/
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <commdlg.h>
  21. #include <mmsystem.h>
  22. #include <mmreg.h>
  23. #include <io.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <memory.h>
  28. #include <dos.h>
  29. #include <vfw.h>
  30. #include <tchar.h>
  31. #include "arrow.h"
  32. #include "rlmeter.h"
  33. #include "vidcap.h"
  34. #include "vidframe.h"
  35. #include "help.h"
  36. static long GetFreeDiskSpaceInKB(LPTSTR) ;
  37. static int CountMCIDevices(UINT) ;
  38. LRESULT FAR PASCAL MCISetupProc(HWND, unsigned, WPARAM, LPARAM);
  39. //--- utility functions ---------------------------------------------------
  40. /*----------------------------------------------------------------------------*\
  41. | SmartWindowPosition (HWND hWndDlg, HWND hWndShow)
  42. | |
  43. | Description: |
  44. | This function attempts to position a dialog box so that it
  45. | does not obscure the hWndShow window. This function is
  46. | typically called during WM_INITDIALOG processing.
  47. | |
  48. | Arguments: |
  49. | hWndDlg handle of the soon to be displayed dialog
  50. | hWndShow handle of the window to keep visible
  51. | |
  52. | Returns: |
  53. | 1 if the windows overlap and positions were adjusted
  54. | 0 if the windows don't overlap
  55. | |
  56. \*----------------------------------------------------------------------------*/
  57. int SmartWindowPosition (HWND hWndDlg, HWND hWndShow)
  58. {
  59. RECT rc, rcDlg, rcShow;
  60. int iHeight, iWidth;
  61. int iScreenHeight, iScreenWidth;
  62. GetWindowRect(hWndDlg, &rcDlg);
  63. GetWindowRect(hWndShow, &rcShow);
  64. iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
  65. iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
  66. InflateRect (&rcShow, 5, 5); // allow a small border
  67. if (IntersectRect(&rc, &rcDlg, &rcShow)){
  68. /* the two do intersect, now figure out where to place */
  69. /* this dialog window. Try to go below the Show window*/
  70. /* first and then to the right, top and left. */
  71. /* get the size of this dialog */
  72. iHeight = rcDlg.bottom - rcDlg.top;
  73. iWidth = rcDlg.right - rcDlg.left;
  74. if ((UINT)(rcShow.bottom + iHeight + 1) < (UINT)iScreenHeight){
  75. /* will fit on bottom, go for it */
  76. rc.top = rcShow.bottom + 1;
  77. rc.left = (((rcShow.right - rcShow.left)/2) + rcShow.left)
  78. - (iWidth/2);
  79. } else if ((UINT)(rcShow.right + iWidth + 1) < (UINT)iScreenWidth){
  80. /* will fit to right, go for it */
  81. rc.left = rcShow.right + 1;
  82. rc.top = (((rcShow.bottom - rcShow.top)/2) + rcShow.top)
  83. - (iHeight/2);
  84. } else if ((UINT)(rcShow.top - iHeight - 1) > 0){
  85. /* will fit on top, handle that */
  86. rc.top = rcShow.top - iHeight - 1;
  87. rc.left = (((rcShow.right - rcShow.left)/2) + rcShow.left)
  88. - (iWidth/2);
  89. } else if ((UINT)(rcShow.left - iWidth - 1) > 0){
  90. /* will fit to left, do it */
  91. rc.left = rcShow.left - iWidth - 1;
  92. rc.top = (((rcShow.bottom - rcShow.top)/2) + rcShow.top)
  93. - (iHeight/2);
  94. } else {
  95. /* we are hosed, they cannot be placed so that there is */
  96. /* no overlap anywhere. To minimize the damage just put*/
  97. /* the dialog in the lower left corner of the screen */
  98. rc.top = (int)iScreenHeight - iHeight;
  99. rc.left = (int)iScreenWidth - iWidth;
  100. }
  101. /* make any adjustments necessary to keep it on the screen */
  102. if (rc.left < 0) rc.left = 0;
  103. else if ((UINT)(rc.left + iWidth) > (UINT)iScreenWidth)
  104. rc.left = (int)(iScreenWidth - iWidth);
  105. if (rc.top < 0) rc.top = 0;
  106. else if ((UINT)(rc.top + iHeight) > (UINT)iScreenHeight)
  107. rc.top = (int)iScreenHeight - iHeight;
  108. SetWindowPos(hWndDlg, NULL, rc.left, rc.top, 0, 0,
  109. SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  110. return 1;
  111. } // if the windows overlap by default
  112. return 0;
  113. }
  114. //
  115. // GetFreeDiskSpace: Function to Measure Available Disk Space
  116. //
  117. static long GetFreeDiskSpaceInKB(LPTSTR pFile)
  118. {
  119. DWORD dwFreeClusters, dwBytesPerSector, dwSectorsPerCluster, dwClusters;
  120. TCHAR RootName[MAX_PATH];
  121. LPTSTR ptmp; //required arg
  122. // need to find path for root directory on drive containing
  123. // this file.
  124. GetFullPathName(pFile, sizeof(RootName)/sizeof(RootName[0]), RootName, &ptmp);
  125. // truncate this to the name of the root directory (god how tedious)
  126. if ((RootName[0] == TEXT('\\')) && (RootName[1] == TEXT('\\'))) {
  127. // path begins with \\server\share\path so skip the first
  128. // three backslashes
  129. ptmp = &RootName[2];
  130. while (*ptmp && (*ptmp != TEXT('\\'))) {
  131. ptmp++;
  132. }
  133. if (*ptmp) {
  134. // advance past the third backslash
  135. ptmp++;
  136. }
  137. } else {
  138. // path must be drv:\path
  139. ptmp = RootName;
  140. }
  141. // find next backslash and put a null after it
  142. while (*ptmp && (*ptmp != TEXT('\\'))) {
  143. ptmp++;
  144. }
  145. // found a backslash ?
  146. if (*ptmp) {
  147. // skip it and insert null
  148. ptmp++;
  149. *ptmp = TEXT('\0');
  150. }
  151. if (!GetDiskFreeSpace(RootName,
  152. &dwSectorsPerCluster,
  153. &dwBytesPerSector,
  154. &dwFreeClusters,
  155. &dwClusters)) {
  156. MessageBoxID(IDS_ERR_MEASUREFREEDISK, MB_OK | MB_ICONINFORMATION);
  157. return (-1);
  158. }
  159. return(MulDiv (dwSectorsPerCluster * dwBytesPerSector,
  160. dwFreeClusters,
  161. 1024));
  162. }
  163. //
  164. // CountMCIDevices: Function to Find the Number of MCI Devices of a Type
  165. //
  166. static int CountMCIDevices(UINT wType)
  167. {
  168. int nTotal = 0 ;
  169. DWORD dwCount ;
  170. MCI_SYSINFO_PARMS mciSIP ;
  171. mciSIP.dwCallback = 0 ;
  172. mciSIP.lpstrReturn = (LPTSTR)(LPVOID) &dwCount ;
  173. mciSIP.dwRetSize = sizeof(DWORD) ;
  174. mciSIP.wDeviceType = wType ;
  175. // Use an MCI command to get the info
  176. if (! mciSendCommand(0, MCI_SYSINFO, MCI_SYSINFO_QUANTITY,
  177. (DWORD_PTR)(LPVOID) &mciSIP))
  178. nTotal = (int) *((LPDWORD) mciSIP.lpstrReturn) ;
  179. return nTotal ;
  180. }
  181. /* lMicroSec = StringRateToMicroSec(szRate)
  182. *
  183. * Convert <szRate> (e.g. "3.75" representing 3.75 frames per second)
  184. * to microseconds (e.g. 266667L microseconds per frame).
  185. *
  186. * If the rate is close to zero or negative, then 0L is returned.
  187. */
  188. DWORD StringRateToMicroSec(PSTR szRate)
  189. {
  190. double dRate;
  191. dRate = atof(szRate);
  192. if (dRate < 0.0001) {
  193. return 0L;
  194. } else {
  195. return (DWORD) /*floor*/((1e6 / dRate) + 0.5);
  196. }
  197. }
  198. /* ach = MicroSecToStringRate(achRate, lMicroSec)
  199. *
  200. * Convert <lMicroSec> (e.g. 266667L microseconds per frame) to a
  201. * string rate (e.g. "3.75" representing 3.75 frames per second).
  202. * Returns <achRate>.
  203. */
  204. PSTR MicroSecToStringRate(PSTR achRate, DWORD dwMicroSec)
  205. {
  206. sprintf(achRate, "%.3f",
  207. (dwMicroSec == 0L) ? 0.0 : (1e6 / (double) dwMicroSec));
  208. return achRate;
  209. }
  210. /*
  211. * update the text of an edit field based on a comarrow up or down change
  212. * - write the text in N.NNN format (truncated to an integer)
  213. */
  214. LONG FAR PASCAL
  215. MilliSecVarArrowEditChange(
  216. HWND hwndEdit,
  217. UINT uCode,
  218. LONG lMin,
  219. LONG lMax,
  220. UINT uInc
  221. )
  222. {
  223. TCHAR achTemp[32];
  224. LONG l;
  225. GetWindowText(hwndEdit, achTemp, sizeof(achTemp));
  226. l = atol(achTemp);
  227. if(uCode == SB_LINEUP ) {
  228. if(l + (long)uInc <= lMax ) {
  229. l += uInc;
  230. wsprintf(achTemp, "%ld.000", l );
  231. SetWindowText(hwndEdit, achTemp );
  232. } else {
  233. MessageBeep( 0 );
  234. }
  235. } else if (uCode == SB_LINEDOWN ) {
  236. if( l-(long)uInc >= lMin ) {
  237. l -= uInc;
  238. wsprintf( achTemp, "%ld.000", l );
  239. SetWindowText( hwndEdit, achTemp );
  240. } else {
  241. MessageBeep( 0 );
  242. }
  243. }
  244. return( l );
  245. }
  246. BOOL MCIGetDeviceNameAndIndex (HWND hwnd, LPINT lpnIndex, LPTSTR lpName)
  247. {
  248. HWND hwndCB;
  249. TCHAR buf[160];
  250. TCHAR *cp;
  251. hwndCB = GetDlgItem( hwnd, IDD_MCI_SOURCE );
  252. *lpnIndex = (int)SendMessage( hwndCB, CB_GETCURSEL, 0, 0L);
  253. SendMessage( hwndCB, CB_GETLBTEXT, *lpnIndex,
  254. (LONG_PTR)(LPTSTR) buf );
  255. // Point cp to the system name
  256. for (cp = buf + lstrlen(buf); cp > buf; cp--) {
  257. if (*cp == ' ' && *(cp-1) == ',') {
  258. cp++;
  259. break;
  260. }
  261. }
  262. lstrcpy (lpName, cp);
  263. return TRUE;
  264. }
  265. /*--------------------------------------------------------------+
  266. | TimeMSToHMSString() - change milliseconds into a time string |
  267. +--------------------------------------------------------------*/
  268. void FAR PASCAL TimeMSToHMSString (DWORD dwMS, LPTSTR lpTime)
  269. {
  270. DWORD dwTotalSecs;
  271. LONG lHundredths;
  272. WORD wSecs;
  273. WORD wMins;
  274. WORD wHours;
  275. /* convert to number of seconds */
  276. dwTotalSecs = dwMS / 1000;
  277. /* keep the remainder part */
  278. lHundredths = (dwMS - (dwTotalSecs * 1000)) / 10;
  279. /* break down into other components */
  280. wHours = (WORD)(dwTotalSecs / 3600); // get # Hours
  281. dwTotalSecs -= (wHours * 3600);
  282. wMins = (WORD)(dwTotalSecs / 60); // get # Mins
  283. dwTotalSecs -= (wMins * 60);
  284. wSecs = (WORD)dwTotalSecs; // what's left is # seconds
  285. /* build the string */
  286. wsprintf((TCHAR far *)lpTime, "%02u:%02u:%02u.%02lu", wHours, wMins,
  287. wSecs, lHundredths);
  288. }
  289. /*--------------------------------------------------------------+
  290. | TimeHMSStringToMS() - change Time string to milliseconds |
  291. | returns dwMilliseconds or -1 if error |
  292. +--------------------------------------------------------------*/
  293. LONG NEAR PASCAL TimeHMSStringToMS (LPTSTR lpsz)
  294. {
  295. TCHAR achTime[12]; // buffer for time string (input)
  296. DWORD dwMSecs; // total MSecs for this thing */
  297. TCHAR *pDelim; // pointer to next delimeter
  298. TCHAR *p; // general pointer
  299. DWORD dwHours = 0; // # of hours
  300. DWORD dwMins = 0; // # of minutes
  301. DWORD dwSecs = 0; // # of seconds
  302. UINT wHundredths = 0; // # hundredths
  303. _tcsncpy(achTime, lpsz, sizeof (achTime));
  304. if (achTime[0] == '\0')
  305. return -1; // bad TCHAR so error out
  306. /* rip through the whole string and look for illegal TCHARs */
  307. for (p = achTime; *p ; p++){
  308. if (!_istdigit(*p) && *p != '.' && *p != ':')
  309. return -1; // bad char so error out
  310. }
  311. /* go find the hundredths portion if it exists */
  312. pDelim = _tcschr(achTime, '.');
  313. if (pDelim && *pDelim){
  314. p = _tcsrchr(achTime, '.');
  315. if (pDelim != p) {
  316. return -1; // string has > 1 '.', return error
  317. }
  318. p++; // move up past delim
  319. if (_tcslen(p) > 2) {
  320. *(p+2) = '\0'; // knock off all but hundredths
  321. }
  322. wHundredths = _ttoi(p); // get the fractional part
  323. *pDelim = '\0'; // null out this terminator
  324. }
  325. /* try and find seconds */
  326. pDelim = _tcsrchr(achTime, ':'); // get last ':'
  327. if (pDelim) {
  328. p = (pDelim+1);
  329. } else {
  330. // no colon - assume just seconds in string
  331. p = achTime;
  332. }
  333. dwSecs = _ttoi(p);
  334. if (pDelim) {
  335. *pDelim = '\0';
  336. /* go and get the minutes part */
  337. pDelim = _tcsrchr(achTime, ':');
  338. if (pDelim) {
  339. p = (pDelim + 1);
  340. } else {
  341. // no more colons - assume remainder is just minutes
  342. p = achTime;
  343. }
  344. dwMins = _ttoi(p);
  345. if (pDelim) {
  346. *pDelim = '\0';
  347. /* get the hours */
  348. p = achTime;
  349. dwHours = _ttoi(p);
  350. }
  351. }
  352. /* now we've got the hours, minutes, seconds and any */
  353. /* fractional part. Time to build up the total time */
  354. dwSecs += (dwHours * 3600); // add in hours worth of seconds
  355. dwSecs += (dwMins * 60); // add in minutes worth of seconds
  356. dwMSecs = (dwSecs * 1000L);
  357. dwMSecs += (wHundredths * 10L);
  358. /* now we've got the total number of milliseconds */
  359. return dwMSecs;
  360. }
  361. /*
  362. * MCIDeviceClose
  363. * This routine closes the open MCI device.
  364. */
  365. void MCIDeviceClose (void)
  366. {
  367. mciSendString( "close mciframes", NULL, 0, NULL );
  368. }
  369. /*
  370. * MCIDeviceOpen
  371. * This routine opens the mci device for use, and sets the
  372. * time format to milliseconds.
  373. * Return FALSE on error;
  374. */
  375. BOOL MCIDeviceOpen (LPTSTR lpDevName)
  376. {
  377. TCHAR ach[160];
  378. DWORD dwMCIError;
  379. wsprintf( ach, "open %s shareable wait alias mciframes", (LPTSTR) lpDevName);
  380. dwMCIError = mciSendString( ach, NULL, 0, NULL );
  381. if( dwMCIError ) {
  382. return(FALSE);
  383. }
  384. dwMCIError = mciSendString( "set mciframes time format milliseconds",
  385. NULL, 0, NULL );
  386. if( dwMCIError ) {
  387. MCIDeviceClose();
  388. return(FALSE);
  389. }
  390. return ( TRUE );
  391. }
  392. /*
  393. * MCIDeviceGetPosition
  394. * Stores the current device position in milliseconds in lpdwPos.
  395. * Returns TRUE on success, FALSE if error.
  396. */
  397. BOOL FAR PASCAL MCIDeviceGetPosition (LPDWORD lpdwPos)
  398. {
  399. TCHAR ach[80];
  400. DWORD dwMCIError;
  401. dwMCIError = mciSendString( "status mciframes position wait",
  402. ach, sizeof(ach), NULL );
  403. if( dwMCIError ) {
  404. *lpdwPos = 0L;
  405. return FALSE;
  406. }
  407. *lpdwPos = _ttol( ach );
  408. return TRUE;
  409. }
  410. #ifndef USE_ACM
  411. // --- audio streaming ------------------------------------------------
  412. // the ShowLevel dialog streams data in from the input and
  413. // shows the current volume.
  414. // buffers into which sound data is recorded
  415. #define NUM_LEVEL_BUFFERS 2
  416. // the buffer size is calculated to be about 1/20 sec
  417. #define UPDATES_PER_SEC 20
  418. /*
  419. * we save all our data in one of these, and write a pointer to it
  420. * into the dialog DWL_USER field.
  421. */
  422. typedef struct _LevelStreamData {
  423. LPWAVEHDR alpWave[NUM_LEVEL_BUFFERS];
  424. PCMWAVEFORMAT FAR * pwf;
  425. HWAVEIN hwav;
  426. int buffersize;
  427. } LEVELSTREAMDATA, FAR * PLEVELSTREAMDATA;
  428. //open the wave-device in the given format, queue all the buffers and
  429. //start data streaming. Save the wavein device to the dialog DWL_USER window
  430. //data area so we can close it on dialog dismissal.
  431. BOOL
  432. OpenStream(HWND hDlg, PCMWAVEFORMAT FAR * pwf)
  433. {
  434. PLEVELSTREAMDATA pInfo;
  435. int i;
  436. pInfo = (PLEVELSTREAMDATA) GlobalLock(GlobalAlloc(GHND, sizeof(LEVELSTREAMDATA)));
  437. if (pInfo == NULL) {
  438. return(FALSE);
  439. }
  440. // complete remaining areas of wf
  441. pwf->wf.wFormatTag = WAVE_FORMAT_PCM;
  442. pwf->wf.nBlockAlign = pwf->wf.nChannels * pwf->wBitsPerSample / 8;
  443. pwf->wf.nAvgBytesPerSec = pwf->wf.nSamplesPerSec * pwf->wf.nBlockAlign;
  444. // save for later use
  445. pInfo->pwf = pwf;
  446. // buffer size a fixed fraction of a second
  447. pInfo->buffersize = pwf->wf.nAvgBytesPerSec/UPDATES_PER_SEC;
  448. pInfo->hwav = NULL;
  449. if (waveInOpen(
  450. &pInfo->hwav,
  451. WAVE_MAPPER,
  452. (LPWAVEFORMATEX)pwf,
  453. (DWORD) hDlg, // callback via MM_WIM_ messages to dialogproc
  454. 0,
  455. CALLBACK_WINDOW)) {
  456. SetWindowLong(hDlg, DWL_USER, 0);
  457. return(FALSE);
  458. }
  459. // store the info structure in the dialog, so that even if we fail
  460. // on this routine we will clean up correctly
  461. SetWindowLong(hDlg, DWL_USER, (long) pInfo);
  462. // set all the wave headers to null (for cleanup if error)
  463. for (i = 0; i < NUM_LEVEL_BUFFERS; i++) {
  464. pInfo->alpWave[i] = NULL;
  465. }
  466. // alloc, prepare and add all the buffers
  467. for (i = 0; i < NUM_LEVEL_BUFFERS; i++) {
  468. pInfo->alpWave[i] = GlobalLock(GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,
  469. sizeof(WAVEHDR) + pInfo->buffersize));
  470. if (pInfo->alpWave[i] == NULL) {
  471. return(FALSE);
  472. }
  473. pInfo->alpWave[i]->lpData = (LPBYTE) (pInfo->alpWave[i] + 1);
  474. pInfo->alpWave[i]->dwBufferLength = pInfo->buffersize;
  475. pInfo->alpWave[i]->dwBytesRecorded = 0;
  476. pInfo->alpWave[i]->dwUser = 0;
  477. pInfo->alpWave[i]->dwFlags = 0;
  478. pInfo->alpWave[i]->dwLoops = 0;
  479. if (waveInPrepareHeader(pInfo->hwav, pInfo->alpWave[i], sizeof(WAVEHDR))) {
  480. return(FALSE);
  481. }
  482. if (waveInAddBuffer(pInfo->hwav, pInfo->alpWave[i], sizeof(WAVEHDR))) {
  483. return(FALSE);
  484. }
  485. }
  486. waveInStart(pInfo->hwav);
  487. return(TRUE);
  488. }
  489. // terminate the data streaming on a wavein device associated with a
  490. // dialog, and clean up the buffers allocated
  491. void
  492. CloseStream(HWND hDlg)
  493. {
  494. PLEVELSTREAMDATA pInfo;
  495. int i;
  496. // pick up our info from the dialog
  497. pInfo = (PLEVELSTREAMDATA) GetWindowLong(hDlg, DWL_USER);
  498. if ((pInfo == NULL) || (pInfo->hwav == NULL)) {
  499. return;
  500. }
  501. // stop streaming data
  502. waveInStop(pInfo->hwav);
  503. // release all buffers
  504. waveInReset(pInfo->hwav);
  505. // unlock and free buffers
  506. for (i = 0; i < NUM_LEVEL_BUFFERS; i++) {
  507. if (pInfo->alpWave[i]) {
  508. waveInUnprepareHeader(pInfo->hwav, pInfo->alpWave[i], sizeof(WAVEHDR));
  509. GlobalFree(GlobalHandle(pInfo->alpWave[i]));
  510. pInfo->alpWave[i] = NULL;
  511. }
  512. }
  513. waveInClose(pInfo->hwav);
  514. GlobalFree(GlobalHandle(pInfo));
  515. SetWindowLong(hDlg, DWL_USER, 0);
  516. }
  517. // we have received a block of data. work out the level(s) and send to
  518. // the appropriate control on the dialog, and then requeue the buffer.
  519. // return FALSE if any error occurs, otherwise TRUE
  520. BOOL
  521. StreamData(HWND hDlg, HWAVEIN hwav, LPWAVEHDR pHdr)
  522. {
  523. PLEVELSTREAMDATA pInfo;
  524. int n = 0;
  525. int LevelLeft = 0, LevelRight = 0;
  526. int i, l;
  527. // pick up our info from the dialog
  528. pInfo = (PLEVELSTREAMDATA) GetWindowLong(hDlg, DWL_USER);
  529. if ((pInfo == NULL) || (pInfo->hwav != hwav)) {
  530. return FALSE;
  531. }
  532. // go through all samples in buffer looking for maximum absolute level
  533. while (n < pInfo->buffersize) {
  534. /*
  535. * volumes go above and below the mean level - we are
  536. * interested in the absolute volume
  537. * 8 bit samples are in the range 0..255
  538. * 16-bit samples are in the range -32768..+32767
  539. */
  540. // skip the first byte if 16-bit
  541. // and adjust to be in range -127..+128
  542. if (pInfo->pwf->wBitsPerSample == 16) {
  543. n++;
  544. i = (int) (signed char) pHdr->lpData[n];
  545. } else {
  546. i = (int) ((unsigned char) pHdr->lpData[n]) - 128;
  547. }
  548. // skip past the byte we've picked up
  549. n++;
  550. // take absolute volume level
  551. if (i < 0) {
  552. i = -i;
  553. }
  554. // convert to percentage
  555. l = (i*100) / 128;
  556. // compare against current max
  557. if (LevelLeft < l) {
  558. LevelLeft = l;
  559. }
  560. // if stereo, repeat for right channel
  561. if (pInfo->pwf->wf.nChannels == 2) {
  562. // skip the first byte if 16-bit
  563. if (pInfo->pwf->wBitsPerSample == 16) {
  564. n++;
  565. i = (int) (signed char) pHdr->lpData[n];
  566. } else {
  567. i = (int) ((unsigned char) pHdr->lpData[n]) - 128;
  568. }
  569. // skip past the byte we've picked up
  570. n++;
  571. // take absolute volume level
  572. if (i < 0) {
  573. i = -i;
  574. }
  575. // convert to percentage
  576. l = (i*100) / 128;
  577. // compare against current max
  578. if (LevelRight < l) {
  579. LevelRight = l;
  580. }
  581. }
  582. }
  583. // put the buffer back on the queue
  584. if (waveInAddBuffer(pInfo->hwav, pHdr, sizeof(WAVEHDR))) {
  585. return(FALSE);
  586. }
  587. // send new level to dialog control
  588. SendDlgItemMessage(hDlg, IDRL_LEVEL1, WMRL_SETLEVEL, 0, LevelLeft);
  589. if (pInfo->pwf->wf.nChannels == 2) {
  590. SendDlgItemMessage(hDlg, IDRL_LEVEL2, WMRL_SETLEVEL, 0, LevelRight);
  591. }
  592. return(TRUE);
  593. }
  594. #endif // ! USE_ACM
  595. // --- dialog procs -----------------------------------------------------
  596. //
  597. // AboutProc: About Dialog Box Procedure
  598. //
  599. LRESULT FAR PASCAL AboutProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  600. {
  601. switch (Message) {
  602. case WM_INITDIALOG :
  603. return TRUE ;
  604. case WM_COMMAND :
  605. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  606. case IDOK :
  607. EndDialog(hDlg, TRUE) ;
  608. return TRUE ;
  609. case IDCANCEL :
  610. EndDialog(hDlg, FALSE) ;
  611. return TRUE ;
  612. }
  613. break ;
  614. }
  615. return FALSE ;
  616. }
  617. #ifndef USE_ACM
  618. /*
  619. * dialog proc for IDD_RECLVLMONO and IDD_RECLVLSTEREO - show current
  620. * volume level
  621. */
  622. LRESULT FAR PASCAL
  623. ShowLevelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  624. {
  625. switch(message) {
  626. case WM_INITDIALOG:
  627. if (!OpenStream(hDlg, (PCMWAVEFORMAT FAR *) lParam)) {
  628. MessageBoxID(IDS_ERR_ACCESS_SOUNDDRIVER, MB_OK|MB_ICONSTOP);
  629. EndDialog(hDlg, FALSE);
  630. }
  631. return(TRUE);
  632. case WM_COMMAND:
  633. switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  634. case IDOK:
  635. case IDCANCEL:
  636. CloseStream(hDlg);
  637. EndDialog(hDlg, TRUE);
  638. return(TRUE);
  639. }
  640. break;
  641. case MM_WIM_DATA:
  642. if (!StreamData(hDlg, (HWAVEIN)wParam, (LPWAVEHDR)lParam)) {
  643. MessageBoxID(IDS_ERR_ACCESS_SOUNDDRIVER, MB_OK|MB_ICONSTOP);
  644. CloseStream(hDlg);
  645. EndDialog(hDlg, FALSE);
  646. }
  647. return(TRUE);
  648. }
  649. return FALSE;
  650. }
  651. //
  652. // AudioFormatProc: Audio Format Setting Dialog Box Procedure
  653. //
  654. LRESULT FAR PASCAL AudioFormatProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  655. {
  656. static int nChannels ;
  657. static UINT wSample ;
  658. static DWORD dwFrequency ;
  659. switch (Message) {
  660. case WM_INITDIALOG :
  661. nChannels = IDD_ChannelIDs + glpwfex->nChannels ;
  662. CheckRadioButton(hDlg, IDD_ChannelMono, IDD_ChannelStereo, nChannels) ;
  663. wSample = IDD_SampleIDs + glpwfex->wBitsPerSample / 8 ;
  664. CheckRadioButton(hDlg, IDD_Sample8Bit, IDD_Sample16Bit, wSample) ;
  665. dwFrequency = IDD_FreqIDs + glpwfex->nSamplesPerSec / 11025 ;
  666. CheckRadioButton(hDlg, IDD_Freq11kHz, IDD_Freq44kHz, (UINT)dwFrequency) ;
  667. return TRUE ;
  668. case WM_COMMAND :
  669. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  670. case IDD_SetLevel:
  671. {
  672. // get the current data into a PCMWAVEFORMAT struct,
  673. // and run the ShowLevel dialog
  674. PCMWAVEFORMAT wf;
  675. UINT dlgid;
  676. if (IsDlgButtonChecked(hDlg, IDD_ChannelMono)) {
  677. wf.wf.nChannels = 1;
  678. dlgid = IDD_RECLVLMONO;
  679. } else {
  680. wf.wf.nChannels = 2;
  681. dlgid = IDD_RECLVLSTEREO;
  682. }
  683. if (IsDlgButtonChecked(hDlg, IDD_Sample8Bit)) {
  684. wf.wBitsPerSample = 8;
  685. } else {
  686. wf.wBitsPerSample = 16;
  687. }
  688. if (IsDlgButtonChecked(hDlg, IDD_Freq11kHz)) {
  689. wf.wf.nSamplesPerSec = 11025 ;
  690. } else if (IsDlgButtonChecked(hDlg, IDD_Freq22kHz)) {
  691. wf.wf.nSamplesPerSec = 22050 ;
  692. } else {
  693. wf.wf.nSamplesPerSec = 44100 ;
  694. }
  695. DoDialog(
  696. hDlg,
  697. dlgid,
  698. ShowLevelProc,
  699. (LPARAM) &wf);
  700. break;
  701. }
  702. case IDOK :
  703. if (IsDlgButtonChecked(hDlg, IDD_ChannelMono))
  704. nChannels = 1 ;
  705. else
  706. if (IsDlgButtonChecked(hDlg, IDD_ChannelStereo))
  707. nChannels = 2 ;
  708. else {
  709. MessageBeep(MB_ICONEXCLAMATION) ;
  710. return FALSE ;
  711. }
  712. if (IsDlgButtonChecked(hDlg, IDD_Sample8Bit))
  713. wSample = 8 ;
  714. else
  715. if (IsDlgButtonChecked(hDlg, IDD_Sample16Bit))
  716. wSample = 16 ;
  717. else {
  718. MessageBeep(MB_ICONEXCLAMATION) ;
  719. return FALSE ;
  720. }
  721. if (IsDlgButtonChecked(hDlg, IDD_Freq11kHz))
  722. dwFrequency = 11025 ;
  723. else
  724. if (IsDlgButtonChecked(hDlg, IDD_Freq22kHz))
  725. dwFrequency = 22050 ;
  726. else
  727. if (IsDlgButtonChecked(hDlg, IDD_Freq44kHz))
  728. dwFrequency = 44100 ;
  729. else {
  730. MessageBeep(MB_ICONEXCLAMATION) ;
  731. return FALSE ;
  732. }
  733. // All the entries verfied OK -- save them now
  734. glpwfex->nChannels = nChannels ;
  735. glpwfex->wBitsPerSample = wSample ;
  736. glpwfex->nSamplesPerSec = dwFrequency ;
  737. glpwfex->nBlockAlign = glpwfex->nChannels * (glpwfex->wBitsPerSample / 8) ;
  738. glpwfex->nAvgBytesPerSec = (long) glpwfex->nSamplesPerSec *
  739. glpwfex->nBlockAlign ;
  740. glpwfex->cbSize = 0 ;
  741. glpwfex->wFormatTag = WAVE_FORMAT_PCM ;
  742. EndDialog(hDlg, TRUE) ;
  743. return TRUE ;
  744. case IDCANCEL :
  745. EndDialog(hDlg, FALSE) ;
  746. return TRUE ;
  747. }
  748. break ;
  749. }
  750. return FALSE ;
  751. }
  752. #endif // ! USE_ACM
  753. //
  754. // AllocCapFileProc: Capture file Space Allocation Dialog Box Procedure
  755. //
  756. LRESULT FAR PASCAL AllocCapFileProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  757. {
  758. static int nFreeMBs = 0 ;
  759. switch (Message) {
  760. case WM_INITDIALOG :
  761. {
  762. int fh ;
  763. long lFileSize = 0 ;
  764. long lFreeSpaceInKB ;
  765. TCHAR achCapFile[_MAX_PATH] ;
  766. // Get current capture file name and measure its size
  767. capFileGetCaptureFile(ghWndCap, achCapFile, sizeof(achCapFile) / sizeof(TCHAR)) ;
  768. if ((fh = _open(achCapFile, _O_RDONLY)) != -1) {
  769. if ((lFileSize = _lseek(fh, 0L, SEEK_END)) == -1L) {
  770. MessageBoxID(IDS_ERR_SIZECAPFILE,
  771. #ifdef BIDI
  772. MB_RTL_READING |
  773. #endif
  774. MB_OK | MB_ICONEXCLAMATION) ;
  775. lFileSize = 0 ;
  776. }
  777. _close(fh) ;
  778. }
  779. // Get free disk space and add current capture file size to that.
  780. // Convert the available space to MBs.
  781. if ((lFreeSpaceInKB = GetFreeDiskSpaceInKB(achCapFile)) != -1L) {
  782. lFreeSpaceInKB += lFileSize / 1024 ;
  783. nFreeMBs = lFreeSpaceInKB / 1024 ;
  784. SetDlgItemInt(hDlg, IDD_SetCapFileFree, nFreeMBs, TRUE) ;
  785. } else {
  786. EnableWindow(GetDlgItem(hDlg, IDD_SetCapFileFree), FALSE);
  787. }
  788. gwCapFileSize = (WORD) (lFileSize / ONEMEG);
  789. SetDlgItemInt(hDlg, IDD_SetCapFileSize, gwCapFileSize, TRUE) ;
  790. return TRUE ;
  791. }
  792. case WM_COMMAND :
  793. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  794. case IDOK :
  795. {
  796. int iCapFileSize ;
  797. iCapFileSize = (int) GetDlgItemInt(hDlg, IDD_SetCapFileSize, NULL, TRUE) ;
  798. if (iCapFileSize <= 0 || iCapFileSize > nFreeMBs) {
  799. // You are asking for more than we have !! Sorry, ...
  800. SetDlgItemInt(hDlg, IDD_SetCapFileSize, iCapFileSize, TRUE) ;
  801. SetFocus(GetDlgItem(hDlg, IDD_SetCapFileSize)) ;
  802. MessageBeep(MB_ICONEXCLAMATION) ;
  803. return FALSE ;
  804. }
  805. gwCapFileSize = (WORD) iCapFileSize ;
  806. EndDialog(hDlg, TRUE) ;
  807. return TRUE ;
  808. }
  809. case IDCANCEL :
  810. EndDialog(hDlg, FALSE) ;
  811. return TRUE ;
  812. case IDD_SetCapFileSize:
  813. {
  814. long l;
  815. BOOL bchanged;
  816. TCHAR achBuffer[21];
  817. // check that entered size is a valid number
  818. GetDlgItemText(hDlg, IDD_SetCapFileSize, achBuffer, sizeof(achBuffer));
  819. l = atol(achBuffer);
  820. bchanged = FALSE;
  821. if (l < 1) {
  822. l = 1;
  823. bchanged = TRUE;
  824. } else if (l > nFreeMBs) {
  825. l = nFreeMBs;
  826. bchanged = TRUE;
  827. } else {
  828. // make sure there are no non-digit chars
  829. // atol() will ignore trailing non-digit characters
  830. int c = 0;
  831. while (achBuffer[c]) {
  832. if (IsCharAlpha(achBuffer[c]) ||
  833. !IsCharAlphaNumeric(achBuffer[c])) {
  834. // string contains non-digit chars - reset
  835. l = 1;
  836. bchanged = TRUE;
  837. break;
  838. }
  839. c++;
  840. }
  841. }
  842. if (bchanged) {
  843. wsprintf(achBuffer, "%ld", l);
  844. SetDlgItemText(hDlg, IDD_SetCapFileSize, achBuffer);
  845. }
  846. break;
  847. }
  848. }
  849. break ;
  850. }
  851. return FALSE ;
  852. }
  853. #if 0
  854. //
  855. // MakePaletteProc: Palette Details Dialog Box Procedure
  856. //
  857. BOOL CALLBACK MakePaletteProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  858. {
  859. switch (Message) {
  860. case WM_INITDIALOG :
  861. SetDlgItemInt(hDlg, IDD_MakePalColors, gwPalColors, FALSE) ;
  862. SetDlgItemInt(hDlg, IDD_MakePalFrames, gwPalFrames, FALSE) ;
  863. return TRUE ;
  864. case WM_COMMAND :
  865. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  866. case IDOK :
  867. {
  868. int iColors ;
  869. int iFrames ;
  870. iColors = (int) GetDlgItemInt(hDlg, IDD_MakePalColors, NULL, TRUE) ;
  871. if (! (iColors > 0 && iColors <= 236 || iColors == 256)) {
  872. // invalid number of palette colors
  873. SetDlgItemInt(hDlg, IDD_MakePalColors, iColors, TRUE) ;
  874. SetFocus(GetDlgItem(hDlg, IDD_MakePalColors)) ;
  875. MessageBeep(MB_ICONEXCLAMATION) ;
  876. return FALSE ;
  877. }
  878. iFrames = (int) GetDlgItemInt(hDlg, IDD_MakePalFrames, NULL, TRUE) ;
  879. if (iFrames <= 0 || iFrames > 10000) {
  880. // no frame or way t-o-o many frames !!!
  881. SetDlgItemInt(hDlg, IDD_MakePalFrames, iFrames, TRUE) ;
  882. SetFocus(GetDlgItem(hDlg, IDD_MakePalFrames)) ;
  883. MessageBeep(MB_ICONEXCLAMATION) ;
  884. return FALSE ;
  885. }
  886. gwPalColors = iColors ;
  887. gwPalFrames = iFrames ;
  888. EndDialog(hDlg, TRUE) ;
  889. return TRUE ;
  890. }
  891. case IDCANCEL :
  892. EndDialog(hDlg, FALSE) ;
  893. return TRUE ;
  894. }
  895. break ;
  896. }
  897. return FALSE ;
  898. }
  899. #endif
  900. #define CAPPAL_TIMER 902
  901. #define CAPTIMER_DELAY 100 // get timers as fast as possible
  902. //
  903. // MakePaletteProc: Palette Details Dialog Box Procedure
  904. //
  905. static int siNumColors = 256;
  906. LRESULT CALLBACK MakePaletteProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  907. {
  908. static UINT_PTR shTimer;
  909. static int siNumFrames;
  910. UINT w;
  911. TCHAR ach[40];
  912. TCHAR achFormat[40];
  913. int i, k;
  914. switch(msg) {
  915. case WM_INITDIALOG:
  916. siNumFrames = 0;
  917. SetDlgItemInt(hwnd, IDD_MakePalColors, siNumColors, FALSE);
  918. SmartWindowPosition (hwnd, ghWndCap);
  919. return TRUE;
  920. break;
  921. case WM_VSCROLL:
  922. /* now handle the scroll */
  923. i = GetDlgItemInt(hwnd, IDD_MakePalColors, NULL, FALSE);
  924. ArrowEditChange(GetDlgItem(hwnd, IDD_MakePalColors),
  925. GET_WM_VSCROLL_CODE(wParam, lParam), 2, 256);
  926. k = GetDlgItemInt(hwnd, IDD_MakePalColors, NULL, FALSE);
  927. // Jump over the range 237 to 255
  928. if (k > 236 && k < 256) {
  929. if (k > i)
  930. w = 256;
  931. else
  932. w = 236;
  933. SetDlgItemInt (hwnd, IDD_MakePalColors, w, TRUE);
  934. }
  935. break;
  936. case WM_COMMAND:
  937. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  938. case IDCANCEL:
  939. if (siNumFrames) {
  940. // The following finishes building the new palette
  941. capPaletteManual (ghWndCap, FALSE, siNumColors);
  942. }
  943. if (shTimer){
  944. KillTimer(hwnd, CAPPAL_TIMER);
  945. shTimer = 0;
  946. }
  947. siNumColors = GetDlgItemInt(hwnd, IDD_MakePalColors, (BOOL FAR *)ach, FALSE);
  948. siNumColors = max (2, min (256, siNumColors));
  949. EndDialog(hwnd, siNumFrames);
  950. break;
  951. case IDD_MakePalStart:
  952. /* see if we are in START or STOP mode at */
  953. /* this time and handle each one. */
  954. SetFocus (GetDlgItem (hwnd, IDD_MakePalStart));
  955. if (!siNumFrames){
  956. /* this is the first frame, change the CANCEL */
  957. /* button to CLOSE */
  958. LoadString(ghInstApp, IDS_CAPPAL_CLOSE, ach, sizeof(ach));
  959. SetDlgItemText(hwnd, IDCANCEL, ach);
  960. }
  961. if (!shTimer) {
  962. shTimer = SetTimer(hwnd, CAPPAL_TIMER, CAPTIMER_DELAY, NULL);
  963. if (shTimer == 0) {
  964. //!!!error message here.
  965. MessageBeep(0);
  966. return TRUE;
  967. }
  968. /* button said START, let's set up to */
  969. /* do continuous capture. This involves*/
  970. /* 1 - disabling FRAME button */
  971. /* 2 - turning myself to STOP button */
  972. /* 3 - setting up frame timer */
  973. EnableWindow(GetDlgItem(hwnd, IDD_MakePalSingleFrame), FALSE);
  974. LoadString(ghInstApp, IDS_CAPPAL_STOP, ach, sizeof(ach));
  975. SetDlgItemText(hwnd, IDD_MakePalStart, ach);
  976. } else {
  977. /* button said STOP, turn things around */
  978. /* by: */
  979. /* 1 - killing off timers *
  980. /* 2 - turning back into START button */
  981. /* 3 - re-enabling FRAME button */
  982. // "&Start"
  983. LoadString(ghInstApp, IDS_CAPPAL_START, ach, sizeof(ach));
  984. SetDlgItemText(hwnd, IDD_MakePalStart, ach);
  985. EnableWindow(GetDlgItem(hwnd, IDD_MakePalSingleFrame), TRUE);
  986. KillTimer(hwnd, CAPPAL_TIMER);
  987. shTimer = 0;
  988. }
  989. return TRUE;
  990. break;
  991. case IDD_MakePalSingleFrame:
  992. if (!siNumFrames){
  993. /* this is the first frame, change the CANCEL */
  994. /* button to CLOSE */
  995. LoadString(ghInstApp, IDS_CAPPAL_CLOSE, ach, sizeof(ach));
  996. SetDlgItemText(hwnd, IDCANCEL, ach);
  997. siNumColors = GetDlgItemInt(hwnd, IDD_MakePalColors, (BOOL FAR *)ach, FALSE);
  998. siNumColors = max (2, min (256, siNumColors));
  999. }
  1000. // Get the palette for a single frame
  1001. capPaletteManual (ghWndCap, TRUE, siNumColors);
  1002. siNumFrames++;
  1003. LoadString(ghInstApp, IDS_CAPPAL_STATUS, achFormat, sizeof(achFormat));
  1004. wsprintf(ach, achFormat, siNumFrames);
  1005. SetDlgItemText(hwnd, IDD_MakePalNumFrames, ach);
  1006. return TRUE;
  1007. break;
  1008. case IDD_MakePalColors:
  1009. if (HIWORD (lParam) == EN_KILLFOCUS) {
  1010. w = GetDlgItemInt (hwnd, (UINT) wParam, NULL, FALSE);
  1011. if ( w < 2) {
  1012. MessageBeep (0);
  1013. SetDlgItemInt (hwnd, (UINT) wParam, 2, FALSE);
  1014. }
  1015. else if (w > 256) {
  1016. MessageBeep (0);
  1017. SetDlgItemInt (hwnd, (UINT) wParam, 256, FALSE);
  1018. }
  1019. }
  1020. return TRUE;
  1021. break;
  1022. default:
  1023. return FALSE;
  1024. } // switch(wParam) on WM_COMMAND
  1025. break;
  1026. case WM_TIMER:
  1027. if (wParam == CAPPAL_TIMER){
  1028. SendMessage(hwnd, WM_COMMAND, IDD_MakePalSingleFrame, 0L);
  1029. }
  1030. break;
  1031. default:
  1032. return FALSE;
  1033. } // switch(msg)
  1034. return FALSE;
  1035. }
  1036. //
  1037. // CapSetUpProc: Capture SetUp Details Dialog Box Procedure
  1038. //
  1039. LRESULT FAR PASCAL CapSetUpProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  1040. {
  1041. static TCHAR achBuffer[21] ;
  1042. UINT fValue;
  1043. switch (Message) {
  1044. case WM_INITDIALOG :
  1045. {
  1046. // Convert from MicroSecPerFrame to FPS -- that's easier !!
  1047. MicroSecToStringRate(achBuffer, gCapParms.dwRequestMicroSecPerFrame);
  1048. SetDlgItemText(hDlg, IDD_FrameRateData, achBuffer);
  1049. // If time limit isn't enabled, disable the time data part
  1050. CheckDlgButton(hDlg, IDD_TimeLimitFlag, (fValue = gCapParms.fLimitEnabled)) ;
  1051. EnableWindow(GetDlgItem(hDlg, IDD_SecondsText), fValue) ;
  1052. EnableWindow(GetDlgItem(hDlg, IDD_SecondsData), fValue) ;
  1053. EnableWindow(GetDlgItem(hDlg, IDD_SecondsArrow), fValue);
  1054. SetDlgItemInt(hDlg, IDD_SecondsData, gCapParms.wTimeLimit, FALSE) ;
  1055. // disable audio buttons if no audio hardware
  1056. {
  1057. CAPSTATUS cs;
  1058. capGetStatus(ghWndCap, &cs, sizeof(cs));
  1059. EnableWindow(GetDlgItem(hDlg, IDD_CapAudioFlag), cs.fAudioHardware);
  1060. EnableWindow(GetDlgItem(hDlg, IDD_AudioConfig), cs.fAudioHardware);
  1061. CheckDlgButton(hDlg, IDD_CapAudioFlag, gCapParms.fCaptureAudio);
  1062. }
  1063. /*
  1064. * Capture To Memory means allocate as many memory buffers
  1065. * as possible.
  1066. * Capture To Disk means only allocate enough buffers
  1067. * to get us through disk seeks and thermal recalibrations.
  1068. */
  1069. // The use of fUsingDOSMemory is now just a means of keeping
  1070. // track of whether using lots of buffers. We never actually
  1071. // allocate exclusively from memory under 1Meg.
  1072. CheckRadioButton(hDlg, IDD_CaptureToDisk, IDD_CaptureToMemory,
  1073. (gCapParms.fUsingDOSMemory)? IDD_CaptureToDisk : IDD_CaptureToMemory);
  1074. // Find out how many MCI devices can source video
  1075. if (CountMCIDevices(MCI_DEVTYPE_VCR) +
  1076. CountMCIDevices(MCI_DEVTYPE_VIDEODISC) == 0) {
  1077. // if no VCRs or Videodiscs, disable the controls
  1078. EnableWindow(GetDlgItem(hDlg, IDD_MCIControlFlag), FALSE);
  1079. EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), FALSE);
  1080. } else {
  1081. EnableWindow(GetDlgItem(hDlg, IDD_MCIControlFlag), TRUE);
  1082. // if MCI Control is selected, enable the setup button
  1083. CheckDlgButton(hDlg, IDD_MCIControlFlag,
  1084. gCapParms.fMCIControl);
  1085. EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), gCapParms.fMCIControl);
  1086. }
  1087. // place the dialog to avoid covering the capture window
  1088. SmartWindowPosition(hDlg, ghWndCap);
  1089. return TRUE ;
  1090. }
  1091. case WM_COMMAND :
  1092. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1093. case IDD_TimeLimitFlag :
  1094. // If this flag changes, en/dis-able time limit data part
  1095. fValue = IsDlgButtonChecked(hDlg, IDD_TimeLimitFlag) ;
  1096. EnableWindow(GetDlgItem(hDlg, IDD_SecondsText), fValue) ;
  1097. EnableWindow(GetDlgItem(hDlg, IDD_SecondsData), fValue) ;
  1098. EnableWindow(GetDlgItem(hDlg, IDD_SecondsArrow), fValue);
  1099. return TRUE ;
  1100. case IDD_MCIControlFlag :
  1101. // If this flag changes, en/dis-able MCI Setup button
  1102. fValue = IsDlgButtonChecked(hDlg, IDD_MCIControlFlag) ;
  1103. EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), fValue) ;
  1104. return TRUE ;
  1105. case IDD_CapAudioFlag:
  1106. fValue = IsDlgButtonChecked(hDlg, IDD_CapAudioFlag) ;
  1107. EnableWindow(GetDlgItem(hDlg, IDD_AudioConfig), fValue) ;
  1108. return TRUE ;
  1109. case IDD_FrameRateData:
  1110. // get the requested frame rate and check it against bounds
  1111. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1112. long l, new_l;
  1113. GetDlgItemText(hDlg, IDD_FrameRateData, achBuffer, sizeof(achBuffer));
  1114. new_l = l = StringRateToMicroSec(achBuffer);
  1115. // note that the MAX rate is SMALL! hence <max, >min
  1116. if (l == 0) {
  1117. new_l = DEF_CAPTURE_RATE;
  1118. } else if (l < MAX_CAPTURE_RATE) {
  1119. new_l = MAX_CAPTURE_RATE;
  1120. } else if (l > MIN_CAPTURE_RATE) {
  1121. new_l = MIN_CAPTURE_RATE;
  1122. }
  1123. if (l != new_l) {
  1124. MicroSecToStringRate(achBuffer, new_l);
  1125. SetDlgItemText(hDlg, IDD_FrameRateData, achBuffer);
  1126. }
  1127. }
  1128. break;
  1129. case IDD_SecondsData:
  1130. {
  1131. long l, new_l;
  1132. // get requested time limit and check validity
  1133. GetDlgItemText(hDlg, IDD_SecondsData, achBuffer, sizeof(achBuffer));
  1134. new_l = l = atol(achBuffer);
  1135. if (l < 1) {
  1136. new_l = 1;
  1137. } else if (l > 9999) {
  1138. new_l = 9999;
  1139. } else {
  1140. // make sure there are no non-digit chars
  1141. // atol() will ignore trailing non-digit characters
  1142. int c = 0;
  1143. while (achBuffer[c]) {
  1144. if (IsCharAlpha(achBuffer[c]) ||
  1145. !IsCharAlphaNumeric(achBuffer[c])) {
  1146. // string contains non-digit chars - reset
  1147. new_l = 1;
  1148. break;
  1149. }
  1150. c++;
  1151. }
  1152. }
  1153. if (new_l != l) {
  1154. wsprintf(achBuffer, "%ld", new_l);
  1155. SetDlgItemText(hDlg, IDD_SecondsData, achBuffer);
  1156. // select the changed text so that if you delete the
  1157. // '1' and then insert '10' you get 10 not 110
  1158. SendDlgItemMessage(hDlg, IDD_SecondsData,
  1159. EM_SETSEL, 0, -1);
  1160. }
  1161. break;
  1162. }
  1163. // show audio format setup dialog
  1164. case IDD_AudioConfig:
  1165. // rather than duplicate lots of code from the
  1166. // main vidcap winproc, lets just ask it to show the dlg...
  1167. SendMessage(ghWndMain, WM_COMMAND,
  1168. GET_WM_COMMAND_MPS(IDM_O_AUDIOFORMAT, NULL, 0));
  1169. break;
  1170. // show MCI step control dialog
  1171. case IDD_MCISetup:
  1172. DoDialog(hDlg, IDD_MCISETUP, MCISetupProc, 0);
  1173. break;
  1174. // show video format setup dialog
  1175. case IDD_VideoConfig:
  1176. // rather than duplicate lots of code from the
  1177. // main vidcap winproc, lets just ask it to show the dlg...
  1178. SendMessage(ghWndMain, WM_COMMAND,
  1179. GET_WM_COMMAND_MPS(IDM_O_VIDEOFORMAT, NULL, 0));
  1180. break;
  1181. // show the compressor selector dialog
  1182. case IDD_CompConfig:
  1183. capDlgVideoCompression(ghWndCap);
  1184. break;
  1185. case IDOK :
  1186. {
  1187. gCapParms.fCaptureAudio =
  1188. IsDlgButtonChecked(hDlg, IDD_CapAudioFlag) ;
  1189. gCapParms.fMCIControl =
  1190. IsDlgButtonChecked(hDlg, IDD_MCIControlFlag);
  1191. gCapParms.fLimitEnabled = IsDlgButtonChecked(hDlg, IDD_TimeLimitFlag) ;
  1192. GetDlgItemText(hDlg, IDD_FrameRateData, achBuffer, sizeof(achBuffer));
  1193. gCapParms.dwRequestMicroSecPerFrame = StringRateToMicroSec(achBuffer);
  1194. if (gCapParms.dwRequestMicroSecPerFrame == 0) {
  1195. gCapParms.dwRequestMicroSecPerFrame = DEF_CAPTURE_RATE;
  1196. }
  1197. GetDlgItemText(hDlg, IDD_SecondsData, achBuffer, sizeof(achBuffer));
  1198. if (gCapParms.fLimitEnabled) {
  1199. gCapParms.wTimeLimit = (UINT) atol(achBuffer);
  1200. }
  1201. // fUsingDOSMemory is archaic and is now just a flag reflecting
  1202. // the "CaptureToDisk" selection.
  1203. //
  1204. gCapParms.fUsingDOSMemory =
  1205. IsDlgButtonChecked(hDlg, IDD_CaptureToDisk);
  1206. EndDialog(hDlg, TRUE) ;
  1207. return TRUE ;
  1208. }
  1209. case IDCANCEL :
  1210. EndDialog(hDlg, FALSE) ;
  1211. return TRUE ;
  1212. }
  1213. break ;
  1214. case WM_VSCROLL:
  1215. // message from one of the arrow spinbuttons
  1216. {
  1217. UINT id;
  1218. id = GetDlgCtrlID(GET_WM_COMMAND_HWND(wParam, lParam));
  1219. if (id == IDD_FrameRateArrow) {
  1220. // format n.nnn
  1221. MilliSecVarArrowEditChange(
  1222. GetDlgItem(hDlg, IDD_FrameRateData),
  1223. GET_WM_VSCROLL_CODE(wParam, lParam),
  1224. 1, 100, 1);
  1225. } else {
  1226. // simple integer format
  1227. ArrowEditChange(
  1228. GetDlgItem(hDlg, IDD_SecondsData),
  1229. GET_WM_VSCROLL_CODE(wParam, lParam),
  1230. 1, 30000);
  1231. }
  1232. break;
  1233. }
  1234. }
  1235. return FALSE ;
  1236. }
  1237. /*
  1238. * preferences dialog - sets global options about background colour,
  1239. * presence of toolbar, status bar etc
  1240. */
  1241. LRESULT FAR PASCAL
  1242. PrefsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1243. {
  1244. DWORD indexsz;
  1245. switch(message) {
  1246. case WM_INITDIALOG:
  1247. CheckDlgButton(hDlg, IDD_PrefsStatus, gbStatusBar);
  1248. CheckDlgButton(hDlg, IDD_PrefsToolbar, gbToolBar);
  1249. CheckDlgButton(hDlg, IDD_PrefsCentre, gbCentre);
  1250. CheckDlgButton(hDlg, IDD_PrefsSizeFrame, gbAutoSizeFrame);
  1251. CheckRadioButton(hDlg, IDD_PrefsDefBackground, IDD_PrefsBlack, gBackColour);
  1252. CheckRadioButton(hDlg, IDD_PrefsSmallIndex, IDD_PrefsBigIndex,
  1253. (gCapParms.dwIndexSize == CAP_LARGE_INDEX) ?
  1254. IDD_PrefsBigIndex : IDD_PrefsSmallIndex);
  1255. CheckRadioButton(hDlg, IDD_PrefsMasterAudio, IDD_PrefsMasterNone,
  1256. gCapParms.AVStreamMaster + IDD_PrefsMasterAudio);
  1257. return(TRUE);
  1258. case WM_COMMAND:
  1259. switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1260. case IDCANCEL:
  1261. EndDialog(hDlg, FALSE);
  1262. return(TRUE);
  1263. case IDOK:
  1264. gbStatusBar = IsDlgButtonChecked(hDlg, IDD_PrefsStatus);
  1265. gbToolBar = IsDlgButtonChecked(hDlg, IDD_PrefsToolbar);
  1266. gbCentre = IsDlgButtonChecked(hDlg, IDD_PrefsCentre);
  1267. gbAutoSizeFrame = IsDlgButtonChecked(hDlg, IDD_PrefsSizeFrame);
  1268. if (IsDlgButtonChecked(hDlg, IDD_PrefsDefBackground)) {
  1269. gBackColour = IDD_PrefsDefBackground;
  1270. } else if (IsDlgButtonChecked(hDlg, IDD_PrefsLtGrey)) {
  1271. gBackColour = IDD_PrefsLtGrey;
  1272. } else if (IsDlgButtonChecked(hDlg, IDD_PrefsDkGrey)) {
  1273. gBackColour = IDD_PrefsDkGrey;
  1274. } else {
  1275. gBackColour = IDD_PrefsBlack;
  1276. }
  1277. if (IsDlgButtonChecked(hDlg, IDD_PrefsSmallIndex)) {
  1278. indexsz = CAP_SMALL_INDEX;
  1279. } else {
  1280. indexsz = CAP_LARGE_INDEX;
  1281. }
  1282. if (indexsz != gCapParms.dwIndexSize) {
  1283. gCapParms.dwIndexSize = indexsz;
  1284. }
  1285. if (IsDlgButtonChecked(hDlg, IDD_PrefsMasterAudio)) {
  1286. gCapParms.AVStreamMaster = AVSTREAMMASTER_AUDIO;
  1287. }
  1288. else {
  1289. gCapParms.AVStreamMaster = AVSTREAMMASTER_NONE;
  1290. }
  1291. EndDialog(hDlg, TRUE);
  1292. return(TRUE);
  1293. }
  1294. break;
  1295. }
  1296. return FALSE;
  1297. }
  1298. LRESULT FAR PASCAL
  1299. NoHardwareDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1300. {
  1301. static HBRUSH hbr;
  1302. switch(message) {
  1303. case WM_INITDIALOG:
  1304. // lParam contains the argument to DialogBoxParam which is the
  1305. // reason text
  1306. SetDlgItemText(hDlg, IDD_FailReason, (LPTSTR) lParam);
  1307. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  1308. return TRUE;
  1309. case WM_DESTROY:
  1310. DeleteObject(hbr);
  1311. #ifdef _WIN32
  1312. case WM_CTLCOLORSTATIC:
  1313. #else
  1314. case WM_CTLCOLOR:
  1315. #endif
  1316. if (GET_WM_CTLCOLOR_HWND(wParam, lParam, message) == GetDlgItem(hDlg, IDD_FailReason)) {
  1317. HDC hdc;
  1318. hdc = GET_WM_CTLCOLOR_HDC(wParam, lParam, message);
  1319. SetTextColor(hdc, RGB(0xff, 0, 0));
  1320. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1321. // in order to ensure that the text colour we have chosen for
  1322. // this control is used, we need to actually return a brush.
  1323. // for win31, we also need to align the brush
  1324. #ifndef _WIN32
  1325. {
  1326. POINT pt;
  1327. pt.x = 0;
  1328. pt.y = 0;
  1329. ClientToScreen(hDlg, &pt);
  1330. UnrealizeObject(hbr);
  1331. SetBrushOrg(hdc, pt.x, pt.y);
  1332. }
  1333. #endif
  1334. return((INT_PTR) hbr);
  1335. }
  1336. break;
  1337. case WM_COMMAND:
  1338. switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1339. case IDOK:
  1340. EndDialog(hDlg, TRUE);
  1341. return(TRUE);
  1342. case IDCANCEL:
  1343. EndDialog(hDlg, FALSE);
  1344. return(TRUE);
  1345. }
  1346. break;
  1347. }
  1348. return(FALSE);
  1349. }
  1350. //capture selected single frames
  1351. LRESULT
  1352. FAR PASCAL
  1353. CapFramesProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  1354. {
  1355. TCHAR ach[MAX_PATH*2];
  1356. TCHAR achName[MAX_PATH];
  1357. static BOOL bFirst;
  1358. static int iFrames;
  1359. switch(Message) {
  1360. case WM_INITDIALOG:
  1361. // write out the prompt message including the capture file name
  1362. capFileGetCaptureFile(ghWndCap, achName, sizeof(achName));
  1363. wsprintf(ach, tmpString(IDS_PROMPT_CAPFRAMES), achName);
  1364. SetDlgItemText(hDlg, IDD_CapMessage, ach);
  1365. bFirst = TRUE;
  1366. //move dialog so it doesn't obscure the capture window
  1367. SmartWindowPosition(hDlg, ghWndCap);
  1368. return(TRUE);
  1369. case WM_COMMAND:
  1370. switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1371. case IDCANCEL:
  1372. if (!bFirst) {
  1373. capCaptureSingleFrameClose(ghWndCap);
  1374. EndDialog(hDlg, TRUE);
  1375. } else {
  1376. EndDialog(hDlg, FALSE);
  1377. }
  1378. return(TRUE);
  1379. case IDOK:
  1380. if (bFirst) {
  1381. bFirst = FALSE;
  1382. iFrames = 0;
  1383. capCaptureSingleFrameOpen(ghWndCap);
  1384. SetDlgItemText(hDlg, IDCANCEL, tmpString(IDS_CAP_CLOSE));
  1385. }
  1386. capCaptureSingleFrame(ghWndCap);
  1387. iFrames++;
  1388. wsprintf(ach, tmpString(IDS_STATUS_NUMFRAMES), iFrames);
  1389. SetDlgItemText(hDlg, IDD_CapNumFrames, ach);
  1390. return(TRUE);
  1391. }
  1392. break;
  1393. }
  1394. return(FALSE);
  1395. }
  1396. // enumerate all the MCI devices of a particular type and add them and
  1397. // their descriptions to a combo box list.
  1398. //
  1399. void
  1400. AddMCIDeviceNames(UINT wDeviceType, HWND hwndCB)
  1401. {
  1402. int nIndex;
  1403. MCI_OPEN_PARMS mciOp;
  1404. MCI_INFO_PARMS mciIp;
  1405. MCI_SYSINFO_PARMS mciSIP;
  1406. MCI_GENERIC_PARMS mciGp;
  1407. TCHAR buf[MAXPNAMELEN + 128]; // Contains eg. Name\t\tVideodisc1
  1408. TCHAR buf2 [64];
  1409. int maxdevs;
  1410. DWORD dwRet;
  1411. // To get the user readable names of the devices, we
  1412. // must open all appropriate devices, and then get info.
  1413. // MCI Open structure
  1414. mciOp.dwCallback = 0;
  1415. mciOp.lpstrElementName = NULL;
  1416. mciOp.lpstrAlias = NULL;
  1417. // MCI Info structure
  1418. mciIp.dwCallback = 0;
  1419. mciIp.lpstrReturn = (LPTSTR) buf;
  1420. mciIp.dwRetSize = MAXPNAMELEN - 1;
  1421. // MCI SysInfo structure
  1422. mciSIP.dwCallback = 0;
  1423. mciSIP.lpstrReturn = (LPTSTR) buf2;
  1424. mciSIP.dwRetSize = sizeof (buf2);
  1425. mciSIP.wDeviceType = wDeviceType;
  1426. // MCI Generic structure
  1427. mciGp.dwCallback = 0;
  1428. // Load the combobox with the product info name, followed by
  1429. // a comma, then a space, and then the mci device name. This allows a
  1430. // single alphabetized list to be kept.
  1431. // eg.
  1432. // Pioneer Laserdisc, videodisc1
  1433. maxdevs = CountMCIDevices((UINT)mciSIP.wDeviceType);
  1434. for (nIndex = 0; nIndex < maxdevs; nIndex++) {
  1435. // Get the system name eg. Videodisc1
  1436. mciSIP.dwNumber = nIndex + 1;
  1437. dwRet = mciSendCommand (0, MCI_SYSINFO,
  1438. MCI_SYSINFO_NAME,
  1439. (DWORD_PTR) (LPVOID) &mciSIP);
  1440. mciOp.lpstrDeviceType =
  1441. (LPTSTR) MAKELONG (wDeviceType, nIndex);
  1442. if (!(dwRet = mciSendCommand(0, MCI_OPEN,
  1443. MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID |
  1444. MCI_OPEN_SHAREABLE,
  1445. (DWORD_PTR) (LPVOID) &mciOp))) {
  1446. if (!(dwRet = mciSendCommand (mciOp.wDeviceID, MCI_INFO,
  1447. MCI_WAIT | MCI_INFO_PRODUCT,
  1448. (DWORD_PTR) (LPVOID) &mciIp))) {
  1449. lstrcat (buf, ", "); // append the delimiter
  1450. lstrcat (buf, buf2); // append the system name
  1451. // Whew, finally put it in the listbox
  1452. SendMessage( hwndCB, CB_ADDSTRING, 0,
  1453. (LONG_PTR)(LPTSTR) buf);
  1454. } //endif got INFO
  1455. // Close it now
  1456. mciSendCommand (mciOp.wDeviceID, MCI_CLOSE,
  1457. MCI_WAIT,
  1458. (DWORD_PTR) (LPVOID) &mciGp);
  1459. } // endif OPEN
  1460. } // endif for all devices of this type
  1461. }
  1462. //
  1463. // dialog proc to select MCI device and parameters, including start,
  1464. // stop times.
  1465. LRESULT FAR PASCAL
  1466. MCISetupProc(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam)
  1467. {
  1468. HWND hwndCB;
  1469. DWORD dw;
  1470. TCHAR buf[MAXPNAMELEN];
  1471. BOOL f;
  1472. int j;
  1473. static int nLastCBIndex = 0;
  1474. static DWORD tdwMCIStartTime;
  1475. static DWORD tdwMCIStopTime;
  1476. switch (msg) {
  1477. case WM_INITDIALOG:
  1478. CheckRadioButton(hwnd, IDD_MCI_PLAY, IDD_MCI_STEP,
  1479. gCapParms.fStepMCIDevice ?
  1480. IDD_MCI_STEP : IDD_MCI_PLAY );
  1481. // enable averaging options only in step mode
  1482. EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_2X), gCapParms.fStepMCIDevice);
  1483. EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_FR), gCapParms.fStepMCIDevice);
  1484. SetDlgItemInt(hwnd, IDD_MCI_AVERAGE_FR, gCapParms.wStepCaptureAverageFrames, FALSE);
  1485. CheckDlgButton (hwnd, IDD_MCI_AVERAGE_2X, gCapParms.fStepCaptureAt2x);
  1486. // save current dialog time settings
  1487. tdwMCIStartTime = gCapParms.dwMCIStartTime;
  1488. tdwMCIStopTime = gCapParms.dwMCIStopTime;
  1489. TimeMSToHMSString (gCapParms.dwMCIStartTime, buf);
  1490. SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1491. TimeMSToHMSString (gCapParms.dwMCIStopTime, buf);
  1492. SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1493. // fill combo box with list of MCI devices
  1494. hwndCB = GetDlgItem( hwnd, IDD_MCI_SOURCE );
  1495. AddMCIDeviceNames(MCI_DEVTYPE_VIDEODISC, hwndCB);
  1496. AddMCIDeviceNames(MCI_DEVTYPE_VCR, hwndCB);
  1497. // set the selection to whatever he chose last time through this dlg
  1498. // default is the first entry.
  1499. SendMessage( hwndCB, CB_SETCURSEL, nLastCBIndex, 0L);
  1500. break;
  1501. case WM_COMMAND:
  1502. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1503. case IDOK:
  1504. // i think the point of this is to ensure that
  1505. // the KILLFOCUS processing for the edit boxes has been done
  1506. // and thus the temp times are the same as the dialog text
  1507. SetFocus(GET_WM_COMMAND_HWND(wParam, lParam));
  1508. MCIGetDeviceNameAndIndex (hwnd, &nLastCBIndex, gachMCIDeviceName);
  1509. capSetMCIDeviceName(ghWndCap, gachMCIDeviceName) ;
  1510. gCapParms.fStepMCIDevice = IsDlgButtonChecked (hwnd, IDD_MCI_STEP);
  1511. // pick up the temp times - these were set on KILLFOCUS msgs
  1512. // (when we did validation and string->dword conversion
  1513. gCapParms.dwMCIStartTime = tdwMCIStartTime;
  1514. gCapParms.dwMCIStopTime = tdwMCIStopTime;
  1515. gCapParms.fStepCaptureAt2x = IsDlgButtonChecked (hwnd, IDD_MCI_AVERAGE_2X);
  1516. gCapParms.wStepCaptureAverageFrames = GetDlgItemInt (hwnd, IDD_MCI_AVERAGE_FR, NULL, FALSE);
  1517. EndDialog(hwnd, TRUE);
  1518. break;
  1519. case IDCANCEL:
  1520. EndDialog(hwnd, 0);
  1521. break;
  1522. case IDD_MCI_STEP:
  1523. case IDD_MCI_PLAY:
  1524. //averaging only enabled in play mode
  1525. f = IsDlgButtonChecked (hwnd, IDD_MCI_STEP);
  1526. EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_2X), f);
  1527. EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_FR), f);
  1528. break;
  1529. case IDD_MCI_AVERAGE_FR:
  1530. // validate the count of frames to average 1..100
  1531. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1532. j = GetDlgItemInt(hwnd,
  1533. GET_WM_COMMAND_ID(wParam, lParam), NULL, FALSE);
  1534. // Limit frames to average between 1 and 100
  1535. if (j < 1 || j > 100) {
  1536. SetDlgItemInt (hwnd,
  1537. GET_WM_COMMAND_ID(wParam, lParam), 1, FALSE);
  1538. }
  1539. }
  1540. break;
  1541. case IDD_MCI_STARTSET:
  1542. case IDD_MCI_STOPSET:
  1543. // set the start or stop time to be the time
  1544. // on the device right now.
  1545. // MCI devices could yield and cause us to re-enter - the
  1546. // simplest answer seems to be to disable the dialog
  1547. EnableWindow(hwnd, FALSE);
  1548. MCIGetDeviceNameAndIndex (hwnd, &nLastCBIndex, buf);
  1549. if (MCIDeviceOpen (buf)) {
  1550. if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTSET) {
  1551. if (MCIDeviceGetPosition (&tdwMCIStartTime)) {
  1552. TimeMSToHMSString (tdwMCIStartTime, buf);
  1553. SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1554. }
  1555. else {
  1556. MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1557. MB_OK|MB_ICONEXCLAMATION);
  1558. }
  1559. }
  1560. else {
  1561. if (MCIDeviceGetPosition (&tdwMCIStopTime)) {
  1562. TimeMSToHMSString (tdwMCIStopTime, buf);
  1563. SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1564. }
  1565. else {
  1566. MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1567. MB_OK|MB_ICONEXCLAMATION);
  1568. }
  1569. }
  1570. MCIDeviceClose ();
  1571. } else {
  1572. // cant open device
  1573. MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1574. MB_OK|MB_ICONEXCLAMATION);
  1575. }
  1576. EnableWindow(hwnd, TRUE);
  1577. break;
  1578. case IDD_MCI_STARTTIME:
  1579. case IDD_MCI_STOPTIME:
  1580. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1581. GetDlgItemText (hwnd,
  1582. GET_WM_COMMAND_ID(wParam, lParam), buf, sizeof (buf));
  1583. if ((dw = TimeHMSStringToMS (buf)) == -1) {
  1584. // Error in string, reset
  1585. MessageBeep (0);
  1586. if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTTIME)
  1587. dw = tdwMCIStartTime;
  1588. else
  1589. dw = tdwMCIStopTime;
  1590. }
  1591. if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTTIME) {
  1592. tdwMCIStartTime = dw;
  1593. TimeMSToHMSString (tdwMCIStartTime, buf);
  1594. SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1595. }
  1596. else {
  1597. tdwMCIStopTime = dw;
  1598. TimeMSToHMSString (tdwMCIStopTime, buf);
  1599. SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1600. }
  1601. }
  1602. break;
  1603. }
  1604. break;
  1605. }
  1606. return FALSE;
  1607. }