////////////////////////////////////////////////////////////////////////// // // winmain.cpp : Application entry-point // // 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) Microsoft Corporation. All rights reserved. // ////////////////////////////////////////////////////////////////////////// #include "ARMFCaptureD3D.h" #include "resource.h" #include "ConfigFile\ConfigFile.h" #include "debug.h" #include "options.h" #include "ARAnalyse.h" // Include the v6 common controls in the manifest #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='*' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"") // // ChooseDeviceParam structure // // Holds an array of IMFActivate pointers that represent video // capture devices. // struct ChooseDeviceParam { IMFActivate **ppDevices; // Array of IMFActivate pointers. UINT32 count; // Number of elements in the array. UINT32 selection; // Selected device, by array index. }; // // ChooseDeviceParam structure // // Holds an array of IMFActivate pointers that represent video // capture devices. // struct ChooseVideoParam { IMFMediaType **ppTypes; // Array of IMFMediaType pointers. UINT32 count; // Number of elements in the array. UINT32 selection; // Selected device, by array index. }; BOOL InitializeApplication(); BOOL InitializeWindow(HWND *pHwnd); void CleanUp(); INT MessageLoop(HWND hwnd); LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DeviceDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK VideoDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void ShowErrorMessage(PCWSTR format, HRESULT hr); // Window message handlers BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct); void OnClose(HWND hwnd); void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify); void OnSize(HWND hwnd, UINT state, int cx, int cy); void OnDeviceChange(HWND hwnd, DEV_BROADCAST_HDR *pHdr); void OnPaint(HWND hwnd); void OnInitMenu(HWND hwnd, HMENU menu); // Command handlers void OnChooseDevice(HWND hwnd, BOOL bPrompt, const WCHAR *name, int instance); void OnChooseFormat(HWND hwnd, BOOL bPrompt, int index); int DeviceGetByName(ChooseDeviceParam *pParam , const WCHAR* name, int instance); // Constants const WCHAR CLASS_NAME[] = L"MFCapture Window Class"; const WCHAR WINDOW_NAME[] = L"MFCapture Sample Application"; // Global variables HWND g_hVideo = NULL; HWND g_hStatus = NULL; HWND g_hTrack = NULL; int g_Threshold = 125; HWND g_hTrackSeuilMin = NULL; int g_ThresholdMin = 127; HWND g_hTrackSeuilMax = NULL; int g_ThresholdMax = 127; CPreview *g_pPreview = NULL; HDEVNOTIFY g_hdevnotify = NULL; ARAnalyse *g_pAnalyse = NULL; ConfigFile *g_config = NULL; std::wstring g_camera_name; int g_camera_instance = 0; std::string g_ivy_domain; int g_format_video = 0; bool g_toggle_video = false; bool g_read_calibrationfile = false; // command line options std::wstring widen( const string& str ) { std::wostringstream wstm ; const std::ctype& ctfacet = std::use_facet< std::ctype >( wstm.getloc() ) ; for( size_t i=0 ; i& ctfacet = std::use_facet< std::ctype >( stm.getloc() ) ; for( size_t i=0 ; i default: Logitech", "i:instcam default: 0", "b:bus ", "v|video non affichage video", "f:format ", "p:projection Read ProjectionFile ", NULL } ; Options opts("ARIvy", optv); opts.ctrls( Options::LONG_ONLY ); OptStrTokIter iter(argv); while( (optchar = opts(iter, pa_optarg)) != 0 ) { switch (optchar) { case 'c': g_camera_name = widen( pa_optarg ); break; case 'i': g_camera_instance = atoi( pa_optarg ); break; case 'b': g_ivy_domain = pa_optarg; break; case 'v': g_toggle_video = true; break; case 'f': g_format_video = atoi( pa_optarg ); break; case 'p': g_read_calibrationfile = true; break; case 'h': // Help default: ++errors; break; } } if (errors) { opts.usage(std::cout,""); getchar(); exit(0); } } //------------------------------------------------------------------- // WinMain // // Application entry-point. //------------------------------------------------------------------- INT WINAPI wWinMain(HINSTANCE/* hInstance*/, HINSTANCE /*hPrevInstance*/,LPWSTR lpCmdLine, INT /*nCmdShow*/ ) { HWND hwnd = 0; char *cmdLine = narrow(lpCmdLine) ; parse_args(cmdLine); free( cmdLine ); try { g_config = new ConfigFile("data\\config.inp"); HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); // camera param if ( g_camera_name.length() == 0 ) g_camera_name = widen(g_config->read("CameraName", "Logitech")); // Ivy if ( g_ivy_domain.length() == 0 ) g_ivy_domain = g_config->read("IvyBus",""); if (InitializeApplication() && InitializeWindow(&hwnd)) { MessageLoop(hwnd); } CleanUp(); return 0; } catch(ConfigFile::file_not_found ex) { WCHAR msg[MAX_PATH]; HRESULT hr = S_OK; hr = StringCbPrintfW(msg, sizeof(msg), L"Fichier de configuration not trouve: %S", ex.filename.c_str()); if (SUCCEEDED(hr)) { MessageBox(NULL, msg, L"Error", MB_ICONERROR); } return -1; } catch( ConfigFile::key_not_found ex) { WCHAR msg[MAX_PATH]; HRESULT hr = S_OK; hr = StringCbPrintfW(msg, sizeof(msg), L"cle manquante dans le fichier de configuration: %S", ex.key.c_str()); if (SUCCEEDED(hr)) { MessageBox(NULL, msg, L"Error", MB_ICONERROR); }return -1; } } //------------------------------------------------------------------- // WindowProc // // Window procedure. //------------------------------------------------------------------- LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hwnd, WM_CREATE, OnCreate); HANDLE_MSG(hwnd, WM_CLOSE, OnClose); HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); HANDLE_MSG(hwnd, WM_SIZE, OnSize); HANDLE_MSG(hwnd, WM_INITMENU, OnInitMenu); case WM_APP_PREVIEW_ERROR: ShowErrorMessage(L"Error", (HRESULT)wParam); break; case WM_DEVICECHANGE: OnDeviceChange(hwnd, (PDEV_BROADCAST_HDR)lParam); break; case WM_ERASEBKGND: // Suppress window erasing, to reduce flickering while the video is playing. return 1; //case WM_PAINT: // OnPaint(hwnd); // break; case WM_HSCROLL: { g_Threshold = SendMessage(g_hTrack, TBM_GETPOS, 0, 0); g_ThresholdMin = SendMessage(g_hTrackSeuilMin, TBM_GETPOS, 0, 0); g_ThresholdMax = SendMessage(g_hTrackSeuilMax, TBM_GETPOS, 0, 0); if ( g_pAnalyse ) g_pAnalyse->setThreshold( g_Threshold ); } break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } //------------------------------------------------------------------- // InitializeApplication // // Initializes the application. //------------------------------------------------------------------- BOOL InitializeApplication() { HRESULT hr = S_OK; InitCommonControls(); hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (SUCCEEDED(hr)) { hr = MFStartup(MF_VERSION); } return (SUCCEEDED(hr)); } //------------------------------------------------------------------- // CleanUp // // Releases resources. //------------------------------------------------------------------- void CleanUp() { if (g_hdevnotify) { UnregisterDeviceNotification(g_hdevnotify); } if (g_pPreview) { g_pPreview->CloseDevice(); } SafeRelease(&g_pPreview); MFShutdown(); CoUninitialize(); } //------------------------------------------------------------------- // InitializeWindow // // Creates the application window. //------------------------------------------------------------------- BOOL InitializeWindow(HWND *pHwnd) { WNDCLASS wc = {0}; wc.lpfnWndProc = WindowProc; wc.hInstance = GetModuleHandle(NULL); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = CLASS_NAME; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); if (!RegisterClass(&wc)) { return FALSE; } HWND hwnd = CreateWindow( CLASS_NAME, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL ); if (!hwnd) { return FALSE; } ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); *pHwnd = hwnd; return TRUE; } //------------------------------------------------------------------- // MessageLoop // // Implements the window message loop. //------------------------------------------------------------------- INT MessageLoop(HWND hwnd) { MSG msg = {0}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } DestroyWindow(hwnd); return INT(msg.wParam); } HWND CreateSlider( HWND parent, int pos, int min, int max, int val) { HWND hwndTrack = CreateWindowEx( 0, // no extended styles TRACKBAR_CLASS, // class name TEXT("Trackbar Control"), // title (caption) WS_CHILD | WS_VISIBLE | TBS_NOTICKS , // style pos, 0, // position 200, 20, // size parent, // parent window NULL, // control identifier NULL, // instance NULL // no WM_CREATE parameter ); SendMessage(hwndTrack, TBM_SETRANGE, (WPARAM) TRUE, // redraw flag (LPARAM) MAKELONG(min, max)); // min. & max. positions SendMessage(hwndTrack, TBM_SETPAGESIZE, 0, (LPARAM) 1); // new page size //SendMessage(hwndTrack, TBM_SETSEL, // (WPARAM) FALSE, // redraw flag // (LPARAM) MAKELONG(0, 255)); SendMessage(hwndTrack, TBM_SETPOS, (WPARAM) TRUE, // redraw flag (LPARAM) val); return hwndTrack; } //------------------------------------------------------------------- // OnCreate // // Handles the WM_CREATE message. //------------------------------------------------------------------- BOOL OnCreate(HWND hwnd, LPCREATESTRUCT) { HRESULT hr = S_OK; // Register this window to get device notification messages. DEV_BROADCAST_DEVICEINTERFACE di = { 0 }; di.dbcc_size = sizeof(di); di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; di.dbcc_classguid = KSCATEGORY_CAPTURE; g_hdevnotify = RegisterDeviceNotification( hwnd, &di, DEVICE_NOTIFY_WINDOW_HANDLE ); if (g_hdevnotify == NULL) { ShowErrorMessage(L"RegisterDeviceNotification failed.", HRESULT_FROM_WIN32(GetLastError())); return FALSE; } // Create status bar HWND hStatus = CreateStatusWindow( WS_CHILD | WS_VISIBLE, L"Status text" , hwnd, 100 ); // Create slider bar HWND hwndTrack = CreateSlider( hwnd, 0, 0, 255, g_Threshold); HWND hwndTrack1 = CreateSlider( hwnd, 210, 0, 255, g_ThresholdMin); HWND hwndTrack2 = CreateSlider( hwnd, 420, 0, 255, g_ThresholdMax); HWND hVideo = CreateWindow( TEXT("STATIC"), NULL, WS_CHILD | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, GetModuleHandle(NULL), NULL ); if (!hVideo) { ShowErrorMessage(L"Create Child Window failed.", GetLastError()); return FALSE; } RECT rcTrackBar; int iTrackHeight; RECT rcStatus; int iStatusHeight; int iEditHeight; RECT rcClient; // Size status bar and get height SendMessage(hStatus, WM_SIZE, 0, 0); GetWindowRect(hwndTrack, &rcTrackBar); GetWindowRect(hStatus, &rcStatus); iStatusHeight = rcStatus.bottom - rcStatus.top; iTrackHeight = rcTrackBar.bottom - rcTrackBar.top; // Calculate remaining height and size edit GetClientRect(hwnd, &rcClient); iEditHeight = rcClient.bottom - iStatusHeight - iTrackHeight; SetWindowPos(hVideo, NULL, 0, iTrackHeight, rcClient.right, iEditHeight, SWP_NOZORDER); g_hVideo = hVideo; g_hStatus = hStatus; g_hTrack = hwndTrack; g_hTrackSeuilMin = hwndTrack1; g_hTrackSeuilMax = hwndTrack2; // Create ArToolKit Analyser g_pAnalyse = new ARAnalyse(); // Create the object that manages video preview. if ( g_hVideo ) { hr = CPreview::CreateInstance(g_hVideo, g_hVideo, &g_pPreview); if (FAILED(hr)) { ShowErrorMessage(L"CPreview::CreateInstance failed.", hr); return FALSE; } // Select the first available device (if any). OnChooseDevice(hwnd, FALSE, g_camera_name.length() ? g_camera_name.c_str() : NULL, g_camera_instance ); } if ( g_toggle_video ) g_pPreview->ToggleVideo(); // start Ivy g_pAnalyse->IvyInit(g_ivy_domain.c_str()); return TRUE; } //------------------------------------------------------------------- // OnClose // // Handles WM_CLOSE messages. //------------------------------------------------------------------- void OnClose(HWND /*hwnd*/) { PostQuitMessage(0); } //------------------------------------------------------------------- // OnSize // // Handles WM_SIZE messages. //------------------------------------------------------------------- void OnSize(HWND hwnd, UINT state, int cx, int cy) { // Size status bar and get height RECT rcStatus; int iStatusHeight; int iVideoHeight; int iTrackHeight; // iconified if ( state == SIZE_MINIMIZED ) return; GetWindowRect(g_hStatus, &rcStatus); iStatusHeight = rcStatus.bottom - rcStatus.top; GetWindowRect(g_hTrack, &rcStatus); iTrackHeight = rcStatus.bottom - rcStatus.top; // Calculate remaining height and size edit iVideoHeight = cy - iStatusHeight -iTrackHeight; SetWindowPos(g_hVideo, NULL, 0, iTrackHeight, cx, iVideoHeight, SWP_NOZORDER); if (g_pPreview) { g_pPreview->ResizeVideo((WORD)cx, (WORD)iVideoHeight); InvalidateRect(hwnd, NULL, FALSE); } // Auto-resize statusbar (Send WM_SIZE message does just that) SendMessage(g_hStatus, WM_SIZE, 0, 0); } //------------------------------------------------------------------- // OnPaint // // Handles WM_PAINT messages. //------------------------------------------------------------------- //void OnPaint(HWND hwnd) //{ // // PAINTSTRUCT ps; // HDC hdc = BeginPaint(hwnd, &ps); // // // The video is not playing, so we must paint the application window. // RECT rc; // GetClientRect(hwnd, &rc); // FillRect(hdc, &rc, (HBRUSH) COLOR_WINDOW); // DrawText( hdc, L"ESSAI",5, &rc, 0); // EndPaint(hwnd, &ps); // // //} //------------------------------------------------------------------- // OnInitMenuChange // // Handles WM_INITMENU messages. //------------------------------------------------------------------- void OnInitMenu(HWND hwnd, HMENU menu) { EnableMenuItem( menu, ID_ACTION_CALIBRATE, g_pAnalyse->IsCalibrationEnabled() ? MF_ENABLED : MF_DISABLED ); EnableMenuItem( menu, ID_ACTION_SAVEPROJECTIONDATA, g_pAnalyse->IsCalibrated() ? MF_ENABLED : MF_DISABLED ); CheckMenuItem( menu, ID_ACTION_CALIBRATE, g_pAnalyse->IsCalibrated() ? MF_CHECKED : MF_UNCHECKED ); // Blur pass CheckMenuItem( menu, ID_BLURPASSE_0PASS, g_pAnalyse->BlurPass == 0 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_1PASS, g_pAnalyse->BlurPass == 1 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_2PASS, g_pAnalyse->BlurPass == 2 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_3PASS, g_pAnalyse->BlurPass == 3 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_4PASS, g_pAnalyse->BlurPass == 4 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_4PASS, g_pAnalyse->BlurPass == 5 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_4PASS, g_pAnalyse->BlurPass == 6 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_BLURPASSE_4PASS, g_pAnalyse->BlurPass == 10 ? MF_CHECKED : MF_UNCHECKED ); // DownSample CheckMenuItem( menu, ID_DOWNSAMPLE_FACTEUR1, g_pAnalyse->DownSample == 1 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_DOWNSAMPLE_FACTEUR2, g_pAnalyse->DownSample == 2 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_DOWNSAMPLE_FACTEUR4, g_pAnalyse->DownSample == 4 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_DOWNSAMPLE_FACTEUR8, g_pAnalyse->DownSample == 8 ? MF_CHECKED : MF_UNCHECKED ); // Affichage CheckMenuItem( menu, ID_AFFICHAGE_GRAYSCALE, g_pAnalyse->Display == ARAnalyse::GrayScale ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_AFFICHAGE_BLUR, g_pAnalyse->Display == ARAnalyse::Blur ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_AFFICHAGE_DIFF, g_pAnalyse->Display == ARAnalyse::Diff ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_AFFICHAGE_THRESHOLD, g_pAnalyse->Display == ARAnalyse::Threshold ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_AFFICHAGE_MOYEN, g_pAnalyse->Display == ARAnalyse::Moyen ? MF_CHECKED : MF_UNCHECKED ); // Filter CheckMenuItem( menu, ID_FILTER_MOYEN, g_pAnalyse->filter == ARAnalyse::FMoyen ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_LAPLACIEN4, g_pAnalyse->filter == ARAnalyse::FLaplacien4 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_LAPLACIEN8, g_pAnalyse->filter == ARAnalyse::FLaplacien8 ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_LAPLACIEND, g_pAnalyse->filter == ARAnalyse::FLaplaciend ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_SOBEL, g_pAnalyse->filter == ARAnalyse::FSobel ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_PREWITT, g_pAnalyse->filter == ARAnalyse::FPrewitt ? MF_CHECKED : MF_UNCHECKED ); CheckMenuItem( menu, ID_FILTER_GAUSSIAN, g_pAnalyse->filter == ARAnalyse::FGaussian ? MF_CHECKED : MF_UNCHECKED ); } //------------------------------------------------------------------- // OnCommand // // Handles WM_COMMAND messages //------------------------------------------------------------------- void OnCommand(HWND hwnd, int id, HWND /*hwndCtl*/, UINT /*codeNotify*/) { switch (id) { case ID_ACTION_CHOOSEDEVICE: OnChooseDevice(hwnd, TRUE, NULL,0); break; case ID_ACTION_CHOOSEFORMAT: OnChooseFormat(hwnd, TRUE, 0); break; case ID_ACTION_DISPLAYVIDEO: if (g_pPreview) { bool video = g_pPreview->ToggleVideo(); CheckMenuItem( GetMenu( hwnd ), ID_ACTION_DISPLAYVIDEO, video ? MF_CHECKED : MF_UNCHECKED ); } break; case ID_ACTION_CALCMOYEN: if (g_pPreview) { bool moy = g_pPreview->ToggleMoyen(); CheckMenuItem( GetMenu( hwnd ), ID_ACTION_CALCMOYEN, moy ? MF_CHECKED : MF_UNCHECKED ); } break;case ID_ACTION_TRANSFORM: if (g_pPreview) { bool trsf = g_pPreview->ToggleTransform(); CheckMenuItem( GetMenu( hwnd ), ID_ACTION_TRANSFORM, trsf ? MF_CHECKED : MF_UNCHECKED ); } break; case ID_ACTION_AUTOTHRESHOLD: if (g_pAnalyse) { bool auto_threshold = g_pAnalyse->ToggleAutoThreshold(); CheckMenuItem( GetMenu( hwnd ), ID_ACTION_AUTOTHRESHOLD, auto_threshold ? MF_CHECKED : MF_UNCHECKED ); if ( ! auto_threshold ) { SendMessage(g_hTrack, TBM_SETPOS, (WPARAM) TRUE, // redraw flag (LPARAM) g_pAnalyse->getThreshold()); } } break; case ID_ACTION_CALIBRATE: if (g_pAnalyse) { bool cal = g_pAnalyse->Calibrate(); CheckMenuItem( GetMenu( hwnd ), ID_ACTION_CALIBRATE, cal ? MF_CHECKED : MF_UNCHECKED ); } break; case ID_ACTION_SAVEPROJECTIONDATA: if ( g_pAnalyse ) { g_pAnalyse->SaveCalibration(); } break; case ID_BLURPASSE_0PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 0; } break; case ID_BLURPASSE_1PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 1; } break; case ID_BLURPASSE_2PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 2; } break; case ID_BLURPASSE_3PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 3; } break; case ID_BLURPASSE_4PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 4; } break; case ID_BLURPASSE_5PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 5; } break; case ID_BLURPASSE_6PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 6; } break; case ID_BLURPASSE_10PASS: if (g_pAnalyse) { g_pAnalyse->BlurPass = 10; } break; case ID_DOWNSAMPLE_FACTEUR1: if (g_pAnalyse) { g_pAnalyse->DownSample = 1; } break; case ID_DOWNSAMPLE_FACTEUR2: if (g_pAnalyse) { g_pAnalyse->DownSample = 2; } break; case ID_DOWNSAMPLE_FACTEUR4: if (g_pAnalyse) { g_pAnalyse->DownSample = 4; } break; case ID_DOWNSAMPLE_FACTEUR8: if (g_pAnalyse) { g_pAnalyse->DownSample = 8; } break; case ID_AFFICHAGE_GRAYSCALE: if (g_pAnalyse) { g_pAnalyse->Display = ARAnalyse::GrayScale; } break; case ID_AFFICHAGE_BLUR: if (g_pAnalyse) { g_pAnalyse->Display = ARAnalyse::Blur; } break; case ID_AFFICHAGE_DIFF: if (g_pAnalyse) { g_pAnalyse->Display = ARAnalyse::Diff; } break; case ID_AFFICHAGE_THRESHOLD: if (g_pAnalyse) { g_pAnalyse->Display = ARAnalyse::Threshold; } break; case ID_AFFICHAGE_MOYEN: if (g_pAnalyse) { g_pAnalyse->Display = ARAnalyse::Moyen; } break; case ID_FILTER_MOYEN: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FMoyen; } break; case ID_FILTER_LAPLACIEN4: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FLaplacien4; } break; case ID_FILTER_LAPLACIEN8: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FLaplacien8; } break; case ID_FILTER_LAPLACIEND: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FLaplaciend; } break; case ID_FILTER_SOBEL: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FSobel; } break; case ID_FILTER_PREWITT: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FPrewitt; } break; case ID_FILTER_GAUSSIAN: if (g_pAnalyse) { g_pAnalyse->filter = ARAnalyse::FGaussian; } break; } } //------------------------------------------------------------------- // OnChooseDevice // // Select a video capture device. // // hwnd: A handle to the application window. /// bPrompt: If TRUE, prompt to user to select the device. Otherwise, // select the first device in the list. //------------------------------------------------------------------- void OnChooseDevice(HWND hwnd, BOOL bPrompt, const WCHAR* name, int instance) { HRESULT hr = S_OK; ChooseDeviceParam param = { 0,0,0 }; UINT iDevice = 0; // Index into the array of devices BOOL bCancel = FALSE; IMFAttributes *pAttributes = NULL; // Initialize an attribute store to specify enumeration parameters. hr = MFCreateAttributes(&pAttributes, 1); if (FAILED(hr)) { goto done; } // Ask for source type = video capture devices. hr = pAttributes->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID ); if (FAILED(hr)) { goto done; } // Enumerate devices. hr = MFEnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count); if (FAILED(hr)) { goto done; } // NOTE: param.count might be zero. if (bPrompt || name == NULL) { // Ask the user to select a device. INT_PTR result = DialogBoxParam( GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_CHOOSE_DEVICE), hwnd, DeviceDlgProc, (LPARAM)¶m ); if (result == IDOK) { iDevice = param.selection; } else { bCancel = TRUE; // User cancelled } } else { iDevice = DeviceGetByName( ¶m, name, instance ); } if (!bCancel && (param.count > 0)) { // Give this source to the CPlayer object for preview. hr = g_pPreview->SetDevice( param.ppDevices[iDevice], g_format_video ); } done: SafeRelease(&pAttributes); for (DWORD i = 0; i < param.count; i++) { SafeRelease(¶m.ppDevices[i]); } CoTaskMemFree(param.ppDevices); if (FAILED(hr)) { ShowErrorMessage(L"Cannot create a video capture device", hr); } } //------------------------------------------------------------------- // OnChooseFormat // // Select a video format capture. // // hwnd: A handle to the application window. /// bPrompt: If TRUE, prompt to user to select the device. Otherwise, // select the first device in the list. //------------------------------------------------------------------- void OnChooseFormat(HWND hwnd, BOOL bPrompt, int index) { HRESULT hr = S_OK; ChooseVideoParam param = { 0, 0, 0 }; UINT iFormat = 0; // Index into the array of devices BOOL bCancel = FALSE; hr = g_pPreview->EnumerateCaptureFormats( ¶m.ppTypes, ¶m.count); // NOTE: param.count might be zero. if (bPrompt) { // Ask the user to select a device. INT_PTR result = DialogBoxParam( GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_CHOOSE_VIDEO), hwnd, VideoDlgProc, (LPARAM)¶m ); if (result == IDOK) { iFormat = param.selection; } else { bCancel = TRUE; // User cancelled } } else { iFormat = index; } if (!bCancel && (param.count > 0)) { // Give this format to the CPlayer object for preview. hr = g_pPreview->SetFormat( param.ppTypes[iFormat] ); } for (DWORD i = 0; i < param.count; i++) { SafeRelease(¶m.ppTypes[i]); } CoTaskMemFree(param.ppTypes); if (FAILED(hr)) { ShowErrorMessage(L"Cannot select a video format", hr); } } //------------------------------------------------------------------- // OnDeviceChange // // Handles WM_DEVICECHANGE messages. //------------------------------------------------------------------- void OnDeviceChange(HWND hwnd, DEV_BROADCAST_HDR *pHdr) { if (g_pPreview == NULL || pHdr == NULL) { return; } HRESULT hr = S_OK; BOOL bDeviceLost = FALSE; // Check if the current device was lost. hr = g_pPreview->CheckDeviceLost(pHdr, &bDeviceLost); if (FAILED(hr) || bDeviceLost) { g_pPreview->CloseDevice(); MessageBox(hwnd, L"Lost the capture device.", WINDOW_NAME, MB_OK); } } ///////////////////////////////////////////////////////////////////// // Dialog functions int DeviceGetByName(ChooseDeviceParam *pParam , const WCHAR* name, int instance) { HRESULT hr = S_OK; DWORD iDevice = 0; int current_inst = 0; bool NameFound = false; for (DWORD i = 0; i < pParam->count; i++) { WCHAR *szFriendlyName = NULL; hr = pParam->ppDevices[i]->GetAllocatedString( MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &szFriendlyName, NULL ); if (FAILED(hr)) { break; } NameFound = wcsstr( szFriendlyName, name ) != NULL; CoTaskMemFree(szFriendlyName); // check if devioce containt name if ( NameFound ) { iDevice = i; if ( current_inst == instance ) break; current_inst++; } } return iDevice; } //------------------------------------------------------------------- // OnInitDialog // // Handles the WM_INITDIALOG message. //------------------------------------------------------------------- void DeviceOnInitDialog(HWND hwnd, ChooseDeviceParam *pParam) { HRESULT hr = S_OK; // Populate the list with the friendly names of the devices. HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST); for (DWORD i = 0; i < pParam->count; i++) { WCHAR *szFriendlyName = NULL; hr = pParam->ppDevices[i]->GetAllocatedString( MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &szFriendlyName, NULL ); if (FAILED(hr)) { break; } int index = ListBox_AddString(hList, szFriendlyName); ListBox_SetItemData(hList, index, i); CoTaskMemFree(szFriendlyName); } // Assume no selection for now. pParam->selection = (UINT32)-1; if (pParam->count == 0) { // If there are no devices, disable the "OK" button. EnableWindow(GetDlgItem(hwnd, IDOK), FALSE); } } HRESULT DeviceOnOK(HWND hwnd, ChooseDeviceParam *pParam) { HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST); int sel = ListBox_GetCurSel(hList); if (sel != LB_ERR) { pParam->selection = (UINT32)ListBox_GetItemData(hList, sel); } return S_OK; } //------------------------------------------------------------------- // DeviceDlgProc // // Dialog procedure for the "Select Device" dialog. //------------------------------------------------------------------- INT_PTR CALLBACK DeviceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static ChooseDeviceParam *pParam = NULL; switch (msg) { case WM_INITDIALOG: pParam = (ChooseDeviceParam*)lParam; DeviceOnInitDialog(hwnd, pParam); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: DeviceOnOK(hwnd, pParam); EndDialog(hwnd, LOWORD(wParam)); return TRUE; case IDCANCEL: EndDialog(hwnd, LOWORD(wParam)); return TRUE; } break; } return FALSE; } void ShowErrorMessage(PCWSTR format, HRESULT hrErr) { HRESULT hr = S_OK; int dwBufferLength; WCHAR msg[MAX_PATH]; static LPCVOID s_hModule = 0; const LPCWSTR MESSAGEFILE = L"mferror.dll"; DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK; WCHAR *lpMsgBuf = 0; dwBufferLength = FormatMessage( dwFormatFlags, NULL, hrErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL ); //lpMsgBuf[strlen(lpMsgBuf) -2] = '\0'; // remove last \n // Not a system message. In theory, you should be able to get both with one call. // In practice (at least on my 64bit box), you need to make 2 calls. if (dwBufferLength == 0) { if (s_hModule == 0) { // Load the Media Foundation error message dll s_hModule = LoadLibraryEx(MESSAGEFILE, NULL, LOAD_LIBRARY_AS_DATAFILE); } if (s_hModule != 0) { // If the load succeeds, make sure we look in it dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; // Scan both the Windows Media library, and the system library looking for the message dwBufferLength = FormatMessage( dwFormatFlags, s_hModule, // module to get message from (NULL == system) hrErr, // error number to get message for MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR)&lpMsgBuf, 0, NULL ); } } hr = StringCbPrintf(msg, sizeof(msg), L"%s (hr=0x%X) \n%s", format, hrErr, lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); if (SUCCEEDED(hr)) { MessageBox(NULL, msg, L"Error", MB_ICONERROR); } else { DebugBreak(); } } // Dialog functions //------------------------------------------------------------------- // VideoOnInitDialog // // Handles the WM_INITDIALOG message. //------------------------------------------------------------------- void VideoOnInitDialog(HWND hwnd, ChooseVideoParam *pParam) { HRESULT hr = S_OK; PROPVARIANT var; UINT32 rate_num; UINT32 rate_denum; UINT32 width; UINT32 height; WCHAR msg[MAX_PATH]; // Populate the list with the friendly names of the devices. HWND hList = GetDlgItem(hwnd, IDC_VIDEO_LIST); for (DWORD i = 0; i < pParam->count; i++) { WCHAR *szSubTypeName = NULL; hr = pParam->ppTypes[i]->GetItem( MF_MT_SUBTYPE, &var ); if (FAILED(hr)) { break; } hr = GetGUIDName(*var.puuid, &szSubTypeName); if (FAILED(hr)) { break; } hr = MFGetAttributeSize( pParam->ppTypes[i], MF_MT_FRAME_RATE, &rate_num, &rate_denum ); if (FAILED(hr)) { break; } hr = MFGetAttributeSize( pParam->ppTypes[i], MF_MT_FRAME_SIZE, &width, &height); if (FAILED(hr)) { break; } if (SUCCEEDED(StringCchPrintf(msg, sizeof(msg), TEXT("%02d %s %dx%d pixel %.01f FPS"), i,szSubTypeName, width,height,((float)rate_num/rate_denum)))) { int index = ListBox_AddString(hList, msg); ListBox_SetItemData(hList, index, i); } CoTaskMemFree(szSubTypeName); } // Assume no selection for now. pParam->selection = (UINT32)-1; if (pParam->count == 0) { // If there are no devices, disable the "OK" button. EnableWindow(GetDlgItem(hwnd, IDOK), FALSE); } } HRESULT VideoOnOK(HWND hwnd, ChooseVideoParam *pParam) { HWND hList = GetDlgItem(hwnd, IDC_DEVICE_LIST); int sel = ListBox_GetCurSel(hList); if (sel != LB_ERR) { pParam->selection = (UINT32)ListBox_GetItemData(hList, sel); } return S_OK; } //------------------------------------------------------------------- // DeviceDlgProc // // Dialog procedure for the "Select Device" dialog. //------------------------------------------------------------------- INT_PTR CALLBACK VideoDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static ChooseVideoParam *pParam = NULL; switch (msg) { case WM_INITDIALOG: pParam = (ChooseVideoParam*)lParam; VideoOnInitDialog(hwnd, pParam); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: VideoOnOK(hwnd, pParam); EndDialog(hwnd, LOWORD(wParam)); return TRUE; case IDCANCEL: EndDialog(hwnd, LOWORD(wParam)); return TRUE; } break; } return FALSE; }