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