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.
1372 lines
34 KiB
1372 lines
34 KiB
/*****************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
|
|
*
|
|
* TITLE: VideoProc.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* DATE: 2000/11/14
|
|
*
|
|
* DESCRIPTION: Manages WiaVideo object.
|
|
*
|
|
*****************************************************************************/
|
|
#include <stdafx.h>
|
|
#include <mmsystem.h>
|
|
#include <streams.h>
|
|
#include <mmreg.h>
|
|
#include "wiavideotest.h"
|
|
|
|
///////////////////////////////
|
|
// LOCAL_GVAR
|
|
//
|
|
static struct
|
|
{
|
|
IWiaVideo *pWiaVideo;
|
|
BOOL bPreviewVisible;
|
|
INT iNumThreads;
|
|
UINT uiNumImagesPerThread;
|
|
UINT uiTakePictureInterval;
|
|
BOOL bExitThreads;
|
|
BOOL bVideoStretched;
|
|
} LOCAL_GVAR =
|
|
{
|
|
NULL,
|
|
TRUE,
|
|
0,
|
|
0,
|
|
0,
|
|
FALSE,
|
|
FALSE
|
|
};
|
|
|
|
///////////////////////////////
|
|
// ThreadArgs_t
|
|
//
|
|
typedef struct ThreadArgs_t
|
|
{
|
|
UINT uiNumPicturesToTake;
|
|
UINT uiThreadSleepTime; // if 0, calc'd as a random number.
|
|
} ThreadArgs_t;
|
|
|
|
|
|
/****************************Local Function Prototypes********************/
|
|
HRESULT CreateWiaVideoObject();
|
|
HRESULT CreateVideoEnumPos();
|
|
HRESULT CreateVideoFriendlyName();
|
|
HRESULT CreateVideoWia();
|
|
HRESULT DestroyVideo();
|
|
HRESULT Play();
|
|
HRESULT Pause();
|
|
HRESULT TakePicture(BOOL bTakePictureThroughDriver);
|
|
HRESULT ShowVideo();
|
|
HRESULT ResizeVideo(BOOL bStretchToFitWindow);
|
|
HRESULT ShowCurrentState();
|
|
HRESULT TakePictureMultiple();
|
|
HRESULT TakePictureStress();
|
|
DWORD WINAPI TakePictureThreadProc(void *pArgs);
|
|
INT_PTR CALLBACK MultipleDlgProc(HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam);
|
|
INT_PTR CALLBACK StressDlgProc(HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam);
|
|
|
|
BOOL GetDeviceProperty(IPropertyBag *pPropertyBag,
|
|
LPCWSTR pwszProperty,
|
|
TCHAR *pszProperty,
|
|
DWORD cchProperty);
|
|
|
|
|
|
///////////////////////////////
|
|
// VideoProc_Init
|
|
//
|
|
HRESULT VideoProc_Init()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CreateWiaVideoObject();
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// VideoProc_Term
|
|
//
|
|
HRESULT VideoProc_Term()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LOCAL_GVAR.bExitThreads = TRUE;
|
|
|
|
//
|
|
// Crude, but for a test app, it is easier than creating an
|
|
// array of thread handles and waiting for each one to finish.
|
|
//
|
|
INT iLoops = 0;
|
|
while ((LOCAL_GVAR.iNumThreads > 0) && (iLoops < 50))
|
|
{
|
|
++iLoops;
|
|
Sleep(100);
|
|
}
|
|
|
|
DestroyVideo();
|
|
|
|
if (LOCAL_GVAR.pWiaVideo)
|
|
{
|
|
LOCAL_GVAR.pWiaVideo->Release();
|
|
LOCAL_GVAR.pWiaVideo = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// VideoProc_DShowListInit
|
|
//
|
|
HRESULT VideoProc_DShowListInit()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LONG lPosNum = 0;
|
|
ICreateDevEnum *pCreateDevEnum = NULL;
|
|
IEnumMoniker *pEnumMoniker = NULL;
|
|
|
|
//
|
|
// Empty the list
|
|
//
|
|
SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_RESETCONTENT,
|
|
0,
|
|
0);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
|
|
//
|
|
// Create the device enumerator
|
|
//
|
|
hr = CoCreateInstance(CLSID_SystemDeviceEnum,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ICreateDevEnum,
|
|
(void**)&pCreateDevEnum);
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = pCreateDevEnum->CreateClassEnumerator(
|
|
CLSID_VideoInputDeviceCategory,
|
|
&pEnumMoniker,
|
|
0);
|
|
}
|
|
|
|
//
|
|
// Loop through all the devices
|
|
//
|
|
|
|
while (hr == S_OK)
|
|
{
|
|
TCHAR szFriendlyName[255 + 1] = {0};
|
|
IMoniker *pMoniker = NULL;
|
|
IPropertyBag *pPropertyBag = NULL;
|
|
|
|
hr = pEnumMoniker->Next(1, &pMoniker, NULL);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
//
|
|
// Get property storage for this DS device so we can get it's
|
|
// device id...
|
|
//
|
|
|
|
hr = pMoniker->BindToStorage(0,
|
|
0,
|
|
IID_IPropertyBag,
|
|
(void **)&pPropertyBag);
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = GetDeviceProperty(pPropertyBag,
|
|
L"FriendlyName",
|
|
szFriendlyName,
|
|
sizeof(szFriendlyName) / sizeof(TCHAR));
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_ADDSTRING,
|
|
0,
|
|
(LPARAM) szFriendlyName);
|
|
}
|
|
|
|
if (pMoniker)
|
|
{
|
|
pMoniker->Release();
|
|
pMoniker = NULL;
|
|
}
|
|
|
|
if (pPropertyBag)
|
|
{
|
|
pPropertyBag->Release();
|
|
pPropertyBag = NULL;
|
|
}
|
|
}
|
|
|
|
SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_SETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
if (pEnumMoniker)
|
|
{
|
|
pEnumMoniker->Release();
|
|
pEnumMoniker = NULL;
|
|
}
|
|
|
|
if (pCreateDevEnum)
|
|
{
|
|
pCreateDevEnum->Release();
|
|
pCreateDevEnum = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// VideoProc_DShowListTerm
|
|
//
|
|
HRESULT VideoProc_DShowListTerm()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Empty the list
|
|
//
|
|
SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_RESETCONTENT,
|
|
0,
|
|
0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////
|
|
// VideoProc_TakePicture
|
|
//
|
|
HRESULT VideoProc_TakePicture()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = TakePicture(FALSE);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////
|
|
// VideoProc_ProcessMsg
|
|
//
|
|
UINT_PTR VideoProc_ProcessMsg(UINT uiControlID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
UINT_PTR uiReturn = 0;
|
|
|
|
switch (uiControlID)
|
|
{
|
|
case IDC_BUTTON_CREATE_VIDEO_WIA:
|
|
hr = CreateVideoWia();
|
|
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_WIA_DEVICE_LIST), FALSE);
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_DSHOW_DEVICE_LIST), FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_CREATE_VIDEO_ENUM_POS:
|
|
hr = CreateVideoEnumPos();
|
|
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_WIA_DEVICE_LIST), FALSE);
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_DSHOW_DEVICE_LIST), FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_CREATE_VIDEO_FRIENDLY_NAME:
|
|
hr = CreateVideoFriendlyName();
|
|
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_WIA_DEVICE_LIST), FALSE);
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_DSHOW_DEVICE_LIST), FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_TAKE_PICTURE_STRESS:
|
|
TakePictureStress();
|
|
break;
|
|
|
|
case IDC_BUTTON_TAKE_PICTURE_MULTIPLE:
|
|
TakePictureMultiple();
|
|
break;
|
|
|
|
case IDC_BUTTON_DESTROY_VIDEO:
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT));
|
|
|
|
DestroyVideo();
|
|
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_WIA_DEVICE_LIST), TRUE);
|
|
EnableWindow(GetDlgItem(APP_GVAR.hwndMainDlg, IDC_RADIO_DSHOW_DEVICE_LIST), TRUE);
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW));
|
|
break;
|
|
|
|
case IDC_BUTTON_PLAY:
|
|
Play();
|
|
break;
|
|
|
|
case IDC_BUTTON_PAUSE:
|
|
Pause();
|
|
break;
|
|
|
|
case IDC_BUTTON_TAKE_PICTURE:
|
|
TakePicture(FALSE);
|
|
break;
|
|
|
|
case IDC_BUTTON_TAKE_PICTURE_DRIVER:
|
|
TakePicture(TRUE);
|
|
break;
|
|
|
|
case IDC_BUTTON_SHOW_VIDEO_TOGGLE:
|
|
ShowVideo();
|
|
break;
|
|
|
|
case IDC_BUTTON_RESIZE_TOGGLE:
|
|
LOCAL_GVAR.bVideoStretched = (LOCAL_GVAR.bVideoStretched ? FALSE : TRUE);
|
|
ResizeVideo(LOCAL_GVAR.bVideoStretched);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
ShowCurrentState();
|
|
|
|
return uiReturn;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// CreateVideoWia
|
|
//
|
|
HRESULT CreateVideoWia()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szDeviceID[MAX_PATH] = {0};
|
|
TCHAR szImagesDirectory[MAX_PATH] = {0};
|
|
BSTR bstrImagesDir = NULL;
|
|
BSTR bstrDeviceID = NULL;
|
|
WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
|
|
DWORD dwStartTime = 0;
|
|
DWORD dwEndTime = 0;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->GetCurrentState(&VideoState);
|
|
|
|
if (VideoState != WIAVIDEO_NO_VIDEO)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_VIDEO_STILL_ACTIVE,
|
|
MB_OK | MB_ICONSTOP);
|
|
|
|
return hr;
|
|
}
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//
|
|
// We need to do this first, otherwise the driver is not loaded yet,
|
|
// and therefore the images directory property will have not been set
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = WiaProc_CreateSelectedDevice(szDeviceID,
|
|
sizeof(szDeviceID) / sizeof(TCHAR));
|
|
}
|
|
|
|
dwStartTime = timeGetTime();
|
|
|
|
//
|
|
// Get the images directory stored in the driver. We don't have to do this
|
|
// we can come up with our own, but the driver will generate a default temp
|
|
// location, which is good enough for our purposes.
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = WiaProc_GetImageDirectory(szImagesDirectory,
|
|
sizeof(szImagesDirectory) / sizeof(TCHAR));
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wszDeviceID[MAX_PATH] = {0};
|
|
|
|
AppUtil_ConvertToWideString(szDeviceID, wszDeviceID,
|
|
sizeof(wszDeviceID) / sizeof(WCHAR));
|
|
|
|
|
|
bstrDeviceID = ::SysAllocString(wszDeviceID);
|
|
}
|
|
|
|
//
|
|
// Set the images directory on the WiaVideo object
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wszImagesDir[MAX_PATH] = {0};
|
|
|
|
AppUtil_ConvertToWideString(szImagesDirectory, wszImagesDir,
|
|
sizeof(wszImagesDir) / sizeof(WCHAR));
|
|
|
|
|
|
bstrImagesDir = ::SysAllocString(wszImagesDir);
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->put_ImagesDirectory(bstrImagesDir);
|
|
}
|
|
|
|
//
|
|
// Create Video.
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = LOCAL_GVAR.pWiaVideo->CreateVideoByWiaDevID(bstrDeviceID,
|
|
GetDlgItem(APP_GVAR.hwndMainDlg,
|
|
IDC_VIDEO_PREVIEW_WINDOW),
|
|
FALSE,
|
|
TRUE);
|
|
}
|
|
|
|
dwEndTime = timeGetTime();
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_GRAPH_BUILD_TIME,
|
|
(UINT) abs(dwEndTime - dwStartTime),
|
|
FALSE);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
SetDlgItemText(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_IMAGES_DIR,
|
|
szImagesDirectory);
|
|
}
|
|
|
|
//
|
|
// Populate our list of items for this device
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = WiaProc_PopulateItemList();
|
|
}
|
|
|
|
if (bstrImagesDir)
|
|
{
|
|
::SysFreeString(bstrImagesDir);
|
|
bstrImagesDir = NULL;
|
|
}
|
|
|
|
if (bstrDeviceID)
|
|
{
|
|
::SysFreeString(bstrDeviceID);
|
|
bstrDeviceID = NULL;
|
|
}
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW));
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_FAILED_TO_CREATE_VIDEO,
|
|
MB_OK | MB_ICONSTOP,
|
|
hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// CreateVideoEnumPos
|
|
//
|
|
HRESULT CreateVideoEnumPos()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szImagesDirectory[MAX_PATH] = {0};
|
|
TCHAR szFriendlyName[255 + 1] = {0};
|
|
BSTR bstrImagesDir = NULL;
|
|
WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
|
|
DWORD dwStartTime = 0;
|
|
DWORD dwEndTime = 0;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->GetCurrentState(&VideoState);
|
|
|
|
if (VideoState != WIAVIDEO_NO_VIDEO)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_VIDEO_STILL_ACTIVE,
|
|
MB_OK | MB_ICONSTOP);
|
|
|
|
return hr;
|
|
}
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT));
|
|
|
|
LRESULT lResult = 0;
|
|
lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
WPARAM Index = (WPARAM) lResult;
|
|
|
|
lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_GETTEXT,
|
|
Index,
|
|
(LPARAM) szFriendlyName);
|
|
|
|
dwStartTime = timeGetTime();
|
|
|
|
//
|
|
// Get the images directory stored in the driver. We don't have to do this
|
|
// we can come up with our own, but the driver will generate a default temp
|
|
// location, which is good enough for our purposes.
|
|
//
|
|
|
|
TCHAR szTempPath[MAX_PATH] = {0};
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
GetTempPath(MAX_PATH, szTempPath);
|
|
_sntprintf(szImagesDirectory, sizeof(szImagesDirectory) / sizeof(TCHAR),
|
|
TEXT("%s\\WiaVideoTest\\%s"), szTempPath, szFriendlyName);
|
|
|
|
}
|
|
|
|
//
|
|
// Set the images directory on the WiaVideo object
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wszImagesDir[MAX_PATH] = {0};
|
|
|
|
AppUtil_ConvertToWideString(szImagesDirectory, wszImagesDir,
|
|
sizeof(wszImagesDir) / sizeof(WCHAR));
|
|
|
|
|
|
bstrImagesDir = ::SysAllocString(wszImagesDir);
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->put_ImagesDirectory(bstrImagesDir);
|
|
}
|
|
|
|
//
|
|
// Create Video.
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
UINT uiDeviceNumber = (UINT) Index;
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->CreateVideoByDevNum(uiDeviceNumber,
|
|
GetDlgItem(APP_GVAR.hwndMainDlg,
|
|
IDC_VIDEO_PREVIEW_WINDOW),
|
|
FALSE,
|
|
TRUE);
|
|
}
|
|
|
|
dwEndTime = timeGetTime();
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_GRAPH_BUILD_TIME,
|
|
(UINT) abs(dwEndTime - dwStartTime),
|
|
FALSE);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
SetDlgItemText(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_IMAGES_DIR,
|
|
szImagesDirectory);
|
|
}
|
|
|
|
//
|
|
// Populate our list of items for this device
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = ImageLst_PopulateDShowItemList(szImagesDirectory);
|
|
}
|
|
|
|
if (bstrImagesDir)
|
|
{
|
|
::SysFreeString(bstrImagesDir);
|
|
bstrImagesDir = NULL;
|
|
}
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW));
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_FAILED_TO_CREATE_VIDEO,
|
|
MB_OK | MB_ICONSTOP,
|
|
hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// CreateVideoFriendlyName
|
|
//
|
|
HRESULT CreateVideoFriendlyName()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szImagesDirectory[MAX_PATH] = {0};
|
|
TCHAR szFriendlyName[255 + 1] = {0};
|
|
BSTR bstrFriendlyName = NULL;
|
|
BSTR bstrImagesDir = NULL;
|
|
WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
|
|
DWORD dwStartTime = 0;
|
|
DWORD dwEndTime = 0;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->GetCurrentState(&VideoState);
|
|
|
|
if (VideoState != WIAVIDEO_NO_VIDEO)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_VIDEO_STILL_ACTIVE,
|
|
MB_OK | MB_ICONSTOP);
|
|
|
|
return hr;
|
|
}
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT));
|
|
|
|
LRESULT lResult = 0;
|
|
lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
WPARAM Index = (WPARAM) lResult;
|
|
|
|
lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg,
|
|
IDC_LIST_WIA_DEVICES,
|
|
LB_GETTEXT,
|
|
Index,
|
|
(LPARAM) szFriendlyName);
|
|
|
|
dwStartTime = timeGetTime();
|
|
|
|
//
|
|
// Get the images directory stored in the driver. We don't have to do this
|
|
// we can come up with our own, but the driver will generate a default temp
|
|
// location, which is good enough for our purposes.
|
|
//
|
|
|
|
TCHAR szTempPath[MAX_PATH] = {0};
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
GetTempPath(MAX_PATH, szTempPath);
|
|
_sntprintf(szImagesDirectory, sizeof(szImagesDirectory) / sizeof(TCHAR),
|
|
TEXT("%s\\WiaVideoTest\\%s"), szTempPath, szFriendlyName);
|
|
|
|
}
|
|
|
|
//
|
|
// Set the images directory on the WiaVideo object
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wszImagesDir[MAX_PATH] = {0};
|
|
|
|
AppUtil_ConvertToWideString(szImagesDirectory, wszImagesDir,
|
|
sizeof(wszImagesDir) / sizeof(WCHAR));
|
|
|
|
|
|
bstrImagesDir = ::SysAllocString(wszImagesDir);
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->put_ImagesDirectory(bstrImagesDir);
|
|
}
|
|
|
|
//
|
|
// Set the images directory on the WiaVideo object
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
WCHAR wszFriendlyName[255 + 1] = {0};
|
|
|
|
AppUtil_ConvertToWideString(szFriendlyName, wszFriendlyName,
|
|
sizeof(wszFriendlyName) / sizeof(WCHAR));
|
|
|
|
bstrFriendlyName = ::SysAllocString(wszFriendlyName);
|
|
}
|
|
|
|
//
|
|
// Create Video.
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
UINT uiDeviceNumber = (UINT) lResult;
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->CreateVideoByName(bstrFriendlyName,
|
|
GetDlgItem(APP_GVAR.hwndMainDlg,
|
|
IDC_VIDEO_PREVIEW_WINDOW),
|
|
FALSE,
|
|
TRUE);
|
|
}
|
|
|
|
dwEndTime = timeGetTime();
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_GRAPH_BUILD_TIME,
|
|
(UINT) abs(dwEndTime - dwStartTime),
|
|
FALSE);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
SetDlgItemText(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_IMAGES_DIR,
|
|
szImagesDirectory);
|
|
}
|
|
|
|
//
|
|
// Populate our list of items for this device
|
|
//
|
|
if (hr == S_OK)
|
|
{
|
|
hr = ImageLst_PopulateDShowItemList(szImagesDirectory);
|
|
}
|
|
|
|
if (bstrImagesDir)
|
|
{
|
|
::SysFreeString(bstrImagesDir);
|
|
bstrImagesDir = NULL;
|
|
}
|
|
|
|
if (bstrFriendlyName)
|
|
{
|
|
::SysFreeString(bstrFriendlyName);
|
|
bstrFriendlyName = NULL;
|
|
}
|
|
|
|
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW));
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
AppUtil_MsgBox(IDS_ERROR,
|
|
IDS_FAILED_TO_CREATE_VIDEO,
|
|
MB_OK | MB_ICONSTOP,
|
|
hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// DestroyVideo
|
|
//
|
|
HRESULT DestroyVideo()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->DestroyVideo();
|
|
|
|
if (APP_GVAR.bWiaDeviceListMode)
|
|
{
|
|
hr = WiaProc_DestroySelectedDevice();
|
|
ImageLst_Clear();
|
|
}
|
|
else
|
|
{
|
|
ImageLst_Clear();
|
|
}
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_GRAPH_BUILD_TIME,
|
|
0,
|
|
FALSE);
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_LIST_LOAD_TIME,
|
|
0,
|
|
FALSE);
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// Play
|
|
//
|
|
HRESULT Play()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
LOCAL_GVAR.pWiaVideo->Play();
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// Pause
|
|
//
|
|
HRESULT Pause()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
LOCAL_GVAR.pWiaVideo->Pause();
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// TakePicture
|
|
//
|
|
HRESULT TakePicture(BOOL bTakePictureThroughDriver)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (APP_GVAR.bWiaDeviceListMode)
|
|
{
|
|
if (bTakePictureThroughDriver)
|
|
{
|
|
//
|
|
// send DeviceCommand to driver. This is an async call for
|
|
// the Wia Video Driver which means we will NOT receive a
|
|
// WiaItem object back.
|
|
//
|
|
|
|
hr = WiaProc_DeviceTakePicture();
|
|
}
|
|
else
|
|
{
|
|
if (LOCAL_GVAR.pWiaVideo)
|
|
{
|
|
BSTR bstrNewImage = NULL;
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->TakePicture(&bstrNewImage);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
WiaProc_SetLastSavedImage(bstrNewImage);
|
|
}
|
|
|
|
if (bstrNewImage)
|
|
{
|
|
::SysFreeString(bstrNewImage);
|
|
bstrNewImage = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (LOCAL_GVAR.pWiaVideo)
|
|
{
|
|
BSTR bstrNewImage = NULL;
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->TakePicture(&bstrNewImage);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
ImageLst_PostAddImageRequest(bstrNewImage);
|
|
|
|
if (bstrNewImage)
|
|
{
|
|
::SysFreeString(bstrNewImage);
|
|
bstrNewImage = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// ShowVideo
|
|
//
|
|
HRESULT ShowVideo()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (LOCAL_GVAR.bPreviewVisible)
|
|
{
|
|
LOCAL_GVAR.bPreviewVisible = FALSE;
|
|
}
|
|
else
|
|
{
|
|
LOCAL_GVAR.bPreviewVisible = TRUE;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->put_PreviewVisible(LOCAL_GVAR.bPreviewVisible);
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// ResizeVideo
|
|
//
|
|
HRESULT ResizeVideo(BOOL bStretchToFitWindow)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->ResizeVideo(bStretchToFitWindow);
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// ShowCurrentState
|
|
//
|
|
HRESULT ShowCurrentState()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
|
|
|
|
if (LOCAL_GVAR.pWiaVideo == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = LOCAL_GVAR.pWiaVideo->GetCurrentState(&VideoState);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
UINT uiResID = 0;
|
|
TCHAR szState[63 + 1] = {0};
|
|
|
|
switch (VideoState)
|
|
{
|
|
case WIAVIDEO_NO_VIDEO:
|
|
uiResID = IDS_NO_VIDEO;
|
|
break;
|
|
|
|
case WIAVIDEO_CREATING_VIDEO:
|
|
uiResID = IDS_CREATING_VIDEO;
|
|
break;
|
|
|
|
case WIAVIDEO_VIDEO_CREATED:
|
|
uiResID = IDS_VIDEO_CREATED;
|
|
break;
|
|
|
|
case WIAVIDEO_VIDEO_PLAYING:
|
|
uiResID = IDS_PLAYING_VIDEO;
|
|
break;
|
|
|
|
case WIAVIDEO_VIDEO_PAUSED:
|
|
uiResID = IDS_VIDEO_PAUSED;
|
|
break;
|
|
|
|
case WIAVIDEO_DESTROYING_VIDEO:
|
|
uiResID = IDS_DESTROYING_VIDEO;
|
|
break;
|
|
|
|
default:
|
|
uiResID = IDS_STATE_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
LoadString(APP_GVAR.hInstance,
|
|
uiResID,
|
|
szState,
|
|
sizeof(szState) / sizeof(TCHAR));
|
|
|
|
if (szState[0] != 0)
|
|
{
|
|
SetDlgItemText(APP_GVAR.hwndMainDlg,
|
|
IDC_EDIT_CURRENT_STATE,
|
|
szState);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// CreateWiaVideoObject
|
|
//
|
|
HRESULT CreateWiaVideoObject()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
// Create the WiaVideo object
|
|
hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWiaVideo, (LPVOID *)&LOCAL_GVAR.pWiaVideo);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// TakePictureStress
|
|
//
|
|
HRESULT TakePictureStress()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INT_PTR iReturn = 0;
|
|
|
|
//
|
|
// Ask user how many threads to use and how many
|
|
// pictures each thread should take.
|
|
//
|
|
|
|
LOCAL_GVAR.iNumThreads = 0;
|
|
LOCAL_GVAR.uiNumImagesPerThread = 0;
|
|
|
|
iReturn = DialogBox(APP_GVAR.hInstance,
|
|
MAKEINTRESOURCE(IDD_STRESSDLG),
|
|
APP_GVAR.hwndMainDlg,
|
|
StressDlgProc);
|
|
|
|
|
|
if (iReturn == IDOK)
|
|
{
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg, IDC_EDIT_NUM_STRESS_THREADS,
|
|
LOCAL_GVAR.iNumThreads, FALSE);
|
|
|
|
UINT uiNumThreads = (UINT) LOCAL_GVAR.iNumThreads;
|
|
|
|
for (UINT i = 0; (i < uiNumThreads) && (hr == S_OK); i++)
|
|
{
|
|
ThreadArgs_t *pArgs = new ThreadArgs_t;
|
|
|
|
if (pArgs)
|
|
{
|
|
DWORD dwThreadID = 0;
|
|
|
|
ZeroMemory(pArgs, sizeof(ThreadArgs_t));
|
|
|
|
pArgs->uiNumPicturesToTake = LOCAL_GVAR.uiNumImagesPerThread;
|
|
pArgs->uiThreadSleepTime = (rand() % 100) + 25; // 25 - 125 ms sleeptime.
|
|
|
|
CreateThread(NULL,
|
|
0,
|
|
TakePictureThreadProc,
|
|
(void*) pArgs,
|
|
0,
|
|
&dwThreadID);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////
|
|
// StressDlgProc
|
|
//
|
|
// Mesage handler for Stress Dialog Box
|
|
//
|
|
INT_PTR CALLBACK StressDlgProc(HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if (LOWORD(wParam) == IDOK)
|
|
{
|
|
BOOL bTranslated = TRUE;
|
|
|
|
LOCAL_GVAR.iNumThreads = GetDlgItemInt(hDlg,
|
|
IDC_EDIT_NUM_THREADS,
|
|
&bTranslated,
|
|
FALSE);
|
|
|
|
LOCAL_GVAR.uiNumImagesPerThread = GetDlgItemInt(hDlg,
|
|
IDC_EDIT_NUM_IMAGES_PER_THREAD,
|
|
&bTranslated,
|
|
FALSE);
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
}
|
|
else if (LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// TakePictureMultiple
|
|
//
|
|
HRESULT TakePictureMultiple()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INT_PTR iReturn = 0;
|
|
|
|
//
|
|
// Ask user how many threads to use and how many
|
|
// pictures each thread should take.
|
|
//
|
|
|
|
LOCAL_GVAR.iNumThreads = 0;
|
|
LOCAL_GVAR.uiNumImagesPerThread = 0;
|
|
|
|
iReturn = DialogBox(APP_GVAR.hInstance,
|
|
MAKEINTRESOURCE(IDD_DIALOG_TAKE_PICTURE_MULTIPLE),
|
|
APP_GVAR.hwndMainDlg,
|
|
MultipleDlgProc);
|
|
|
|
|
|
if (iReturn == IDOK)
|
|
{
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg, IDC_EDIT_NUM_STRESS_THREADS,
|
|
1, FALSE);
|
|
|
|
//
|
|
// uiNumThreads should be 1.
|
|
//
|
|
UINT uiNumThreads = 1;
|
|
|
|
for (UINT i = 0; i < uiNumThreads; i++)
|
|
{
|
|
ThreadArgs_t *pArgs = new ThreadArgs_t;
|
|
|
|
if (pArgs)
|
|
{
|
|
ZeroMemory(pArgs, sizeof(ThreadArgs_t));
|
|
pArgs->uiNumPicturesToTake = LOCAL_GVAR.uiNumImagesPerThread;
|
|
pArgs->uiThreadSleepTime = LOCAL_GVAR.uiTakePictureInterval;
|
|
|
|
DWORD dwThreadID = 0;
|
|
|
|
CreateThread(NULL,
|
|
0,
|
|
TakePictureThreadProc,
|
|
(void*) pArgs,
|
|
0,
|
|
&dwThreadID);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////
|
|
// MultipleDlgProc
|
|
//
|
|
// Mesage handler for Stress Dialog Box
|
|
//
|
|
INT_PTR CALLBACK MultipleDlgProc(HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if (LOWORD(wParam) == IDOK)
|
|
{
|
|
BOOL bTranslated = TRUE;
|
|
|
|
LOCAL_GVAR.iNumThreads = 1;
|
|
|
|
LOCAL_GVAR.uiNumImagesPerThread = GetDlgItemInt(hDlg,
|
|
IDC_EDIT_NUM_PICTURES_TO_TAKE,
|
|
&bTranslated,
|
|
FALSE);
|
|
|
|
LOCAL_GVAR.uiTakePictureInterval = GetDlgItemInt(hDlg,
|
|
IDC_EDIT_TAKE_PICTURE_FREQUENCY,
|
|
&bTranslated,
|
|
FALSE);
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
}
|
|
else if (LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// TakePictureThreadProc
|
|
//
|
|
DWORD WINAPI TakePictureThreadProc(void *pArgs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bDone = FALSE;
|
|
ThreadArgs_t *pThreadArgs = (ThreadArgs_t*) pArgs;
|
|
|
|
if (pThreadArgs == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
UINT uiNumPicturesToTake = pThreadArgs->uiNumPicturesToTake;
|
|
UINT uiSleepTime = pThreadArgs->uiThreadSleepTime;
|
|
UINT uiNumPicturesTaken = 0;
|
|
|
|
delete pThreadArgs;
|
|
pThreadArgs = NULL;
|
|
|
|
while (!bDone)
|
|
{
|
|
if ((LOCAL_GVAR.pWiaVideo == NULL) ||
|
|
(LOCAL_GVAR.bExitThreads == TRUE))
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
|
|
if (!bDone)
|
|
{
|
|
hr = TakePicture(FALSE);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
|
|
Sleep(uiSleepTime);
|
|
|
|
++uiNumPicturesTaken;
|
|
|
|
if (uiNumPicturesTaken >= uiNumPicturesToTake)
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
InterlockedDecrement((LONG*) &LOCAL_GVAR.iNumThreads);
|
|
|
|
SetDlgItemInt(APP_GVAR.hwndMainDlg, IDC_EDIT_NUM_STRESS_THREADS,
|
|
LOCAL_GVAR.iNumThreads, FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////////////
|
|
// GetDeviceProperty
|
|
//
|
|
// Static Fn
|
|
//
|
|
BOOL GetDeviceProperty(IPropertyBag *pPropertyBag,
|
|
LPCWSTR pwszProperty,
|
|
TCHAR *pszProperty,
|
|
DWORD cchProperty)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
VARIANT VarName;
|
|
|
|
if ((pPropertyBag == NULL) ||
|
|
(pwszProperty == NULL) ||
|
|
(pszProperty == NULL))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VariantInit(&VarName);
|
|
VarName.vt = VT_BSTR;
|
|
hr = pPropertyBag->Read(pwszProperty, &VarName, 0);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = AppUtil_ConvertToTCHAR(VarName.bstrVal,
|
|
pszProperty,
|
|
cchProperty);
|
|
|
|
VariantClear(&VarName);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|