Update the changelog
[opencv] / apps / Hawk / MainFrm.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/// MainFrm.cpp : implementation of the CMainFrame class
41 //
42
43 #include "stdafx.h"
44 #include "Hawk.h"
45
46 #include "MainFrm.h"
47 #include "HawkDoc.h"
48 #include "ProxyTransuids.h"
49 #include <HighGUI.h>
50
51 extern "C"
52 {
53 #include <eic.h>
54 }
55
56
57 #ifdef _DEBUG
58 #define new DEBUG_NEW
59 #undef THIS_FILE
60 static char THIS_FILE[] = __FILE__;
61 #endif
62
63 #define WM_GRAPHNOTIFY  WM_USER+13
64
65 /////////////////////////////////////////////////////////////////////////////
66 // CMainFrame
67
68 IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
69
70 BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
71         //{{AFX_MSG_MAP(CMainFrame)
72         ON_WM_CREATE()
73         ON_WM_CLOSE()
74         ON_COMMAND(ID_VIDEO_PP, OnVideoPp)
75         ON_UPDATE_COMMAND_UI(ID_VIDEO_PP, OnUpdateVideoPp)
76         ON_COMMAND(ID_PIN_PP, OnPinPp)
77         ON_UPDATE_COMMAND_UI(ID_PIN_PP, OnUpdatePinPp)
78         //}}AFX_MSG_MAP
79 END_MESSAGE_MAP()
80
81 static UINT indicators[] =
82 {
83         ID_SEPARATOR,           // status line indicator
84         ID_SEPARATOR,           // x-coordinate of the cursor
85         ID_SEPARATOR,           // y-coordinate of the cursor
86 //      ID_SEPARATOR,
87 };
88
89 /////////////////////////////////////////////////////////////////////////////
90 // CMainFrame construction/destruction
91
92 CMainFrame::CMainFrame() : m_SourceFilter(0), m_FilterGraph(0), m_GraphBuilder(0),
93                                                         m_MediaControl(0), m_MediaEventEx(0), m_VideoWindow(0), m_ProxyTrans(0),
94                             m_isIntRun(FALSE), m_isDSRunning(0), m_pRunDoc(0)
95 {
96         // TODO: add member initialization code here
97         
98 }
99
100 CMainFrame::~CMainFrame()
101 {
102 }
103
104 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
105 {
106         if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
107                 return -1;
108         
109         if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
110                 | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
111                 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
112         {
113                 TRACE0("Failed to create toolbar\n");
114                 return -1;      // fail to create
115         }
116
117         if (!m_eicToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
118                 | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
119                 !m_eicToolBar.LoadToolBar(IDR_EICTOOLBAR))
120         {
121                 TRACE0("Failed to create toolbar\n");
122                 return -1;      // fail to create
123         }
124
125     if (!m_wndStatusBar.Create(this) ||
126                 !m_wndStatusBar.SetIndicators(indicators,
127                   sizeof(indicators)/sizeof(UINT)))
128         {
129                 TRACE0("Failed to create status bar\n");
130                 return -1;      // fail to create
131         }
132
133     // Setup the status bar
134     m_wndStatusBar.SetPaneInfo(1, ID_SEPARATOR, SBPS_NORMAL, 20);
135     m_wndStatusBar.SetPaneInfo(2, ID_SEPARATOR, SBPS_NORMAL, 20);
136         // TODO: Delete these three lines if you don't want the toolbar to
137         //  be dockable
138         m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
139         m_eicToolBar.EnableDocking(CBRS_ALIGN_ANY);
140         EnableDocking(CBRS_ALIGN_ANY);
141         DockControlBar(&m_wndToolBar);
142         DockControlBar(&m_eicToolBar);
143
144         // Initialize DirectShow
145         CoInitialize(0);
146         /*if(CreateCamera() && CreateFilterGraph())
147         {
148         //Camera video source is available
149                 m_DSOn = TRUE;
150         }
151         else*/
152         {
153                 m_DSOn = FALSE;
154         }
155
156         return 0;
157 }
158
159 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
160 {
161         if( !CMDIFrameWnd::PreCreateWindow(cs) )
162                 return FALSE;
163         // TODO: Modify the Window class or styles here by modifying
164         //  the CREATESTRUCT cs
165
166         return TRUE;
167 }
168
169 /////////////////////////////////////////////////////////////////////////////
170 // CMainFrame diagnostics
171
172 #ifdef _DEBUG
173 void CMainFrame::AssertValid() const
174 {
175         CMDIFrameWnd::AssertValid();
176 }
177
178 void CMainFrame::Dump(CDumpContext& dc) const
179 {
180         CMDIFrameWnd::Dump(dc);
181 }
182
183 #endif //_DEBUG
184
185 IPin* get_pin( IBaseFilter* pFilter, PIN_DIRECTION dir )
186 {
187     IEnumPins*  pEnumPins = 0;
188     IPin*       pPin = 0;
189
190     if( pFilter )
191     {
192         pFilter->EnumPins( &pEnumPins );
193         if( pEnumPins != 0 )
194         {
195             for(;;)
196             {
197                 ULONG  cFetched = 0;
198                 PIN_DIRECTION pinDir = PIN_DIRECTION(-1); 
199                 pPin = 0;
200
201                 pEnumPins->Next( 1, &pPin, &cFetched );
202                 if( cFetched == 1 && pPin != 0 )
203                 {
204                     pPin->QueryDirection( &pinDir );
205                     if( pinDir == dir ) break;
206                     pPin->Release();
207                 }
208                 else if(cFetched == 0)
209                 {
210                     return 0;
211                 }
212             }
213             pEnumPins->Release();
214         }
215     }
216
217     return pPin;
218 }
219
220 BOOL CMainFrame::CreateCamera()
221 {
222     ICreateDevEnum* pCreateDevEnum = 0;
223     IEnumMoniker*   pEnumMon = 0;
224     IMoniker*       pMon = 0;
225     ULONG           cFetched = 0;
226     
227     SafeRelease( m_SourceFilter );
228     
229     if(FAILED(CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
230                       IID_ICreateDevEnum, (void**)&pCreateDevEnum )))
231         {
232                 return FALSE;
233         }
234     
235         ASSERT(pCreateDevEnum);
236     /* Create capture device */
237         if(FAILED(pCreateDevEnum->CreateClassEnumerator( 
238                                 CLSID_VideoInputDeviceCategory, &pEnumMon, 0)) || !pEnumMon)
239         {
240                 SafeRelease(pCreateDevEnum);
241                 return FALSE;
242         }
243
244         ASSERT(pEnumMon);
245     if(SUCCEEDED( pEnumMon->Next(1, &pMon, &cFetched)) && cFetched == 1 && pMon)
246     {
247         ASSERT(pMon);
248         pMon->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_SourceFilter );
249         if(!m_SourceFilter)
250         {
251                 SafeRelease(pCreateDevEnum);
252                 SafeRelease(pEnumMon);
253                 return FALSE;
254         }
255                 FILTER_INFO info;
256                 m_SourceFilter->QueryFilterInfo(&info);
257     }
258         else
259         {
260                 SafeRelease(pCreateDevEnum);
261                 SafeRelease(pEnumMon);
262                 return FALSE;
263         }
264
265         // Create a proxy transform filter to enable scripts process images
266         if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER, 
267                                         IID_IProxyTransform, (void**)&m_ProxyTrans)))
268         {
269                 SafeRelease(pCreateDevEnum);
270                 SafeRelease(pEnumMon);
271                 SafeRelease(m_SourceFilter);
272                 return FALSE;
273         }
274
275
276     SafeRelease( pMon );
277     SafeRelease( pEnumMon );
278     SafeRelease( pCreateDevEnum );
279
280         return TRUE;
281 }
282
283
284 BOOL CMainFrame::CreateFilterGraph()
285 {
286     
287     if(FAILED(CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
288                       IID_IGraphBuilder, (void **)&m_GraphBuilder )))
289         {
290                 SafeRelease(m_GraphBuilder);
291                 return FALSE;
292         }
293
294         ASSERT(m_GraphBuilder);
295     m_GraphBuilder->QueryInterface(IID_IMediaControl,(void**)&m_MediaControl);
296     m_GraphBuilder->QueryInterface(IID_IMediaEventEx,(void**)&m_MediaEventEx);
297     m_GraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&m_VideoWindow);
298     m_GraphBuilder->QueryInterface(IID_IFilterGraph, (void**)&m_FilterGraph);
299
300         IBaseFilter* pProxyTrans = 0;
301         m_ProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pProxyTrans);
302
303 /*    if( m_MediaEventEx )
304     {
305         // Have the graph signal event via window callbacks for performance
306         m_MediaEventEx->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);
307     }*/
308
309     /* link filters */
310     if( m_FilterGraph )
311     {
312         HRESULT hr;
313
314         hr = m_FilterGraph->AddFilter( m_SourceFilter, L"Video Source" );
315
316         IPin* pSourceOut    = get_pin( m_SourceFilter, PINDIR_OUTPUT );
317
318                 IPin* pProxyTransIn             = get_pin( pProxyTrans, PINDIR_INPUT );
319                 IPin* pProxyTransOut    = get_pin( pProxyTrans, PINDIR_OUTPUT );
320     
321         if( pSourceOut && pProxyTransIn && pProxyTransOut )
322         {
323             hr = m_FilterGraph->AddFilter( pProxyTrans, L"Script processing");
324             hr = m_GraphBuilder->Connect(pSourceOut, pProxyTransIn);
325             hr = m_GraphBuilder->Render( pProxyTransOut );
326                     AM_MEDIA_TYPE amt;
327                     pSourceOut->ConnectionMediaType(&amt);
328                     pProxyTransOut->ConnectionMediaType(&amt);
329                     VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat;
330                     if(!vih || vih->bmiHeader.biBitCount != 24)
331                     {
332                 SafeRelease( pSourceOut );
333                 SafeRelease( pProxyTransIn );
334                 SafeRelease( pProxyTransOut );
335                             return FALSE;
336                     }
337         }
338
339         SafeRelease( pSourceOut );
340         SafeRelease( pProxyTransIn );
341         SafeRelease( pProxyTransOut );
342     }
343     return TRUE;
344 }
345
346
347 void CMainFrame::StartGraph(CWnd* pWnd) 
348 {
349     if( m_MediaControl )
350     {
351         m_VideoWindow->put_Owner((OAHWND)pWnd->m_hWnd);
352                 long flags;
353                 m_VideoWindow->get_WindowStyle(&flags);
354         m_VideoWindow->put_WindowStyle( flags | WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
355 //        m_VideoWindow->put_MessageDrain((OAHWND)pWnd->m_hWnd);
356 //        m_CamShiftProp->SetDrawBox(false);
357
358         SetVideoWindowSize(pWnd->m_hWnd); 
359         m_MediaControl->Run();
360         m_isDSRunning = TRUE;
361     }
362 }
363
364 void CMainFrame::SetVideoWindowSize(HWND hWnd) 
365 {
366     CRect rc = GetVideoWindowSize(hWnd);
367     if( m_VideoWindow )
368     {
369         m_VideoWindow->SetWindowPosition( rc.left, rc.top, rc.right, rc.bottom );
370     }
371 }
372
373 CRect CMainFrame::GetVideoWindowSize(HWND hWnd) 
374 {
375     CRect rc;
376     if(hWnd)
377     {
378 //        int width, height;
379 //        GetScaleFactor( width, height );
380
381         ::GetClientRect( hWnd, &rc );
382
383 //        rc.right  = rc.right * width / 100;
384 //        rc.bottom = rc.bottom * height / 100;
385     }
386
387     return rc;
388 }
389
390 /////////////////////////////////////////////////////////////////////////////
391 // CMainFrame message handlers
392
393
394 CStatusBar* CMainFrame::GetStatusBar()
395 {
396     return &m_wndStatusBar;
397 }
398
399 BOOL CMainFrame::IsDirectShowOn()
400 {
401         return m_DSOn;
402 }
403
404 void CMainFrame::SetTransformCallback(void (__cdecl *cb)(void *))
405 {
406         m_ProxyTrans->set_transform(cb, 0);
407 }
408
409 void CMainFrame::StopGraph()
410 {
411         if( m_MediaControl )
412     {
413         m_MediaControl->StopWhenReady();
414         m_VideoWindow->put_Visible(OAFALSE);
415         m_VideoWindow->put_Owner(NULL);
416         m_VideoWindow->put_MessageDrain(0);
417         m_isDSRunning = FALSE;
418     }
419 }
420
421 void CMainFrame::StartGraph(HWND hWnd)
422 {
423     if( m_MediaControl )
424     {
425         m_VideoWindow->put_Owner((OAHWND)hWnd);
426                 long flags;
427         m_MediaEventEx->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);
428         m_MediaEventEx->SetNotifyFlags(0x00);
429         m_MediaEventEx->CancelDefaultHandling(EC_COMPLETE);
430                 m_VideoWindow->get_WindowStyle(&flags);
431         m_VideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD);
432         m_VideoWindow->put_MessageDrain((OAHWND)hWnd);
433
434         SetVideoWindowSize(hWnd); 
435         m_MediaControl->Run();
436         m_isDSRunning = TRUE;
437     }
438 }
439
440 void CMainFrame::OnClose() 
441 {
442     // Wait while all interpreters stop
443 /*    if(IsIntRun())
444     {
445 //        destroy_all();
446         m_isInt
447         PostMessage(WM_CLOSE);
448         return;
449     }*/
450
451     CHawkApp* app = (CHawkApp*)AfxGetApp();
452     app->CloseEiCHandles();
453     if(m_pRunDoc)
454     {
455         if(WaitForSingleObject(m_pRunDoc->m_hScriptExec, 0) == WAIT_TIMEOUT)
456         {
457             //TerminateThread(m_pRunDoc->m_hScriptExec, 0);
458             int f = TerminateThread(m_pRunDoc->m_hScriptExec, 0);
459         }
460         if(WaitForSingleObject(m_pRunDoc->m_hThread, 0) == WAIT_TIMEOUT)
461         {
462             //TerminateThread(m_pRunDoc->m_hThread, 0);
463             int f = TerminateThread(m_pRunDoc->m_hThread, 0);
464         }
465     }    
466     cvDestroyAllWindows();
467         CMDIFrameWnd::OnClose();
468 }
469
470 BOOL CMainFrame::IsIntRun()
471 {
472     return m_isIntRun;
473 }
474
475 void CMainFrame::SetIntRun(BOOL isRun)
476 {
477     m_isIntRun = isRun;
478 }
479
480 void CMainFrame::OnVideoPp() 
481 {
482     CAUUID uuID;
483     ISpecifyPropertyPages* pspp = 0;
484     m_SourceFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pspp);
485     if(!pspp)
486     {
487         return;
488     }
489
490     pspp->GetPages(&uuID);
491     SafeRelease(pspp);
492
493     OleCreatePropertyFrame(NULL, 0, 0, L"Video Source", 1, 
494         (IUnknown**)&m_SourceFilter, uuID.cElems, uuID.pElems,
495         0, 0, NULL);
496 }
497
498 void CMainFrame::OnUpdateVideoPp(CCmdUI* pCmdUI) 
499 {
500         pCmdUI->Enable(IsDirectShowOn());
501 }
502
503 void CMainFrame::SetDocRun(CHawkDoc *pDoc)
504 {
505     m_pRunDoc = pDoc;
506 }
507
508 static int __cdecl DS_ON_SIZE(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, int* ret)
509 {
510     CMainFrame* frame = (CMainFrame*)AfxGetMainWnd();
511         if(hWnd == frame->GetDSHWND() && msg == WM_SIZE)
512         {
513                 frame->SetVideoWindowSize(hWnd);
514         }
515         *ret = 0;
516         return 0;
517 }
518
519 void CMainFrame::RunDS(void(*cb)(void*), BOOL ret)
520 {
521     CHawkApp* app = (CHawkApp*)AfxGetApp();
522     char *wndName = "DirectShow";
523     cvNamedWindow(wndName, 0);
524     m_DSWnd = (HWND)cvGetWindowHandle(wndName);
525     SetTransformCallback(cb);
526     set_postprocess_func(DS_ON_SIZE);
527     StartGraph(m_DSWnd);
528
529     if(!ret)
530     {
531         MSG message;
532         /* Organize message processing... */
533         while(IsDSRunning())
534         {
535             Sleep(10);
536             if(PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
537             {
538                 TranslateMessage(&message);
539                 DispatchMessage(&message);
540             };
541
542             if(!cvGetWindowHandle("DirectShow"))
543             {
544                 // The ds window has been destroyed...
545     /*            OAFilterState state;
546                 hres = pimc->GetState(INFINITE, &state);
547                 hres = pimc->Pause();
548                 hres = pimc->GetState(INFINITE, &state);
549                 hres = pimc->Stop();
550                 hres = pimc->GetState(INFINITE, &state);
551                 ASSERT(state == State_Stopped);*/
552                 StopGraph();
553                 break;
554             }
555         }
556     }
557 }
558
559 void CMainFrame::OnPinPp() 
560 {
561     //Find the output pit that is connected to the next filter...
562     CAUUID uuID;
563     ISpecifyPropertyPages* pspp = 0;
564     IPin* pPin = get_pin(m_SourceFilter, PINDIR_OUTPUT);
565     pPin->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pspp);
566     if(!pspp)
567     {
568         return;
569     }
570
571     pspp->GetPages(&uuID);
572     SafeRelease(pspp);
573
574     /* Disconnect the pin to enable possible changes in the output format... */
575     pPin->Disconnect();
576     IBaseFilter* pFilter;
577     m_ProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
578     IPin* pProxyPin = get_pin(pFilter, PINDIR_INPUT);
579     pProxyPin->Disconnect();
580     OleCreatePropertyFrame(NULL, 0, 0, L"Video Source", 1, 
581         (IUnknown**)&pPin, uuID.cElems, uuID.pElems,
582         0, 0, NULL);
583     m_GraphBuilder->Connect(pPin, pProxyPin);
584 }
585
586 void CMainFrame::OnUpdatePinPp(CCmdUI* pCmdUI) 
587 {
588         pCmdUI->Enable(IsDirectShowOn());
589 }
590
591 HWND CMainFrame::GetDSHWND()
592 {
593     return m_DSWnd;
594 }