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