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