|
|
/**************************************************************************
* * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * PURPOSE. * * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved. * **************************************************************************/ /****************************************************************************
* * vidcap.c: WinMain and command processing * * Vidcap32 Source code * ***************************************************************************/ #include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <dos.h>
#include <shellapi.h>
#include <vfw.h>
#include <tchar.h>
#include "vidcap.h"
#include "vidframe.h"
#include "profile.h"
// generic window control classes
#include "toolbar.h"
#include "status.h"
#include "arrow.h"
#include "rlmeter.h"
#include "help.h"
// the standard toolbar class 'exports' this but doesn't put it in the
// header file
extern TCHAR szToolBarClass[];//HACK!
// height of the buttons on a toolbar - depends on the
// size of the bitmaps within IDBMP_TOOLBAR
#define BUTTONWIDTH 24
#define BUTTONHEIGHT 22
#define TOOLBAR_HEIGHT BUTTONHEIGHT + 6
// description and layout of toolbar buttons within IDBMP_TOOLBAR
#define APP_NUMTOOLS 8
#define BTN_SETFILE 0
#define BTN_EDITCAP 1
#define BTN_LIVE 2
#define BTN_CAPFRAME 3
#define BTN_CAPSEL 4
#define BTN_CAPAVI 5
#define BTN_CAPPAL 6
#define BTN_OVERLAY 7
static int aiButton[] = {BTN_SETFILE, BTN_EDITCAP, BTN_LIVE, BTN_OVERLAY, BTN_CAPFRAME, BTN_CAPSEL, BTN_CAPAVI, BTN_CAPPAL }; static int aiState[] = {BTNST_FOCUSUP, BTNST_UP, BTNST_UP, BTNST_UP, BTNST_UP, BTNST_UP, BTNST_UP, BTNST_UP}; static int aiType[] ={BTNTYPE_PUSH, BTNTYPE_PUSH, BTNTYPE_CHECKBOX, BTNTYPE_CHECKBOX, BTNTYPE_PUSH, BTNTYPE_PUSH, BTNTYPE_PUSH, BTNTYPE_PUSH}; static int aiString[] = { IDC_toolbarSETFILE, IDC_toolbarEDITCAP, IDC_toolbarLIVE, IDC_toolbarOVERLAY, IDC_toolbarCAPFRAME, IDC_toolbarCAPSEL, IDC_toolbarCAPAVI, IDC_toolbarCAPPAL }; static int aPos[] = { 10, 35, 75, 100, 150, 175, 200, 225 };
//
// Global Variables
//
// preferences
BOOL gbCentre; BOOL gbToolBar; BOOL gbStatusBar; BOOL gbAutoSizeFrame; int gBackColour;
BOOL gbLive, gbOverlay; BOOL gfIsRTL;
// saved window sizes
int gWinX, gWinY; int gWinCX, gWinCY; int gWinShow;
// command line options
int gCmdLineDeviceID = -1;
TCHAR gachAppName[] = "vidcapApp" ; TCHAR gachIconName[] = "vidcapIcon" ; TCHAR gachMenuName[] = "vidcapMenu" ; TCHAR gachAppTitle[20]; //VidCap
TCHAR gachCaptureFile[_MAX_PATH]; TCHAR gachMCIDeviceName[21]; TCHAR gachString[128] ; TCHAR gachBuffer[200] ; TCHAR gachLastError[256];
HINSTANCE ghInstApp ; HWND ghWndMain = NULL ; HWND ghWndFrame; // child of ghWndMain - frames and scrolls
HWND ghWndCap ; // child of ghWndCap
HWND ghWndToolBar; HWND ghWndStatus;
HANDLE ghAccel ; WORD gwDeviceIndex ; WORD gwPalFrames = DEF_PALNUMFRAMES ; WORD gwPalColors = DEF_PALNUMCOLORS ; WORD gwCapFileSize ;
CAPSTATUS gCapStatus ; CAPDRIVERCAPS gCapDriverCaps ; CAPTUREPARMS gCapParms ; BOOL gbHaveHardware; UINT gDriverCount; BOOL gbIsScrncap; // For Scrncap.drv, we must yield
BOOL gbInLayout; UINT gAVStreamMaster;
HANDLE ghwfex ; LPWAVEFORMATEX glpwfex ;
FARPROC fpErrorCallback ; FARPROC fpStatusCallback ; FARPROC fpYieldCallback ;
// set to false when we capture a palette (or if we have warned him and
// he says its ok
BOOL bDefaultPalette = TRUE;
#ifdef DEBUG
int nTestCount; #endif
// c-runtime cmd line
extern char ** __argv; extern int __argc;
#define LimitRange(Val,Low,Hi) (max(Low,(min(Val,Hi))))
//
// Function prototypes
//
LRESULT FAR PASCAL MainWndProc(HWND, UINT, WPARAM, LPARAM) ; LRESULT FAR PASCAL ErrorCallbackProc(HWND, int, LPSTR) ; LRESULT FAR PASCAL StatusCallbackProc(HWND, int, LPSTR) ; LRESULT FAR PASCAL YieldCallbackProc(HWND) ; void vidcapSetLive(BOOL bLive); void vidcapSetOverlay(BOOL bOverlay); void vidcapSetCaptureFile(LPTSTR pFileName);
BOOL vidcapRegisterClasses(HINSTANCE hInstance, HINSTANCE hPrevInstance); BOOL vidcapCreateWindows(HINSTANCE hInstance, HINSTANCE hPrevInstance); void vidcapLayout(HWND hwnd); BOOL vidcapEnumerateDrivers(HWND hwnd); BOOL vidcapInitHardware(HWND hwnd, HWND hwndCap, UINT uIndex); void vidcapReadProfile(void); void vidcapWriteProfile(void); void vidcapReadSettingsProfile(void); void vidcapWriteSettingsProfile(void);
/* --- initialisation -------------------------------------------------- */
//
// WinMain: Application Entry Point Function
//
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { ///////////////////////////////////////////////////////////////////////
// hInstance: handle for this instance
// hPrevInstance: handle for possible previous instances
// lpszCmdLine: long pointer to exec command line
// nCmdShow: Show code for main window display
///////////////////////////////////////////////////////////////////////
MSG msg ; BOOL bValidCmdline; BOOL fOK; int i; char ach[2];
ghInstApp = hInstance ; LoadString(hInstance, IDS_CAP_RTL, ach, sizeof(ach)); gfIsRTL = ach[0] == '1'; gCmdLineDeviceID = -1;
// read the app title string - used in several message boxes
LoadString(hInstance, IDS_APP_TITLE, gachAppTitle, sizeof(gachAppTitle));
// read defaults out of the registry
vidcapReadProfile();
// look for cmd line options
bValidCmdline = TRUE;
for ( i = 1; (i < __argc) && bValidCmdline; i++) { if ((__argv[i][0] == '/') || (__argv[i][0] == '-')) {
switch(__argv[i][1]) { case 'D': case 'd': if (gCmdLineDeviceID < 0) { // allow "-d0" and "-d 0"
PSTR p = &__argv[i][2];
if ((*p == 0) && ((i+1) < __argc)) { p = __argv[++i]; }
gCmdLineDeviceID = atoi(p); } else { bValidCmdline = FALSE; } break;
default: bValidCmdline = FALSE; } } else { bValidCmdline = FALSE; } } if (gCmdLineDeviceID == -1) gCmdLineDeviceID = 0;
if (!bValidCmdline) { MessageBoxID(IDS_ERR_CMDLINE, MB_OK|MB_ICONEXCLAMATION); return(0); }
if (!vidcapRegisterClasses(hInstance, hPrevInstance)) {
MessageBoxID(IDS_ERR_REGISTER_CLASS, #ifdef BIDI
MB_RTL_READING | #endif
MB_ICONEXCLAMATION) ; return 0 ; }
if (!vidcapCreateWindows(hInstance, hPrevInstance)) {
MessageBoxID(IDS_ERR_CREATE_WINDOW, #ifdef BIDI
MB_RTL_READING | #endif
MB_ICONEXCLAMATION | MB_OK) ; return IDS_ERR_CREATE_WINDOW ; }
// Get the default setup for video capture from the AVICap window
capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
// Overwrite the defaults with settings we have saved in the profile
vidcapReadSettingsProfile();
// Show the main window before connecting the hardware as this can be
// time consuming and the user should see something happening first...
ShowWindow(ghWndMain, nCmdShow) ; UpdateWindow(ghWndMain) ; ghAccel = LoadAccelerators(hInstance, "VIDCAP") ;
// Create a list of all capture drivers and append them to the Options menu
if (!(fOK = vidcapEnumerateDrivers(ghWndMain))) { LoadString(ghInstApp, IDS_ERR_FIND_HARDWARE, gachLastError, sizeof(gachLastError)/sizeof(*gachLastError)); } // Try to connect to a capture driver
else if (fOK = vidcapInitHardware(ghWndMain, ghWndCap, bValidCmdline ? gCmdLineDeviceID : 0)) { // Hooray, we now have a capture driver connected!
vidcapSetCaptureFile(gachCaptureFile); } if (!fOK) { if (!DoDialog(ghWndMain, IDD_NoCapHardware, NoHardwareDlgProc, (LONG_PTR) (LPSTR) gachLastError)) { // The user has asked to abort, since no driver was available
PostMessage(ghWndMain, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_F_EXIT, 0, 0)); } } // All set; get and process messages
while (GetMessage(&msg, NULL, 0, 0)) { if (! TranslateAccelerator(ghWndMain, ghAccel, &msg)) { TranslateMessage(&msg) ; DispatchMessage(&msg) ; } }
return (int) msg.wParam; } // End of WinMain
BOOL vidcapRegisterClasses(HINSTANCE hInstance, HINSTANCE hPrevInstance) { WNDCLASS wc;
if (! hPrevInstance) { // If it's the first instance, register the window class
wc.lpszClassName = gachAppName ; wc.hInstance = hInstance ; wc.lpfnWndProc = MainWndProc ; wc.hCursor = LoadCursor(NULL, IDC_ARROW) ; wc.hIcon = LoadIcon(hInstance, gachIconName) ; wc.lpszMenuName = gachMenuName ; wc.hbrBackground = GetStockObject(WHITE_BRUSH) ; wc.style = CS_HREDRAW | CS_VREDRAW ; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ;
if (!RegisterClass(&wc)) { return(FALSE); }
if (!ArrowInit(hInstance)) { return(FALSE); }
if (!RLMeter_Register(hInstance)) { return(FALSE); } }
if (!toolbarInit(hInstance, hPrevInstance)) { return(FALSE); }
if (!statusInit(hInstance, hPrevInstance)) { return(FALSE); } return(TRUE);
}
BOOL vidcapCreateWindows(HINSTANCE hInstance, HINSTANCE hPrevInstance) {
POINT pt; RECT rc; TOOLBUTTON tb; int i;
// Create Application's Main window
ghWndMain = CreateWindowEx( gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0, gachAppName, gachAppTitle, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN | WS_OVERLAPPED, gWinX, gWinY, gWinCX, gWinCY, NULL, NULL, hInstance, 0) ;
if (ghWndMain == NULL) { return(FALSE); }
/*
* create a vidframe child window - this will create a child * AVICAP window within itself. * * Don't worry about size and position - vidcapLayout will do this * later (once we know the video format size). */ ghWndFrame = vidframeCreate( ghWndMain, hInstance, hPrevInstance, 0, 0, 0, 0, &ghWndCap);
if ((ghWndFrame == NULL) || (ghWndCap == NULL)) { return(FALSE); }
// Register the status and error callbacks before driver connects
// so we can get feedback about the connection process
fpErrorCallback = MakeProcInstance((FARPROC)ErrorCallbackProc, ghInstApp) ; capSetCallbackOnError(ghWndCap, fpErrorCallback) ;
fpStatusCallback = MakeProcInstance((FARPROC)StatusCallbackProc, ghInstApp) ; capSetCallbackOnStatus(ghWndCap, fpStatusCallback) ;
// We'll only install a yield callback later if using Scrncap.drv
fpYieldCallback = MakeProcInstance((FARPROC)YieldCallbackProc, ghInstApp) ;
/*
* CREATE THE TOOL BAR WINDOW */ /* NOTE: let vidcapLayout() position it */ ghWndToolBar = CreateWindowEx( gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0, szToolBarClass, NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP| WS_CLIPSIBLINGS, 0, 0, 0, 0, ghWndMain, NULL, hInstance, NULL);
if (ghWndToolBar == NULL) { return(FALSE); }
/* set the bitmap and button size to be used for this toolbar */ pt.x = BUTTONWIDTH; pt.y = BUTTONHEIGHT; toolbarSetBitmap(ghWndToolBar, hInstance, IDBMP_TOOLBAR, pt);
for (i = 0; i < APP_NUMTOOLS; i++) { rc.left = aPos[i]; rc.top = 2; rc.right = rc.left + pt.x; rc.bottom = rc.top + pt.y; tb.rc = rc; tb.iButton = aiButton[i]; tb.iState = aiState[i]; tb.iType = aiType[i]; tb.iString = aiString[i]; toolbarAddTool(ghWndToolBar, tb); }
// create the status bar - let vidcapLayout do the positioning
ghWndStatus = CreateWindowEx( gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0, szStatusClass, NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|WS_CLIPSIBLINGS, 0, 0, 0, 0, ghWndMain, NULL, hInstance, NULL); if (ghWndStatus == NULL) { return(FALSE); }
return(TRUE);
}
/*
* Enumerate the potential capture drivers and add the list to the Options * menu. This function is only called once at startup. * Returns FALSE if no drivers are available. */ BOOL vidcapEnumerateDrivers(HWND hwnd) { TCHAR achDeviceVersion[80] ; TCHAR achDeviceAndVersion[160] ; UINT uIndex ; HMENU hMenuSub;
gDriverCount = 0 ;
hMenuSub = GetSubMenu (GetMenu (hwnd), 2); // Options menu
for (uIndex = 0 ; uIndex < MAXVIDDRIVERS ; uIndex++) { if (capGetDriverDescription(uIndex, (LPSTR)achDeviceAndVersion, sizeof(achDeviceAndVersion), (LPSTR)achDeviceVersion, sizeof(achDeviceVersion))) { // Concatenate the device name and version strings
lstrcat (achDeviceAndVersion, ", "); lstrcat (achDeviceAndVersion, achDeviceVersion);
AppendMenu (hMenuSub, MF_STRING, IDM_O_DRIVER0 + uIndex, achDeviceAndVersion); gDriverCount++; } else break; }
// Now refresh menu, position capture window, start driver etc
DrawMenuBar(ghWndMain) ;
return (gDriverCount); }
/*
* Connect the capture window to a capture driver. * uIndex specifies the index of the driver to use. * Returns TRUE on success, or FALSE if the driver connection failed. */ BOOL vidcapInitHardware(HWND hwnd, HWND hwndCap, UINT uIndex) { UINT uError ; UINT uI; HMENU hMenu; TCHAR szName[MAX_PATH]; TCHAR szVersion[MAX_PATH];
// Since the driver may not provide a reliable error string
// provide a default
LoadString(ghInstApp, IDS_ERR_FIND_HARDWARE, gachLastError, sizeof(gachLastError)/sizeof(*gachLastError));
// Try connecting to the capture driver
if (uError = capDriverConnect(hwndCap, uIndex)) { gbHaveHardware = TRUE; gwDeviceIndex = (WORD) uIndex; } else { gbHaveHardware = FALSE; gbLive = FALSE; gbOverlay = FALSE; }
// Get the capabilities of the capture driver
capDriverGetCaps(hwndCap, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)) ;
// Get the settings for the capture window
capGetStatus(hwndCap, &gCapStatus , sizeof(gCapStatus));
// Modify the toolbar buttons
toolbarModifyState(ghWndToolBar, BTN_CAPFRAME, gbHaveHardware ? BTNST_UP : BTNST_GRAYED); toolbarModifyState(ghWndToolBar, BTN_CAPSEL, gbHaveHardware ? BTNST_UP : BTNST_GRAYED); toolbarModifyState(ghWndToolBar, BTN_CAPAVI, gbHaveHardware ? BTNST_UP : BTNST_GRAYED); toolbarModifyState(ghWndToolBar, BTN_LIVE, gbHaveHardware ? BTNST_UP : BTNST_GRAYED);
// Is overlay supported?
toolbarModifyState(ghWndToolBar, BTN_OVERLAY, (gbHaveHardware && gCapDriverCaps.fHasOverlay) ? BTNST_UP : BTNST_GRAYED);
// Can the device create palettes?
toolbarModifyState(ghWndToolBar, BTN_CAPPAL, (gbHaveHardware && gCapDriverCaps.fDriverSuppliesPalettes) ? BTNST_UP : BTNST_GRAYED);
// Check the appropriate driver in the Options menu
hMenu = GetMenu (hwnd); for (uI = 0; uI < gDriverCount; uI++) { CheckMenuItem (hMenu, IDM_O_DRIVER0 + uI, MF_BYCOMMAND | ((uIndex == uI) ? MF_CHECKED : MF_UNCHECKED)); }
// Unlike all other capture drivers, Scrncap.drv needs to use
// a Yield callback, and we don't want to abort on mouse clicks,
// so determine if the current driver is Scrncap.drv
capGetDriverDescription (uIndex, szName, sizeof (szName), szVersion, sizeof (szVersion));
// Set a flag if we're using Scrncap.drv
gbIsScrncap = (_tcsstr (szName, "Screen Capture") != NULL);
// Get video format and adjust capture window
vidcapLayout(ghWndMain); InvalidateRect(ghWndMain, NULL, TRUE);
// set the preview rate (units are millisecs)
capPreviewRate(hwndCap, gbHaveHardware ? 33 : 0);
// set live/overlay to default
vidcapSetLive(gbLive); vidcapSetOverlay(gbOverlay);
_tcscat (szName, ", "); _tcscat (szName, szVersion);
statusUpdateStatus(ghWndStatus, gbHaveHardware ? szName : gachLastError);
return gbHaveHardware; }
/*
* layout the main window. Put the toolbar at the top and the status * line at the bottom, and then give all the rest to vidframe, * - it will centre or scroll the AVICAP window appropriately. */ void vidcapLayout(HWND hwnd) { RECT rc; RECT rw; int cy; int cyBorder, cxBorder; int cyTotal; int cxToolbar; int cyMenuAndToolbarAndCaption;
gbInLayout = TRUE; // So that we process WM_GETMINMAXINFO normally
/* for both the toolbar and status bar window,
* we want just one of the four borders. We do this * by setting the WS_BORDER style, and sizing and positioning * the window so that the 3 unwanted borders are outside the parent. */ cyBorder = GetSystemMetrics(SM_CYBORDER); cxBorder = GetSystemMetrics(SM_CXBORDER);
// Figure out the height of the menu, toolbar, and caption
GetWindowRect (hwnd, &rw); GetClientRect (hwnd, &rc);
ClientToScreen (hwnd, (LPPOINT) &rc); cyMenuAndToolbarAndCaption = (rc.top - rw.top) + TOOLBAR_HEIGHT;
cxToolbar = aPos[APP_NUMTOOLS - 1] + BUTTONWIDTH * 3;
if (gbAutoSizeFrame && gbHaveHardware && gCapStatus.uiImageWidth) { cyTotal = gCapStatus.uiImageHeight + cyMenuAndToolbarAndCaption + (gbStatusBar ? statusGetHeight() : 0) + cyBorder * 2 + 12; // vidFrame height
// Never make the frame smaller than the toolbar
if (gCapStatus.uiImageWidth >= (UINT) cxToolbar) { SetWindowPos( hwnd, 0, // placement-order handle
0, // horizontal position
0, // vertical position
gCapStatus.uiImageWidth + cxBorder * 24, // width
cyTotal, // height
SWP_NOZORDER | SWP_NOMOVE // window-positioning flags
); } else { SetWindowPos( hwnd, 0, // placement-order handle
0, // horizontal position
0, // vertical position
cxToolbar, // width
cyTotal, // height
SWP_NOZORDER | SWP_NOMOVE // window-positioning flags
); } }
GetClientRect(hwnd, &rc);
if (gbToolBar) { // put the toolbar at the top - in fact, just off the top so as to
// hide it's border
MoveWindow( ghWndToolBar, -cxBorder, -cyBorder, RECTWIDTH(rc)+ (cxBorder * 2), TOOLBAR_HEIGHT, TRUE); rc.top += (TOOLBAR_HEIGHT - cyBorder); } else { MoveWindow(ghWndToolBar, 0, 0, 0, 0, TRUE); }
// status bar at the bottom
if (gbStatusBar) { cy = statusGetHeight() + cyBorder; MoveWindow( ghWndStatus, -cxBorder, rc.bottom - cy, RECTWIDTH(rc) + (2 * cxBorder), cy + cyBorder, TRUE); rc.bottom -= cy; } else { MoveWindow(ghWndStatus, 0, 0, 0, 0, TRUE); }
// rest of window goes to vidframe window
MoveWindow( ghWndFrame, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc), TRUE);
// Always layout the frame window, since it is aligned on a
// DWORD boundary for maximum codec drawing efficiency
vidframeLayout(ghWndFrame, ghWndCap);
gbInLayout = FALSE; }
/*
* initialise settings from the profile used before window creation time */ void vidcapReadProfile(void) { // read defaults out of the registry
gbCentre = mmGetProfileFlag(gachAppTitle, "CenterImage", TRUE); gbToolBar = mmGetProfileFlag(gachAppTitle, "ToolBar", TRUE); gbStatusBar = mmGetProfileFlag(gachAppTitle, "StatusBar", TRUE); gbAutoSizeFrame = mmGetProfileFlag(gachAppTitle, "AutoSizeFrame", TRUE); gBackColour = mmGetProfileInt(gachAppTitle, "BackgroundColor", IDD_PrefsLtGrey);
gWinX = mmGetProfileInt(gachAppTitle, "WindowXPos", (UINT) CW_USEDEFAULT); if (gWinX != (UINT) CW_USEDEFAULT) gWinX = LimitRange(gWinX, 0, GetSystemMetrics (SM_CXSCREEN) - 40); gWinY = mmGetProfileInt(gachAppTitle, "WindowYPos", 0); gWinY = LimitRange(gWinY, 0, GetSystemMetrics (SM_CYSCREEN) - 40); gWinCX = mmGetProfileInt(gachAppTitle, "WindowWidth", 320); gWinCX = LimitRange(gWinCX, 20, GetSystemMetrics (SM_CXSCREEN)); gWinCY = mmGetProfileInt(gachAppTitle, "WindowHeight", 240); gWinCY = LimitRange(gWinCY, 20, GetSystemMetrics (SM_CYSCREEN)); gWinShow = mmGetProfileInt(gachAppTitle, "WindowShow", SW_SHOWDEFAULT); gWinShow = LimitRange(gWinShow, SW_SHOWNORMAL, SW_SHOWDEFAULT);
gbOverlay = mmGetProfileInt(gachAppTitle, "OverlayWindow", FALSE); gbLive = mmGetProfileInt(gachAppTitle, "LiveWindow", TRUE); }
void vidcapWriteProfile(void) { mmWriteProfileFlag(gachAppTitle, "CenterImage", gbCentre, TRUE); mmWriteProfileFlag(gachAppTitle, "ToolBar", gbToolBar, TRUE); mmWriteProfileFlag(gachAppTitle, "StatusBar", gbStatusBar, TRUE); mmWriteProfileFlag(gachAppTitle, "AutoSizeFrame", gbAutoSizeFrame, TRUE); mmWriteProfileInt(gachAppTitle, "BackgroundColor", gBackColour, IDD_PrefsLtGrey);
mmWriteProfileInt(gachAppTitle, "WindowXPos", gWinX, (UINT) CW_USEDEFAULT); mmWriteProfileInt(gachAppTitle, "WindowYPos", gWinY, 0); mmWriteProfileInt(gachAppTitle, "WindowWidth", gWinCX, 320); mmWriteProfileInt(gachAppTitle, "WindowHeight", gWinCY, 240); mmWriteProfileInt(gachAppTitle, "WindowShow", gWinShow, SW_SHOWDEFAULT);
mmWriteProfileInt(gachAppTitle, "OverlayWindow", gbOverlay, FALSE); mmWriteProfileInt(gachAppTitle, "LiveWindow", gbLive, TRUE); }
/*
* initialise settings from the profile used AFTER window creation time */ void vidcapReadSettingsProfile(void) { DWORD dwSize; mmGetProfileString(gachAppTitle, "CaptureFile", "", gachCaptureFile, sizeof(gachCaptureFile));
mmGetProfileString(gachAppTitle, "MCIDevice", "VideoDisc", gachMCIDeviceName, sizeof(gachMCIDeviceName));
gCapParms.dwRequestMicroSecPerFrame = mmGetProfileInt(gachAppTitle, "MicroSecPerFrame", DEF_CAPTURE_RATE);
gCapParms.dwRequestMicroSecPerFrame = mmGetProfileInt(gachAppTitle, "MicroSecPerFrame", DEF_CAPTURE_RATE);
gCapParms.fCaptureAudio = mmGetProfileFlag(gachAppTitle, "CaptureAudio", gCapStatus.fAudioHardware);
gCapParms.fLimitEnabled = mmGetProfileFlag(gachAppTitle, "LimitEnabled", FALSE);
gCapParms.wTimeLimit = mmGetProfileInt(gachAppTitle, "TimeLimit", 30);
gCapParms.fMCIControl= mmGetProfileFlag(gachAppTitle, "MCIControl", FALSE);
gCapParms.fStepMCIDevice= mmGetProfileFlag(gachAppTitle, "StepMCIDevice", FALSE);
gCapParms.dwMCIStartTime = mmGetProfileInt(gachAppTitle, "MCIStartTime", 10000);
gCapParms.dwMCIStopTime = mmGetProfileInt(gachAppTitle, "MCIStopTime", 20000);
gCapParms.fStepCaptureAt2x = mmGetProfileFlag(gachAppTitle, "StepCapture2x", FALSE);
gCapParms.wStepCaptureAverageFrames = mmGetProfileInt(gachAppTitle, "StepCaptureAverageFrames", 3);
gCapParms.AVStreamMaster = mmGetProfileInt (gachAppTitle, "AVStreamMaster", AVSTREAMMASTER_AUDIO);
gCapParms.fUsingDOSMemory = mmGetProfileFlag (gachAppTitle, "CaptureToDisk", TRUE);
gCapParms.dwIndexSize = mmGetProfileInt(gachAppTitle, "IndexSize", CAP_SMALL_INDEX); // Retrieve the saved audio format
// Ask the ACM what the largest known wave format is
acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
// If a wave format was saved in the registry, use that size
dwSize = max (dwSize, mmGetProfileBinary(gachAppTitle, "WaveFormatBinary", NULL, NULL, 0)); if (glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize)) { capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ; mmGetProfileBinary(gachAppTitle, "WaveFormatBinary", glpwfex, glpwfex, dwSize);
// Do some sanity checking
if (MMSYSERR_NOERROR == waveInOpen (NULL, WAVE_MAPPER, glpwfex, 0, 0, WAVE_FORMAT_QUERY)) { capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ; } GlobalFreePtr(glpwfex) ; } }
void vidcapWriteSettingsProfile(void) { mmWriteProfileString(gachAppTitle, "CaptureFile", gachCaptureFile);
mmWriteProfileString(gachAppTitle, "MCIDevice", gachMCIDeviceName);
mmWriteProfileInt(gachAppTitle, "MicroSecPerFrame", gCapParms.dwRequestMicroSecPerFrame, DEF_CAPTURE_RATE);
mmWriteProfileFlag(gachAppTitle, "CaptureAudio", gCapParms.fCaptureAudio, gCapStatus.fAudioHardware);
mmWriteProfileFlag(gachAppTitle, "LimitEnabled", gCapParms.fLimitEnabled, FALSE);
mmWriteProfileInt(gachAppTitle, "TimeLimit", gCapParms.wTimeLimit, 30);
mmWriteProfileFlag(gachAppTitle, "MCIControl", gCapParms.fMCIControl, FALSE);
mmWriteProfileFlag(gachAppTitle, "StepMCIDevice", gCapParms.fStepMCIDevice, FALSE);
mmWriteProfileInt(gachAppTitle, "MCIStartTime", gCapParms.dwMCIStartTime, 10000);
mmWriteProfileInt(gachAppTitle, "MCIStopTime", gCapParms.dwMCIStopTime, 20000);
mmWriteProfileFlag(gachAppTitle, "StepCapture2x", gCapParms.fStepCaptureAt2x, FALSE);
mmWriteProfileInt(gachAppTitle, "StepCaptureAverageFrames", gCapParms.wStepCaptureAverageFrames, 3);
mmWriteProfileInt(gachAppTitle, "AVStreamMaster", gCapParms.AVStreamMaster, AVSTREAMMASTER_AUDIO);
mmWriteProfileFlag(gachAppTitle, "CaptureToDisk", gCapParms.fUsingDOSMemory, TRUE);
mmWriteProfileInt(gachAppTitle, "IndexSize", gCapParms.dwIndexSize, CAP_SMALL_INDEX);
// The audio format is written whenever it is changed via dlg
}
/* --- error/status functions -------------------------------------------*/
/*
* put up a message box loading a string from the * resource file */ int MessageBoxID(UINT idString, UINT fuStyle) { TCHAR achMessage[256]; // max message length
LoadString(ghInstApp, idString, achMessage, sizeof(achMessage));
return MessageBox(ghWndMain, achMessage, gachAppTitle, fuStyle); }
//
// ErrorCallbackProc: Error Callback Function
//
LRESULT FAR PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText) { ////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// nErrID: Error code for the encountered error
// lpErrorText: Error text string for the encountered error
////////////////////////////////////////////////////////////////////////
if (!ghWndMain) return FALSE;
if (nErrID == 0) // Starting a new major function
return TRUE; // Clear out old errors...
// save the error message for use in NoHardwareDlgProc
_tcscpy(gachLastError, lpErrorText);
// Show the error ID and text
MessageBox(hWnd, lpErrorText, gachAppTitle, #ifdef BIDI
MB_RTL_READING | #endif
MB_OK | MB_ICONEXCLAMATION) ;
return (LRESULT) TRUE ; }
//
// StatusCallbackProc: Status Callback Function
//
LRESULT FAR PASCAL StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText) { ////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// nID: Status code for the current status
// lpStatusText: Status text string for the current status
////////////////////////////////////////////////////////////////////////
static int CurrentID;
if (!ghWndMain) { return FALSE; }
// the CAP_END message sometimes overwrites a useful
// statistics message.
if (nID == IDS_CAP_END) { if ((CurrentID == IDS_CAP_STAT_VIDEOAUDIO) || (CurrentID == IDS_CAP_STAT_VIDEOONLY)) {
return(TRUE); } } CurrentID = nID;
statusUpdateStatus(ghWndStatus, lpStatusText);
return (LRESULT) TRUE ; }
//
// YieldCallbackProc: Status Callback Function
// (Only used for Scrncap.drv driver)
//
LRESULT FAR PASCAL YieldCallbackProc(HWND hWnd) { ////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
////////////////////////////////////////////////////////////////////////
MSG msg;
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); }
// Return TRUE to continue capturing
return (LRESULT) TRUE; }
/*
* load a string from the string table and return * a pointer to it for temporary use. Each call * overwrites the previous */ LPTSTR tmpString(UINT idString) { static TCHAR ach[350];
LoadString(ghInstApp, idString, ach, sizeof(ach)/sizeof(TCHAR));
// ensure null terminated
ach[sizeof(ach) -1] = 0;
return(ach); }
/* --- connect to and init hardware ------------------------------------- */
void vidcapSetLive(BOOL bLive) { capPreview(ghWndCap, bLive); toolbarModifyState(ghWndToolBar, BTN_LIVE, bLive? BTNST_DOWN : BTNST_UP); CheckMenuItem(GetMenu(ghWndMain), IDM_O_PREVIEW, MF_BYCOMMAND | (bLive ? MF_CHECKED : MF_UNCHECKED));
gbLive = bLive;
if (bLive == TRUE) { vidcapSetOverlay(FALSE); } }
void vidcapSetOverlay(BOOL bOverlay) { if (!gCapDriverCaps.fHasOverlay) { CheckMenuItem(GetMenu(ghWndMain), IDM_O_OVERLAY, MF_BYCOMMAND | MF_UNCHECKED); gbOverlay = FALSE; return; }
capOverlay(ghWndCap, bOverlay); toolbarModifyState(ghWndToolBar, BTN_OVERLAY, bOverlay ? BTNST_DOWN : BTNST_UP); CheckMenuItem(GetMenu(ghWndMain), IDM_O_OVERLAY, MF_BYCOMMAND | (bOverlay ? MF_CHECKED : MF_UNCHECKED));
gbOverlay = bOverlay;
if (bOverlay == TRUE) { vidcapSetLive(FALSE); } }
void vidcapSetCaptureFile(LPTSTR pFileName) { TCHAR achBuffer[_MAX_PATH];
if ((pFileName != NULL) && (_tcslen(pFileName) > 0)) { // record the capture filename
if (_tcscmp(gachCaptureFile, pFileName)) { _tcscpy(gachCaptureFile, pFileName); }
// and set window title
wsprintf(achBuffer, "%s - %s", gachAppTitle, pFileName); } else { gachCaptureFile[0] = 0; _tcscpy(achBuffer, gachAppTitle); }
capFileSetCaptureFile(ghWndCap, gachCaptureFile); SetWindowText(ghWndMain, achBuffer); }
/* --- winproc and message handling --------------------------------------- */
/*
* called from WM_COMMAND processing if the * message is from the toolbar. iButton contains the * button ID in the lower 8 bits, and the flags in the upper 8 bits/ */ LONG FAR PASCAL toolbarCommand (HWND hWnd, int iButton, HWND hwndToolbar) { int iBtnPos, iState, iActivity, iString;
// check repeat bit
if (iButton & BTN_REPEAT) { return(0); } iButton &= 0xff;
iBtnPos = toolbarIndexFromButton(hwndToolbar, iButton); iState = toolbarStateFromButton(hwndToolbar, iButton); iActivity = toolbarActivityFromButton(hwndToolbar, iButton); iString = toolbarStringFromIndex(hwndToolbar, iBtnPos);
switch(iActivity) {
case BTNACT_MOUSEDOWN: case BTNACT_KEYDOWN: case BTNACT_MOUSEMOVEON: statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(iString)); break;
case BTNACT_MOUSEMOVEOFF: statusUpdateStatus(ghWndStatus, NULL); break;
case BTNACT_MOUSEUP: case BTNACT_KEYUP:
statusUpdateStatus(ghWndStatus, NULL); switch(iButton) { case BTN_SETFILE: SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_F_SETCAPTUREFILE, NULL, 0)); break;
case BTN_EDITCAP: // edit captured video
SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_F_EDITVIDEO, NULL, 0)); break;
case BTN_LIVE: SendMessage(hWnd,WM_COMMAND, GET_WM_COMMAND_MPS(IDM_O_PREVIEW, NULL, 0)); break;
case BTN_CAPFRAME: SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_C_CAPTUREFRAME, NULL, 0)); break;
case BTN_CAPSEL: // capture selected frames
SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_C_CAPSEL, NULL, 0)); break;
case BTN_CAPAVI: SendMessage(hWnd,WM_COMMAND, GET_WM_COMMAND_MPS(IDM_C_CAPTUREVIDEO, NULL, 0)); break;
case BTN_CAPPAL: SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_C_PALETTE, NULL, 0)); break;
case BTN_OVERLAY: SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_O_OVERLAY, NULL, 0)); break; } break; } return(0); }
/*
* Put up a dialog to allow the user to select a capture file. */ LONG FAR PASCAL cmdSetCaptureFile(HWND hWnd) { OPENFILENAME ofn ; LPTSTR p; TCHAR achFileName[_MAX_PATH]; TCHAR achBuffer[_MAX_PATH] ; UINT wError ; HANDLE hFilter; int oldhelpid;
// Get current capture file name and
// then try to get the new capture file name
if (wError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName))) {
// Get just the path info
// Terminate the full path at the last backslash
_tcscpy (achBuffer, achFileName); for (p = achBuffer + _tcslen(achBuffer); p > achBuffer; p--) { if (*p == '\\') { *(p+1) = '\0'; break; } }
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ; ofn.lStructSize = sizeof(OPENFILENAME) ; ofn.hwndOwner = hWnd ;
//load filters from resource stringtable
if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_AVI), RT_RCDATA)) && (hFilter = LoadResource(ghInstApp, hFilter)) ) { ofn.lpstrFilter = LockResource(hFilter); } else { ofn.lpstrFilter = NULL; }
ofn.nFilterIndex = 0 ; ofn.lpstrFile = achFileName ; ofn.nMaxFile = sizeof(achFileName) ; ofn.lpstrFileTitle = NULL; ofn.lpstrTitle = tmpString(IDS_TITLE_SETCAPTUREFILE); ofn.nMaxFileTitle = 0 ; ofn.lpstrInitialDir = achBuffer; ofn.Flags = #ifdef BIDI
OFN_BIDIDIALOG | #endif
OFN_HIDEREADONLY | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST ;
// set help context for dialog
oldhelpid = SetCurrentHelpContext(IDA_SETCAPFILE);
if (GetOpenFileName(&ofn)) { OFSTRUCT os;
vidcapSetCaptureFile(achFileName);
/*
* if this is a new file, then invite the user to * allocate some space */ if (OpenFile(achFileName, &os, OF_EXIST) == HFILE_ERROR) {
/*
* show the allocate file space dialog to encourage * the user to pre-allocate space */ if (DoDialog(hWnd, IDD_AllocCapFileSpace, AllocCapFileProc, 0)) {
// ensure repaint after dismissing dialog before
// possibly lengthy operation
UpdateWindow(ghWndMain);
// If user has hit OK then alloc requested capture file space
if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG)) { MessageBoxID(IDS_ERR_CANT_PREALLOC, #ifdef BIDI
MB_RTL_READING | #endif
MB_OK | MB_ICONEXCLAMATION) ; } } }
}
// restore old help context
SetCurrentHelpContext(oldhelpid);
if (hFilter) { UnlockResource(hFilter); }
} return(0); }
/*
* query the user for a filename, and then save the captured video * to that file */ LONG FAR PASCAL cmdSaveVideoAs(HWND hWnd) { OPENFILENAME ofn ; TCHAR achFileName[_MAX_PATH]; UINT wError ; HANDLE hFilter; int oldhelpid;
// Get the current capture file name and
// then get the substitute file name to save video in
if (wError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName))) {
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ; ofn.lStructSize = sizeof(OPENFILENAME) ; ofn.hwndOwner = hWnd ;
//load filters from resource stringtable
if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_AVI), RT_RCDATA)) && (hFilter = LoadResource(ghInstApp, hFilter)) ) { ofn.lpstrFilter = LockResource(hFilter); } else { ofn.lpstrFilter = NULL; }
ofn.nFilterIndex = 0 ; ofn.lpstrFile = achFileName ; ofn.nMaxFile = sizeof(achFileName) ; ofn.lpstrFileTitle = NULL ; ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEAS); ofn.nMaxFileTitle = 0 ; ofn.lpstrInitialDir = NULL ; ofn.Flags = #ifdef BIDI
OFN_BIDIDIALOG | #endif
OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST ;
// set help context
oldhelpid = SetCurrentHelpContext(IDA_SAVECAPFILE);
if (GetSaveFileName(&ofn)) { // If the user has hit OK then set save file name
capFileSaveAs(ghWndCap, achFileName) ; }
SetCurrentHelpContext(oldhelpid);
if (hFilter) { UnlockResource(hFilter); } } return(0); }
/*
* Put up a dialog to allow the user to select a palette file and then * load that palette */ LONG FAR PASCAL cmdLoadPalette(HWND hWnd) { OPENFILENAME ofn ; TCHAR achFileName[_MAX_PATH]; HANDLE hFilter; int oldhelpid;
achFileName[0] = 0;
_fmemset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd;
//load filters from resource stringtable
if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_PALETTE), RT_RCDATA)) && (hFilter = LoadResource(ghInstApp, hFilter)) ) { ofn.lpstrFilter = LockResource(hFilter); } else { ofn.lpstrFilter = NULL; }
ofn.nFilterIndex = 1; ofn.lpstrFile = achFileName; ofn.nMaxFile = sizeof(achFileName); ofn.lpstrFileTitle = NULL; ofn.lpstrTitle = tmpString(IDS_TITLE_LOADPALETTE); ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = #ifdef BIDI
OFN_BIDIDIALOG | #endif
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
// set help context id
oldhelpid = SetCurrentHelpContext(IDA_LOADPAL);
if (GetOpenFileName(&ofn)) { // If the user has hit OK then load palette
capPaletteOpen(ghWndCap, achFileName); }
SetCurrentHelpContext(oldhelpid);
if (hFilter) { UnlockResource(hFilter); } return(0); }
/*
* query the user for a filename, and then save the current palette * to that file */ LONG FAR PASCAL cmdSavePalette(HWND hWnd) { OPENFILENAME ofn ; TCHAR achFileName[_MAX_PATH]; HANDLE hFilter; int oldhelpid;
achFileName[0] = 0;
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ; ofn.lStructSize = sizeof(OPENFILENAME) ; ofn.hwndOwner = hWnd ;
//load filters from resource stringtable
if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_PALETTE), RT_RCDATA)) && (hFilter = LoadResource(ghInstApp, hFilter)) ) { ofn.lpstrFilter = LockResource(hFilter); } else { ofn.lpstrFilter = NULL; }
ofn.nFilterIndex = 1; ofn.lpstrFile = achFileName; ofn.nMaxFile = sizeof(achFileName); ofn.lpstrFileTitle = NULL; ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEPALETTE); ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = #ifdef BIDI
OFN_BIDIDIALOG | #endif
OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
// set help context for F1 key
oldhelpid = SetCurrentHelpContext(IDA_SAVEPAL);
if (GetSaveFileName(&ofn)) { // If the user has hit OK then set save file name
capPaletteSave(ghWndCap, achFileName); }
SetCurrentHelpContext(oldhelpid);
if (hFilter) { UnlockResource(hFilter); }
return(0); }
/*
* query the user for a filename, and then save the current frame * to that file */ LONG FAR PASCAL cmdSaveDIB(HWND hWnd) { OPENFILENAME ofn ; TCHAR achFileName[_MAX_PATH]; HANDLE hFilter; int oldhelpid;
achFileName[0] = 0;
_fmemset(&ofn, 0, sizeof(OPENFILENAME)) ; ofn.lStructSize = sizeof(OPENFILENAME) ; ofn.hwndOwner = hWnd ;
//load filters from resource stringtable
if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_DIB), RT_RCDATA) ) && (hFilter = LoadResource(ghInstApp, hFilter) ) ) { ofn.lpstrFilter = LockResource(hFilter); } else { ofn.lpstrFilter = NULL; }
ofn.nFilterIndex = 1; ofn.lpstrFile = achFileName; ofn.nMaxFile = sizeof(achFileName); ofn.lpstrFileTitle = NULL; ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEDIB); ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = #ifdef BIDI
OFN_BIDIDIALOG | #endif
OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
// set help context for F1 handling
oldhelpid = SetCurrentHelpContext(IDA_SAVEDIB);
if (GetSaveFileName(&ofn)) {
// If the user has hit OK then set save file name
capFileSaveDIB(ghWndCap, achFileName); }
SetCurrentHelpContext(oldhelpid);
if (hFilter) { UnlockResource(hFilter); }
return(0); }
//
// MenuProc: Processes All Menu-based Operations
//
LRESULT FAR PASCAL MenuProc(HWND hWnd, WPARAM wParam, LPARAM lParam) { ////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// hMenu: Application menu handle
// wParam: Menu option
// lParam: Additional info for any menu option
////////////////////////////////////////////////////////////////////////
BOOL fResult ; DWORD dwSize = 0; int oldhelpid;
HMENU hMenu = GetMenu(hWnd) ;
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDC_TOOLBAR: return toolbarCommand(hWnd, GET_WM_COMMAND_CMD(wParam, lParam), ghWndToolBar);
/* --- file --- */ case IDM_F_SETCAPTUREFILE: return cmdSetCaptureFile(hWnd);
case IDM_F_SAVEVIDEOAS: return cmdSaveVideoAs(hWnd); break;
case IDM_F_ALLOCATESPACE: if (DoDialog(hWnd, IDD_AllocCapFileSpace, AllocCapFileProc, 0)) {
// ensure repaint after dismissing dialog before
// possibly lengthy operation
UpdateWindow(ghWndMain);
// If user has hit OK then alloc requested capture file space
if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG)) { MessageBoxID(IDS_ERR_CANT_PREALLOC, #ifdef BIDI
MB_RTL_READING | #endif
MB_OK | MB_ICONEXCLAMATION) ; } } break ;
case IDM_F_EXIT: DestroyWindow(hWnd) ; break;
case IDM_F_LOADPALETTE: return cmdLoadPalette(hWnd);
case IDM_F_SAVEPALETTE: return cmdSavePalette(hWnd);
case IDM_F_SAVEFRAME: return cmdSaveDIB(hWnd);
case IDM_F_EDITVIDEO: { HINSTANCE u; BOOL f = TRUE; /* assume the best */ HCURSOR hOldCursor;
/* build up the command line "AviEdit -n filename" */ if (lstrlen(gachCaptureFile) > 0) {
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); u = ShellExecute (hWnd, TEXT("open"), gachCaptureFile, NULL, NULL, SW_SHOWNORMAL); if ((UINT_PTR) u < 32){ /* report error on forking VidEdit */ MessageBoxID(IDS_ERR_VIDEDIT, MB_OK|MB_ICONEXCLAMATION); f = FALSE; }
SetCursor(hOldCursor); } return f;
}
/* --- edit --- */
case IDM_E_COPY: capEditCopy(ghWndCap) ; break;
case IDM_E_PASTEPALETTE: capPalettePaste(ghWndCap) ; break;
case IDM_E_PREFS: { if (DoDialog(hWnd, IDD_Prefs, PrefsDlgProc, 0)) {
// write prefs to profile
// force new brush
vidframeSetBrush(ghWndFrame, gBackColour);
// re-do layout
vidcapLayout(hWnd);
} } break;
/* --- options --- */
case IDM_O_PREVIEW: // Toggle Preview
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ; vidcapSetLive(!gCapStatus.fLiveWindow) ; break;
case IDM_O_OVERLAY: // Toggle Overlay
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ; vidcapSetOverlay(!gCapStatus.fOverlayWindow); break ;
case IDM_O_AUDIOFORMAT: #ifdef USE_ACM
{ ACMFORMATCHOOSE cfmt; static BOOL fDialogUp = FALSE;
if (fDialogUp) return FALSE;
fDialogUp = TRUE; // Ask the ACM what the largest wave format is.....
acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
// Get the current audio format
dwSize = max (dwSize, capGetAudioFormatSize (ghWndCap)); if (glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize)) { capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
_fmemset (&cfmt, 0, sizeof (ACMFORMATCHOOSE)); cfmt.cbStruct = sizeof (ACMFORMATCHOOSE); cfmt.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT; cfmt.fdwEnum = ACM_FORMATENUMF_HARDWARE | ACM_FORMATENUMF_INPUT; cfmt.hwndOwner = hWnd; cfmt.pwfx = glpwfex; cfmt.cbwfx = dwSize;
//oldhelpid = SetCurrentHelpContext(IDA_AUDIOSETUP);
if (!acmFormatChoose(&cfmt)) { capSetAudioFormat(ghWndCap, glpwfex, (WORD)glpwfex->cbSize + sizeof (WAVEFORMATEX)) ; mmWriteProfileBinary(gachAppTitle, "WaveFormatBinary", (LPVOID) glpwfex, glpwfex->cbSize + sizeof (WAVEFORMATEX)); } //SetCurrentHelpContext(oldhelpid);
GlobalFreePtr(glpwfex) ; } fDialogUp = FALSE; } #else
{ // Get current audio format and then find required format
dwSize = capGetAudioFormatSize (ghWndCap); glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ; capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
if (DoDialog(hWnd, IDD_AudioFormat, AudioFormatProc, 0)) { // If the user has hit OK, set the new audio format
capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ; mmWriteProfileBinary(gachAppTitle, "WaveFormatBinary", (LPVOID) glpwfex, dwSize); } GlobalFreePtr(glpwfex) ; } #endif
break ;
case IDM_O_VIDEOFORMAT: if (gCapDriverCaps.fHasDlgVideoFormat) { // Only if the driver has a "Video Format" dialog box
oldhelpid = SetCurrentHelpContext(IDA_VIDFORMAT); if (capDlgVideoFormat(ghWndCap)) { // If successful,
// Get the new image dimension and center capture window
capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ; vidcapLayout(hWnd); } SetCurrentHelpContext(oldhelpid); } break;
case IDM_O_VIDEOSOURCE: if (gCapDriverCaps.fHasDlgVideoSource) { // Only if the driver has a "Video Source" dialog box
oldhelpid = SetCurrentHelpContext(IDA_VIDSOURCE); capDlgVideoSource(ghWndCap) ; capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ; vidcapLayout(hWnd); SetCurrentHelpContext(oldhelpid); } break ;
case IDM_O_VIDEODISPLAY: if (gCapDriverCaps.fHasDlgVideoDisplay) { // Only if the driver has a "Video Display" dialog box
oldhelpid = SetCurrentHelpContext(IDA_VIDDISPLAY); capDlgVideoDisplay(ghWndCap) ; capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ; SetCurrentHelpContext(oldhelpid); } break ;
case IDM_O_CHOOSECOMPRESSOR: oldhelpid = SetCurrentHelpContext(IDA_COMPRESSION); capDlgVideoCompression(ghWndCap); SetCurrentHelpContext(oldhelpid); break;
// Select a driver to activate
case IDM_O_DRIVER0: case IDM_O_DRIVER1: case IDM_O_DRIVER2: case IDM_O_DRIVER3: case IDM_O_DRIVER4: case IDM_O_DRIVER5: case IDM_O_DRIVER6: case IDM_O_DRIVER7: case IDM_O_DRIVER8: case IDM_O_DRIVER9: vidcapInitHardware(ghWndMain, ghWndCap, (UINT) (wParam - IDM_O_DRIVER0)); break;
/* --- capture --- */
case IDM_C_PALETTE: if (DoDialog(hWnd, IDD_MakePalette, MakePaletteProc, 0)) { // Palette is created within the dialog
bDefaultPalette = FALSE; } break;
case IDM_C_CAPTUREVIDEO:
// warn user if he is still using the default palette
if (bDefaultPalette) {
LPBITMAPINFOHEADER lpbi; int sz;
// fUsingDefaultPalette will be TRUE even if the
// current capture format is non-palettised. This is a
// bizarre decision of Jay's.
sz = (int)capGetVideoFormatSize(ghWndCap); lpbi = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, sz);
if (lpbi) { // We can warn s/he
if (capGetVideoFormat(ghWndCap, lpbi, sz) && (lpbi->biCompression == BI_RGB) && (lpbi->biBitCount <= 8)) {
CAPSTATUS cs;
// if we've warned him once, we can forget it
bDefaultPalette = FALSE;
capGetStatus(ghWndCap, &cs, sizeof(cs));
if (cs.fUsingDefaultPalette) {
if (MessageBoxID(IDS_WARN_DEFAULT_PALETTE, MB_OKCANCEL| MB_ICONEXCLAMATION)== IDCANCEL) { break; } } } LocalFree(lpbi); } }
// Invoke a Dlg box to setup all the params
if (DoDialog(hWnd, IDD_CapSetUp, CapSetUpProc, 0)) {
// set the defaults we won't bother the user with
gCapParms.fMakeUserHitOKToCapture = !gCapParms.fMCIControl; gCapParms.wPercentDropForError = 10;
// fUsingDOSMemory is obsolete, but we use it here as
// a flag which is TRUE if "CapturingToDisk"
// The number of video buffers should be enough to get through
// disk seeks and thermal recalibrations if "CapturingToDisk"
// If "CapturingToMemory", get as many buffers as we can.
gCapParms.wNumVideoRequested = gCapParms.fUsingDOSMemory ? 32 : 1000;
// Don't abort on the left mouse anymore!
gCapParms.fAbortLeftMouse = FALSE; gCapParms.fAbortRightMouse = TRUE;
// If the Driver is Scrncap.drv, the following values are special
// If wChunkGranularity is zero, the granularity will be set to the
// disk sector size.
gCapParms.wChunkGranularity = (gbIsScrncap ? 32 : 0);
// Scrncap requires a callback for the message pump
capSetCallbackOnYield(ghWndCap, (gbIsScrncap ? fpYieldCallback : NULL));
// If the user has hit OK, set the new setup info
capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ; } else { break; }
// if no capture file, get that
if (lstrlen(gachCaptureFile) <= 0) { cmdSetCaptureFile(hWnd); if (lstrlen(gachCaptureFile) <= 0) { break; } }
// Capture video sequence
fResult = capCaptureSequence(ghWndCap) ; break;
case IDM_C_CAPTUREFRAME: // Turn off overlay / preview (gets turned off by frame capture)
vidcapSetLive(FALSE); vidcapSetOverlay(FALSE);
// Grab a frame
fResult = capGrabFrameNoStop(ghWndCap) ; break;
case IDM_C_CAPSEL: { //FARPROC fproc;
// if no capture file, get that
if (lstrlen(gachCaptureFile) <= 0) { cmdSetCaptureFile(hWnd); if (lstrlen(gachCaptureFile) <= 0) { break; } }
//fproc = MakeProcInstance(CapFramesProc, ghInstApp);
DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_CAPFRAMES), hWnd, CapFramesProc); //FreeProcInstance(fproc);
} break;
#ifdef DEBUG
case IDM_C_TEST: nTestCount = 0; // Intentional fall through
case IDM_C_TESTAGAIN: // set the defaults we won't bother the user with
gCapParms.fMakeUserHitOKToCapture = FALSE; gCapParms.wPercentDropForError = 100;
gCapParms.wNumVideoRequested = gCapParms.fUsingDOSMemory ? 32 : 1000;
// Don't abort on the left mouse anymore!
gCapParms.fAbortLeftMouse = FALSE; gCapParms.fAbortRightMouse = TRUE;
// If wChunkGranularity is zero, the granularity will be set to the
// disk sector size.
gCapParms.wChunkGranularity = (gbIsScrncap ? 32 : 0);
// If the user has hit OK, set the new setup info
capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
// if no capture file, get that
if (lstrlen(gachCaptureFile) <= 0) { cmdSetCaptureFile(hWnd); if (lstrlen(gachCaptureFile) <= 0) { break; } } { TCHAR buf[80];
gCapParms.wNumVideoRequested = 10; gCapParms.wNumAudioRequested = 5; gCapParms.fLimitEnabled = TRUE; if (gCapParms.wTimeLimit == 0) gCapParms.wTimeLimit = 5; capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ; // Capture video sequence
fResult = capCaptureSequence(ghWndCap) ; wsprintf (buf, "TestCount = %d", nTestCount++); statusUpdateStatus(ghWndStatus, buf); // Hold down the right mouse button to abort
if (!GetAsyncKeyState(VK_RBUTTON) & 0x0001) PostMessage (hWnd, WM_COMMAND, IDM_C_TESTAGAIN, 0L); } break; #endif
/* --- help --- */ case IDM_H_CONTENTS: HelpContents(); break;
case IDM_H_ABOUT: ShellAbout( hWnd, "VidCap", "Video Capture Tool", LoadIcon(ghInstApp, gachIconName) ); //DoDialog(hWnd, IDD_HelpAboutBox, AboutProc, 0);
break ;
}
return 0L ; }
/* --- menu help and enable/disable handling ------------------------ */
// write or clear status line help text when the user brings up or cancels a
// menu. This depends on there being strings in the string table with
// the same ID as the corresponding menu item.
// Help text for the items along the menu bar (File, Edit etc) depends
// on IDM_FILE, IDM_EDIT being defined with values 100 apart in the same
// order as their index in the menu
void MenuSelect(HWND hwnd, UINT cmd, UINT flags, HMENU hmenu) { if ((LOWORD(flags) == 0xffff) && (hmenu == NULL)) { //menu closing - remove message
statusUpdateStatus(ghWndStatus, NULL); } else if ( (flags & (MF_SYSMENU|MF_POPUP)) == (MF_SYSMENU|MF_POPUP)) { // the system menu itself
statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(IDM_SYSMENU)); } else if ((flags & MF_POPUP) == 0) { // a menu command item
statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(cmd)); } else { //a popup menu - we need to search to find which one.
// note that the cmd item in Win16 will now have a
// menu handle, whereas in Win32 it has an index.
// NOTE: this code assumes that the menu items
// are #defined 100 apart in the same order, starting
// with IDM_FILE
#ifdef _WIN32
statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(IDM_FILE + (cmd * 100))); #else
int i,c; HMENU hmenuMain;
hmenuMain = GetMenu(hWnd); c = GetMenuItemCount(hmenuMain);
for(i = 0; i < c; i++) { if (hmenu == GetSubMenu(hmenuMain, i)) { statusUpdateStatus(MAKEINTRESOURCE(IDM_FILE + (cmd*100))); return(0); } } statusUpdateStatus(NULL); #endif
} }
// a popup menu is being selected - enable or disable menu items
int InitMenuPopup( HWND hwnd, HMENU hmenu, int index ) { int i = MF_ENABLED; CAPSTATUS cs; BOOL bUsesPalettes;
capGetStatus(ghWndCap, &cs, sizeof(cs));
// try to see if the driver uses palettes
if ((cs.hPalCurrent != NULL) || (cs.fUsingDefaultPalette)) { bUsesPalettes = TRUE; } else { bUsesPalettes = FALSE; }
switch(index) { case 0: // IDM_FILE
if (lstrlen(gachCaptureFile) <= 0) { i = MF_GRAYED; } // save as enabled only if we have a capture file
EnableMenuItem(hmenu, IDM_F_SAVEVIDEOAS, i); // edit video possible only if we have a capture file AND we've
// captured something
EnableMenuItem(hmenu, IDM_F_EDITVIDEO, (cs.dwCurrentVideoFrame > 0) ? i : MF_GRAYED);
// allow save palette if there is one
EnableMenuItem(hmenu, IDM_F_SAVEPALETTE, (cs.hPalCurrent != NULL) ? MF_ENABLED:MF_GRAYED);
// allow load palette if the driver uses palettes
EnableMenuItem(hmenu, IDM_F_LOADPALETTE, bUsesPalettes ? MF_ENABLED : MF_GRAYED);
break;
case 1: // IDM_EDIT
// paste palettes if driver uses them and there is one pastable
EnableMenuItem(hmenu, IDM_E_PASTEPALETTE, (bUsesPalettes && IsClipboardFormatAvailable(CF_PALETTE)) ? MF_ENABLED:MF_GRAYED);
break;
case 2: // IDM_OPTIONS
EnableMenuItem(hmenu, IDM_O_AUDIOFORMAT, cs.fAudioHardware ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hmenu, IDM_O_OVERLAY, gCapDriverCaps.fHasOverlay ? MF_ENABLED:MF_GRAYED);
EnableMenuItem(hmenu, IDM_O_VIDEOFORMAT, gCapDriverCaps.fHasDlgVideoFormat ? MF_ENABLED:MF_GRAYED);
EnableMenuItem(hmenu, IDM_O_VIDEODISPLAY, gCapDriverCaps.fHasDlgVideoDisplay ? MF_ENABLED:MF_GRAYED);
EnableMenuItem(hmenu, IDM_O_VIDEOSOURCE, gCapDriverCaps.fHasDlgVideoSource ? MF_ENABLED:MF_GRAYED);
EnableMenuItem(hmenu, IDM_O_PREVIEW, gbHaveHardware ? MF_ENABLED:MF_GRAYED);
case 3: // IDM_CAPTURE
if (!gbHaveHardware) { i = MF_GRAYED; } EnableMenuItem(hmenu, IDM_C_CAPSEL, i); EnableMenuItem(hmenu, IDM_C_CAPTUREFRAME, i); EnableMenuItem(hmenu, IDM_C_CAPTUREVIDEO, i); EnableMenuItem(hmenu, IDM_C_PALETTE, (gbHaveHardware && gCapDriverCaps.fDriverSuppliesPalettes) ? MF_ENABLED : MF_GRAYED);
break; } return(0); }
//
// MainWndProc: Application Main Window Procedure
//
LRESULT FAR PASCAL MainWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) { ////////////////////////////////////////////////////////////////////////
// hWnd: Application main window handle
// Message: Next message to be processed
// wParam: WORD param for the message
// lParam: LONG param for the message
////////////////////////////////////////////////////////////////////////
switch (Message) {
static BOOL fMinimized;
case WM_SYSCOMMAND: if ((wParam & 0xfff0) == SC_MAXIMIZE) fMinimized = FALSE; else if ((wParam & 0xfff0) == SC_RESTORE) fMinimized = FALSE; else if ((wParam & 0xfff0) == SC_MINIMIZE) fMinimized = TRUE; return DefWindowProc(hWnd, Message, wParam, lParam); break;
case WM_COMMAND: MenuProc(hWnd, wParam, lParam) ; break ;
case WM_CREATE: HelpInit(ghInstApp, "vidcap.hlp", hWnd); break;
case WM_NCHITTEST: { LRESULT dw;
dw = DefWindowProc(hWnd, Message, wParam, lParam); // Don't allow border resize if autosizing
if (gbAutoSizeFrame) { if (dw >= HTSIZEFIRST && dw <= HTSIZELAST) dw = HTCAPTION; } return dw; } break;
case WM_GETMINMAXINFO: // Don't allow manual sizing if window locked to the capture size
if (gbHaveHardware && gbAutoSizeFrame && !gbInLayout) { RECT rW;
LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
GetWindowRect (hWnd, &rW); lpMMI->ptMinTrackSize.x = rW.right - rW.left; lpMMI->ptMinTrackSize.y = rW.bottom - rW.top; lpMMI->ptMaxTrackSize = lpMMI->ptMinTrackSize; } break;
case WM_MOVE: if (!fMinimized) { vidcapLayout (hWnd); } break;
case WM_SIZE: if (!fMinimized) { vidcapLayout (hWnd); } break;
case WM_MENUSELECT: { UINT cmd = GET_WM_MENUSELECT_CMD(wParam, lParam); UINT flags = GET_WM_MENUSELECT_FLAGS(wParam, lParam); HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
MenuSelect(hWnd, cmd, flags, hmenu); } break;
case WM_INITMENUPOPUP: { BOOL bSystem = (BOOL) HIWORD(lParam);
if (!bSystem) { return InitMenuPopup(hWnd, (HMENU) wParam, (int) LOWORD(lParam)); } else { return(DefWindowProc(hWnd, Message, wParam, lParam)); } }
case WM_SYSCOLORCHANGE: // we don't use this ourselves, but we should pass
// it on to all three children
SendMessage(ghWndFrame, Message, wParam, lParam); SendMessage(ghWndToolBar, Message, wParam, lParam); SendMessage(ghWndStatus, Message, wParam, lParam); return (TRUE);
case WM_PALETTECHANGED: case WM_QUERYNEWPALETTE: // Pass the buck to Capture window proc
return SendMessage(ghWndCap, Message, wParam, lParam) ; break ;
case WM_SETFOCUS: // the toolbar is the only part that needs the focus
SetFocus(ghWndToolBar); break;
case WM_ACTIVATEAPP: if (wParam && ghWndCap) capPreviewRate(ghWndCap, 15); // Fast preview when active
else capPreviewRate(ghWndCap, 1000); // Slow preview when inactive
break;
case WM_NEXTDLGCTL: // if anyone is tabbing about, move the focus to the
// toolbar
SetFocus(ghWndToolBar);
// select the correct button to handle moving off one
// end and back on the other end
if (lParam == FALSE) { // are we moving forwards or backwards ?
if (wParam == 0) { // move to next - so select first button
toolbarSetFocus(ghWndToolBar, TB_FIRST); } else { // move to previous - so select last
toolbarSetFocus(ghWndToolBar, TB_LAST); } } break;
case WM_PAINT: { HDC hDC ; PAINTSTRUCT ps ;
hDC = BeginPaint(hWnd, &ps) ;
// Included in case the background is not a pure color
SetBkMode(hDC, TRANSPARENT) ;
EndPaint(hWnd, &ps) ; break ; }
case WM_CLOSE: // Disable and free all the callbacks
capSetCallbackOnError(ghWndCap, NULL) ; if (fpErrorCallback) { FreeProcInstance(fpErrorCallback) ; fpErrorCallback = NULL; }
capSetCallbackOnStatus(ghWndCap, NULL) ; if (fpStatusCallback) { FreeProcInstance(fpStatusCallback) ; fpStatusCallback = NULL; }
capSetCallbackOnYield(ghWndCap, NULL) ; if (fpYieldCallback) { FreeProcInstance(fpYieldCallback) ; fpYieldCallback = NULL; }
// Disconnect the current capture driver
capDriverDisconnect (ghWndCap);
// Destroy child windows, modeless dialogs, then this window...
// DestroyWindow(ghWndCap) ;
DestroyWindow(hWnd) ; break ;
case WM_DESTROY: { // remember window size and position
// - this will be written to the profile
WINDOWPLACEMENT wp;
wp.length = sizeof (WINDOWPLACEMENT); GetWindowPlacement(hWnd, &wp);
gWinShow = wp.showCmd; gWinX = wp.rcNormalPosition.left; gWinY = wp.rcNormalPosition.top; gWinCX = RECTWIDTH(wp.rcNormalPosition); gWinCY = RECTHEIGHT(wp.rcNormalPosition);
// write defaults out to the registry
vidcapWriteProfile(); vidcapWriteSettingsProfile();
HelpShutdown();
}
PostQuitMessage(0) ; break ;
default: return DefWindowProc(hWnd, Message, wParam, lParam) ; }
return 0L; } // End of MainWndProc
|