DIALOGS.C
上传用户:carrie980
上传日期:2013-03-28
资源大小:1143k
文件大小:65k
源码类别:

视频捕捉/采集

开发平台:

Visual C++

  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 - 1996 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 "arrow.h"
  31. #include "rlmeter.h"
  32. #include "vidcap.h"
  33. #include "vidframe.h"
  34. #include "help.h"
  35. static long GetFreeDiskSpaceInKB(LPTSTR) ;
  36. static int  CountMCIDevices(WORD) ;
  37. BOOL FAR PASCAL MCISetupProc(HWND, unsigned, UINT, LONG);
  38. //--- utility functions  ---------------------------------------------------
  39. /*----------------------------------------------------------------------------*
  40. |   SmartWindowPosition (HWND hWndDlg, HWND hWndShow)
  41. |                                                                              |
  42. |   Description:                                                               |
  43. |       This function attempts to position a dialog box so that it
  44. |       does not obscure the hWndShow window. This function is
  45. |       typically called during WM_INITDIALOG processing.
  46. |                                                                              |
  47. |   Arguments:                                                                 |
  48. |       hWndDlg         handle of the soon to be displayed dialog
  49. |       hWndShow        handle of the window to keep visible
  50. |                                                                              |
  51. |   Returns:                                                                   |
  52. |       1 if the windows overlap and positions were adjusted
  53. |       0 if the windows don't overlap
  54. |                                                                              |
  55. *----------------------------------------------------------------------------*/
  56. int SmartWindowPosition (HWND hWndDlg, HWND hWndShow)
  57. {
  58.     RECT rc, rcDlg, rcShow;
  59.     int iHeight, iWidth;
  60.     int iScreenHeight, iScreenWidth;
  61.     GetWindowRect(hWndDlg, &rcDlg);
  62.     GetWindowRect(hWndShow, &rcShow);
  63.     iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
  64.     iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
  65.     InflateRect (&rcShow, 5, 5); // allow a small border
  66.     if (IntersectRect(&rc, &rcDlg, &rcShow)){
  67.         /* the two do intersect, now figure out where to place */
  68.         /* this dialog window.  Try to go below the Show window*/
  69.         /* first and then to the right, top and left.    */
  70.         /* get the size of this dialog */
  71.         iHeight = rcDlg.bottom - rcDlg.top;
  72.         iWidth = rcDlg.right - rcDlg.left;
  73.         if ((WORD)(rcShow.bottom + iHeight + 1) <  iScreenHeight){
  74.                 /* will fit on bottom, go for it */
  75.                 rc.top = rcShow.bottom + 1;
  76.                 rc.left = (((rcShow.right - rcShow.left)/2) + rcShow.left)
  77.              - (iWidth/2);
  78.         } else if ((WORD)(rcShow.right + iWidth + 1) < iScreenWidth){
  79.                 /* will fit to right, go for it */
  80.                 rc.left = rcShow.right + 1;
  81.                 rc.top = (((rcShow.bottom - rcShow.top)/2) + rcShow.top)
  82.              - (iHeight/2);
  83.         } else if ((WORD)(rcShow.top - iHeight - 1) > 0){
  84.                 /* will fit on top, handle that */
  85.                 rc.top = rcShow.top - iHeight - 1;
  86.                 rc.left = (((rcShow.right - rcShow.left)/2) + rcShow.left)
  87.              - (iWidth/2);
  88.         } else if ((WORD)(rcShow.left - iWidth - 1) > 0){
  89.                 /* will fit to left, do it */
  90.                 rc.left = rcShow.left - iWidth - 1;
  91.                 rc.top = (((rcShow.bottom - rcShow.top)/2) + rcShow.top)
  92.              - (iHeight/2);
  93.         } else {
  94.                 /* we are hosed, they cannot be placed so that there is */
  95.                 /* no overlap anywhere.  To minimize the damage just put*/
  96.                 /* the dialog in the lower left corner of the screen    */
  97.                 rc.top = (int)iScreenHeight - iHeight;
  98.                 rc.left = (int)iScreenWidth - iWidth;
  99.         }
  100.         /* make any adjustments necessary to keep it on the screen */
  101.         if (rc.left < 0) rc.left = 0;
  102.         else if ((WORD)(rc.left + iWidth) > iScreenWidth)
  103.                 rc.left = (int)(iScreenWidth - iWidth);
  104.         if (rc.top < 0)  rc.top = 0;
  105.         else if ((WORD)(rc.top + iHeight) > iScreenHeight)
  106.                 rc.top = (int)iScreenHeight - iHeight;
  107.         SetWindowPos(hWndDlg, NULL, rc.left, rc.top, 0, 0,
  108.              SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  109.         return 1;
  110.     } // if the windows overlap by default
  111.     return 0;
  112. }
  113. //
  114. // GetFreeDiskSpace: Function to Measure Available Disk Space
  115. //
  116. static long GetFreeDiskSpaceInKB(LPTSTR pFile)
  117. {
  118.     DWORD dwFreeClusters, dwBytesPerSector, dwSectorsPerCluster, dwClusters;
  119.     char RootName[MAX_PATH];
  120.     LPSTR ptmp;    //required arg
  121.     // need to find path for root directory on drive containing
  122.     // this file.
  123.     GetFullPathName(pFile, sizeof(RootName)/sizeof(RootName[0]), RootName, &ptmp);
  124.     // truncate this to the name of the root directory (god how tedious)
  125.     if ((RootName[0] == TEXT('\')) && (RootName[1] == TEXT('\'))) {
  126.         // path begins with  \serversharepath so skip the first
  127.         // three backslashes
  128.         ptmp = &RootName[2];
  129.         while (*ptmp && (*ptmp != TEXT('\'))) {
  130.             ptmp++;
  131.         }
  132.         if (*ptmp) {
  133.             // advance past the third backslash
  134.             ptmp++;
  135.         }
  136.     } else {
  137.         // path must be drv:path
  138.         ptmp = RootName;
  139.     }
  140.     // find next backslash and put a null after it
  141.     while (*ptmp && (*ptmp != TEXT('\'))) {
  142.         ptmp++;
  143.     }
  144.     // found a backslash ?
  145.     if (*ptmp) {
  146.         // skip it and insert null
  147.         ptmp++;
  148.         *ptmp = TEXT('');
  149.     }
  150.     if (!GetDiskFreeSpace(RootName,
  151. &dwSectorsPerCluster,
  152. &dwBytesPerSector,
  153. &dwFreeClusters,
  154. &dwClusters)) {
  155.     MessageBoxID(IDS_ERR_MEASUREFREEDISK, MB_OK | MB_ICONINFORMATION);
  156.     return (-1);
  157.     }
  158.     return(MulDiv (dwSectorsPerCluster * dwBytesPerSector,
  159.    dwFreeClusters,
  160.    1024));
  161. }
  162. //
  163. // CountMCIDevices: Function to Find the Number of MCI Devices of a Type
  164. //
  165. static int CountMCIDevices(WORD wType)
  166. {
  167.     int               nTotal = 0 ;
  168.     DWORD             dwCount ;
  169.     MCI_SYSINFO_PARMS mciSIP ;
  170.     mciSIP.dwCallback = 0 ;
  171.     mciSIP.lpstrReturn = (LPSTR)(LPVOID) &dwCount ;
  172.     mciSIP.dwRetSize = sizeof(DWORD) ;
  173.     mciSIP.wDeviceType = wType ;
  174.     // Use an MCI command to get the info
  175.     if (! mciSendCommand(0, MCI_SYSINFO, MCI_SYSINFO_QUANTITY,
  176.                          (DWORD)(LPVOID) &mciSIP))
  177.         nTotal = (int) *((LPDWORD) mciSIP.lpstrReturn) ;
  178.     return nTotal ;
  179. }
  180. /* lMicroSec = StringRateToMicroSec(szRate)
  181.  *
  182.  * Convert <szRate> (e.g. "3.75" representing 3.75 frames per second)
  183.  * to microseconds (e.g. 266667L microseconds per frame).
  184.  *
  185.  * If the rate is close to zero or negative, then 0L is returned.
  186.  */
  187. DWORD StringRateToMicroSec(PSTR szRate)
  188. {
  189. double dRate;
  190. dRate = atof(szRate);
  191. if (dRate < 0.0001) {
  192. return 0L;
  193. } else {
  194. return (DWORD) /*floor*/((1e6 / dRate) + 0.5);
  195.         }
  196. }
  197. /* ach = MicroSecToStringRate(achRate, lMicroSec)
  198.  *
  199.  * Convert <lMicroSec> (e.g. 266667L microseconds per frame) to a
  200.  * string rate (e.g. "3.75" representing 3.75 frames per second).
  201.  * Returns <achRate>.
  202.  */
  203. PSTR MicroSecToStringRate(PSTR achRate, DWORD dwMicroSec)
  204. {
  205. sprintf(achRate, "%.3f",
  206. (dwMicroSec == 0L) ? 0.0 : (1e6 / (double) dwMicroSec));
  207. return achRate;
  208. }
  209. /*
  210.  * update the text of an edit field based on a comarrow up or down change
  211.  * - write the text in N.NNN format (truncated to an integer)
  212.  */
  213. LONG FAR PASCAL
  214. MilliSecVarArrowEditChange(
  215.     HWND hwndEdit,
  216.     UINT uCode,
  217.     LONG lMin,
  218.     LONG lMax,
  219.     UINT uInc
  220. )
  221. {
  222.     char achTemp[32];
  223.     LONG l;
  224.     GetWindowText(hwndEdit, achTemp, sizeof(achTemp));
  225.     l = atol(achTemp);
  226.     if(uCode == SB_LINEUP ) {
  227. if(l + (long)uInc <= lMax ) {
  228.     l += uInc;
  229.     wsprintf(achTemp, "%ld.000", l );
  230.     SetWindowText(hwndEdit, achTemp );
  231.         } else {
  232.     MessageBeep( 0 );
  233. }
  234.     } else if (uCode == SB_LINEDOWN ) {
  235. if( l-(long)uInc >= lMin ) {
  236.     l -= uInc;
  237.     wsprintf( achTemp, "%ld.000", l );
  238.     SetWindowText( hwndEdit, achTemp );
  239.         } else {
  240.     MessageBeep( 0 );
  241. }
  242.     }
  243.     return( l );
  244. }
  245. BOOL MCIGetDeviceNameAndIndex (HWND hwnd, LPINT lpnIndex, LPSTR lpName)
  246. {
  247.     HWND hwndCB;
  248.     char buf[160];
  249.     char *cp;
  250.     hwndCB = GetDlgItem( hwnd, IDD_MCI_SOURCE );
  251.     *lpnIndex = (int)SendMessage( hwndCB, CB_GETCURSEL, 0, 0L);
  252.     SendMessage( hwndCB, CB_GETLBTEXT, *lpnIndex,
  253.      (LONG)(LPSTR) buf );
  254.     // Point cp to the system name
  255.     for (cp = buf + lstrlen(buf); cp > buf; cp--) {
  256.         if (*cp == ' ' && *(cp-1) == ',') {
  257.             cp++;
  258.             break;
  259. }
  260.     }
  261.     lstrcpy (lpName, cp);
  262.     return TRUE;
  263. }
  264. /*--------------------------------------------------------------+
  265. | TimeMSToHMSString() - change milliseconds into a time string   |
  266. +--------------------------------------------------------------*/
  267. void FAR PASCAL TimeMSToHMSString (DWORD dwMS, LPSTR lpTime)
  268. {
  269. DWORD dwTotalSecs;
  270. LONG lHundredths;
  271. WORD wSecs;
  272. WORD wMins;
  273. WORD wHours;
  274. /* convert to number of seconds */
  275. dwTotalSecs = dwMS / 1000;
  276. /* keep the remainder part */
  277. lHundredths = (dwMS - (dwTotalSecs * 1000)) / 10;
  278. /* break down into other components */
  279. wHours = (WORD)(dwTotalSecs / 3600); // get # Hours
  280. dwTotalSecs -= (wHours * 3600);
  281. wMins = (WORD)(dwTotalSecs / 60); // get # Mins
  282. dwTotalSecs -= (wMins * 60);
  283. wSecs = (WORD)dwTotalSecs; // what's left is # seconds
  284. /* build the string */
  285. wsprintf((char far *)lpTime, "%02u:%02u:%02u.%02lu", wHours, wMins,
  286.     wSecs, lHundredths);
  287. }
  288. /*--------------------------------------------------------------+
  289. | TimeHMSStringToMS() - change Time string to milliseconds     |
  290. |                       returns dwMilliseconds or -1 if error  |
  291. +--------------------------------------------------------------*/
  292. LONG NEAR PASCAL  TimeHMSStringToMS (LPSTR lpsz)
  293. {
  294.     char achTime[12]; // buffer for time string (input)
  295.     DWORD dwMSecs; // total MSecs for this thing */
  296.     char *pDelim; // pointer to next delimeter
  297.     char *p; // general pointer
  298.     DWORD dwHours = 0; // # of hours
  299.     DWORD dwMins = 0; // # of minutes
  300.     DWORD dwSecs = 0; // # of seconds
  301.     WORD wHundredths = 0; // # hundredths
  302.     _fstrncpy(achTime, lpsz, sizeof (achTime));
  303.     if (achTime[0] == '')
  304.         return -1; // bad char so error out
  305.     
  306.     /* rip through the whole string and look for illegal chars */
  307.     for (p = achTime; *p ; p++){
  308.         if (!isdigit(*p) && *p != '.' && *p != ':')
  309.      return -1; // bad char so error out
  310.     }
  311.     /* go find the hundredths portion if it exists */
  312.     pDelim = strchr(achTime, '.');
  313.     if (*pDelim){
  314.         p = strrchr(achTime, '.');
  315.         if (pDelim != p) {
  316.          return -1; // string has > 1 '.', return error
  317.         }
  318.         p++; // move up past delim
  319.         if (strlen(p) > 2) {
  320.          *(p+2) = ''; // knock off all but hundredths
  321.         }
  322.         wHundredths = atoi(p); // get the fractional part
  323.         *pDelim = ''; // null out this terminator
  324.     }
  325.     /* try and find seconds */
  326.     pDelim = strrchr(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 = atoi(p);
  334.     if (*pDelim) {
  335.         *pDelim = '';
  336.         /* go and get the minutes part */
  337.         pDelim = strrchr(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 = atoi(p);
  345.         if (*pDelim) {
  346.             *pDelim = '';
  347.             /* get the hours */
  348.             p = achTime;
  349.             dwHours = atoi(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 (LPSTR lpDevName)
  376. {
  377.     char        ach[160];
  378.     DWORD dwMCIError;
  379.     wsprintf( ach, "open %s shareable wait alias mciframes", (LPSTR) 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.     char        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 = atol( 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. int FAR PASCAL AboutProc(HWND hDlg, UINT Message, UINT wParam, LONG 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. int 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. int FAR PASCAL AudioFormatProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam)
  655. {
  656.     static int                nChannels ;
  657.     static WORD               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, (WORD)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. int FAR PASCAL AllocCapFileProc(HWND hDlg, UINT Message, UINT wParam, LONG 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.                     MB_OK | MB_ICONEXCLAMATION) ;
  772.                     lFileSize = 0 ;
  773.                 }
  774.                 _close(fh) ;
  775.             }
  776.             // Get free disk space and add current capture file size to that.
  777.             // Convert the available space to MBs.
  778.             if ((lFreeSpaceInKB = GetFreeDiskSpaceInKB(achCapFile)) != -1L) {
  779.                 lFreeSpaceInKB += lFileSize / 1024 ;
  780.                 nFreeMBs = lFreeSpaceInKB / 1024 ;
  781.                 SetDlgItemInt(hDlg, IDD_SetCapFileFree, nFreeMBs, TRUE) ;
  782.             } else {
  783.                 EnableWindow(GetDlgItem(hDlg, IDD_SetCapFileFree), FALSE);
  784.             }
  785.             gwCapFileSize = (WORD) (lFileSize / ONEMEG);
  786.             SetDlgItemInt(hDlg, IDD_SetCapFileSize, gwCapFileSize, TRUE) ;
  787.             return TRUE ;
  788.         }
  789.         case WM_COMMAND :
  790.             switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  791.                 case IDOK :
  792.                 {
  793.                     int         iCapFileSize ;
  794.                     iCapFileSize = (int) GetDlgItemInt(hDlg, IDD_SetCapFileSize, NULL, TRUE) ;
  795.                     if (iCapFileSize <= 0 || iCapFileSize > nFreeMBs) {
  796.                         // You are asking for more than we have !! Sorry, ...
  797.                         SetDlgItemInt(hDlg, IDD_SetCapFileSize, iCapFileSize, TRUE) ;
  798.                         SetFocus(GetDlgItem(hDlg, IDD_SetCapFileSize)) ;
  799.                         MessageBeep(MB_ICONEXCLAMATION) ;
  800.                         return FALSE ;
  801.                     }
  802.                     gwCapFileSize = iCapFileSize ;
  803.                     EndDialog(hDlg, TRUE) ;
  804.                     return TRUE ;
  805.                 }
  806.                 case IDCANCEL :
  807.                     EndDialog(hDlg, FALSE) ;
  808.                     return TRUE ;
  809.                 case IDD_SetCapFileSize:
  810.                 {
  811.                     long l;
  812.                     BOOL bchanged;
  813.                     char achBuffer[21];
  814.                     // check that entered size is a valid number
  815.                     GetDlgItemText(hDlg, IDD_SetCapFileSize, achBuffer, sizeof(achBuffer));
  816.                     l = atol(achBuffer);
  817.                     bchanged = FALSE;
  818.                     if (l < 1) {
  819.                         l = 1;
  820.                         bchanged = TRUE;
  821.                     } else if (l > nFreeMBs) {
  822.                         l = nFreeMBs;
  823.                         bchanged = TRUE;
  824.                     } else {
  825.                         // make sure there are no non-digit chars
  826.                         // atol() will ignore trailing non-digit characters
  827.                         int c = 0;
  828.                         while (achBuffer[c]) {
  829.                             if (IsCharAlpha(achBuffer[c]) ||
  830.                                 !IsCharAlphaNumeric(achBuffer[c])) {
  831.                                 // string contains non-digit chars - reset
  832.                                 l = 1;
  833.                                 bchanged = TRUE;
  834.                                 break;
  835.                             }
  836.                             c++;
  837.                         }
  838.                     }
  839.                     if (bchanged) {
  840.                         wsprintf(achBuffer, "%ld", l);
  841.                         SetDlgItemText(hDlg, IDD_SetCapFileSize, achBuffer);
  842.                     }
  843.                     break;
  844.                 }
  845.             }
  846.             break ;
  847.     }
  848.     return FALSE ;
  849. }
  850. #if 0
  851. //
  852. // MakePaletteProc: Palette Details Dialog Box Procedure
  853. //
  854. BOOL CALLBACK MakePaletteProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam)
  855. {
  856.     switch (Message) {
  857.         case WM_INITDIALOG :
  858.             SetDlgItemInt(hDlg, IDD_MakePalColors, gwPalColors, FALSE) ;
  859.             SetDlgItemInt(hDlg, IDD_MakePalFrames, gwPalFrames, FALSE) ;
  860.             return TRUE ;
  861.         case WM_COMMAND :
  862.             switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  863.                 case IDOK :
  864.                 {
  865.                     int         iColors ;
  866.                     int         iFrames ;
  867.                     iColors = (int) GetDlgItemInt(hDlg, IDD_MakePalColors, NULL, TRUE) ;
  868.                     if (! (iColors > 0 && iColors <= 236 || iColors == 256)) {
  869.                         // invalid number of palette colors
  870.                         SetDlgItemInt(hDlg, IDD_MakePalColors, iColors, TRUE) ;
  871.                         SetFocus(GetDlgItem(hDlg, IDD_MakePalColors)) ;
  872.                         MessageBeep(MB_ICONEXCLAMATION) ;
  873.                         return FALSE ;
  874.                     }
  875.                     iFrames = (int) GetDlgItemInt(hDlg, IDD_MakePalFrames, NULL, TRUE) ;
  876.                     if (iFrames <= 0 || iFrames > 10000) {
  877.                         // no frame or way t-o-o many frames !!!
  878.                         SetDlgItemInt(hDlg, IDD_MakePalFrames, iFrames, TRUE) ;
  879.                         SetFocus(GetDlgItem(hDlg, IDD_MakePalFrames)) ;
  880.                         MessageBeep(MB_ICONEXCLAMATION) ;
  881.                         return FALSE ;
  882.                     }
  883.                     gwPalColors = iColors ;
  884.                     gwPalFrames = iFrames ;
  885.                     EndDialog(hDlg, TRUE) ;
  886.                     return TRUE ;
  887.                 }
  888.                 case IDCANCEL :
  889.                     EndDialog(hDlg, FALSE) ;
  890.                     return TRUE ;
  891.             }
  892.             break ;
  893.     }
  894.     return FALSE ;
  895. }
  896. #endif
  897. #define CAPPAL_TIMER    902    
  898. #define CAPTIMER_DELAY  100       // get timers as fast as possible
  899. //
  900. // MakePaletteProc: Palette Details Dialog Box Procedure
  901. //
  902. static int      siNumColors = 256;
  903. BOOL CALLBACK MakePaletteProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  904. {
  905.     static UINT shTimer;
  906.     static int  siNumFrames;
  907.     UINT        w;
  908.     char        ach[40];
  909.     char        achFormat[40];
  910.     int         i, k;
  911.     switch(msg) {
  912.         case WM_INITDIALOG:
  913.             siNumFrames = 0;
  914.             SetDlgItemInt(hwnd, IDD_MakePalColors, siNumColors, FALSE);
  915.             SmartWindowPosition (hwnd, ghWndCap);
  916.             return TRUE;
  917.             break;
  918.         case WM_VSCROLL:
  919.             /* now handle the scroll */
  920.             i = GetDlgItemInt(hwnd, IDD_MakePalColors, NULL, FALSE);
  921.             ArrowEditChange(GetDlgItem(hwnd, IDD_MakePalColors),
  922.                 GET_WM_VSCROLL_CODE(wParam, lParam), 2, 256);
  923.             k = GetDlgItemInt(hwnd, IDD_MakePalColors, NULL, FALSE);
  924.             // Jump over the range 237 to 255
  925.             if (k > 236 && k < 256) {
  926.                 if (k > i) 
  927.                    w = 256;
  928.                 else
  929.                    w = 236;
  930.                 SetDlgItemInt (hwnd, IDD_MakePalColors, w, TRUE);
  931.             }
  932.             break;
  933.         case WM_COMMAND:
  934.             switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  935.                 case IDCANCEL:
  936.                     if (siNumFrames) {
  937.                         // The following finishes building the new palette
  938.                         capPaletteManual (ghWndCap, FALSE, siNumColors);
  939.                     }
  940.                     if (shTimer){
  941.                         KillTimer(hwnd, CAPPAL_TIMER);
  942.                         shTimer = 0;
  943.                     }
  944.                     siNumColors = GetDlgItemInt(hwnd, IDD_MakePalColors, (BOOL FAR *)ach, FALSE);
  945.                     siNumColors = max (2, min (256, siNumColors)); 
  946.                     EndDialog(hwnd, siNumFrames);
  947.                     break;
  948.                     
  949.                 case IDD_MakePalStart:
  950.                     /* see if we are in START or STOP mode at   */
  951.                     /* this time and handle each one.           */
  952.                     SetFocus (GetDlgItem (hwnd, IDD_MakePalStart));
  953.                     if (!siNumFrames){
  954.                         /* this is the first frame, change the CANCEL */
  955.                         /* button to CLOSE                              */
  956.                         LoadString(ghInstApp, IDS_CAPPAL_CLOSE, ach, sizeof(ach));
  957.                         SetDlgItemText(hwnd, IDCANCEL, ach);
  958.                     }
  959.                     if (!shTimer) {
  960.                         shTimer = SetTimer(hwnd, CAPPAL_TIMER, CAPTIMER_DELAY, NULL);
  961.                         if (shTimer == 0) {
  962.                             //!!!error message here.
  963.                             MessageBeep(0);
  964.                             return TRUE;
  965.                         }
  966.                         /* button said START, let's set up to   */
  967.                         /* do continuous capture.  This involves*/
  968.                         /*   1 - disabling FRAME button         */
  969.                         /*   2 - turning myself to STOP button  */
  970.                         /*   3 - setting up frame timer         */
  971.                         EnableWindow(GetDlgItem(hwnd, IDD_MakePalSingleFrame), FALSE);
  972.                         LoadString(ghInstApp, IDS_CAPPAL_STOP, ach, sizeof(ach));
  973.                         SetDlgItemText(hwnd, IDD_MakePalStart, ach);
  974.                     } else {
  975.                         /* button said STOP, turn things around */
  976.                         /* by:                                  */
  977.                         /*   1 - killing off timers             *
  978.                         /*   2 - turning back into START button */
  979.                         /*   3 - re-enabling FRAME button       */
  980.                         // "&Start"
  981.                         LoadString(ghInstApp, IDS_CAPPAL_START, ach, sizeof(ach));
  982.                         SetDlgItemText(hwnd, IDD_MakePalStart, ach);
  983.                         EnableWindow(GetDlgItem(hwnd, IDD_MakePalSingleFrame), TRUE);
  984.                         KillTimer(hwnd, CAPPAL_TIMER);
  985.                         shTimer = 0;
  986.                     }
  987.                     return TRUE;
  988.                     break;
  989.                     
  990.                 case IDD_MakePalSingleFrame:
  991.                     if (!siNumFrames){
  992.                         /* this is the first frame, change the CANCEL */
  993.                         /* button to CLOSE                              */
  994.                         LoadString(ghInstApp, IDS_CAPPAL_CLOSE, ach, sizeof(ach));
  995.                         SetDlgItemText(hwnd, IDCANCEL, ach);
  996.                         siNumColors = GetDlgItemInt(hwnd, IDD_MakePalColors, (BOOL FAR *)ach, FALSE);
  997.                         siNumColors = max (2, min (256, siNumColors)); 
  998.                     }
  999.                     // Get the palette for a single frame
  1000.                     capPaletteManual (ghWndCap, TRUE, siNumColors);
  1001.                     siNumFrames++;
  1002.                     LoadString(ghInstApp, IDS_CAPPAL_STATUS, achFormat, sizeof(achFormat));
  1003.                     wsprintf(ach, achFormat, siNumFrames);
  1004.                     SetDlgItemText(hwnd, IDD_MakePalNumFrames, ach);
  1005.                     return TRUE;
  1006.                     break;
  1007.                 case IDD_MakePalColors:
  1008.                     if (HIWORD (lParam) == EN_KILLFOCUS) {
  1009.                         w = GetDlgItemInt (hwnd, wParam, NULL, FALSE);
  1010.                         if ( w < 2) {
  1011.                             MessageBeep (0);
  1012.                             SetDlgItemInt (hwnd, wParam, 2, FALSE);
  1013.                         }
  1014.                         else if (w > 256) {
  1015.                             MessageBeep (0);
  1016.                             SetDlgItemInt (hwnd, wParam, 256, FALSE);
  1017.                         }
  1018.                     }
  1019.                     return TRUE;
  1020.                     break;
  1021.                 default:
  1022.                     return FALSE;
  1023.                     
  1024.             } // switch(wParam) on WM_COMMAND 
  1025.             break;
  1026.             
  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.             
  1035.     } // switch(msg)
  1036.     return FALSE;
  1037. }
  1038. //
  1039. // CapSetUpProc: Capture SetUp Details Dialog Box Procedure
  1040. //
  1041. int FAR PASCAL CapSetUpProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam)
  1042. {
  1043.     static char     achBuffer[21] ;
  1044.     UINT fValue;
  1045.     switch (Message) {
  1046.         case WM_INITDIALOG :
  1047.         {
  1048.             // Convert from MicroSecPerFrame to FPS -- that's easier !!
  1049.             MicroSecToStringRate(achBuffer, gCapParms.dwRequestMicroSecPerFrame);
  1050.             SetDlgItemText(hDlg, IDD_FrameRateData, achBuffer);
  1051.             // If time limit isn't enabled, disable the time data part
  1052.             CheckDlgButton(hDlg, IDD_TimeLimitFlag, (fValue = gCapParms.fLimitEnabled)) ;
  1053.             EnableWindow(GetDlgItem(hDlg, IDD_SecondsText), fValue) ;
  1054.             EnableWindow(GetDlgItem(hDlg, IDD_SecondsData), fValue) ;
  1055.             EnableWindow(GetDlgItem(hDlg, IDD_SecondsArrow), fValue);
  1056.             SetDlgItemInt(hDlg, IDD_SecondsData, gCapParms.wTimeLimit, FALSE) ;
  1057.             // disable audio buttons if no audio hardware
  1058.             {
  1059.                 CAPSTATUS cs;
  1060.                 capGetStatus(ghWndCap, &cs, sizeof(cs));
  1061.                 EnableWindow(GetDlgItem(hDlg, IDD_CapAudioFlag), cs.fAudioHardware);
  1062.                 EnableWindow(GetDlgItem(hDlg, IDD_AudioConfig), cs.fAudioHardware);
  1063.                 CheckDlgButton(hDlg, IDD_CapAudioFlag, gCapParms.fCaptureAudio);
  1064.             }
  1065.             /*
  1066.              * Capture To Memory means allocate as many memory buffers
  1067.              *  as possible.
  1068.              * Capture To Disk means only allocate enough buffers
  1069.              *  to get us through disk seeks and thermal recalibrations.
  1070.              */
  1071.             // The use of fUsingDOSMemory is now just a means of keeping
  1072.             // track of whether using lots of buffers.  We never actually
  1073.             // allocate exclusively from memory under 1Meg.
  1074.             CheckRadioButton(hDlg, IDD_CaptureToDisk, IDD_CaptureToMemory,
  1075.               (gCapParms.fUsingDOSMemory)? IDD_CaptureToDisk : IDD_CaptureToMemory);
  1076.             // Find out how many MCI devices can source video
  1077.             if (CountMCIDevices(MCI_DEVTYPE_VCR) +
  1078.                 CountMCIDevices(MCI_DEVTYPE_VIDEODISC) == 0) {
  1079.                 // if no VCRs or Videodiscs, disable the controls
  1080.                 EnableWindow(GetDlgItem(hDlg, IDD_MCIControlFlag), FALSE);
  1081.                 EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), FALSE);
  1082.             } else {
  1083.                 EnableWindow(GetDlgItem(hDlg, IDD_MCIControlFlag), TRUE);
  1084.                 // if MCI Control is selected, enable the setup button
  1085.                 CheckDlgButton(hDlg, IDD_MCIControlFlag,
  1086.                     gCapParms.fMCIControl);
  1087.                 EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), gCapParms.fMCIControl);
  1088.             }
  1089.             // place the dialog to avoid covering the capture window
  1090.             SmartWindowPosition(hDlg, ghWndCap);
  1091.             return TRUE ;
  1092.         }
  1093.         case WM_COMMAND :
  1094.             switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1095.                 case IDD_TimeLimitFlag :
  1096.                     // If this flag changes, en/dis-able time limit data part
  1097.                     fValue = IsDlgButtonChecked(hDlg, IDD_TimeLimitFlag) ;
  1098.                     EnableWindow(GetDlgItem(hDlg, IDD_SecondsText), fValue) ;
  1099.                     EnableWindow(GetDlgItem(hDlg, IDD_SecondsData), fValue) ;
  1100.                     EnableWindow(GetDlgItem(hDlg, IDD_SecondsArrow), fValue);
  1101.                     return TRUE ;
  1102.                 case IDD_MCIControlFlag :
  1103.                     // If this flag changes, en/dis-able MCI Setup button
  1104.                     fValue = IsDlgButtonChecked(hDlg, IDD_MCIControlFlag) ;
  1105.                     EnableWindow(GetDlgItem(hDlg, IDD_MCISetup), fValue) ;
  1106.                     return TRUE ;
  1107.                 case IDD_CapAudioFlag:
  1108.                     fValue = IsDlgButtonChecked(hDlg, IDD_CapAudioFlag) ;
  1109.                     EnableWindow(GetDlgItem(hDlg, IDD_AudioConfig), fValue) ;
  1110.                     return TRUE ;
  1111.                 case IDD_FrameRateData:
  1112.                     // get the requested frame rate and check it against bounds
  1113.                     if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1114.                         long l, new_l;
  1115.                         GetDlgItemText(hDlg, IDD_FrameRateData, achBuffer, sizeof(achBuffer));
  1116.                         new_l = l = StringRateToMicroSec(achBuffer);
  1117.                         // note that the MAX rate is SMALL! hence <max, >min
  1118.                         if (l == 0) {
  1119.                             new_l = DEF_CAPTURE_RATE;
  1120.                         } else if (l < MAX_CAPTURE_RATE) {
  1121.                             new_l = MAX_CAPTURE_RATE;
  1122.                         } else if (l > MIN_CAPTURE_RATE) {
  1123.                             new_l = MIN_CAPTURE_RATE;
  1124.                         }
  1125.                         if (l != new_l) {
  1126.                             MicroSecToStringRate(achBuffer, new_l);
  1127.                             SetDlgItemText(hDlg, IDD_FrameRateData, achBuffer);
  1128.                         }
  1129.                     }
  1130.                     break;
  1131.                 case IDD_SecondsData:
  1132.                 {
  1133.                     long l, new_l;
  1134.                     // get requested time limit and check validity
  1135.                     GetDlgItemText(hDlg, IDD_SecondsData, achBuffer, sizeof(achBuffer));
  1136.                     new_l = l = atol(achBuffer);
  1137.                     if (l < 1) {
  1138.                         new_l = 1;
  1139.                     } else if (l > 9999) {
  1140.                         new_l = 9999;
  1141.                     } else {
  1142.                         // make sure there are no non-digit chars
  1143.                         // atol() will ignore trailing non-digit characters
  1144.                         int c = 0;
  1145.                         while (achBuffer[c]) {
  1146.                             if (IsCharAlpha(achBuffer[c]) ||
  1147.                                 !IsCharAlphaNumeric(achBuffer[c])) {
  1148.                                 // string contains non-digit chars - reset
  1149.                                 new_l = 1;
  1150.                                 break;
  1151.                             }
  1152.                             c++;
  1153.                         }
  1154.                     }
  1155.                     if (new_l != l) {
  1156.                         wsprintf(achBuffer, "%ld", new_l);
  1157.                         SetDlgItemText(hDlg, IDD_SecondsData, achBuffer);
  1158.                     }
  1159.                     break;
  1160.                 }
  1161.                 // show audio format setup dialog
  1162.                 case IDD_AudioConfig:
  1163.                     // rather than duplicate lots of code from the
  1164.                     // main vidcap winproc, lets just ask it to show the dlg...
  1165.                     SendMessage(ghWndMain, WM_COMMAND,
  1166.                             GET_WM_COMMAND_MPS(IDM_O_AUDIOFORMAT, NULL, 0));
  1167.                     break;
  1168.                 // show MCI step control dialog
  1169.                 case IDD_MCISetup:
  1170.                     DoDialog(hDlg, IDD_MCISETUP, MCISetupProc, 0);
  1171.                     break;
  1172.                 // show video format setup dialog
  1173.                 case IDD_VideoConfig:
  1174.                     // rather than duplicate lots of code from the
  1175.                     // main vidcap winproc, lets just ask it to show the dlg...
  1176.                     SendMessage(ghWndMain, WM_COMMAND,
  1177.                             GET_WM_COMMAND_MPS(IDM_O_VIDEOFORMAT, NULL, 0));
  1178.                     break;
  1179.                 // show the compressor selector dialog
  1180.                 case IDD_CompConfig:
  1181.                     capDlgVideoCompression(ghWndCap);
  1182.                     break;
  1183.                 case IDOK :
  1184.                 {
  1185.                     gCapParms.fCaptureAudio =
  1186.                                 IsDlgButtonChecked(hDlg, IDD_CapAudioFlag) ;
  1187.                     gCapParms.fMCIControl =
  1188.                             IsDlgButtonChecked(hDlg, IDD_MCIControlFlag);
  1189.                     gCapParms.fLimitEnabled = IsDlgButtonChecked(hDlg, IDD_TimeLimitFlag) ;
  1190.                     GetDlgItemText(hDlg, IDD_FrameRateData, achBuffer, sizeof(achBuffer));
  1191.                     gCapParms.dwRequestMicroSecPerFrame = StringRateToMicroSec(achBuffer);
  1192.                     if (gCapParms.dwRequestMicroSecPerFrame == 0) {
  1193.                         gCapParms.dwRequestMicroSecPerFrame = DEF_CAPTURE_RATE;
  1194.                     }
  1195.                     GetDlgItemText(hDlg, IDD_SecondsData, achBuffer, sizeof(achBuffer));
  1196.                     if (gCapParms.fLimitEnabled) {
  1197.                          gCapParms.wTimeLimit  = (UINT) atol(achBuffer);
  1198.                     }
  1199.                     // fUsingDOSMemory is archaic and is now just a flag reflecting
  1200.                     // the "CaptureToDisk" selection.
  1201.                     // 
  1202.                     gCapParms.fUsingDOSMemory = 
  1203.                                 IsDlgButtonChecked(hDlg, IDD_CaptureToDisk);
  1204.                     EndDialog(hDlg, TRUE) ;
  1205.                     return TRUE ;
  1206.                 }
  1207.                 case IDCANCEL :
  1208.                     EndDialog(hDlg, FALSE) ;
  1209.                     return TRUE ;
  1210.             }
  1211.             break ;
  1212.         case WM_VSCROLL:
  1213.         // message from one of the arrow spinbuttons
  1214.         {
  1215.             UINT id;
  1216.             id = GetDlgCtrlID(GET_WM_COMMAND_HWND(wParam, lParam));
  1217.             if (id == IDD_FrameRateArrow) {
  1218.                 // format n.nnn
  1219.                 MilliSecVarArrowEditChange(
  1220.                     GetDlgItem(hDlg, IDD_FrameRateData),
  1221.                     GET_WM_VSCROLL_CODE(wParam, lParam),
  1222.                     1, 100, 1);
  1223.             } else {
  1224.                 // simple integer format
  1225.                 ArrowEditChange(
  1226.                     GetDlgItem(hDlg, IDD_SecondsData),
  1227.                     GET_WM_VSCROLL_CODE(wParam, lParam),
  1228.                     1, 30000);
  1229.             }
  1230.             break;
  1231.         }
  1232.     }
  1233.     return FALSE ;
  1234. }
  1235. /*
  1236.  * preferences dialog - sets global options about background colour,
  1237.  * presence of toolbar, status bar etc
  1238.  */
  1239. int FAR PASCAL
  1240. PrefsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1241. {
  1242.     DWORD indexsz;
  1243.     switch(message) {
  1244.     case WM_INITDIALOG:
  1245.         CheckDlgButton(hDlg, IDD_PrefsStatus, gbStatusBar);
  1246.         CheckDlgButton(hDlg, IDD_PrefsToolbar, gbToolBar);
  1247.         CheckDlgButton(hDlg, IDD_PrefsCentre, gbCentre);
  1248.         CheckDlgButton(hDlg, IDD_PrefsSizeFrame, gbAutoSizeFrame);
  1249.         CheckRadioButton(hDlg, IDD_PrefsDefBackground, IDD_PrefsBlack, gBackColour);
  1250.         CheckRadioButton(hDlg, IDD_PrefsSmallIndex, IDD_PrefsBigIndex,
  1251.                     (gCapParms.dwIndexSize == CAP_LARGE_INDEX) ?
  1252.                     IDD_PrefsBigIndex : IDD_PrefsSmallIndex);
  1253.         CheckRadioButton(hDlg, IDD_PrefsMasterAudio, IDD_PrefsMasterNone,
  1254.                     gCapParms.AVStreamMaster + IDD_PrefsMasterAudio);
  1255.         return(TRUE);
  1256.     case WM_COMMAND:
  1257.         switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1258.         case IDCANCEL:
  1259.             EndDialog(hDlg, FALSE);
  1260.             return(TRUE);
  1261.         case IDOK:
  1262.             gbStatusBar = IsDlgButtonChecked(hDlg, IDD_PrefsStatus);
  1263.             gbToolBar = IsDlgButtonChecked(hDlg, IDD_PrefsToolbar);
  1264.             gbCentre = IsDlgButtonChecked(hDlg, IDD_PrefsCentre);
  1265.             gbAutoSizeFrame = IsDlgButtonChecked(hDlg, IDD_PrefsSizeFrame);
  1266.             if (IsDlgButtonChecked(hDlg, IDD_PrefsDefBackground)) {
  1267.                 gBackColour = IDD_PrefsDefBackground;
  1268.             } else if (IsDlgButtonChecked(hDlg, IDD_PrefsLtGrey)) {
  1269.                 gBackColour = IDD_PrefsLtGrey;
  1270.             } else if (IsDlgButtonChecked(hDlg, IDD_PrefsDkGrey)) {
  1271.                 gBackColour = IDD_PrefsDkGrey;
  1272.             } else {
  1273.                 gBackColour = IDD_PrefsBlack;
  1274.             }
  1275.             if (IsDlgButtonChecked(hDlg, IDD_PrefsSmallIndex)) {
  1276.                 indexsz = CAP_SMALL_INDEX;
  1277.             } else {
  1278.                 indexsz = CAP_LARGE_INDEX;
  1279.             }
  1280.             if (indexsz != gCapParms.dwIndexSize) {
  1281.                 gCapParms.dwIndexSize = indexsz;
  1282.             }
  1283.             if (IsDlgButtonChecked(hDlg, IDD_PrefsMasterAudio)) {
  1284.                 gCapParms.AVStreamMaster = AVSTREAMMASTER_AUDIO;
  1285.             }
  1286.             else {
  1287.                 gCapParms.AVStreamMaster = AVSTREAMMASTER_NONE;
  1288.             }
  1289.             EndDialog(hDlg, TRUE);
  1290.             return(TRUE);
  1291.         }
  1292.         break;
  1293.     }
  1294.     return FALSE;
  1295. }
  1296. int FAR PASCAL
  1297. NoHardwareDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1298. {
  1299.     static HBRUSH hbr;
  1300.     switch(message) {
  1301.     case WM_INITDIALOG:
  1302.         // lParam contains the argument to DialogBoxParam which is the
  1303.         // reason text
  1304.         SetDlgItemText(hDlg, IDD_FailReason, (LPSTR) lParam);
  1305.         hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  1306.         return TRUE;
  1307.     case WM_DESTROY:
  1308.         DeleteObject(hbr);
  1309. #ifdef _WIN32
  1310.     case WM_CTLCOLORSTATIC:
  1311. #else
  1312.     case WM_CTLCOLOR:
  1313. #endif
  1314.         if (GET_WM_CTLCOLOR_HWND(wParam, lParam, message) == GetDlgItem(hDlg, IDD_FailReason)) {
  1315.             HDC hdc;
  1316.             hdc = GET_WM_CTLCOLOR_HDC(wParam, lParam, message);
  1317.             SetTextColor(hdc, RGB(0xff, 0, 0));
  1318.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1319.             // in order to ensure that the text colour we have chosen for
  1320.             // this control is used, we need to actually return a brush.
  1321.             // for win31, we also need to align the brush
  1322. #ifndef _WIN32
  1323.             {
  1324.                 POINT pt;
  1325.                 pt.x = 0;
  1326.                 pt.y = 0;
  1327.                 ClientToScreen(hDlg, &pt);
  1328.                 UnrealizeObject(hbr);
  1329.                 SetBrushOrg(hdc, pt.x, pt.y);
  1330.             }
  1331. #endif
  1332.             return((int) hbr);
  1333.         }
  1334.         break;
  1335.     case WM_COMMAND:
  1336.         switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1337.         case IDOK:
  1338.             EndDialog(hDlg, TRUE);
  1339.             return(TRUE);
  1340.         case IDCANCEL:
  1341.             EndDialog(hDlg, FALSE);
  1342.             return(TRUE);
  1343.         }
  1344.         break;
  1345.     }
  1346.     return(FALSE);
  1347. }
  1348. //capture selected single frames
  1349. long
  1350. FAR PASCAL
  1351. CapFramesProc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam)
  1352. {
  1353.     char ach[MAX_PATH*2];
  1354.     char achName[MAX_PATH];
  1355.     static BOOL bFirst;
  1356.     static int iFrames;
  1357.     switch(Message) {
  1358.     case WM_INITDIALOG:
  1359.         // write out the prompt message including the capture file name
  1360.         capFileGetCaptureFile(ghWndCap, achName, sizeof(achName));
  1361.         wsprintf(ach, tmpString(IDS_PROMPT_CAPFRAMES), achName);
  1362.         SetDlgItemText(hDlg, IDD_CapMessage, ach);
  1363.         bFirst = TRUE;
  1364.         //move dialog so it doesn't obscure the capture window
  1365.         SmartWindowPosition(hDlg, ghWndCap);
  1366.         return(TRUE);
  1367.     case WM_COMMAND:
  1368.         switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1369.         case IDCANCEL:
  1370.             if (!bFirst) {
  1371.                 capCaptureSingleFrameClose(ghWndCap);
  1372.                 EndDialog(hDlg, TRUE);
  1373.             } else {
  1374.                 EndDialog(hDlg, FALSE);
  1375.             }
  1376.             return(TRUE);
  1377.         case IDOK:
  1378.             if (bFirst) {
  1379.                 bFirst = FALSE;
  1380.                 iFrames = 0;
  1381.                 capCaptureSingleFrameOpen(ghWndCap);
  1382.                 SetDlgItemText(hDlg, IDCANCEL, tmpString(IDS_CAP_CLOSE));
  1383.             }
  1384.             capCaptureSingleFrame(ghWndCap);
  1385.             iFrames++;
  1386.             wsprintf(ach, tmpString(IDS_STATUS_NUMFRAMES), iFrames);
  1387.             SetDlgItemText(hDlg, IDD_CapNumFrames, ach);
  1388.             return(TRUE);
  1389.         }
  1390.         break;
  1391.     }
  1392.     return(FALSE);
  1393. }
  1394. // enumerate all the MCI devices of a particular type and add them and
  1395. // their descriptions to a combo box list.
  1396. //
  1397. void
  1398. AddMCIDeviceNames(WORD wDeviceType, HWND hwndCB)
  1399. {
  1400.     int   nIndex;
  1401.     MCI_OPEN_PARMS mciOp;
  1402.     MCI_INFO_PARMS mciIp;
  1403.     MCI_SYSINFO_PARMS mciSIP;
  1404.     MCI_GENERIC_PARMS mciGp;
  1405.     char buf[MAXPNAMELEN + 128]; // Contains eg. NamettVideodisc1
  1406.     char buf2 [64];
  1407.     int maxdevs;
  1408.     DWORD dwRet;
  1409.     // To get the user readable names of the devices, we
  1410.     // must open all appropriate devices, and then get info.
  1411.     // MCI Open structure
  1412.     mciOp.dwCallback = 0;
  1413.     mciOp.lpstrElementName = NULL;
  1414.     mciOp.lpstrAlias = NULL;
  1415.     // MCI Info structure
  1416.     mciIp.dwCallback = 0;
  1417.     mciIp.lpstrReturn = (LPSTR) buf;
  1418.     mciIp.dwRetSize = MAXPNAMELEN - 1;
  1419.     // MCI SysInfo structure
  1420.     mciSIP.dwCallback = 0;
  1421.     mciSIP.lpstrReturn = (LPSTR) buf2;
  1422.     mciSIP.dwRetSize = sizeof (buf2);
  1423.     mciSIP.wDeviceType = wDeviceType;
  1424.     // MCI Generic structure
  1425.     mciGp.dwCallback = 0;
  1426.     // Load the combobox with the product info name, followed by
  1427.     // a comma, then a space, and then the mci device name. This allows a
  1428.     // single alphabetized list to be kept.
  1429.     // eg.
  1430.     // Pioneer Laserdisc, videodisc1
  1431.     maxdevs = CountMCIDevices((WORD)mciSIP.wDeviceType);
  1432.     for (nIndex = 0; nIndex < maxdevs; nIndex++) {
  1433.        // Get the system name eg. Videodisc1
  1434.        mciSIP.dwNumber = nIndex + 1;
  1435.        dwRet = mciSendCommand (0, MCI_SYSINFO,
  1436.                     MCI_SYSINFO_NAME,
  1437.                     (DWORD) (LPVOID) &mciSIP);
  1438.        mciOp.lpstrDeviceType =
  1439.             (LPSTR) MAKELONG (wDeviceType, nIndex);
  1440.        if (!(dwRet = mciSendCommand(0, MCI_OPEN,
  1441.                     MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID |
  1442.                     MCI_OPEN_SHAREABLE,
  1443.                     (DWORD) (LPVOID) &mciOp))) {
  1444.             if (!(dwRet = mciSendCommand (mciOp.wDeviceID, MCI_INFO,
  1445.                             MCI_WAIT | MCI_INFO_PRODUCT,
  1446.                             (DWORD) (LPVOID) &mciIp))) {
  1447.                 lstrcat (buf, ", ");         // append the delimiter
  1448.                 lstrcat (buf, buf2);         // append the system name
  1449.                 // Whew, finally put it in the listbox
  1450.                 SendMessage( hwndCB, CB_ADDSTRING, 0,
  1451.                                 (LONG)(LPSTR) buf);
  1452.             } //endif got INFO
  1453.             // Close it now
  1454.             mciSendCommand (mciOp.wDeviceID, MCI_CLOSE,
  1455.                             MCI_WAIT,
  1456.                             (DWORD) (LPVOID) &mciGp);
  1457.        } // endif OPEN
  1458.     } // endif for all devices of this type
  1459. }
  1460. //
  1461. // dialog proc to select MCI device and parameters, including start,
  1462. // stop times.
  1463. BOOL FAR PASCAL
  1464. MCISetupProc(HWND hwnd, unsigned msg, UINT wParam, LONG lParam)
  1465. {
  1466.   HWND  hwndCB;
  1467.   DWORD dw;
  1468.   char buf[MAXPNAMELEN];
  1469.   BOOL f;
  1470.   int j;
  1471.   static int nLastCBIndex = 0;
  1472.   static DWORD tdwMCIStartTime;
  1473.   static DWORD tdwMCIStopTime;
  1474.   switch (msg) {
  1475.     case WM_INITDIALOG:
  1476.        CheckRadioButton(hwnd, IDD_MCI_PLAY, IDD_MCI_STEP,
  1477.     gCapParms.fStepMCIDevice ?
  1478.                             IDD_MCI_STEP : IDD_MCI_PLAY );
  1479.         // enable averaging options only in step mode
  1480.         EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_2X), gCapParms.fStepMCIDevice);
  1481.         EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_FR), gCapParms.fStepMCIDevice);
  1482. SetDlgItemInt(hwnd, IDD_MCI_AVERAGE_FR, gCapParms.wStepCaptureAverageFrames, FALSE);
  1483.         CheckDlgButton (hwnd, IDD_MCI_AVERAGE_2X, gCapParms.fStepCaptureAt2x);
  1484.         // save current dialog time settings
  1485.         tdwMCIStartTime = gCapParms.dwMCIStartTime;
  1486.         tdwMCIStopTime  = gCapParms.dwMCIStopTime;
  1487.         TimeMSToHMSString (gCapParms.dwMCIStartTime, buf);
  1488.         SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1489.         TimeMSToHMSString (gCapParms.dwMCIStopTime, buf);
  1490.         SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1491.         // fill combo box with list of MCI devices
  1492. hwndCB = GetDlgItem( hwnd, IDD_MCI_SOURCE );
  1493.         AddMCIDeviceNames(MCI_DEVTYPE_VIDEODISC, hwndCB);
  1494.         AddMCIDeviceNames(MCI_DEVTYPE_VCR, hwndCB);
  1495.         // set the selection to whatever he chose last time through this dlg
  1496.         // default is the first entry.
  1497.         SendMessage( hwndCB, CB_SETCURSEL, nLastCBIndex, 0L);
  1498. break;
  1499.     case WM_COMMAND:
  1500. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1501.     case IDOK:
  1502.                 // i think the point of this is to ensure that
  1503.                 // the KILLFOCUS processing for the edit boxes has been done
  1504.                 // and thus the temp times are the same as the dialog text
  1505.                 SetFocus(GET_WM_COMMAND_HWND(wParam, lParam));
  1506.                 MCIGetDeviceNameAndIndex (hwnd, &nLastCBIndex, gachMCIDeviceName);
  1507.                 capSetMCIDeviceName(ghWndCap, gachMCIDeviceName) ;
  1508.                 gCapParms.fStepMCIDevice = IsDlgButtonChecked (hwnd, IDD_MCI_STEP);
  1509.                 // pick up the temp times - these were set on KILLFOCUS msgs
  1510.                 // (when we did validation and string->dword conversion
  1511.                 gCapParms.dwMCIStartTime = tdwMCIStartTime;
  1512.                 gCapParms.dwMCIStopTime  = tdwMCIStopTime;
  1513.                 gCapParms.fStepCaptureAt2x = IsDlgButtonChecked (hwnd, IDD_MCI_AVERAGE_2X);
  1514.                 gCapParms.wStepCaptureAverageFrames = GetDlgItemInt (hwnd, IDD_MCI_AVERAGE_FR, NULL, FALSE);
  1515. EndDialog(hwnd, TRUE);
  1516. break;
  1517.     case IDCANCEL:
  1518. EndDialog(hwnd, 0);
  1519. break;
  1520.             case IDD_MCI_STEP:
  1521.             case IDD_MCI_PLAY:
  1522.                 //averaging only enabled in play mode
  1523.                 f = IsDlgButtonChecked (hwnd, IDD_MCI_STEP);
  1524.                 EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_2X), f);
  1525.                 EnableWindow (GetDlgItem (hwnd, IDD_MCI_AVERAGE_FR), f);
  1526.                 break;
  1527.             case IDD_MCI_AVERAGE_FR:
  1528.                 // validate the count of frames to average 1..100
  1529.                 if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1530.                     j = GetDlgItemInt(hwnd,
  1531.                             GET_WM_COMMAND_ID(wParam, lParam), NULL, FALSE);
  1532.                     // Limit frames to average between 1 and 100
  1533.                     if (j < 1 || j > 100) {
  1534.                 SetDlgItemInt (hwnd,
  1535.                             GET_WM_COMMAND_ID(wParam, lParam), 1, FALSE);
  1536.                     }
  1537.                 }
  1538.                 break;
  1539.             case IDD_MCI_STARTSET:
  1540.     case IDD_MCI_STOPSET:
  1541.                 // set the start or stop time to be the time
  1542.                 // on the device right now.
  1543.                 // MCI devices could yield and cause us to re-enter - the
  1544.                 // simplest answer seems to be to disable the dialog
  1545.                 EnableWindow(hwnd, FALSE);
  1546.                 MCIGetDeviceNameAndIndex (hwnd, &nLastCBIndex, buf);
  1547.                 if (MCIDeviceOpen (buf)) {
  1548.                     if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTSET) {
  1549.                         if (MCIDeviceGetPosition (&tdwMCIStartTime)) {
  1550.                            TimeMSToHMSString (tdwMCIStartTime, buf);
  1551.                            SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1552.                         }
  1553.                         else {
  1554.                             MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1555.                                         MB_OK|MB_ICONEXCLAMATION);
  1556.                         }
  1557.                     }
  1558.                     else {
  1559.                         if (MCIDeviceGetPosition (&tdwMCIStopTime)) {
  1560.                             TimeMSToHMSString (tdwMCIStopTime, buf);
  1561.                             SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1562.                         }
  1563.                         else {
  1564.                             MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1565.                                         MB_OK|MB_ICONEXCLAMATION);
  1566.                         }
  1567.                     }
  1568.                     MCIDeviceClose ();
  1569.                 } else {
  1570.                     // cant open device
  1571.                     MessageBoxID(IDS_MCI_CONTROL_ERROR,
  1572.                                 MB_OK|MB_ICONEXCLAMATION);
  1573.                 }
  1574.                 EnableWindow(hwnd, TRUE);
  1575.                 break;
  1576.             case IDD_MCI_STARTTIME:
  1577.             case IDD_MCI_STOPTIME:
  1578.                 if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS) {
  1579.                     GetDlgItemText (hwnd,
  1580.                         GET_WM_COMMAND_ID(wParam, lParam), buf, sizeof (buf));
  1581.                     if ((dw = TimeHMSStringToMS (buf)) == -1) {
  1582.                         // Error in string, reset
  1583.                         MessageBeep (0);
  1584.                         if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTTIME)
  1585.                             dw = tdwMCIStartTime;
  1586.                         else
  1587.                             dw = tdwMCIStopTime;
  1588.                     }
  1589.                     if (GET_WM_COMMAND_ID(wParam, lParam) == IDD_MCI_STARTTIME) {
  1590.                         tdwMCIStartTime = dw;
  1591.                         TimeMSToHMSString (tdwMCIStartTime, buf);
  1592.                         SetDlgItemText (hwnd, IDD_MCI_STARTTIME, buf);
  1593.                     }
  1594.                     else {
  1595.                         tdwMCIStopTime = dw;
  1596.                         TimeMSToHMSString (tdwMCIStopTime, buf);
  1597.                         SetDlgItemText (hwnd, IDD_MCI_STOPTIME, buf);
  1598.                     }
  1599.                 }
  1600.                 break;
  1601. }
  1602. break;
  1603.   }
  1604.   return FALSE;
  1605. }