]> git.sesse.net Git - casparcg/blob - core/producer/flash/FlashAxContainer.cpp
2.0.0.2: graph - Changed interface.
[casparcg] / core / producer / flash / FlashAxContainer.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20  \r
21 #include "..\..\stdafx.h"\r
22 \r
23 #include "FlashAxContainer.h"\r
24 #include "TimerHelper.h"\r
25 \r
26 #include <common/log/log.h>\r
27 \r
28 #if defined(_MSC_VER)\r
29 #pragma warning (push, 2) // TODO\r
30 #endif\r
31 \r
32 using namespace ATL;\r
33 \r
34 namespace caspar { namespace flash {\r
35 \r
36 CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}"));\r
37 \r
38 _ATL_FUNC_INFO fnInfoFlashCallEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };\r
39 _ATL_FUNC_INFO fnInfoReadyStateChangeEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };\r
40 \r
41 FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), pTimerHelper(0), bInvalidRect_(false), bReadyToRender_(false), bHasNewTiming_(false), m_lpDD4(0), timerCount_(0)\r
42 {\r
43 }\r
44 FlashAxContainer::~FlashAxContainer()\r
45 {       \r
46         if(m_lpDD4)\r
47         {\r
48                 m_lpDD4->Release();\r
49                 m_lpDD4 = nullptr;\r
50         }\r
51 \r
52         if(pTimerHelper != 0)\r
53                 delete pTimerHelper;\r
54 }\r
55 \r
56 \r
57 ///////////////////\r
58 // IObjectWithSite\r
59 ///////////////////\r
60 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetSite(IUnknown* pUnkSite)\r
61 {\r
62         ATLTRACE(_T("IObjectWithSite::SetSite\n"));\r
63         HRESULT hr = IObjectWithSiteImpl<FlashAxContainer>::SetSite(pUnkSite);\r
64 \r
65         if (SUCCEEDED(hr) && m_spUnkSite)\r
66         {\r
67                 // Look for "outer" IServiceProvider\r
68                 hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices);\r
69                 ATLASSERT( !hr && _T("No ServiceProvider!") );\r
70         }\r
71 \r
72         if (pUnkSite == NULL)\r
73                 m_spServices.Release();\r
74 \r
75         return hr;\r
76 }\r
77 \r
78 ///////////////////\r
79 // IOleClientSite\r
80 ///////////////////\r
81 HRESULT STDMETHODCALLTYPE FlashAxContainer::SaveObject()\r
82 {\r
83         ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject"));\r
84 }\r
85 \r
86 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)\r
87 {\r
88 /*      if(*ppmk != NULL) {\r
89                 if(m_spMyMoniker == NULL) {\r
90                         ATL::CComObject<MyMoniker>* pMoniker = NULL;\r
91                         HRESULT hr = ATL::CComObject<MyMoniker>::CreateInstance(&pMoniker);\r
92                         if(SUCCEEDED(hr))\r
93                                 m_spMyMoniker = pMoniker;\r
94                 }\r
95 \r
96                 if(m_spMyMoniker != NULL) {\r
97                         *ppmk = m_spMyMoniker;\r
98                         (*ppmk)->AddRef();\r
99                         return S_OK;\r
100                 }\r
101         }\r
102 */      if(ppmk != NULL)\r
103                 *ppmk = NULL;\r
104         return E_FAIL;\r
105 }\r
106 \r
107 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetContainer(IOleContainer** ppContainer)\r
108 {\r
109         ATLTRACE(_T("IOleClientSite::GetContainer\n"));\r
110         (*ppContainer) = NULL;\r
111         return E_NOINTERFACE;\r
112 }\r
113 \r
114 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowObject()\r
115 {\r
116         ATLTRACE(_T("IOleClientSite::ShowObject\n"));\r
117         return S_OK;\r
118 }\r
119 \r
120 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnShowWindow(BOOL fShow)\r
121 {\r
122         ATLTRACE(_T("IOleClientSite::OnShowWindow"));\r
123         return S_OK;\r
124 }\r
125 \r
126 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestNewObjectLayout()\r
127 {\r
128         ATLTRACE(_T("IOleClientSite::RequestNewObjectLayout"));\r
129         return S_OK;\r
130 }\r
131 \r
132 ///////////////////\r
133 // IOleInPlaceSite\r
134 ///////////////////\r
135 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindow(HWND* pHwnd)\r
136 {\r
137         ATLTRACE(_T("IOleInPlaceSite::GetWindow\n"));\r
138         (*pHwnd) = NULL;//GetApplication()->GetMainWindow()->getHwnd();\r
139         return E_FAIL;\r
140 }\r
141 HRESULT STDMETHODCALLTYPE FlashAxContainer::ContextSensitiveHelp(BOOL fEnterMode)\r
142 {\r
143         ATLTRACE(_T("IOleInPlaceSite::ContextSensitiveHelp"));\r
144         return S_OK;\r
145 }\r
146 \r
147 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanInPlaceActivate()\r
148 {\r
149         ATLTRACE(_T("IOleInPlaceSite::CanInPlaceActivate\n"));\r
150         return S_OK;\r
151 }\r
152 \r
153 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivate()\r
154 {\r
155         ATLTRACE(_T("IOleInPlaceSite::OnInPlaceActivate"));\r
156         return S_OK;\r
157 }\r
158 \r
159 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIActivate()\r
160 {\r
161         ATLTRACE(_T("IOleInPlaceSite::OnUIActivate\n"));\r
162         bUIActive_ = TRUE;\r
163         return S_OK;\r
164 }\r
165 \r
166 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)\r
167 {\r
168         ATLTRACE(_T("IOleInPlaceSite::GetWindowContext\n"));\r
169         if (ppFrame != NULL)\r
170                 *ppFrame = NULL;\r
171         if (ppDoc != NULL)\r
172                 *ppDoc = NULL;\r
173 \r
174         if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL)\r
175                 return E_POINTER;\r
176 \r
177         pFrameInfo->fMDIApp = FALSE;\r
178         pFrameInfo->haccel = NULL;\r
179         pFrameInfo->cAccelEntries = 0;\r
180         pFrameInfo->hwndFrame = NULL;\r
181 \r
182         lprcPosRect->top = m_rcPos.top;\r
183         lprcPosRect->left = m_rcPos.left;\r
184         lprcPosRect->right = m_rcPos.right;\r
185         lprcPosRect->bottom = m_rcPos.bottom;\r
186 \r
187         lprcClipRect->top = m_rcPos.top;\r
188         lprcClipRect->left = m_rcPos.left;\r
189         lprcClipRect->right = m_rcPos.right;\r
190         lprcClipRect->bottom = m_rcPos.bottom;\r
191 \r
192         return S_OK;\r
193 }\r
194 \r
195 HRESULT STDMETHODCALLTYPE FlashAxContainer::Scroll(SIZE scrollExtant)\r
196 {\r
197         ATLTRACE(_T("IOleInPlaceSite::Scroll"));\r
198         return S_OK;\r
199 }\r
200 \r
201 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIDeactivate(BOOL fUndoable)\r
202 {\r
203         ATLTRACE(_T("IOleInPlaceSite::OnUIDeactivate\n"));\r
204         bUIActive_ = FALSE;\r
205         return S_OK;\r
206 }\r
207 \r
208 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivate()\r
209 {\r
210         ATLTRACE(_T("IOleInPlaceSite::OnInPlaceDeactivate\n"));\r
211         bInPlaceActive_ = FALSE;\r
212         m_spInPlaceObjectWindowless.Release();\r
213         return S_OK;\r
214 }\r
215 \r
216 HRESULT STDMETHODCALLTYPE FlashAxContainer::DiscardUndoState()\r
217 {\r
218         ATLTRACE(_T("IOleInPlaceSite::DiscardUndoState"));\r
219         return S_OK;\r
220 }\r
221 \r
222 HRESULT STDMETHODCALLTYPE FlashAxContainer::DeactivateAndUndo()\r
223 {\r
224         ATLTRACE(_T("IOleInPlaceSite::DeactivateAndUndo"));\r
225         return S_OK;\r
226 }\r
227 \r
228 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnPosRectChange(LPCRECT lprcPosRect)\r
229 {\r
230         ATLTRACE(_T("IOleInPlaceSite::OnPosRectChange"));\r
231         return S_OK;\r
232 }\r
233 \r
234 \r
235 /////////////////////\r
236 // IOleInPlaceSiteEx\r
237 /////////////////////\r
238 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)\r
239 {\r
240         // should only be called once the first time control is inplace-activated\r
241         ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceActivateEx\n"));\r
242         ATLASSERT(bInPlaceActive_ == FALSE);\r
243         ATLASSERT(m_spInPlaceObjectWindowless == NULL);\r
244 \r
245         bInPlaceActive_ = TRUE;\r
246         OleLockRunning(m_spOleObject, TRUE, FALSE);\r
247         HRESULT hr = E_FAIL;\r
248         if (dwFlags & ACTIVATE_WINDOWLESS)\r
249         {\r
250                 hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless);\r
251 \r
252                 if (m_spInPlaceObjectWindowless != NULL)\r
253                         m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
254         }\r
255 \r
256         return (m_spInPlaceObjectWindowless != NULL) ? S_OK : E_FAIL;\r
257 }\r
258 \r
259 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivateEx(BOOL fNoRedraw)\r
260 {\r
261         ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceDeactivateEx\n"));\r
262         bInPlaceActive_ = FALSE;\r
263         m_spInPlaceObjectWindowless.Release();\r
264         return S_OK;\r
265 }\r
266 \r
267 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestUIActivate()\r
268 {\r
269         ATLTRACE(_T("IOleInPlaceSiteEx::RequestUIActivate\n"));\r
270         return S_OK;\r
271 }\r
272 \r
273 \r
274 /////////////////////////////\r
275 // IOleInPlaceSiteWindowless\r
276 /////////////////////////////\r
277 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanWindowlessActivate()\r
278 {\r
279         ATLTRACE(_T("IOleInPlaceSiteWindowless::CanWindowlessActivate\n"));\r
280         return S_OK;\r
281 //      return S_FALSE;\r
282 }\r
283 \r
284 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetCapture()\r
285 {\r
286         ATLTRACE(_T("IOleInPlaceSiteWindowless::GetCapture\n"));\r
287         return bCapture_ ? S_OK : S_FALSE;\r
288 }\r
289 \r
290 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetCapture(BOOL fCapture)\r
291 {\r
292         ATLTRACE(_T("IOleInPlaceSiteWindowless::SetCapture\n"));\r
293         bCapture_ = fCapture;\r
294         return S_OK;\r
295 }\r
296 \r
297 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetFocus()\r
298 {\r
299         ATLTRACE(_T("IOleInPlaceSiteWindowless::GetFocus\n"));\r
300         return bHaveFocus_ ? S_OK : S_FALSE;\r
301 }\r
302 \r
303 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetFocus(BOOL fGotFocus)\r
304 {\r
305         ATLTRACE(_T("IOleInPlaceSiteWindowless::SetFocus\n"));\r
306         bHaveFocus_ = fGotFocus;\r
307         return S_OK;\r
308 }\r
309 \r
310 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)\r
311 {\r
312         ATLTRACE(_T("IOleInPlaceSiteWindowless::GetDC"));\r
313         return S_OK;\r
314 }\r
315 \r
316 HRESULT STDMETHODCALLTYPE FlashAxContainer::ReleaseDC(HDC hDC)\r
317 {\r
318         ATLTRACE(_T("IOleInPlaceSiteWindowless::ReleaseDC"));\r
319         return S_OK;\r
320 }\r
321 \r
322 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRect(LPCRECT pRect, BOOL fErase)\r
323 {\r
324 //      ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRect\n"));\r
325         \r
326         bInvalidRect_ = true;\r
327 \r
328 /*      //Keep a list of dirty rectangles in order to be able to redraw only them\r
329         if(pRect != NULL) {\r
330                 bDirtyRects_.push_back(DirtyRect(*pRect, fErase != 0));\r
331         }\r
332         else {\r
333                 bDirtyRects_.push_back(DirtyRect(true));\r
334         }\r
335 */      return S_OK;\r
336 }\r
337 \r
338 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRgn(HRGN hRGN, BOOL fErase)\r
339 {\r
340         ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRng\n"));\r
341         return S_OK;\r
342 }\r
343 \r
344 HRESULT STDMETHODCALLTYPE FlashAxContainer::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)\r
345 {\r
346         ATLTRACE(_T("IOleInPlaceSiteWindowless::ScrollRect"));\r
347         return S_OK;\r
348 }\r
349 \r
350 HRESULT STDMETHODCALLTYPE FlashAxContainer::AdjustRect(LPRECT prc)\r
351 {\r
352         ATLTRACE(_T("IOleInPlaceSiteWindowless::AdjustRect"));\r
353         return S_OK;\r
354 }\r
355 \r
356 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)\r
357 {\r
358         ATLTRACE(_T("IOleInPlaceSiteWindowless::OnDefWindowMessage"));\r
359         return S_OK;\r
360 }\r
361 \r
362 ///////////////////\r
363 // IOleControlSite\r
364 ///////////////////\r
365 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnControlInfoChanged()\r
366 {\r
367         ATLTRACE(_T("IOleControlSite::OnControlInfoChanged"));\r
368         return S_OK;\r
369 }\r
370 \r
371 HRESULT STDMETHODCALLTYPE FlashAxContainer::LockInPlaceActive(BOOL fLock)\r
372 {\r
373         ATLTRACE(_T("IOleControlSite::LockInPlaceActive"));\r
374         return S_OK;\r
375 }\r
376 \r
377 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetExtendedControl(IDispatch** ppDisp)\r
378 {\r
379         ATLTRACE(_T("IOleControlSite::GetExtendedControl"));\r
380 \r
381         if (ppDisp == NULL)\r
382                 return E_POINTER;\r
383         return m_spOleObject.QueryInterface(ppDisp);\r
384 }\r
385 \r
386 HRESULT STDMETHODCALLTYPE FlashAxContainer::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)\r
387 {\r
388         ATLTRACE(_T("IOleControlSite::TransformCoords"));\r
389         return S_OK;\r
390 }\r
391 \r
392 HRESULT STDMETHODCALLTYPE FlashAxContainer::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)\r
393 {\r
394         ATLTRACE(_T("IOleControlSite::TranslateAccelerator"));\r
395         return S_FALSE;\r
396 }\r
397 \r
398 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnFocus(BOOL fGotFocus)\r
399 {\r
400         bHaveFocus_ = fGotFocus;\r
401         return S_OK;\r
402 }\r
403 \r
404 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()\r
405 {\r
406         ATLTRACE(_T("IOleControlSite::ShowPropertyFrame"));\r
407         return S_OK;\r
408 }\r
409 \r
410 \r
411 ///////////////////\r
412 // IAdviseSink\r
413 ///////////////////\r
414 void STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)\r
415 {\r
416         ATLTRACE(_T("IAdviseSink::OnDataChange\n"));\r
417 }\r
418 \r
419 void STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)\r
420 {\r
421         ATLTRACE(_T("IAdviseSink::OnViewChange\n"));\r
422 }\r
423 \r
424 void STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk)\r
425 {\r
426         ATLTRACE(_T("IAdviseSink::OnRename\n"));\r
427 }\r
428 \r
429 void STDMETHODCALLTYPE FlashAxContainer::OnSave()\r
430 {\r
431         ATLTRACE(_T("IAdviseSink::OnSave\n"));\r
432 }\r
433 \r
434 void STDMETHODCALLTYPE FlashAxContainer::OnClose()\r
435 {\r
436         ATLTRACE(_T("IAdviseSink::OnClose\n"));\r
437 }\r
438 \r
439 \r
440 //DirectDraw GUIDS\r
441 \r
442 DEFINE_GUID2(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35);\r
443 DEFINE_GUID2(CLSID_DirectDraw7,0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5);\r
444 \r
445 DEFINE_GUID2(IID_IDirectDraw,0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);\r
446 DEFINE_GUID2(IID_IDirectDraw3,0x618f8ad4,0x8b7a,0x11d0,0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d);\r
447 DEFINE_GUID2(IID_IDirectDraw4,0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5);\r
448 DEFINE_GUID2(IID_IDirectDraw7,0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b);\r
449 \r
450 ///////////////////\r
451 // IServiceProvider\r
452 ///////////////////\r
453 HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID riid, void** ppvObj) \r
454 {\r
455 //      ATLTRACE(_T("IServiceProvider::QueryService\n"));\r
456         //the flashcontrol asks for an interface {618F8AD4-8B7A-11D0-8FCC-00C04FD9189D}, this is IID for a DirectDraw3 object\r
457 \r
458         ATLASSERT(ppvObj != NULL);\r
459         if (ppvObj == NULL)\r
460                 return E_POINTER;\r
461         *ppvObj = NULL;\r
462         \r
463         HRESULT hr;\r
464         // Author: Makarov Igor\r
465         // Transparent Flash Control in Plain C++ \r
466         // http://www.codeproject.com/KB/COM/flashcontrol.aspx \r
467         if (IsEqualGUID(rsid, IID_IDirectDraw3))\r
468         {\r
469                 if (!m_lpDD4)\r
470                 {\r
471                         m_lpDD4 = new IDirectDraw4Ptr;\r
472                         hr = m_lpDD4->CreateInstance(CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER); \r
473                         if (FAILED(hr))\r
474                         {\r
475                                 delete m_lpDD4;\r
476                                 m_lpDD4 = NULL;\r
477                                 CASPAR_LOG(info) << print_() << " DirectDraw not installed. Running without DirectDraw.";\r
478                                 return E_NOINTERFACE;\r
479                         }\r
480                 }\r
481                 if (m_lpDD4 && m_lpDD4->GetInterfacePtr())\r
482                 {\r
483                         *ppvObj = m_lpDD4->GetInterfacePtr();\r
484                         m_lpDD4->AddRef();\r
485                         return S_OK;\r
486                 }\r
487         }\r
488 \r
489         //TODO: The fullscreen-consumer requires that ths does NOT return an ITimerService\r
490         hr = QueryInterface(riid, ppvObj);//E_NOINTERFACE;\r
491 \r
492         return hr;\r
493 }\r
494 \r
495 \r
496 ///////////////////\r
497 // ITimerService\r
498 ///////////////////\r
499 HRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer *pReferenceTimer, ITimer **ppNewTimer)\r
500 {\r
501         ATLTRACE(_T("ITimerService::CreateTimer\n"));\r
502         if(pTimerHelper != 0)\r
503         {\r
504                 delete pTimerHelper;\r
505                 pTimerHelper = 0;\r
506         }\r
507         pTimerHelper = new TimerHelper();\r
508         return QueryInterface(__uuidof(ITimer), (void**) ppNewTimer);\r
509 }\r
510 \r
511 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer **ppTimer)\r
512 {\r
513         ATLTRACE(_T("ITimerService::GetNamedTimer"));\r
514         if(ppTimer == NULL)\r
515                 return E_POINTER;\r
516         else\r
517                 *ppTimer = NULL;\r
518 \r
519         return E_FAIL;\r
520 }\r
521 \r
522 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer *pReferenceTimer)\r
523 {\r
524         ATLTRACE(_T("ITimerService::SetNamedTimerReference"));\r
525         return S_OK;\r
526 }\r
527 \r
528 ///////////\r
529 // ITimer\r
530 ///////////\r
531 HRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie)\r
532 {\r
533         ATLTRACE(_T("Timer::Advise\n"));\r
534 \r
535         if(pdwCookie == 0)\r
536                 return E_POINTER;\r
537 \r
538         if(pTimerHelper != 0)\r
539         {\r
540                 pTimerHelper->Setup(vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);\r
541                 *pdwCookie = pTimerHelper->ID;\r
542                 bHasNewTiming_ = true;\r
543 \r
544                 return S_OK;\r
545         }\r
546         else\r
547                 return E_OUTOFMEMORY;\r
548 }\r
549 \r
550 HRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)\r
551 {\r
552         ATLTRACE(_T("Timer::Unadvice\n"));\r
553         if(pTimerHelper != 0)\r
554         {\r
555                 pTimerHelper->pTimerSink = 0;\r
556                 return S_OK;\r
557         }\r
558         else\r
559                 return E_FAIL;\r
560 }\r
561 \r
562 HRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)\r
563 {\r
564         ATLTRACE(_T("Timer::Freeze\n"));\r
565         return S_OK;\r
566 }\r
567 \r
568 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT *pvtime)\r
569 {\r
570         ATLTRACE(_T("Timer::GetTime\n"));\r
571         if(pvtime == 0)\r
572                 return E_POINTER;\r
573 \r
574 //      return E_NOTIMPL;\r
575         pvtime->lVal = 0;\r
576         return S_OK;\r
577 }\r
578 \r
579 double FlashAxContainer::GetFPS() {\r
580         if(pTimerHelper != 0 && pTimerHelper->interval > 0)\r
581                 return (1000.0 / static_cast<double>(pTimerHelper->interval));\r
582         \r
583         return 0.0;\r
584 }\r
585 \r
586 bool FlashAxContainer::IsReadyToRender() const {\r
587         return bReadyToRender_;\r
588 }\r
589 \r
590 void FlashAxContainer::EnterFullscreen()\r
591 {\r
592         if(m_spInPlaceObjectWindowless != 0)\r
593         {\r
594                 HRESULT result;\r
595                 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1), &result);\r
596                 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(1, 1), &result);\r
597         }\r
598 }\r
599 \r
600 void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)\r
601 {\r
602         std::wstring str(request);\r
603         if(str.find(TEXT("DisplayedTemplate")) != std::wstring::npos)\r
604         {\r
605                 ATLTRACE(_T("ShockwaveFlash::DisplayedTemplate\n"));\r
606                 bReadyToRender_ = true;\r
607         }\r
608         else if(str.find(TEXT("OnCommand")) != std::wstring::npos) {\r
609                 //this is how templatehost 1.8 reports that a command has been received\r
610                 CASPAR_LOG(info)  << print_()  << L" Command: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
611                 bCallSuccessful_ = true;\r
612         }\r
613         else if(str.find(TEXT("Activity")) != std::wstring::npos)\r
614         {\r
615                 CASPAR_LOG(info) << print_() << L" Activity: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
616 \r
617                 //this is how templatehost 1.7 reports that a command has been received\r
618                 if(str.find(TEXT("Command recieved")) != std::wstring::npos)\r
619                         bCallSuccessful_ = true;\r
620 \r
621                 /*if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
622                         std::wstring::size_type pos = str.find(TEXT('@'));\r
623                         if(pos != std::wstring::npos)\r
624                                 pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
625                 }*/\r
626         }\r
627         else if(str.find(TEXT("OnNotify")) != std::wstring::npos)\r
628         {\r
629                 CASPAR_LOG(info) << print_() << L" Notification: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
630 \r
631                 //if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\r
632                 //      std::wstring::size_type pos = str.find(TEXT('@'));\r
633                 //      if(pos != std::wstring::npos)\r
634                 //              pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\r
635                 //}\r
636         }\r
637         else if(str.find(TEXT("IsEmpty")) != std::wstring::npos)\r
638         {\r
639                 CASPAR_LOG(info) << print_() << L" Empty.";\r
640                 ATLTRACE(_T("ShockwaveFlash::IsEmpty\n"));\r
641                 bIsEmpty_ = true;\r
642         }\r
643         else if(str.find(TEXT("OnError")) != std::wstring::npos)\r
644         {\r
645                 CASPAR_LOG(error) << print_() << L" Error: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";\r
646         }\r
647 \r
648         CComPtr<IShockwaveFlash> spFlash;\r
649         HRESULT hr = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);\r
650         if(hr == S_OK && spFlash)\r
651         {\r
652                 hr = spFlash->SetReturnValue(TEXT("<null/>"));\r
653         }\r
654 }\r
655 \r
656 void STDMETHODCALLTYPE FlashAxContainer::OnReadyStateChange(long newState)\r
657 {\r
658         if(newState == 4)\r
659         {\r
660                 bReadyToRender_ = true;\r
661         }\r
662         else\r
663                 bReadyToRender_ = false;\r
664 }\r
665 \r
666 void FlashAxContainer::DestroyAxControl()\r
667 {\r
668         GetControllingUnknown()->AddRef();\r
669 \r
670         if ((!m_spViewObject) == false)\r
671                 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);\r
672 \r
673         if ((!m_spOleObject) == false)\r
674         {\r
675                 DispEventUnadvise(m_spOleObject, &DIID__IShockwaveFlashEvents);\r
676                 m_spOleObject->Unadvise(m_dwOleObject);\r
677                 m_spOleObject->Close(OLECLOSE_NOSAVE);\r
678                 m_spOleObject->SetClientSite(NULL);\r
679         }\r
680 \r
681         if ((!m_spUnknown) == false)\r
682         {\r
683                 CComPtr<IObjectWithSite> spSite;\r
684                 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\r
685                 if (spSite != NULL)\r
686                         spSite->SetSite(NULL);\r
687         }\r
688 \r
689         if ((!m_spViewObject) == false)\r
690                 m_spViewObject.Release();\r
691 \r
692         if ((!m_spInPlaceObjectWindowless) == false)\r
693                 m_spInPlaceObjectWindowless.Release();\r
694 \r
695         if ((!m_spOleObject) == false)\r
696                 m_spOleObject.Release();\r
697 \r
698         if ((!m_spUnknown) == false)\r
699                 m_spUnknown.Release();\r
700 }\r
701 \r
702 bool FlashAxContainer::CheckForFlashSupport()\r
703 {\r
704         CLSID clsid;\r
705         return SUCCEEDED(CLSIDFromString((LPOLESTR)flashGUID_, &clsid));\r
706 }\r
707 \r
708 HRESULT FlashAxContainer::CreateAxControl()\r
709 {\r
710         CLSID clsid;\r
711         HRESULT hr = CLSIDFromString((LPOLESTR)flashGUID_, &clsid); \r
712         if(SUCCEEDED(hr))\r
713                 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), (void**)&m_spUnknown);\r
714 \r
715 //Start ActivateAx\r
716         if(SUCCEEDED(hr))\r
717         {\r
718                 m_spUnknown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);\r
719                 if(m_spOleObject)\r
720                 {\r
721                         m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);\r
722                         if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)\r
723                         {\r
724                                 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
725                                 m_spOleObject->SetClientSite(spClientSite);\r
726                         }\r
727 \r
728                         //Initialize control\r
729                         CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);\r
730                         if (spPSI)\r
731                                 hr = spPSI->InitNew();\r
732 \r
733                         if (FAILED(hr)) // If the initialization of the control failed...\r
734                         {\r
735                                 // Clean up and return\r
736                                 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)\r
737                                         m_spOleObject->SetClientSite(NULL);\r
738 \r
739                                 m_dwMiscStatus = 0;\r
740                                 m_spOleObject.Release();\r
741                                 m_spUnknown.Release();\r
742 \r
743                                 return hr;\r
744                         }\r
745                         //end Initialize object\r
746 \r
747                         if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))\r
748                         {\r
749                                 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
750                                 m_spOleObject->SetClientSite(spClientSite);\r
751                         }\r
752 \r
753                         CComPtr<IShockwaveFlash> spFlash;\r
754                         HRESULT hResultQuality;\r
755                         HRESULT hr2 = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);\r
756                         if(hr2 == S_OK && spFlash)\r
757                         {\r
758                                 if(FAILED(spFlash->put_WMode(TEXT("Transparent"))))\r
759                                         CASPAR_LOG(warning) << print_() << L" Failed to set flash container to transparent mode.";\r
760                                 //spFlash->put_WMode(TEXT("GPU"));\r
761                                 hResultQuality = spFlash->put_Quality2(TEXT("Best"));\r
762                         }\r
763                         if(SUCCEEDED(DispEventAdvise(spFlash, &DIID__IShockwaveFlashEvents)))\r
764                         {\r
765                         }\r
766 \r
767                         HRESULT hrView = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);\r
768 \r
769                         CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());\r
770                         m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);\r
771                         if (m_spViewObject)\r
772                                 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);\r
773 \r
774                         if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0)\r
775                         {\r
776                                 //Initialize window to some dummy size\r
777                                 m_rcPos.top = 0;\r
778                                 m_rcPos.left = 0;\r
779                                 m_rcPos.right = 720;\r
780                                 m_rcPos.bottom = 576;\r
781 \r
782                                 m_pxSize.cx = m_rcPos.right - m_rcPos.left;\r
783                                 m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\r
784                                 AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\r
785                                 m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\r
786                                 m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\r
787                                 AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\r
788                                 m_rcPos.right = m_rcPos.left + m_pxSize.cx;\r
789                                 m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\r
790 \r
791                                 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\r
792                                 hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);\r
793                         }\r
794                 }\r
795                 CComPtr<IObjectWithSite> spSite;\r
796                 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\r
797                 if (spSite != NULL)\r
798                         spSite->SetSite(GetControllingUnknown());\r
799         }\r
800 //End ActivateAx\r
801 \r
802 //      hr = E_FAIL;\r
803         if (FAILED(hr) || m_spUnknown == NULL)\r
804         {\r
805                 return E_FAIL;\r
806                 // We don't have a control or something failed so release\r
807 //              ReleaseAll();\r
808         }\r
809 \r
810         return S_OK;\r
811 }\r
812 \r
813 void FlashAxContainer::SetFormat(const core::video_format_desc& fmtDesc) {\r
814         if(m_spInPlaceObjectWindowless != 0)\r
815         {\r
816                 m_rcPos.top = 0;\r
817                 m_rcPos.left = 0;\r
818                 m_rcPos.right = fmtDesc.width;\r
819                 m_rcPos.bottom = fmtDesc.height;\r
820 \r
821                 m_pxSize.cx = m_rcPos.right - m_rcPos.left;\r
822                 m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\r
823                 AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\r
824                 m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\r
825                 m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\r
826                 AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\r
827                 m_rcPos.right = m_rcPos.left + m_pxSize.cx;\r
828                 m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\r
829 \r
830                 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
831                 bInvalidRect_ = true;\r
832         }\r
833 }\r
834 \r
835 HRESULT FlashAxContainer::QueryControl(REFIID iid, void** ppUnk)\r
836 {\r
837         ATLASSERT(ppUnk != NULL);\r
838         if (ppUnk == NULL)\r
839                 return E_POINTER;\r
840         HRESULT hr;\r
841         hr = m_spOleObject->QueryInterface(iid, ppUnk);\r
842         return hr;\r
843 }\r
844 \r
845 bool FlashAxContainer::DrawControl(HDC targetDC)\r
846 {\r
847 //      ATLTRACE(_T("FlashAxContainer::DrawControl\n"));\r
848         DVASPECTINFO aspectInfo = {sizeof(DVASPECTINFO), DVASPECTINFOFLAG_CANOPTIMIZE};\r
849         HRESULT hr = S_OK;\r
850 \r
851         hr = m_spViewObject->Draw(DVASPECT_CONTENT, -1, &aspectInfo, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
852         bInvalidRect_ = false;\r
853 /*      const video_format_desc& fmtDesc = video_format_desc::FormatDescriptions[format_];\r
854 \r
855         //Trying to redraw just the dirty rectangles. Doesn't seem to work when the movie uses "filters", such as glow, dropshadow etc.\r
856         std::vector<flash::DirtyRect>::iterator it = bDirtyRects_.begin();\r
857         std::vector<flash::DirtyRect>::iterator end = bDirtyRects_.end();\r
858         for(; it != end; ++it) {\r
859                 flash::DirtyRect& dirtyRect = (*it);\r
860                 if(dirtyRect.bWhole || dirtyRect.rect.right >= fmtDesc.width || dirtyRect.rect.bottom >= fmtDesc.height) {\r
861                         m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\r
862                         hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
863                         break;\r
864                 }\r
865                 else {\r
866                         m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &(dirtyRect.rect));\r
867                         hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL); \r
868                 }\r
869         }\r
870         bDirtyRects_.clear();\r
871 */\r
872 \r
873         return (hr == S_OK);\r
874 }\r
875 \r
876 void FlashAxContainer::Tick()\r
877 {\r
878         if(pTimerHelper)\r
879         {\r
880                 DWORD time = pTimerHelper->Invoke(); // Tick flash\r
881                 if(time - timerCount_ >= 400)\r
882                 {\r
883                         timerCount_ = time;\r
884                         HRESULT hr;\r
885                         m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);\r
886                 }\r
887         }\r
888 }\r
889 \r
890 bool FlashAxContainer::FlashCall(const std::wstring& str)\r
891 {\r
892         CComBSTR result;\r
893         CComPtr<IShockwaveFlash> spFlash;\r
894         QueryControl(&spFlash);\r
895         CComBSTR request(str.c_str());\r
896         \r
897         bIsEmpty_ = false;\r
898         bCallSuccessful_ = false;\r
899         for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)\r
900                 spFlash->CallFunction(request, &result);\r
901         return bCallSuccessful_;\r
902 }\r
903 \r
904 }       //namespace flash\r
905 }       //namespace caspar