Move the sources to trunk
[opencv] / filters / Tracker3dFilter / src / Tracker3dPropertyPage.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) 2002, 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 //   * Redistributions of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistributions 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*/
41
42 #include <string>
43 #include <stdio.h>
44 #include <streams.h>
45 #include <shellapi.h>
46 #include <comcat.h>
47 #include "autorelease.h"
48 #include "ITracker3dFilter.h"
49 #include "Tracker3dPropertyPage.h"
50 #include "resource.h"
51 #include "FilenamesDialog.h"
52
53 //
54 // CreateInstance
55 //
56 // Used by the DirectShow base classes to create instances
57 //
58 CUnknown *Tracker3dPropertyPage::CreateInstance(IUnknown *outer, HRESULT *phr)
59 {
60     CUnknown *punk = new Tracker3dPropertyPage(outer, phr);
61     if (punk == NULL) {
62         *phr = E_OUTOFMEMORY;
63     }
64     return punk;
65
66 }
67
68 //
69 // Constructor
70 //
71 Tracker3dPropertyPage::Tracker3dPropertyPage(IUnknown *outer, HRESULT *phr) :
72     CBasePropertyPage(NAME("Tracker3d Property Page"), outer, IDD_Tracker3dPropertyPage, IDS_TITLE),
73     m_pITracker3dFilter(NULL),
74     m_internal_change(false),
75     m_num_trackers(0)
76 {
77 }
78
79 Tracker3dPropertyPage::~Tracker3dPropertyPage()
80 {
81     SAFE_RELEASE(m_pITracker3dFilter);
82 }
83
84 STDMETHODIMP Tracker3dPropertyPage::NonDelegatingQueryInterface(REFIID riid, void **ppv)
85 {
86     if (riid == IID_ITracker3dCallback)
87         return GetInterface(static_cast<ITracker3dCallback *>(this), ppv);
88     else
89         return CBasePropertyPage::NonDelegatingQueryInterface(riid, ppv);
90 }
91
92 void Tracker3dPropertyPage::SetDirty()
93 {
94     if (!m_internal_change)
95     {
96         m_bDirty = true;
97         if (m_pPageSite)
98             m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
99     }
100 }
101
102 //
103 // OnReceiveMessage
104 //
105 // Handles the messages for our property window
106 //
107 BOOL Tracker3dPropertyPage::OnReceiveMessage(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
108 {
109     switch (msg)
110     {
111         case WM_COMMAND:
112             switch (HIWORD(w))
113             {
114                 case BN_CLICKED:
115                     switch (LOWORD(w))
116                     {
117                         case IDC_ANY_SIZE:
118                         case IDC_640x480:
119                         case IDC_320x240:
120                             SetDirty();
121                             break;
122
123                         case IDC_CALIBRATE_CAMERAS:
124                             bool continuous = (GetKeyState(VK_CONTROL) < 0);
125                             bool dialog = (GetKeyState(VK_SHIFT) < 0 || m_camera_intrinsics_filenames.size() != m_num_trackers);
126                             int m = GetDlgItemInt(m_Dlg, IDC_CHECKERBOARD_WIDTH, NULL, false);
127                             int n = GetDlgItemInt(m_Dlg, IDC_CHECKERBOARD_HEIGHT, NULL, false);
128                             if (m > 0 && n > 0)
129                             {
130                                 if (!dialog || FilenamesDialog(m_Dlg, m_num_trackers, m_camera_intrinsics_filenames)) // returns false if cancelled by user
131                                 {
132                                     std::vector<const char *> filenames(m_num_trackers);
133                                     for (int i = 0; i < m_num_trackers; i++)
134                                         filenames[i] = m_camera_intrinsics_filenames[i].c_str();
135
136                                     if (m_pITracker3dFilter->CalibrateCameras(m, n, &filenames[0], 1.0f, continuous) != NOERROR)
137                                         MessageBox(hwnd, "Error in Calibrate_Cameras", "Tracker3d", 0);
138                                 }
139                             }
140                             break;
141                     }
142                     break;
143
144                 case EN_CHANGE:
145                     switch (LOWORD(w))
146                     {
147                         case IDC_NUMBER_OF_CAMERAS:
148                             SetDirty();
149                             break;
150                     }
151                     break;
152
153                 case CBN_SELCHANGE:
154                 case CBN_EDITCHANGE:
155                     switch (LOWORD(w))
156                     {
157                         case IDC_TRACKER_DLL:
158                             SetDirty();
159                             break;
160                     }
161                     break;
162             }
163             break;
164
165         case WM_APP:
166         {
167             HWND dlg = GetParent(GetParent(m_Dlg));
168             RECT rect;
169             GetWindowRect(dlg, &rect);
170             int width = rect.right - rect.left;
171             int height = rect.bottom - rect.top;
172             RECT screen_rect;
173             GetWindowRect(GetDesktopWindow(), &screen_rect);
174             int screen_width = screen_rect.right - screen_rect.left;
175             int screen_height = screen_rect.bottom - screen_rect.top;
176             int top = (screen_height - 40) - height;
177             MoveWindow(dlg, screen_width - 10 - width, top, width, height, true);
178             HWND parent = GetParent(dlg);
179             char text[100];
180             GetWindowText(parent, text, sizeof(text));
181             if (strstr(text, "GraphEdit") != NULL)
182                 MoveWindow(GetParent(dlg), 10, top, screen_width - 30 - width, height, true);
183             return 0;
184         }
185     }
186
187     return CBasePropertyPage::OnReceiveMessage(hwnd, msg, w, l);
188 }
189
190 STDMETHODIMP Tracker3dPropertyPage::Callback(const std::vector<Cv3dTrackerTrackedObject> &objects, const unsigned char *, IUnknown *)
191 {
192     unsigned long i;
193
194     for (i = 0; i < MAX_OBJECTS; i++)
195         EnableWindow(GetDlgItem(m_Dlg, IDC_LOCATION1 + i), false);
196
197     for (i = 0; i < objects.size(); i++)
198     {
199         char text[80];
200         sprintf(text, "(%#6.1f, %#6.1f, %#6.1f)", objects[i].p.x, objects[i].p.y, objects[i].p.z);
201         SetDlgItemText(m_Dlg, IDC_LOCATION1 + objects[i].id, text);
202         EnableWindow(GetDlgItem(m_Dlg, IDC_LOCATION1 + objects[i].id), true);
203     }
204     return NOERROR;
205 }
206
207 //
208 // OnConnect
209 //
210 // Called when we connect to the filter
211 //
212 HRESULT Tracker3dPropertyPage::OnConnect(IUnknown *pUnknown)
213 {
214     SAFE_RELEASE(m_pITracker3dFilter); // shouldn't happen
215
216     HRESULT hr = pUnknown->QueryInterface(IID_ITracker3dFilter, (void **) &m_pITracker3dFilter);
217     if (FAILED(hr))
218         return hr;
219
220     hr = m_pITracker3dFilter->AddCallback(this);
221     if (FAILED(hr))
222        return hr;
223
224     return NOERROR;
225 }
226
227
228 //
229 // OnDisconnect
230 //
231 // Called when we disconnect from the filter
232 //
233 HRESULT Tracker3dPropertyPage::OnDisconnect()
234 {
235     if (m_pITracker3dFilter == NULL)
236         return E_UNEXPECTED;
237
238     m_pITracker3dFilter->RemoveCallback(this);
239     SAFE_RELEASE(m_pITracker3dFilter);
240
241     return NOERROR;
242 }
243
244 //
245 // OnActivate
246 //
247 // We are being activated
248 //
249 HRESULT Tracker3dPropertyPage::OnActivate()
250 {
251     PostMessage(m_Dlg, WM_APP, 0, 0);
252
253     m_internal_change = true;
254
255     LoadTrackers();
256
257     GUID tracker_clsid;
258     m_pITracker3dFilter->GetDefaultTracker(tracker_clsid);
259     if (tracker_clsid != GUID_NULL)
260         SelectTracker(tracker_clsid);
261
262     ITracker3dFilter::InputSize size;
263     m_pITracker3dFilter->GetPreferredInputSize(size);
264     if (size == ITracker3dFilter::SIZE_640x480)
265         CheckRadioButton(m_Dlg, IDC_ANY_SIZE, IDC_640x480, IDC_640x480);
266     else if (size == ITracker3dFilter::SIZE_320x240)
267         CheckRadioButton(m_Dlg, IDC_ANY_SIZE, IDC_640x480, IDC_320x240);
268     else
269         CheckRadioButton(m_Dlg, IDC_ANY_SIZE, IDC_640x480, IDC_ANY_SIZE);
270
271     m_pITracker3dFilter->GetNumberOfCameras(m_num_trackers);
272     SetDlgItemInt(m_Dlg, IDC_NUMBER_OF_CAMERAS, m_num_trackers, false);
273
274     SetDlgItemInt(m_Dlg, IDC_CHECKERBOARD_WIDTH, 6, false);
275     SetDlgItemInt(m_Dlg, IDC_CHECKERBOARD_HEIGHT, 4, false);
276
277     bool any_connected, all_connected;
278     m_pITracker3dFilter->IsConnected(any_connected, all_connected);
279     if (any_connected)
280     {
281         EnableWindow(GetDlgItem(m_Dlg, IDC_ANY_SIZE), false);
282         EnableWindow(GetDlgItem(m_Dlg, IDC_640x480), false);
283         EnableWindow(GetDlgItem(m_Dlg, IDC_320x240), false);
284         EnableWindow(GetDlgItem(m_Dlg, IDC_NUMBER_OF_CAMERAS), false);
285         EnableWindow(GetDlgItem(m_Dlg, IDC_TRACKER_DLL), false);
286     }
287
288     m_internal_change = false;
289
290     return NOERROR;
291 }
292
293 //
294 // OnDeactivate
295 //
296 // We are being deactivated
297 //
298 HRESULT Tracker3dPropertyPage::OnDeactivate(void)
299 {
300     return NOERROR;
301 }
302
303 //
304 // OnApplyChanges
305 //
306 // Apply any changes so far made
307 //
308 HRESULT Tracker3dPropertyPage::OnApplyChanges()
309 {
310     if (IsDlgButtonChecked(m_Dlg, IDC_ANY_SIZE))
311         m_pITracker3dFilter->SetPreferredInputSize(ITracker3dFilter::SIZE_Any);
312     else if (IsDlgButtonChecked(m_Dlg, IDC_640x480))
313         m_pITracker3dFilter->SetPreferredInputSize(ITracker3dFilter::SIZE_640x480);
314     else if (IsDlgButtonChecked(m_Dlg, IDC_320x240))
315         m_pITracker3dFilter->SetPreferredInputSize(ITracker3dFilter::SIZE_320x240);
316
317     int new_num_trackers = GetDlgItemInt(m_Dlg, IDC_NUMBER_OF_CAMERAS, NULL, false);
318     GUID new_tracker, prev_tracker;
319     GetSelectedTracker(new_tracker);
320     m_pITracker3dFilter->GetDefaultTracker(prev_tracker);
321
322     if (new_num_trackers != m_num_trackers || prev_tracker != new_tracker)
323     {
324         m_pITracker3dFilter->SetDefaultTracker(new_tracker);
325         m_pITracker3dFilter->SetTrackers(new_num_trackers, NULL); // force it to reallocate the trackers
326         m_num_trackers = new_num_trackers;
327     }
328
329     return NOERROR;
330 }
331
332
333
334 class AutoCloseKey
335 {
336     HKEY *m_pkey;
337
338 public:
339     AutoCloseKey(HKEY *pkey) : m_pkey(pkey) { };
340     ~AutoCloseKey()
341     {
342         if (*m_pkey != 0)
343         {
344             RegCloseKey(*m_pkey);
345             *m_pkey = 0;
346         }
347     };
348 };
349
350 #define AUTO_CLOSE_KEY(f) AutoCloseKey AutoCloseKey##f(&f)
351
352 static const char key_name[] = "Software\\Intel\\VAI\\3d Tracker\\";
353
354
355 void Tracker3dPropertyPage::LoadTrackers()
356 {
357     HRESULT hr;
358
359     ICatInformation *catman;
360     hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_ALL, IID_ICatInformation, (void **)&catman);
361     if (FAILED(hr))
362         return;
363
364     IEnumCLSID *e;
365     hr = catman->EnumClassesOfCategories(1, const_cast<GUID *>(&CATID_Trackers), -1, NULL, &e);
366     if (FAILED(hr))
367     {
368         catman->Release();
369         return;
370     }
371
372     CLSID clsid;
373     while (e->Next(1, &clsid, NULL) == S_OK)
374     {
375         char tracker_name[80];
376
377         LONG r;
378
379         wchar_t textw[50];
380         StringFromGUID2(clsid, textw, 50);
381
382         char key_name[80];
383         wsprintf(key_name, "CLSID\\%ls", textw);
384     
385         HKEY key = 0; AUTO_CLOSE_KEY(key);
386         r = RegOpenKeyEx(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ, &key);
387         if (r == ERROR_SUCCESS)
388         {
389             DWORD size = sizeof(tracker_name);
390             r = RegQueryValueEx(key, "", 0, NULL, (BYTE *)tracker_name, &size);
391         }
392
393         if (r != ERROR_SUCCESS)
394         {
395             // Since we don't have a name, we just have to add the CLSID text
396             wcstombs(tracker_name, textw, 50);
397         }
398
399         GUID *guid = new GUID;
400         *guid = clsid;
401         int item = SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_ADDSTRING, 0, (LPARAM)tracker_name);
402         SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_SETITEMDATA, item, (LPARAM)guid);
403     }
404
405     e->Release();
406     catman->Release();
407 }
408
409 void Tracker3dPropertyPage::SelectTracker(const GUID &tracker_clsid)
410 {
411     // See if it's already there
412     int item;
413     int n = SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_GETCOUNT, 0, 0);
414     for (item = 0; item < n; item++)
415         if (tracker_clsid == *(GUID *)SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_GETITEMDATA, item, 0))
416             break;
417
418     // If it wasn't found, add it.
419     // Since we don't have a name, we just have to add the CLSID text
420     if (item == n)
421     {
422         char text[50];
423         wchar_t textw[50];
424         StringFromGUID2(tracker_clsid, textw, 50);
425         wcstombs(text, textw, 50);
426         item = SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_ADDSTRING, 0, (LPARAM)text);
427         GUID *guid = new GUID;
428         *guid = tracker_clsid;
429         SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_SETITEMDATA, item, (LPARAM)guid);
430     }
431     
432     SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_SETCURSEL, item, 0);
433 }
434
435 void Tracker3dPropertyPage::GetSelectedTracker(GUID &tracker_clsid)
436 {
437     int item = SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_GETCURSEL, 0, 0);
438     tracker_clsid = *(GUID *)SendDlgItemMessage(m_Dlg, IDC_TRACKER_DLL, CB_GETITEMDATA, item, 0);
439 }