Windows NT 4.0 source code leak
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.

1861 lines
56 KiB

4 years ago
  1. /****************************************************************************
  2. *
  3. * capwin.c
  4. *
  5. * Main window proceedure.
  6. *
  7. * Microsoft Video for Windows Sample Capture Class
  8. *
  9. * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved.
  10. *
  11. * You have a royalty-free right to use, modify, reproduce and
  12. * distribute the Sample Files (and/or any modified version) in
  13. * any way you find useful, provided that you agree that
  14. * Microsoft has no warranty obligations or liability for any
  15. * Sample Application Files which are modified.
  16. *
  17. ***************************************************************************/
  18. #define INC_OLE2
  19. #pragma warning(disable:4103)
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <win32.h>
  23. #include <mmsystem.h>
  24. #include <msvideo.h>
  25. #include <drawdib.h>
  26. #include <mmreg.h>
  27. #include <memory.h>
  28. #include "ivideo32.h"
  29. #include "avicap.h"
  30. #include "avicapi.h"
  31. #include "cappal.h"
  32. #include "capdib.h"
  33. #include "dibmap.h"
  34. #ifdef UNICODE
  35. #include <stdlib.h>
  36. #endif
  37. // GetWindowLong assignments
  38. #define GWL_CAPSTREAM 0
  39. #define GWL_CAPVBSTATUS 4 // Used by VB Status callback
  40. #define GWL_CAPVBERROR 8 // Used by VB Error callback
  41. #define GWL_CAP_SPARE1 12 // Room to grow
  42. #define GWL_CAP_SPARE2 16 // Room to grow
  43. #define ID_PREVIEWTIMER 9
  44. //#ifdef _DEBUG
  45. #ifdef PLASTIQUE
  46. #define MB(lpsz) MessageBoxA(NULL, lpsz, "", MB_OK);
  47. #else
  48. #define MB(lpsz)
  49. #endif
  50. // #if defined _WIN32 && defined CHICAGO
  51. #if defined NO_LONGER_USED
  52. #include <mmdevldr.h>
  53. #include <vmm.h>
  54. #include "mmdebug.h"
  55. #pragma message (SQUAWK "move these defines later")
  56. #define MMDEVLDR_IOCTL_PAGEALLOCATE 7
  57. #define MMDEVLDR_IOCTL_PAGEFREE 8
  58. #define PageContig 0x00000004
  59. #define PageFixed 0x00000008
  60. //end
  61. HANDLE hMMDevLdr = NULL;
  62. /*****************************************************************************
  63. @doc INTERNAL
  64. @function HANDLE | OpenMMDEVLDR | Open a file handle to the MMDEVLDR VxD
  65. in order to access the DeviceIoControl functions.
  66. @rdesc opens a shared handle to MMDEVLDR
  67. *****************************************************************************/
  68. VOID WINAPI OpenMMDEVLDR(
  69. void)
  70. {
  71. AuxDebugEx (5, DEBUGLINE "OpenMMDEVLDR()r\n");
  72. if (hMMDevLdr)
  73. return;
  74. hMMDevLdr = CreateFile(
  75. "\\\\.\\MMDEVLDR.VXD", // magic name to attach to an already loaded vxd
  76. GENERIC_WRITE,
  77. FILE_SHARE_WRITE,
  78. NULL,
  79. OPEN_ALWAYS,
  80. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
  81. NULL);
  82. AuxDebugEx (5, DEBUGLINE "OpenMMDEVLDR returns %08Xr\n", hMMDevLdr);
  83. return;
  84. }
  85. VOID WINAPI CloseMMDEVLDR(
  86. void)
  87. {
  88. if (! hMMDevLdr)
  89. return;
  90. CloseHandle (hMMDevLdr);
  91. hMMDevLdr = NULL;
  92. }
  93. /*****************************************************************************
  94. @doc INTERNAL
  95. @function DWORD | LinPageLock | Call the VMM service LinPageLock via
  96. DeviceIoControl through MMDEVLDR.
  97. @parm DWORD | dwStartPage | Starting page of the linear region to lock.
  98. @parm DWORD | dwPageCount | Number of 4K pages to lock.
  99. @parm DWORD | fdwLinPageLock | Flags expected by the VMM service.
  100. @flag PAGEMAPGLOBAL | Return an alias to the locked region which
  101. is valid in all process contexts.
  102. @rdesc Meaningless unless PAGEMAPGLOBAL specified. If it was, then the
  103. return value is the alias pointer to the start of the linear region
  104. (NOTE: A *POINTER*, NOT a page address). The pointer will be page
  105. aligned (i.e. the low 12 bits will be zero.)
  106. *****************************************************************************/
  107. DWORD WINAPI LinPageLock(
  108. DWORD dwStartPage,
  109. DWORD dwPageCount,
  110. DWORD fdwLinPageLock)
  111. {
  112. LOCKUNLOCKPARMS lup;
  113. DWORD dwRet;
  114. DWORD cbRet;
  115. AuxDebugEx (6, DEBUGLINE "LinPageLock(%08x,%08x,%08x)\r\n",
  116. dwStartPage, dwPageCount, fdwLinPageLock);
  117. assert (hMMDevLdr != NULL);
  118. if (INVALID_HANDLE_VALUE == hMMDevLdr)
  119. return 0;
  120. lup.dwStartPage = dwStartPage;
  121. lup.dwPageCount = dwPageCount;
  122. lup.fdwOperation= fdwLinPageLock;
  123. if ( ! DeviceIoControl (hMMDevLdr,
  124. MMDEVLDR_IOCTL_LINPAGELOCK,
  125. &lup,
  126. sizeof(lup),
  127. &dwRet,
  128. sizeof(dwRet),
  129. &cbRet,
  130. NULL))
  131. {
  132. AuxDebug("LinPageLock failed!!!");
  133. dwRet = 0;
  134. }
  135. return dwRet;
  136. }
  137. /*****************************************************************************
  138. @doc INTERNAL
  139. @function DWORD | LinPageUnLock | Call the VMM service LinPageUnLock via
  140. DeviceIoControl through MMDEVLDR.
  141. @parm DWORD | dwStartPage | Starting page of the linear region to unlock.
  142. @parm DWORD | dwPageCount | Number of 4K pages to lock.
  143. @parm DWORD | fdwLinPageLock | Flags expected by the VMM service.
  144. @flag PAGEMAPGLOBAL | Return an alias to the locked region which
  145. is valid in all process contexts.
  146. @comm
  147. If PAGEMAPGLOBAL was specified on the <f LinPageLock> call, it must
  148. also be specified here. In this case, <p dwStartPage> should be the
  149. page address of the returned alias pointer in global memory.
  150. *****************************************************************************/
  151. void WINAPI LinPageUnLock(
  152. DWORD dwStartPage,
  153. DWORD dwPageCount,
  154. DWORD fdwLinPageLock)
  155. {
  156. LOCKUNLOCKPARMS lup;
  157. AuxDebugEx (6, DEBUGLINE "LinPageUnLock (%08x,%08x,%08x)\r\n",
  158. dwStartPage, dwPageCount, fdwLinPageLock);
  159. assert (hMMDevLdr != NULL);
  160. assert (INVALID_HANDLE_VALUE != hMMDevLdr);
  161. if (INVALID_HANDLE_VALUE == hMMDevLdr)
  162. return;
  163. lup.dwStartPage = dwStartPage;
  164. lup.dwPageCount = dwPageCount;
  165. lup.fdwOperation = fdwLinPageLock;
  166. DeviceIoControl (hMMDevLdr,
  167. MMDEVLDR_IOCTL_LINPAGEUNLOCK,
  168. &lup,
  169. sizeof(lup),
  170. NULL,
  171. 0,
  172. NULL,
  173. NULL);
  174. }
  175. /*+ FreeContigMem
  176. *
  177. *-==================================================================*/
  178. VOID FreeContigMem (
  179. DWORD hMemContig)
  180. {
  181. DWORD dwRet;
  182. DWORD cbRet;
  183. assert (hMMDevLdr != NULL);
  184. assert (INVALID_HANDLE_VALUE != hMMDevLdr);
  185. if (INVALID_HANDLE_VALUE == hMMDevLdr)
  186. return;
  187. DeviceIoControl (hMMDevLdr,
  188. MMDEVLDR_IOCTL_PAGEFREE,
  189. &hMemContig,
  190. sizeof(hMemContig),
  191. &dwRet,
  192. sizeof(dwRet),
  193. &cbRet,
  194. NULL);
  195. }
  196. /*+ AllocContigMem
  197. *
  198. *-==================================================================*/
  199. LPVOID AllocContigMem (
  200. DWORD cbSize,
  201. LPDWORD phMemContig)
  202. {
  203. struct _memparms {
  204. DWORD flags;
  205. DWORD nPages;
  206. } mp;
  207. struct _memret {
  208. LPVOID lpv;
  209. DWORD hMem;
  210. DWORD nPages;
  211. DWORD dwPhys;
  212. } mr;
  213. DWORD cbRet;
  214. mr.lpv = NULL;
  215. *phMemContig = 0;
  216. mp.nPages = (cbSize + 4095) >> 12;
  217. mp.flags = PageContig+PageFixed;
  218. AuxDebugEx (2, DEBUGLINE "Contig allocate %08X pages\r\n", mp.nPages);
  219. assert (hMMDevLdr != NULL);
  220. assert (INVALID_HANDLE_VALUE != hMMDevLdr);
  221. if (INVALID_HANDLE_VALUE == hMMDevLdr)
  222. return NULL;
  223. if ( ! DeviceIoControl (hMMDevLdr,
  224. MMDEVLDR_IOCTL_PAGEALLOCATE,
  225. &mp,
  226. sizeof(mp),
  227. &mr,
  228. sizeof(mr),
  229. &cbRet,
  230. NULL))
  231. {
  232. AuxDebugEx(0, "Contig Allocate failed!!!\r\n");
  233. mr.lpv = NULL;
  234. mr.hMem = 0;
  235. mr.nPages = 0;
  236. mr.dwPhys = 0;
  237. }
  238. *phMemContig = mr.hMem;
  239. AuxDebugEx(2, "Contig Allocate returns %08X\r\n", mr.lpv);
  240. return mr.lpv;
  241. }
  242. /*+
  243. *
  244. *-================================================================*/
  245. PVOID WINAPI CreateGlobalAlias (
  246. PVOID pOriginal,
  247. DWORD cbOriginal,
  248. LPDWORD pnPages)
  249. {
  250. DWORD dwStartPage;
  251. DWORD dwPageCount;
  252. DWORD dwPageOffset;
  253. DWORD dwAliasBase;
  254. PVOID pAlias;
  255. AuxDebugEx (6, DEBUGLINE "CreateGlobalAlias(%08X,%08X,..)\r\n",
  256. pOriginal, cbOriginal);
  257. dwStartPage = ((DWORD)pOriginal) >> 12;
  258. dwPageOffset = ((DWORD)pOriginal) & ((1 << 12)-1);
  259. dwPageCount = ((((DWORD)pOriginal) + cbOriginal - 1) >> 12) - dwStartPage + 1;
  260. *pnPages = 0;
  261. dwAliasBase = LinPageLock (dwStartPage, dwPageCount, PAGEMAPGLOBAL);
  262. if ( ! dwAliasBase)
  263. return NULL;
  264. pAlias = (PVOID)(dwAliasBase + dwPageOffset);
  265. *pnPages = dwPageCount;
  266. AuxDebugEx (6, DEBUGLINE "CreateGlobalAlias returns %08X nPages %d\r\n", pAlias, dwPageCount);
  267. return pAlias;
  268. }
  269. /*+
  270. *
  271. *-================================================================*/
  272. VOID WINAPI FreeGlobalAlias(
  273. PVOID pAlias,
  274. DWORD nPages)
  275. {
  276. AuxDebugEx (6, DEBUGLINE "FreeGlobalAlias(%08X,%08X)\r\n", pAlias, nPages);
  277. LinPageUnLock (((DWORD)pAlias) >> 12, nPages, PAGEMAPGLOBAL);
  278. }
  279. #endif
  280. #if defined _WIN32 && defined CHICAGO
  281. /*+ videoFrame
  282. *
  283. *-================================================================*/
  284. DWORD WINAPI videoFrame (
  285. HVIDEO hVideo,
  286. LPVIDEOHDR lpVHdr)
  287. {
  288. return vidxFrame (hVideo, lpVHdr);
  289. }
  290. #endif
  291. //
  292. // Set the overlay rectangles on capture cards which support
  293. // overlay, and then enable/disable the key color.
  294. //
  295. static void SetOverlayRectangles (LPCAPSTREAM lpcs)
  296. {
  297. HDC hdc;
  298. BOOL fVisible;
  299. RECT rc;
  300. if (!lpcs->hVideoDisplay)
  301. return;
  302. hdc = GetDC (lpcs->hwnd);
  303. fVisible = (GetClipBox (hdc, &rc) != NULLREGION);
  304. ReleaseDC (lpcs->hwnd, hdc);
  305. if (!fVisible) // disable the overlay if iconic
  306. videoStreamFini (lpcs->hVideoDisplay);
  307. else {
  308. // Destination
  309. GetClientRect (lpcs->hwnd, &rc);
  310. ClientToScreen (lpcs->hwnd, (LPPOINT)&rc);
  311. ClientToScreen (lpcs->hwnd, (LPPOINT)&rc+1);
  312. videoSetRect (lpcs->hVideoDisplay, DVM_DST_RECT, rc);
  313. // Overlay channel Source rectangle
  314. SetRect (&rc, lpcs->ptScroll.x, lpcs->ptScroll.y,
  315. lpcs->ptScroll.x + rc.right - rc.left,
  316. lpcs->ptScroll.y + rc.bottom - rc.top);
  317. videoSetRect (lpcs->hVideoDisplay, DVM_SRC_RECT, rc);
  318. videoStreamInit (lpcs->hVideoDisplay, 0L, 0L, 0L, 0L);
  319. }
  320. }
  321. // WM_POSITIONCHANGED and WM_POSITIONCHANGING don't do enough to
  322. // handle clipping of the overlay window on the Intel board,
  323. // which keys on black. Do this routine on WM_PAINT and
  324. // WM_ENTERIDLE messages.
  325. void CheckWindowMove(LPCAPSTREAM lpcs, HDC hdcWnd, BOOL fForce)
  326. {
  327. UINT wRgn;
  328. RECT rc;
  329. #ifdef _WIN32
  330. POINT ptOrg;
  331. #else
  332. DWORD dwOrg;
  333. #endif
  334. HDC hdc;
  335. BOOL f;
  336. if (!lpcs->hwnd || !lpcs->hVideoDisplay || !lpcs->fOverlayWindow)
  337. return;
  338. //
  339. // when the screen is locked for update by a window move operation
  340. // we dont want to turn off the video.
  341. //
  342. // we can tell if the screen is locked by checking a DC to the screen.
  343. //
  344. hdc = GetDC(NULL);
  345. f = GetClipBox(hdc, &rc) == NULLREGION;
  346. ReleaseDC(NULL, hdc);
  347. if (f) {
  348. lpcs->uiRegion = (UINT) -1;
  349. return;
  350. }
  351. if (fForce)
  352. lpcs->uiRegion = (UINT) -1;
  353. hdc = GetDC (lpcs->hwnd);
  354. wRgn = GetClipBox(hdc, &rc);
  355. #ifdef _WIN32
  356. GetDCOrgEx(hdc, &ptOrg);
  357. #else
  358. dwOrg = GetDCOrg(hdc);
  359. #endif
  360. ReleaseDC(lpcs->hwnd, hdc);
  361. if (wRgn == lpcs->uiRegion &&
  362. #ifdef _WIN32
  363. ptOrg.x == lpcs->ptRegionOrigin.x &&
  364. ptOrg.y == lpcs->ptRegionOrigin.y &&
  365. #else
  366. dwOrg == lpcs->dwRegionOrigin &&
  367. #endif
  368. EqualRect(&rc, &lpcs->rcRegionRect))
  369. return;
  370. lpcs->uiRegion = wRgn;
  371. #ifdef _WIN32
  372. lpcs->ptRegionOrigin = ptOrg;
  373. #else
  374. lpcs->dwRegionOrigin = dwOrg;
  375. #endif
  376. lpcs->rcRegionRect = rc;
  377. SetOverlayRectangles (lpcs);
  378. if (hdcWnd)
  379. videoUpdate (lpcs->hVideoDisplay, lpcs->hwnd, hdcWnd);
  380. else
  381. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  382. }
  383. //
  384. // Create our little world
  385. //
  386. LPCAPSTREAM CapWinCreate (HWND hwnd)
  387. {
  388. LPCAPSTREAM lpcs;
  389. WAVEFORMATEX wfex;
  390. if (!(lpcs = (LPCAPSTREAM) GlobalAllocPtr (GHND, sizeof (CAPSTREAM))))
  391. return NULL;
  392. SetWindowLong (hwnd, GWL_CAPSTREAM, (LONG)lpcs);
  393. lpcs->dwSize = sizeof (CAPSTREAM);
  394. lpcs->uiVersion = CAPSTREAM_VERSION;
  395. lpcs->hwnd = hwnd;
  396. lpcs->hInst = ghInstDll;
  397. lpcs->hWaitCursor = LoadCursor(NULL, IDC_WAIT);
  398. lpcs->hdd = DrawDibOpen();
  399. lpcs->fAudioHardware = !!waveOutGetNumDevs(); // force 1 or 0
  400. // Video defaults
  401. lpcs->sCapParms.dwRequestMicroSecPerFrame = 66667; // 15fps
  402. lpcs->sCapParms.vKeyAbort = VK_ESCAPE;
  403. lpcs->sCapParms.fAbortLeftMouse = TRUE;
  404. lpcs->sCapParms.fAbortRightMouse = TRUE;
  405. lpcs->sCapParms.wNumVideoRequested = MIN_VIDEO_BUFFERS;
  406. lpcs->sCapParms.wPercentDropForError = 10; // error msg if dropped > 10%
  407. lpcs->sCapParms.wChunkGranularity = 0;
  408. // Audio defaults to 11K, 8bit, Mono
  409. lpcs->sCapParms.fCaptureAudio = lpcs->fAudioHardware;
  410. lpcs->sCapParms.wNumAudioRequested = DEF_WAVE_BUFFERS;
  411. lpcs->fCaptureFlags |= CAP_fCapturingToDisk;
  412. lpcs->fCaptureFlags |= CAP_fDefaultVideoBuffers;
  413. lpcs->fCaptureFlags |= CAP_fDefaultAudioBuffers;
  414. wfex.wFormatTag = WAVE_FORMAT_PCM;
  415. wfex.nChannels = 1;
  416. wfex.nSamplesPerSec = 11025;
  417. wfex.nAvgBytesPerSec = 11025;
  418. wfex.nBlockAlign = 1;
  419. wfex.wBitsPerSample = 8;
  420. wfex.cbSize = 0;
  421. SendMessage (hwnd, WM_CAP_SET_AUDIOFORMAT, 0, (LONG)(LPVOID)&wfex);
  422. // Palette defaults
  423. lpcs->nPaletteColors = 256;
  424. // Capture defaults
  425. lpcs->sCapParms.fUsingDOSMemory = FALSE;
  426. lstrcpy (lpcs->achFile, TEXT("C:\\CAPTURE.AVI")); // Default capture file
  427. lpcs->fCapFileExists = fileCapFileIsAVI (lpcs->achFile);
  428. // Allocate index to 32K frames plus proportionate number of audio chunks
  429. lpcs->sCapParms.dwIndexSize = (32768ul + (32768ul / 15));
  430. lpcs->sCapParms.fDisableWriteCache = FALSE;
  431. #ifdef NEW_COMPMAN
  432. // Init the COMPVARS structure
  433. lpcs->CompVars.cbSize = sizeof (COMPVARS);
  434. lpcs->CompVars.dwFlags = 0;
  435. #endif
  436. return lpcs;
  437. }
  438. //
  439. // Destroy our little world
  440. //
  441. void CapWinDestroy (LPCAPSTREAM lpcs)
  442. {
  443. // Uh, oh. Somebodys trying to kill us while capturing
  444. if (lpcs->fCaptureFlags & CAP_fCapturingNow) {
  445. if (lpcs->fCaptureFlags & CAP_fFrameCapturingNow) {
  446. // Single frame capture in progress
  447. SingleFrameCaptureClose (lpcs);
  448. }
  449. else {
  450. // Streaming capture in progress, OR
  451. // MCI step capture in progress
  452. lpcs->fCaptureFlags |= CAP_fAbortCapture;
  453. #ifdef _WIN32
  454. // wait for capture thread to go away
  455. // we must have a capture thread
  456. WinAssert(lpcs->hThreadCapture != 0);
  457. while (MsgWaitForMultipleObjects(1, &lpcs->hThreadCapture, FALSE,
  458. INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0) {
  459. MSG msg;
  460. // just a single peekmessage with NOREMOVE will
  461. // process the inter-thread send and not affect the queue
  462. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  463. }
  464. CloseHandle(lpcs->hThreadCapture);
  465. lpcs->hThreadCapture = 0;
  466. // it should have stopped capturing
  467. WinAssert(!(lpcs->fCaptureFlags & CAP_fCapturingNow));
  468. #else
  469. while (lpcs->fCapturingNow)
  470. Yield ();
  471. #endif
  472. }
  473. }
  474. if (lpcs->idTimer)
  475. KillTimer(lpcs->hwnd, lpcs->idTimer);
  476. PalFini (lpcs);
  477. DibFini (lpcs);
  478. CapWinDisconnectHardware (lpcs);
  479. DrawDibClose (lpcs->hdd);
  480. if (lpcs->lpWaveFormat)
  481. GlobalFreePtr (lpcs->lpWaveFormat);
  482. #ifdef NEW_COMPMAN
  483. if (lpcs->CompVars.hic)
  484. ICCompressorFree(&lpcs->CompVars);
  485. #endif
  486. if (lpcs->lpInfoChunks)
  487. GlobalFreePtr(lpcs->lpInfoChunks);
  488. WinAssert (!lpcs->pAsync);
  489. GlobalFreePtr (lpcs); // Free the instance memory
  490. }
  491. UINT GetSizeOfWaveFormat (LPWAVEFORMATEX lpwf)
  492. {
  493. UINT wSize;
  494. if ((lpwf == NULL) || (lpwf->wFormatTag == WAVE_FORMAT_PCM))
  495. wSize = sizeof (PCMWAVEFORMAT);
  496. else
  497. wSize = sizeof (WAVEFORMATEX) + lpwf->cbSize;
  498. return wSize;
  499. }
  500. // Returns TRUE if we got a new frame, else FALSE
  501. // if fForce, then always get a new frame
  502. BOOL GetAFrameThenCallback (LPCAPSTREAM lpcs, BOOL fForce)
  503. {
  504. BOOL fOK = FALSE;
  505. static BOOL fRecursion = FALSE;
  506. BOOL fVisible;
  507. RECT rc;
  508. HDC hdc;
  509. if (fRecursion)
  510. return FALSE;
  511. if (!lpcs->sCapDrvCaps.fCaptureInitialized)
  512. return fOK;
  513. fRecursion = TRUE;
  514. // Update the preview window if we got a timer and not saving to disk
  515. if (lpcs->fOverlayWindow)
  516. CheckWindowMove(lpcs, NULL, FALSE);
  517. if ((!(lpcs->fCaptureFlags & CAP_fCapturingNow))
  518. || (lpcs->fCaptureFlags & CAP_fStepCapturingNow)
  519. || (lpcs->fCaptureFlags & CAP_fFrameCapturingNow)) {
  520. hdc = GetDC (lpcs->hwnd);
  521. fVisible = (GetClipBox (hdc, &rc) != NULLREGION);
  522. ReleaseDC (lpcs->hwnd, hdc);
  523. if (fForce || (fVisible && (lpcs->fLiveWindow || lpcs->CallbackOnVideoFrame))) {
  524. videoFrame (lpcs->hVideoIn, &lpcs->VidHdr);
  525. fOK = TRUE;
  526. if (lpcs->CallbackOnVideoFrame)
  527. lpcs->CallbackOnVideoFrame(lpcs->hwnd, &lpcs->VidHdr);
  528. if (fForce || lpcs->fLiveWindow) {
  529. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  530. UpdateWindow (lpcs->hwnd);
  531. }
  532. } // if visible
  533. } // if we're not streaming
  534. fRecursion = FALSE;
  535. return fOK;
  536. }
  537. // Clear the Status and Error strings via callback
  538. __inline void FAR PASCAL ClearStatusAndError (LPCAPSTREAM lpcs)
  539. {
  540. statusUpdateStatus(lpcs, 0); // Clear status
  541. errorUpdateError(lpcs, 0); // Clear error
  542. }
  543. // Process class specific commands >= WM_USER
  544. DWORD PASCAL ProcessCommandMessages (LPCAPSTREAM lpcs, UINT msg, UINT wParam, LPARAM lParam)
  545. {
  546. DWORD dwReturn = 0L;
  547. DWORD dwT;
  548. switch (msg) {
  549. // Don't clear status and error on the following innocuous msgs
  550. case WM_CAP_GET_CAPSTREAMPTR:
  551. case WM_CAP_GET_USER_DATA:
  552. case WM_CAP_DRIVER_GET_NAME:
  553. case WM_CAP_DRIVER_GET_VERSION:
  554. case WM_CAP_DRIVER_GET_CAPS:
  555. case WM_CAP_GET_AUDIOFORMAT:
  556. case WM_CAP_GET_VIDEOFORMAT:
  557. case WM_CAP_GET_STATUS:
  558. case WM_CAP_SET_SEQUENCE_SETUP:
  559. case WM_CAP_GET_SEQUENCE_SETUP:
  560. case WM_CAP_GET_MCI_DEVICE:
  561. case WM_CAP_SET_PREVIEWRATE:
  562. case WM_CAP_SET_SCROLL:
  563. #ifdef UNICODE
  564. // ...or on the ansi thunks for these messages
  565. case WM_CAP_DRIVER_GET_NAMEA:
  566. case WM_CAP_DRIVER_GET_VERSIONA:
  567. case WM_CAP_GET_MCI_DEVICEA:
  568. #endif
  569. break;
  570. default:
  571. ClearStatusAndError (lpcs);
  572. break;
  573. }
  574. switch (msg) {
  575. case WM_CAP_GET_CAPSTREAMPTR:
  576. // return a pointer to the CAPSTREAM
  577. return (DWORD) (LPVOID) lpcs;
  578. case WM_CAP_GET_USER_DATA:
  579. return lpcs->lUser;
  580. // unicode and win-16 version - see ansi thunk below
  581. case WM_CAP_DRIVER_GET_NAME:
  582. // Return the name of the capture driver in use
  583. // wParam is the length of the buffer pointed to by lParam
  584. if (!lpcs->fHardwareConnected)
  585. return FALSE;
  586. return (capInternalGetDriverDesc (lpcs->sCapDrvCaps.wDeviceIndex,
  587. (LPTSTR) lParam, (int) wParam, NULL, 0));
  588. // unicode and win-16 version - see ansi thunk below
  589. case WM_CAP_DRIVER_GET_VERSION:
  590. // Return the version of the capture driver in use as text
  591. // wParam is the length of the buffer pointed to by lParam
  592. if (!lpcs->fHardwareConnected)
  593. return FALSE;
  594. return (capInternalGetDriverDesc (lpcs->sCapDrvCaps.wDeviceIndex,
  595. NULL, 0, (LPTSTR) lParam, (int) wParam));
  596. #ifdef UNICODE
  597. // ansi/unicode thunk versions of the above entrypoint
  598. case WM_CAP_DRIVER_GET_NAMEA:
  599. if (!lpcs->fHardwareConnected)
  600. return FALSE;
  601. return capInternalGetDriverDescA(lpcs->sCapDrvCaps.wDeviceIndex,
  602. (LPSTR) lParam, (int) wParam, NULL, 0);
  603. // ansi/unicode thunk versions of the above entrypoint
  604. case WM_CAP_DRIVER_GET_VERSIONA:
  605. if (!lpcs->fHardwareConnected)
  606. return FALSE;
  607. return capInternalGetDriverDescA(lpcs->sCapDrvCaps.wDeviceIndex,
  608. NULL, 0, (LPSTR) lParam, (int) wParam);
  609. #endif
  610. case WM_CAP_DRIVER_GET_CAPS:
  611. // wParam is the size of the CAPDRIVERCAPS struct
  612. // lParam points to a CAPDRIVERCAPS struct
  613. if (!lpcs->fHardwareConnected)
  614. return FALSE;
  615. if (wParam <= sizeof (CAPDRIVERCAPS) &&
  616. !IsBadWritePtr ((LPVOID) lParam, (UINT) wParam)) {
  617. dwT = min (wParam, sizeof (CAPDRIVERCAPS));
  618. _fmemcpy ((LPVOID) lParam, (LPVOID) &lpcs->sCapDrvCaps, (UINT) dwT);
  619. dwReturn = TRUE;
  620. }
  621. break;
  622. // unicode and win-16 version - see ansi thunk below
  623. case WM_CAP_FILE_GET_CAPTURE_FILE:
  624. // wParam is the size (in characters)
  625. // lParam points to a buffer in which capture file name is copied
  626. if (lParam) {
  627. lstrcpyn ((LPTSTR) lParam, lpcs->achFile, wParam);
  628. dwReturn = TRUE;
  629. }
  630. break;
  631. #ifdef UNICODE
  632. // ansi/unicode thunk
  633. case WM_CAP_FILE_GET_CAPTURE_FILEA:
  634. if (lParam) {
  635. Iwcstombs((LPSTR) lParam, lpcs->achFile, (int) wParam);
  636. dwReturn = TRUE;
  637. }
  638. break;
  639. #endif
  640. case WM_CAP_GET_AUDIOFORMAT:
  641. // if lParam == NULL, return the size
  642. // if lParam != NULL, wParam is the size, return bytes copied
  643. if (lpcs->lpWaveFormat == NULL)
  644. return FALSE;
  645. dwT = GetSizeOfWaveFormat ((LPWAVEFORMATEX) lpcs->lpWaveFormat);
  646. if (lParam == 0)
  647. return (dwT);
  648. else {
  649. if (wParam < (UINT) dwT)
  650. return FALSE;
  651. else {
  652. hmemcpy ((LPVOID) lParam, (LPVOID) lpcs->lpWaveFormat, dwT);
  653. dwReturn = dwT;
  654. }
  655. }
  656. break;
  657. // unicode and win-16 version - see ansi thunk below
  658. case WM_CAP_GET_MCI_DEVICE:
  659. // wParam is the size in characters
  660. // lParam points to a buffer in which MCI device name is copied
  661. if (lParam) {
  662. lstrcpyn ((LPTSTR) lParam, lpcs->achMCIDevice, wParam);
  663. dwReturn = TRUE;
  664. }
  665. break;
  666. #ifdef UNICODE
  667. // ansi thunk of above
  668. case WM_CAP_GET_MCI_DEVICEA:
  669. if (lParam) {
  670. Iwcstombs( (LPSTR) lParam, lpcs->achMCIDevice, (int) wParam);
  671. dwReturn = TRUE;
  672. }
  673. break;
  674. #endif
  675. case WM_CAP_GET_STATUS:
  676. // wParam is the size of the CAPSTATUS struct pointed to by lParam
  677. if (!lpcs->fHardwareConnected)
  678. return FALSE;
  679. if (IsBadWritePtr ((LPVOID) lParam, (UINT) wParam))
  680. return FALSE;
  681. if (wParam >= sizeof (CAPSTATUS)) {
  682. LPCAPSTATUS lpcc = (LPCAPSTATUS) lParam;
  683. lpcc->fLiveWindow = lpcs->fLiveWindow;
  684. lpcc->fOverlayWindow = lpcs->fOverlayWindow;
  685. lpcc->fScale = lpcs->fScale;
  686. lpcc->ptScroll = lpcs->ptScroll;
  687. lpcc->fUsingDefaultPalette = lpcs->fUsingDefaultPalette;
  688. lpcc->fCapFileExists = lpcs->fCapFileExists;
  689. lpcc->fAudioHardware = lpcs->fAudioHardware;
  690. lpcc->uiImageWidth = lpcs->dxBits;
  691. lpcc->uiImageHeight = lpcs->dyBits;
  692. // The following are updated dynamically during capture
  693. lpcc->dwCurrentVideoFrame = lpcs->dwVideoChunkCount;
  694. lpcc->dwCurrentVideoFramesDropped = lpcs->dwFramesDropped;
  695. if (lpcs->lpWaveFormat != NULL) {
  696. lpcc->dwCurrentWaveSamples =
  697. MulDiv (lpcs->dwWaveBytes,
  698. lpcs->lpWaveFormat->nSamplesPerSec,
  699. lpcs->lpWaveFormat->nAvgBytesPerSec);
  700. }
  701. lpcc->dwCurrentTimeElapsedMS = lpcs->dwTimeElapsedMS;
  702. // Added post alpha release
  703. if (lpcs->fCaptureFlags & CAP_fCapturingNow) {
  704. lpcc->fCapturingNow = TRUE;
  705. } else {
  706. lpcc->fCapturingNow = FALSE;
  707. }
  708. lpcc->hPalCurrent = lpcs->hPalCurrent;
  709. lpcc->dwReturn = lpcs->dwReturn;
  710. lpcc->wNumVideoAllocated = lpcs->iNumVideo;
  711. lpcc->wNumAudioAllocated = lpcs->iNumAudio;
  712. dwReturn = TRUE;
  713. }
  714. break;
  715. case WM_CAP_GET_SEQUENCE_SETUP:
  716. // wParam is sizeof CAPTUREPARMS
  717. // lParam = LPCAPTUREPARMS
  718. if (wParam <= sizeof (CAPTUREPARMS) &&
  719. !IsBadWritePtr ((LPVOID) lParam, (UINT) wParam)) {
  720. dwT = min (wParam, sizeof (CAPTUREPARMS));
  721. _fmemcpy ((LPVOID) lParam, (LPVOID) &lpcs->sCapParms, (UINT) dwT);
  722. dwReturn = TRUE;
  723. }
  724. break;
  725. case WM_CAP_STOP:
  726. // Stop capturing a sequence
  727. if (lpcs->fCaptureFlags & CAP_fCapturingNow) {
  728. lpcs->fCaptureFlags |= CAP_fStopCapture;
  729. dwReturn = TRUE;
  730. }
  731. break;
  732. case WM_CAP_ABORT:
  733. // Stop capturing a sequence
  734. if (lpcs->fCaptureFlags & CAP_fCapturingNow) {
  735. lpcs->fCaptureFlags |= CAP_fAbortCapture;
  736. dwReturn = TRUE;
  737. }
  738. break;
  739. case WM_CAP_GET_VIDEOFORMAT:
  740. // if lParam == NULL, return the size
  741. // if lParam != NULL, wParam is the size, return bytes copied
  742. if (!lpcs->fHardwareConnected)
  743. return FALSE;
  744. dwT = ((LPBITMAPINFOHEADER)lpcs->lpBitsInfo)->biSize +
  745. ((LPBITMAPINFOHEADER)lpcs->lpBitsInfo)->biClrUsed * sizeof(RGBQUAD);
  746. if (lParam == 0)
  747. return dwT;
  748. else {
  749. if (wParam < (UINT) dwT)
  750. return FALSE;
  751. else {
  752. hmemcpy ((LPVOID) lParam, (LPVOID) lpcs->lpBitsInfo, dwT);
  753. dwReturn = dwT;
  754. }
  755. }
  756. break;
  757. case WM_CAP_SINGLE_FRAME_OPEN:
  758. // wParam is not used
  759. // lParam is not used
  760. if (!lpcs->fHardwareConnected)
  761. return FALSE;
  762. return SingleFrameCaptureOpen (lpcs);
  763. case WM_CAP_SINGLE_FRAME_CLOSE:
  764. // wParam is not used
  765. // lParam is not used
  766. if (!lpcs->fHardwareConnected)
  767. return FALSE;
  768. return SingleFrameCaptureClose (lpcs);
  769. case WM_CAP_SINGLE_FRAME:
  770. // wParam is not used
  771. // lParam is not used
  772. if (!lpcs->fHardwareConnected)
  773. return FALSE;
  774. return SingleFrameCapture (lpcs);
  775. // unicode and win-16 version - see ansi thunk below
  776. case WM_CAP_SET_CALLBACK_STATUS:
  777. // Set the status callback proc
  778. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  779. return FALSE;
  780. lpcs->CallbackOnStatus = (CAPSTATUSCALLBACK) lParam;
  781. lpcs->fLastStatusWasNULL = TRUE;
  782. #ifdef UNICODE
  783. lpcs->fUnicode &= ~VUNICODE_STATUSISANSI;
  784. #endif
  785. return TRUE;
  786. #ifdef UNICODE
  787. // ansi thunk for above
  788. case WM_CAP_SET_CALLBACK_STATUSA:
  789. // Set the status callback proc
  790. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  791. return FALSE;
  792. lpcs->CallbackOnStatus = (CAPSTATUSCALLBACK) lParam;
  793. lpcs->fLastStatusWasNULL = TRUE;
  794. lpcs->fUnicode |= VUNICODE_STATUSISANSI;
  795. return TRUE;
  796. #endif
  797. // unicode and win-16 version - see ansi version below
  798. case WM_CAP_SET_CALLBACK_ERROR:
  799. // Set the error callback proc
  800. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  801. return FALSE;
  802. lpcs->CallbackOnError = (CAPERRORCALLBACK) lParam;
  803. lpcs->fLastErrorWasNULL = TRUE;
  804. #ifdef UNICODE
  805. lpcs->fUnicode &= ~VUNICODE_ERRORISANSI;
  806. #endif
  807. return TRUE;
  808. #ifdef UNICODE
  809. // ansi version of above
  810. case WM_CAP_SET_CALLBACK_ERRORA:
  811. // Set the error callback proc
  812. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  813. return FALSE;
  814. lpcs->CallbackOnError = (CAPERRORCALLBACK) lParam;
  815. lpcs->fLastErrorWasNULL = TRUE;
  816. lpcs->fUnicode |= VUNICODE_ERRORISANSI;
  817. return TRUE;
  818. #endif
  819. case WM_CAP_SET_CALLBACK_FRAME:
  820. // Set the callback proc for single frame during preview
  821. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  822. return FALSE;
  823. lpcs->CallbackOnVideoFrame = (CAPVIDEOCALLBACK) lParam;
  824. return TRUE;
  825. default:
  826. break;
  827. }
  828. // Once we start capturing, don't change anything
  829. if (lpcs->fCaptureFlags & CAP_fCapturingNow)
  830. return dwReturn;
  831. switch (msg) {
  832. case WM_CAP_SET_CALLBACK_YIELD:
  833. // Set the callback proc for wave buffer processing to net
  834. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  835. return FALSE;
  836. lpcs->CallbackOnYield = (CAPYIELDCALLBACK) lParam;
  837. return TRUE;
  838. case WM_CAP_SET_CALLBACK_VIDEOSTREAM:
  839. // Set the callback proc for video buffer processing to net
  840. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  841. return FALSE;
  842. lpcs->CallbackOnVideoStream = (CAPVIDEOCALLBACK) lParam;
  843. return TRUE;
  844. case WM_CAP_SET_CALLBACK_WAVESTREAM:
  845. // Set the callback proc for wave buffer processing to net
  846. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  847. return FALSE;
  848. lpcs->CallbackOnWaveStream = (CAPWAVECALLBACK) lParam;
  849. return TRUE;
  850. case WM_CAP_SET_CALLBACK_CAPCONTROL:
  851. // Set the callback proc for frame accurate capture start/stop
  852. if (lParam != 0 && IsBadCodePtr ((FARPROC) lParam))
  853. return FALSE;
  854. lpcs->CallbackOnControl = (CAPCONTROLCALLBACK) lParam;
  855. return TRUE;
  856. case WM_CAP_SET_USER_DATA:
  857. lpcs->lUser = lParam;
  858. return TRUE;
  859. case WM_CAP_DRIVER_CONNECT:
  860. // Connect to a device
  861. // wParam contains the index of the driver
  862. // If the same driver ID is requested, skip the request
  863. // Prevents multiple Inits from VB apps
  864. if (lpcs->fHardwareConnected &&
  865. (lpcs->sCapDrvCaps.wDeviceIndex == wParam))
  866. return TRUE;
  867. // First disconnect from any (possibly) existing device
  868. SendMessage (lpcs->hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0l);
  869. // and then connect to the new device
  870. if (CapWinConnectHardware (lpcs, (UINT) wParam /*wDeviceIndex*/)) {
  871. if (!DibGetNewFormatFromDriver (lpcs)) { // Allocate our bitspace
  872. // Use the cached palette if available
  873. if (lpcs->hPalCurrent && lpcs->lpCacheXlateTable) {
  874. PalSendPaletteToDriver (lpcs, lpcs->hPalCurrent, lpcs->lpCacheXlateTable);
  875. }
  876. else
  877. PalGetPaletteFromDriver (lpcs);
  878. // Get a frame using the possibly cached palette
  879. videoFrame (lpcs->hVideoIn, &lpcs->VidHdr);
  880. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  881. lpcs->sCapDrvCaps.fCaptureInitialized = TRUE; // everything AOK!
  882. dwReturn = TRUE;
  883. }
  884. }
  885. break;
  886. case WM_CAP_DRIVER_DISCONNECT:
  887. MB ("About to disconnect from driver");
  888. // Disconnect from a device
  889. // wParam and lParam unused
  890. if (!lpcs->fHardwareConnected)
  891. return FALSE;
  892. CapWinDisconnectHardware (lpcs);
  893. DibFini (lpcs);
  894. /* PalFini (lpcs); keep the palette cached for reconnections */
  895. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  896. lpcs->sCapDrvCaps.fCaptureInitialized = FALSE;
  897. dwReturn = TRUE;
  898. break;
  899. // unicode and win-16 version - see ansi thunk below
  900. case WM_CAP_FILE_SET_CAPTURE_FILE:
  901. // lParam points to the name of the capture file
  902. if (lParam) {
  903. BOOL fAlreadyExists; // Don't create a file if new name
  904. #ifndef _WIN32
  905. OFSTRUCT of;
  906. #endif
  907. HANDLE hFile;
  908. // Check for valid file names...
  909. #ifdef _WIN32
  910. // can't use OpenFile for UNICODE names
  911. if ((hFile = CreateFile(
  912. (LPTSTR) lParam,
  913. GENERIC_WRITE,
  914. 0,
  915. NULL,
  916. OPEN_EXISTING,
  917. FILE_ATTRIBUTE_NORMAL,
  918. NULL)) == INVALID_HANDLE_VALUE) {
  919. if ((hFile = CreateFile(
  920. (LPTSTR) lParam,
  921. GENERIC_WRITE,
  922. 0,
  923. NULL,
  924. CREATE_NEW,
  925. FILE_ATTRIBUTE_NORMAL,
  926. NULL)) == INVALID_HANDLE_VALUE) {
  927. #else
  928. if ((hFile = OpenFile ((LPTSTR) lParam, &of, OF_WRITE)) == -1) {
  929. if ((hFile = OpenFile ((LPTSTR) lParam, &of, OF_CREATE | OF_WRITE)) == -1) {
  930. #endif
  931. return FALSE;
  932. }
  933. fAlreadyExists = FALSE;
  934. }
  935. else
  936. fAlreadyExists = TRUE;
  937. #ifdef _WIN32
  938. CloseHandle(hFile);
  939. #else
  940. _lclose (hFile);
  941. #endif
  942. lstrcpyn (lpcs->achFile, (LPTSTR) lParam, NUMELMS(lpcs->achFile));
  943. lpcs->fCapFileExists = fileCapFileIsAVI (lpcs->achFile);
  944. if (!fAlreadyExists) {
  945. // Delete the file created by CREATE_NEW (or OF_CREATE)
  946. // when verifying that we can write to this file location
  947. #ifdef _WIN32
  948. DeleteFile ((LPTSTR) lParam);
  949. #else
  950. OpenFile ((LPTSTR) lParam, &of, OF_DELETE);
  951. #endif
  952. }
  953. dwReturn = TRUE;
  954. }
  955. break;
  956. #ifdef UNICODE
  957. // Ansi thunk for above.
  958. case WM_CAP_FILE_SET_CAPTURE_FILEA:
  959. // lParam points to the name of the capture file
  960. if (lParam) {
  961. LPWSTR pw;
  962. int chsize;
  963. // remember the null
  964. chsize = lstrlenA( (LPSTR) lParam) + 1;
  965. pw = LocalAlloc(LPTR, chsize * sizeof(WCHAR));
  966. if (pw) {
  967. Imbstowcs(pw, (LPSTR) lParam, chsize);
  968. dwReturn = ProcessCommandMessages(lpcs, WM_CAP_FILE_SET_CAPTURE_FILEW,
  969. 0, (LPARAM)pw);
  970. LocalFree(pw);
  971. }
  972. }
  973. break;
  974. #endif
  975. case WM_CAP_FILE_ALLOCATE:
  976. // lParam contains the size to preallocate the capture file in bytes
  977. return fileAllocCapFile(lpcs, lParam);
  978. // unicode and win-16 version - see ansi thunk below
  979. case WM_CAP_FILE_SAVEAS:
  980. // lParam points to the name of the SaveAs file
  981. if (lParam) {
  982. lstrcpyn (lpcs->achSaveAsFile, (LPTSTR) lParam,
  983. NUMELMS(lpcs->achSaveAsFile));
  984. return (fileSaveCopy(lpcs));
  985. }
  986. break;
  987. #ifdef UNICODE
  988. // ansi thunk for above
  989. case WM_CAP_FILE_SAVEASA:
  990. // lParam points to the name of the SaveAs file
  991. if (lParam) {
  992. LPWSTR pw;
  993. int chsize;
  994. // remember the null
  995. chsize = lstrlenA( (LPSTR) lParam)+1;
  996. pw = LocalAlloc(LPTR, chsize * sizeof(WCHAR));
  997. if (pw) {
  998. Imbstowcs(pw, (LPSTR) lParam, chsize);
  999. dwReturn = ProcessCommandMessages(lpcs, WM_CAP_FILE_SAVEASW,
  1000. 0, (LPARAM)pw);
  1001. LocalFree(pw);
  1002. }
  1003. }
  1004. break;
  1005. #endif
  1006. case WM_CAP_FILE_SET_INFOCHUNK:
  1007. // wParam is not used
  1008. // lParam is an LPCAPINFOCHUNK
  1009. if (lParam) {
  1010. return (SetInfoChunk(lpcs, (LPCAPINFOCHUNK) lParam));
  1011. }
  1012. break;
  1013. // unicode and win-16 version - see ansi thunk below
  1014. case WM_CAP_FILE_SAVEDIB:
  1015. // lParam points to the name of the DIB file
  1016. if (lParam) {
  1017. if (lpcs->fOverlayWindow)
  1018. GetAFrameThenCallback (lpcs, TRUE /*fForce*/);
  1019. return (fileSaveDIB(lpcs, (LPTSTR)lParam));
  1020. }
  1021. break;
  1022. #ifdef UNICODE
  1023. // ansi thunk for above
  1024. case WM_CAP_FILE_SAVEDIBA:
  1025. if (lParam) {
  1026. LPWSTR pw;
  1027. int chsize;
  1028. if (lpcs->fOverlayWindow)
  1029. GetAFrameThenCallback (lpcs, TRUE /*fForce*/);
  1030. // remember the null
  1031. chsize = lstrlenA( (LPSTR) lParam)+1;
  1032. pw = LocalAlloc(LPTR, chsize * sizeof(WCHAR));
  1033. if (pw) {
  1034. Imbstowcs(pw, (LPSTR) lParam, chsize);
  1035. dwReturn = fileSaveDIB(lpcs, pw);
  1036. LocalFree(pw);
  1037. }
  1038. }
  1039. break;
  1040. #endif
  1041. case WM_CAP_EDIT_COPY:
  1042. // Copy the current image and palette to the clipboard
  1043. // wParam and lParam unused
  1044. if (!lpcs->fHardwareConnected)
  1045. return FALSE;
  1046. if (lpcs->fOverlayWindow)
  1047. GetAFrameThenCallback (lpcs, TRUE /*fForce*/);
  1048. if (lpcs->sCapDrvCaps.fCaptureInitialized && OpenClipboard (lpcs->hwnd)) {
  1049. EmptyClipboard();
  1050. // put a copy of the current palette in the clipboard
  1051. if (lpcs->hPalCurrent && lpcs->lpBitsInfo->bmiHeader.biBitCount <= 8)
  1052. SetClipboardData(CF_PALETTE, CopyPalette (lpcs->hPalCurrent));
  1053. // make a packed DIB out of the current image
  1054. if (lpcs->lpBits && lpcs->lpBitsInfo ) {
  1055. if (SetClipboardData (CF_DIB, CreatePackedDib (lpcs->lpBitsInfo,
  1056. lpcs->lpBits, lpcs->hPalCurrent)))
  1057. dwReturn = TRUE;
  1058. else
  1059. errorUpdateError (lpcs, IDS_CAP_OUTOFMEM);
  1060. }
  1061. CloseClipboard();
  1062. }
  1063. break;
  1064. case WM_CAP_SET_AUDIOFORMAT:
  1065. {
  1066. // wParam is unused
  1067. // lParam is LPWAVEFORMAT or LPWAVEFORMATEX
  1068. UINT wSize;
  1069. LPWAVEFORMATEX lpwf = (LPWAVEFORMATEX) lParam;
  1070. UINT uiError;
  1071. // Verify the waveformat is valid
  1072. uiError = waveInOpen(NULL, WAVE_MAPPER, lpwf, 0, 0L,WAVE_FORMAT_QUERY);
  1073. if (uiError) {
  1074. errorUpdateError (lpcs, IDS_CAP_WAVE_OPEN_ERROR);
  1075. return FALSE;
  1076. }
  1077. if (lpcs->lpWaveFormat)
  1078. GlobalFreePtr (lpcs->lpWaveFormat);
  1079. wSize = GetSizeOfWaveFormat (lpwf);
  1080. if (lpcs->lpWaveFormat = (LPWAVEFORMATEX)
  1081. GlobalAllocPtr (GHND, sizeof (CAPSTREAM))) {
  1082. hmemcpy (lpcs->lpWaveFormat, lpwf, (LONG) wSize);
  1083. }
  1084. dwReturn = TRUE;
  1085. }
  1086. break;
  1087. case WM_CAP_DLG_VIDEOSOURCE:
  1088. // Show the dialog which controls the video source
  1089. // NTSC vs PAL, input channel selection, etc.
  1090. // wParam and lParam are unused
  1091. if (!lpcs->fHardwareConnected)
  1092. return FALSE;
  1093. if (lpcs->dwDlgsActive & VDLG_VIDEOSOURCE)
  1094. return FALSE;
  1095. if (lpcs->sCapDrvCaps.fHasDlgVideoSource) {
  1096. lpcs->dwDlgsActive |= VDLG_VIDEOSOURCE;
  1097. videoDialog (lpcs->hVideoCapture, lpcs->hwnd, 0L );
  1098. // Changing from NTSC to PAL could affect image dimensions!!!
  1099. DibGetNewFormatFromDriver (lpcs);
  1100. PalGetPaletteFromDriver (lpcs);
  1101. // May need to inform parent of new layout here!
  1102. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  1103. UpdateWindow(lpcs->hwnd);
  1104. lpcs->dwDlgsActive &= ~VDLG_VIDEOSOURCE;
  1105. }
  1106. return (lpcs->sCapDrvCaps.fHasDlgVideoSource);
  1107. case WM_CAP_DLG_VIDEOFORMAT:
  1108. // Show the format dialog, user selects dimensions, depth, compression
  1109. // wParam and lParam are unused
  1110. if (!lpcs->fHardwareConnected)
  1111. return FALSE;
  1112. if (lpcs->dwDlgsActive & VDLG_VIDEOFORMAT)
  1113. return FALSE;
  1114. if (lpcs->sCapDrvCaps.fHasDlgVideoFormat) {
  1115. lpcs->dwDlgsActive |= VDLG_VIDEOFORMAT;
  1116. videoDialog (lpcs->hVideoIn, lpcs->hwnd, 0L );
  1117. DibGetNewFormatFromDriver (lpcs);
  1118. PalGetPaletteFromDriver (lpcs);
  1119. // May need to inform parent of new layout here!
  1120. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  1121. UpdateWindow(lpcs->hwnd);
  1122. lpcs->dwDlgsActive &= ~VDLG_VIDEOFORMAT;
  1123. }
  1124. return (lpcs->sCapDrvCaps.fHasDlgVideoFormat);
  1125. case WM_CAP_DLG_VIDEODISPLAY:
  1126. // Show the dialog which controls output.
  1127. // This dialog only affects the presentation, never the data format
  1128. // wParam and lParam are unused
  1129. if (!lpcs->fHardwareConnected)
  1130. return FALSE;
  1131. if (lpcs->dwDlgsActive & VDLG_VIDEODISPLAY)
  1132. return FALSE;
  1133. if (lpcs->sCapDrvCaps.fHasDlgVideoDisplay) {
  1134. lpcs->dwDlgsActive |= VDLG_VIDEODISPLAY;
  1135. videoDialog (lpcs->hVideoDisplay, lpcs->hwnd, 0L);
  1136. lpcs->dwDlgsActive &= ~VDLG_VIDEODISPLAY;
  1137. }
  1138. return (lpcs->sCapDrvCaps.fHasDlgVideoDisplay);
  1139. case WM_CAP_DLG_VIDEOCOMPRESSION:
  1140. #ifndef NEW_COMPMAN
  1141. return FALSE;
  1142. #else
  1143. // Show the dialog which selects video compression options.
  1144. // wParam and lParam are unused
  1145. if (!lpcs->fHardwareConnected)
  1146. return FALSE;
  1147. if (lpcs->dwDlgsActive & VDLG_COMPRESSION)
  1148. return FALSE;
  1149. lpcs->dwDlgsActive |= VDLG_COMPRESSION;
  1150. ICCompressorChoose(
  1151. lpcs->hwnd, // parent window for dialog
  1152. ICMF_CHOOSE_KEYFRAME, // want "key frame every" box
  1153. lpcs->lpBitsInfo, // input format (optional)
  1154. NULL, // input data (optional)
  1155. &lpcs->CompVars, // data about the compressor/dlg
  1156. NULL); // title bar (optional)
  1157. lpcs->dwDlgsActive &= ~VDLG_COMPRESSION;
  1158. return TRUE;
  1159. #endif
  1160. case WM_CAP_SET_VIDEOFORMAT:
  1161. // wParam is the size of the BITMAPINFO
  1162. // lParam is an LPBITMAPINFO
  1163. if (!lpcs->fHardwareConnected)
  1164. return FALSE;
  1165. if (IsBadReadPtr ((LPVOID) lParam, (UINT) wParam))
  1166. return FALSE;
  1167. return (DibNewFormatFromApp (lpcs, (LPBITMAPINFO) lParam, (UINT) wParam));
  1168. case WM_CAP_SET_PREVIEW:
  1169. // if wParam, enable preview via drawdib
  1170. if (!lpcs->fHardwareConnected)
  1171. return FALSE;
  1172. if (wParam) {
  1173. // turn off the overlay, if it is in use
  1174. if (lpcs->fOverlayWindow)
  1175. SendMessage(lpcs->hwnd, WM_CAP_SET_OVERLAY, 0, 0L);
  1176. lpcs->fLiveWindow = TRUE;
  1177. statusUpdateStatus(lpcs, IDS_CAP_STAT_LIVE_MODE);
  1178. } // endif enabling preview
  1179. else {
  1180. lpcs->fLiveWindow = FALSE;
  1181. }
  1182. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  1183. return TRUE;
  1184. case WM_CAP_SET_OVERLAY:
  1185. // if wParam, enable overlay in hardware
  1186. if (!lpcs->fHardwareConnected)
  1187. return FALSE;
  1188. if (wParam && lpcs->sCapDrvCaps.fHasOverlay) {
  1189. if (lpcs->fLiveWindow) // turn off preview mode
  1190. SendMessage(lpcs->hwnd, WM_CAP_SET_PREVIEW, 0, 0L);
  1191. lpcs->fOverlayWindow = TRUE;
  1192. statusUpdateStatus(lpcs, IDS_CAP_STAT_OVERLAY_MODE);
  1193. }
  1194. else {
  1195. lpcs->fOverlayWindow = FALSE;
  1196. videoStreamFini (lpcs->hVideoDisplay); // disable overlay on hardware
  1197. }
  1198. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  1199. return (lpcs->sCapDrvCaps.fHasOverlay);
  1200. case WM_CAP_SET_PREVIEWRATE:
  1201. // wParam contains preview update rate in mS.
  1202. // if wParam == 0 no timer is in use.
  1203. if (lpcs->idTimer) {
  1204. KillTimer(lpcs->hwnd, ID_PREVIEWTIMER);
  1205. lpcs->idTimer = 0;
  1206. }
  1207. if (wParam != 0) {
  1208. lpcs->idTimer = SetTimer (lpcs->hwnd, ID_PREVIEWTIMER,
  1209. (UINT) wParam, NULL);
  1210. }
  1211. lpcs->uTimeout = (UINT) wParam;
  1212. dwReturn = TRUE;
  1213. break;
  1214. case WM_CAP_GRAB_FRAME:
  1215. // grab a single frame
  1216. // wParam and lParam unused
  1217. if (!lpcs->fHardwareConnected)
  1218. return FALSE;
  1219. if (lpcs->sCapDrvCaps.fCaptureInitialized) {
  1220. dwReturn = (DWORD) GetAFrameThenCallback (lpcs, TRUE /*fForce*/);
  1221. // disable live and overlay mode when capturing a single frame
  1222. if (lpcs->fLiveWindow)
  1223. SendMessage(lpcs->hwnd, WM_CAP_SET_PREVIEW, 0, 0L);
  1224. else if (lpcs->fOverlayWindow)
  1225. SendMessage(lpcs->hwnd, WM_CAP_SET_OVERLAY, 0, 0L);
  1226. }
  1227. break;
  1228. case WM_CAP_GRAB_FRAME_NOSTOP:
  1229. // grab a single frame, but don't change state of overlay/preview
  1230. // wParam and lParam unused
  1231. if (!lpcs->fHardwareConnected)
  1232. return FALSE;
  1233. dwReturn = (LONG) GetAFrameThenCallback (lpcs, TRUE /*fForce*/);
  1234. break;
  1235. case WM_CAP_SEQUENCE:
  1236. // This is the main entry for streaming video capture
  1237. // wParam is unused
  1238. // lParam is unused
  1239. if (!lpcs->fHardwareConnected)
  1240. return FALSE;
  1241. if (lpcs->sCapDrvCaps.fCaptureInitialized) {
  1242. lpcs->fCaptureFlags |= CAP_fCapturingToDisk;
  1243. return (AVICapture(lpcs));
  1244. }
  1245. break;
  1246. case WM_CAP_SEQUENCE_NOFILE:
  1247. // wParam is unused
  1248. // lParam is unused
  1249. if (!lpcs->fHardwareConnected)
  1250. return FALSE;
  1251. if (lpcs->sCapDrvCaps.fCaptureInitialized) {
  1252. lpcs->fCaptureFlags &= ~CAP_fCapturingToDisk;
  1253. return (AVICapture(lpcs));
  1254. }
  1255. break;
  1256. case WM_CAP_SET_SEQUENCE_SETUP:
  1257. // wParam is sizeof CAPTUREPARMS
  1258. // lParam = LPCAPTUREPARMS
  1259. // The following were added after the Beta, init in case the client
  1260. // has a smaller structure and doesn't access them.
  1261. // WHICH BETA ?? (SteveDav) We should change the comment to include a date
  1262. lpcs->sCapParms.dwAudioBufferSize = 0;
  1263. lpcs->sCapParms.fDisableWriteCache = TRUE;
  1264. lpcs->sCapParms.AVStreamMaster = AVSTREAMMASTER_AUDIO;
  1265. if (wParam <= sizeof (CAPTUREPARMS)) {
  1266. dwT = min (sizeof (CAPTUREPARMS), wParam);
  1267. if (IsBadReadPtr ((LPVOID) lParam, (UINT) dwT))
  1268. break;
  1269. _fmemcpy ((LPVOID) &lpcs->sCapParms, (LPVOID) lParam, (UINT) dwT);
  1270. // Validate stuff that isn't handled elsewhere
  1271. if (lpcs->sCapParms.wChunkGranularity != 0 &&
  1272. lpcs->sCapParms.wChunkGranularity < 16)
  1273. lpcs->sCapParms.wChunkGranularity = 16;
  1274. if (lpcs->sCapParms.wChunkGranularity > 16384)
  1275. lpcs->sCapParms.wChunkGranularity = 16384;
  1276. if (lpcs->sCapParms.fLimitEnabled && (lpcs->sCapParms.wTimeLimit == 0))
  1277. lpcs->sCapParms.wTimeLimit = 1;
  1278. // Force Step MCI off if not using MCI control
  1279. if (lpcs->sCapParms.fStepMCIDevice && !lpcs->sCapParms.fMCIControl)
  1280. lpcs->sCapParms.fStepMCIDevice = FALSE;
  1281. // Prevent audio capture if no audio hardware
  1282. lpcs->sCapParms.fCaptureAudio =
  1283. lpcs->fAudioHardware && lpcs->sCapParms.fCaptureAudio;
  1284. // Limit audio buffers
  1285. lpcs->sCapParms.wNumAudioRequested =
  1286. min (MAX_WAVE_BUFFERS, lpcs->sCapParms.wNumAudioRequested);
  1287. // Limit video buffers
  1288. lpcs->sCapParms.wNumVideoRequested =
  1289. min (MAX_VIDEO_BUFFERS, lpcs->sCapParms.wNumVideoRequested);
  1290. dwReturn = TRUE;
  1291. }
  1292. break;
  1293. // unicode and win-16 version - see ansi thunk below
  1294. case WM_CAP_SET_MCI_DEVICE:
  1295. // lParam points to the name of the MCI Device
  1296. if (IsBadStringPtr ((LPVOID) lParam, 1))
  1297. return FALSE;
  1298. if (lParam) {
  1299. lstrcpyn (lpcs->achMCIDevice, (LPTSTR) lParam, NUMELMS(lpcs->achMCIDevice));
  1300. dwReturn = TRUE;
  1301. }
  1302. break;
  1303. #ifdef UNICODE
  1304. // ansi thunk for above
  1305. case WM_CAP_SET_MCI_DEVICEA:
  1306. // lParam points to Ansi name of MCI device
  1307. if (lParam) {
  1308. //remember the null
  1309. int chsize = lstrlenA( (LPSTR) lParam)+1;
  1310. Imbstowcs(lpcs->achMCIDevice, (LPSTR) lParam,
  1311. min(chsize, NUMELMS(lpcs->achMCIDevice)));
  1312. dwReturn = TRUE;
  1313. }
  1314. break;
  1315. #endif
  1316. case WM_CAP_SET_SCROLL:
  1317. // lParam is an LPPOINT which points to the new scroll position
  1318. if (!lpcs->fHardwareConnected)
  1319. return FALSE;
  1320. if (IsBadReadPtr ((LPVOID) lParam, sizeof (POINT)))
  1321. return FALSE;
  1322. {
  1323. LPPOINT lpP = (LPPOINT) lParam;
  1324. if (lpP->x < lpcs->dxBits && lpP->y < lpcs->dyBits) {
  1325. lpcs->ptScroll = *lpP;
  1326. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  1327. dwReturn = TRUE;
  1328. }
  1329. }
  1330. break;
  1331. case WM_CAP_SET_SCALE:
  1332. // if wParam, Scale the window to the client region?
  1333. if (!lpcs->fHardwareConnected)
  1334. return FALSE;
  1335. lpcs->fScale = (BOOL) wParam;
  1336. return TRUE;
  1337. // unicode and win-16 version - see ansi thunk below
  1338. case WM_CAP_PAL_OPEN:
  1339. // Open a new palette
  1340. // wParam is unused
  1341. // lParam contains an LPTSTR to the file
  1342. if (!lpcs->fHardwareConnected)
  1343. return FALSE;
  1344. if (IsBadStringPtr ((LPVOID) lParam, 1))
  1345. return FALSE;
  1346. return fileOpenPalette(lpcs, (LPTSTR) lParam /*lpszFileName*/);
  1347. #ifdef UNICODE
  1348. // ansi thunk for above
  1349. case WM_CAP_PAL_OPENA:
  1350. // lParam contains (ANSI) lpstr for filename
  1351. if (lParam) {
  1352. // remember the null
  1353. int chsize = lstrlenA( (LPSTR) lParam)+1;
  1354. LPWSTR pw = LocalAlloc(LPTR, chsize * sizeof(WCHAR));
  1355. if (pw) {
  1356. Imbstowcs(pw, (LPSTR) lParam, chsize);
  1357. dwReturn = fileOpenPalette(lpcs, pw);
  1358. LocalFree(pw);
  1359. }
  1360. }
  1361. break;
  1362. #endif
  1363. // unicode and win-16 version - see ansi thunk below
  1364. case WM_CAP_PAL_SAVE:
  1365. // Save the current palette in a file
  1366. // wParam is unused
  1367. // lParam contains an LPTSTR to the file
  1368. if (!lpcs->fHardwareConnected)
  1369. return FALSE;
  1370. if (IsBadStringPtr ((LPVOID) lParam, 1))
  1371. return FALSE;
  1372. return fileSavePalette(lpcs, (LPTSTR) lParam /*lpszFileName*/);
  1373. #ifdef UNICODE
  1374. // ansi thunk for above
  1375. case WM_CAP_PAL_SAVEA:
  1376. // lParam contains (ANSI) lpstr for filename
  1377. if (lParam) {
  1378. // remember the null
  1379. int chsize = lstrlenA( (LPSTR) lParam)+1;
  1380. LPWSTR pw = LocalAlloc(LPTR, chsize * sizeof(WCHAR));
  1381. if (pw) {
  1382. Imbstowcs(pw, (LPSTR) lParam, chsize);
  1383. dwReturn = fileSavePalette(lpcs, pw);
  1384. LocalFree(pw);
  1385. }
  1386. }
  1387. break;
  1388. #endif
  1389. case WM_CAP_PAL_AUTOCREATE:
  1390. // Automatically capture a palette
  1391. // wParam contains a count of the number of frames to average
  1392. // lParam contains the number of colors desired in the palette
  1393. if (!lpcs->fHardwareConnected)
  1394. return FALSE;
  1395. return CapturePaletteAuto (lpcs, (int) wParam, (int) lParam);
  1396. case WM_CAP_PAL_MANUALCREATE:
  1397. // Manually capture a palette
  1398. // wParam contains TRUE for each frame to capture, FALSE when done
  1399. // lParam contains the number of colors desired in the palette
  1400. if (!lpcs->fHardwareConnected)
  1401. return FALSE;
  1402. return CapturePaletteManual (lpcs, (BOOL) wParam, (int) lParam);
  1403. case WM_CAP_PAL_PASTE:
  1404. // Paste a palette from the clipboard, send to the driver
  1405. if (!lpcs->fHardwareConnected)
  1406. return FALSE;
  1407. if (lpcs->sCapDrvCaps.fCaptureInitialized && OpenClipboard(lpcs->hwnd)) {
  1408. HANDLE hPal;
  1409. hPal = GetClipboardData(CF_PALETTE);
  1410. CloseClipboard();
  1411. if (hPal) {
  1412. PalSendPaletteToDriver (lpcs, CopyPalette(hPal), NULL /* XlateTable */);
  1413. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  1414. dwReturn = TRUE;
  1415. }
  1416. }
  1417. break;
  1418. default:
  1419. break;
  1420. }
  1421. return dwReturn;
  1422. }
  1423. /*--------------------------------------------------------------+
  1424. | ****************** THE WINDOW PROCEDURE ********************* |
  1425. +--------------------------------------------------------------*/
  1426. LONG FAR PASCAL LOADDS EXPORT CapWndProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  1427. {
  1428. LPCAPSTREAM lpcs;
  1429. PAINTSTRUCT ps;
  1430. HDC hdc;
  1431. MSG PMsg;
  1432. int f;
  1433. lpcs = (LPCAPSTREAM) GetWindowLong (hwnd, GWL_CAPSTREAM);
  1434. if (msg >= WM_CAP_START && msg <= WM_CAP_END)
  1435. return (ProcessCommandMessages (lpcs, msg, wParam, lParam));
  1436. switch (msg) {
  1437. case WM_CREATE:
  1438. lpcs = CapWinCreate (hwnd);
  1439. break;
  1440. case WM_TIMER:
  1441. // Update the preview window if we got a timer and not saving to disk
  1442. GetAFrameThenCallback (lpcs, FALSE /*fForce*/);
  1443. // Added VFW 1.1b, Clear the queue of additional timer msgs!!!
  1444. // Even in Win32, processing frame timers can swamp all other
  1445. // activity in the app, so clear the queue after each frame is done.
  1446. // This successfully corrected a problem with the "Hit OK to continue"
  1447. // dialog not appearing bug due to app message queue
  1448. // swamping with timer messages at large
  1449. // image dimensions and preview rates.
  1450. PeekMessage (&PMsg, hwnd, WM_TIMER, WM_TIMER,PM_REMOVE|PM_NOYIELD);
  1451. break;
  1452. case WM_CLOSE:
  1453. break;
  1454. case WM_DESTROY:
  1455. CapWinDestroy (lpcs);
  1456. break;
  1457. case WM_PALETTECHANGED:
  1458. if (lpcs->hdd == NULL)
  1459. break;
  1460. hdc = GetDC(hwnd);
  1461. if (f = DrawDibRealize(lpcs->hdd, hdc, TRUE /*fBackground*/))
  1462. InvalidateRect(hwnd,NULL,TRUE);
  1463. ReleaseDC(hwnd,hdc);
  1464. return f;
  1465. case WM_QUERYNEWPALETTE:
  1466. if (lpcs->hdd == NULL)
  1467. break;
  1468. hdc = GetDC(hwnd);
  1469. f = DrawDibRealize(lpcs->hdd, hdc, FALSE);
  1470. ReleaseDC(hwnd, hdc);
  1471. if (f)
  1472. InvalidateRect(hwnd, NULL, TRUE);
  1473. return f;
  1474. case WM_SIZE:
  1475. case WM_MOVE:
  1476. if (lpcs->fOverlayWindow) // Make the driver paint the key color
  1477. InvalidateRect(hwnd, NULL, TRUE);
  1478. break;
  1479. case WM_WINDOWPOSCHANGED:
  1480. if (lpcs->fOverlayWindow) // Make the driver paint the key color
  1481. InvalidateRect(hwnd, NULL, TRUE);
  1482. return 0;
  1483. case WM_ERASEBKGND:
  1484. return 0; // don't bother to erase it
  1485. case WM_PAINT:
  1486. hdc = BeginPaint(hwnd, &ps);
  1487. if (lpcs->fOverlayWindow) {
  1488. CheckWindowMove(lpcs, ps.hdc, TRUE);
  1489. }
  1490. else {
  1491. #ifdef _WIN32
  1492. SetWindowOrgEx(hdc, lpcs->ptScroll.x, lpcs->ptScroll.y, NULL);
  1493. #else
  1494. SetWindowOrg(hdc, lpcs->ptScroll.x, lpcs->ptScroll.y);
  1495. #endif
  1496. DibPaint(lpcs, hdc);
  1497. }
  1498. EndPaint(hwnd, &ps);
  1499. break;
  1500. default:
  1501. break;
  1502. }
  1503. return DefWindowProc(hwnd, msg, wParam, lParam);
  1504. }
  1505. #if 0
  1506. void dummyTest ()
  1507. {
  1508. HWND hwnd;
  1509. FARPROC fpProc;
  1510. DWORD dwSize;
  1511. WORD wSize;
  1512. BOOL f;
  1513. int i;
  1514. char szName[80];
  1515. char szVer[80];
  1516. DWORD dwMS;
  1517. int iFrames, iColors;
  1518. char s;
  1519. LPPOINT lpP;
  1520. capSetCallbackOnError(hwnd, fpProc);
  1521. capSetCallbackOnStatus(hwnd, fpProc);
  1522. capSetCallbackOnYield(hwnd, fpProc);
  1523. capSetCallbackOnFrame(hwnd, fpProc);
  1524. capSetCallbackOnVideoStream(hwnd, fpProc);
  1525. capSetCallbackOnWaveStream(hwnd, fpProc);
  1526. capDriverConnect(hwnd, i);
  1527. capDriverDisconnect(hwnd);
  1528. capDriverGetName(hwnd, szName, wSize);
  1529. capDriverGetVersion(hwnd, szVer, wSize);
  1530. capDriverGetCaps(hwnd, s, wSize);
  1531. capFileSetCaptureFile(hwnd, szName);
  1532. capFileGetCaptureFile(hwnd, szName, wSize);
  1533. capFileAlloc(hwnd, dwSize);
  1534. capFileSaveAs(hwnd, szName);
  1535. capEditCopy(hwnd);
  1536. capSetAudioFormat(hwnd, s, wSize);
  1537. capGetAudioFormat(hwnd, s, wSize);
  1538. capGetAudioFormatSize(hwnd);
  1539. capDlgVideoFormat(hwnd);
  1540. capDlgVideoSource(hwnd);
  1541. capDlgVideoDisplay(hwnd);
  1542. capPreview(hwnd, f);
  1543. capPreviewRate(hwnd, dwMS);
  1544. capOverlay(hwnd, f);
  1545. capPreviewScale(hwnd, f);
  1546. capGetStatus(hwnd, s, wSize);
  1547. capSetScrollPos(hwnd, lpP);
  1548. capGrabFrame(hwnd);
  1549. capGrabFrameNoStop(hwnd);
  1550. capCaptureSequence(hwnd);
  1551. capCaptureSequenceNoFile(hwnd);
  1552. capCaptureGetSetup(hwnd, s, wSize);
  1553. capCaptureSetSetup(hwnd, s, wSize);
  1554. capCaptureSingleFrameOpen(hwnd);
  1555. capCaptureSingleFrameClose(hwnd);
  1556. capCaptureSingleFrame(hwnd);
  1557. capSetMCIDeviceName(hwnd, szName);
  1558. capGetMCIDeviceName(hwnd, szName, wSize);
  1559. capPalettePaste(hwnd);
  1560. capPaletteAuto(hwnd, iFrames, iColors);
  1561. }
  1562. #endif