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.

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