2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
4 * This file is part of CasparCG (www.casparcg.com).
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.
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.
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/>.
19 * Author: Nicklas P Andersson
22 #include "../stdafx.h"
24 #include "FlashAxContainer.h"
25 #include "../interop/TimerHelper.h"
27 #include <common/log.h>
28 #include <common/os/general_protection_fault.h>
31 #pragma warning (push, 2) // TODO
36 namespace caspar { namespace flash {
38 CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}"));
40 _ATL_FUNC_INFO fnInfoFlashCallEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };
41 _ATL_FUNC_INFO fnInfoReadyStateChangeEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };
43 FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), pTimerHelper(0), bInvalidRect_(false), bReadyToRender_(false), bHasNewTiming_(false), m_lpDD4(0), timerCount_(0), bIsEmpty_(true)
46 FlashAxContainer::~FlashAxContainer()
62 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetSite(IUnknown* pUnkSite)
64 ATLTRACE(_T("IObjectWithSite::SetSite\n"));
65 HRESULT hr = IObjectWithSiteImpl<FlashAxContainer>::SetSite(pUnkSite);
67 if (SUCCEEDED(hr) && m_spUnkSite)
69 // Look for "outer" IServiceProvider
70 hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices);
71 ATLASSERT( !hr && _T("No ServiceProvider!") );
75 m_spServices.Release();
83 HRESULT STDMETHODCALLTYPE FlashAxContainer::SaveObject()
85 ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject"));
88 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)
90 /* if(*ppmk != NULL) {
91 if(m_spMyMoniker == NULL) {
92 ATL::CComObject<MyMoniker>* pMoniker = NULL;
93 HRESULT hr = ATL::CComObject<MyMoniker>::CreateInstance(&pMoniker);
95 m_spMyMoniker = pMoniker;
98 if(m_spMyMoniker != NULL) {
99 *ppmk = m_spMyMoniker;
109 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetContainer(IOleContainer** ppContainer)
111 ATLTRACE(_T("IOleClientSite::GetContainer\n"));
112 (*ppContainer) = NULL;
113 return E_NOINTERFACE;
116 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowObject()
118 ATLTRACE(_T("IOleClientSite::ShowObject\n"));
122 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnShowWindow(BOOL fShow)
124 ATLTRACE(_T("IOleClientSite::OnShowWindow"));
128 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestNewObjectLayout()
130 ATLTRACE(_T("IOleClientSite::RequestNewObjectLayout"));
137 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindow(HWND* pHwnd)
139 ATLTRACE(_T("IOleInPlaceSite::GetWindow\n"));
140 (*pHwnd) = NULL;//GetApplication()->GetMainWindow()->getHwnd();
143 HRESULT STDMETHODCALLTYPE FlashAxContainer::ContextSensitiveHelp(BOOL fEnterMode)
145 ATLTRACE(_T("IOleInPlaceSite::ContextSensitiveHelp"));
149 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanInPlaceActivate()
151 ATLTRACE(_T("IOleInPlaceSite::CanInPlaceActivate\n"));
155 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivate()
157 ATLTRACE(_T("IOleInPlaceSite::OnInPlaceActivate"));
161 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIActivate()
163 ATLTRACE(_T("IOleInPlaceSite::OnUIActivate\n"));
168 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)
170 ATLTRACE(_T("IOleInPlaceSite::GetWindowContext\n"));
176 if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL)
179 pFrameInfo->fMDIApp = FALSE;
180 pFrameInfo->haccel = NULL;
181 pFrameInfo->cAccelEntries = 0;
182 pFrameInfo->hwndFrame = NULL;
184 lprcPosRect->top = m_rcPos.top;
185 lprcPosRect->left = m_rcPos.left;
186 lprcPosRect->right = m_rcPos.right;
187 lprcPosRect->bottom = m_rcPos.bottom;
189 lprcClipRect->top = m_rcPos.top;
190 lprcClipRect->left = m_rcPos.left;
191 lprcClipRect->right = m_rcPos.right;
192 lprcClipRect->bottom = m_rcPos.bottom;
197 HRESULT STDMETHODCALLTYPE FlashAxContainer::Scroll(SIZE scrollExtant)
199 ATLTRACE(_T("IOleInPlaceSite::Scroll"));
203 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIDeactivate(BOOL fUndoable)
205 ATLTRACE(_T("IOleInPlaceSite::OnUIDeactivate\n"));
210 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivate()
212 ATLTRACE(_T("IOleInPlaceSite::OnInPlaceDeactivate\n"));
213 bInPlaceActive_ = FALSE;
214 m_spInPlaceObjectWindowless.Release();
218 HRESULT STDMETHODCALLTYPE FlashAxContainer::DiscardUndoState()
220 ATLTRACE(_T("IOleInPlaceSite::DiscardUndoState"));
224 HRESULT STDMETHODCALLTYPE FlashAxContainer::DeactivateAndUndo()
226 ATLTRACE(_T("IOleInPlaceSite::DeactivateAndUndo"));
230 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnPosRectChange(LPCRECT lprcPosRect)
232 ATLTRACE(_T("IOleInPlaceSite::OnPosRectChange"));
240 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)
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);
247 bInPlaceActive_ = TRUE;
248 OleLockRunning(m_spOleObject, TRUE, FALSE);
250 if (dwFlags & ACTIVATE_WINDOWLESS)
252 hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless);
254 if (m_spInPlaceObjectWindowless != NULL)
255 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
258 return (m_spInPlaceObjectWindowless != NULL) ? S_OK : E_FAIL;
261 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivateEx(BOOL fNoRedraw)
263 ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceDeactivateEx\n"));
264 bInPlaceActive_ = FALSE;
265 m_spInPlaceObjectWindowless.Release();
269 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestUIActivate()
271 ATLTRACE(_T("IOleInPlaceSiteEx::RequestUIActivate\n"));
277 // IOleInPlaceSiteWindowless
279 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanWindowlessActivate()
281 ATLTRACE(_T("IOleInPlaceSiteWindowless::CanWindowlessActivate\n"));
286 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetCapture()
288 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetCapture\n"));
289 return bCapture_ ? S_OK : S_FALSE;
292 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetCapture(BOOL fCapture)
294 ATLTRACE(_T("IOleInPlaceSiteWindowless::SetCapture\n"));
295 bCapture_ = fCapture;
299 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetFocus()
301 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetFocus\n"));
302 return bHaveFocus_ ? S_OK : S_FALSE;
305 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetFocus(BOOL fGotFocus)
307 ATLTRACE(_T("IOleInPlaceSiteWindowless::SetFocus\n"));
308 bHaveFocus_ = fGotFocus;
312 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
314 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetDC"));
318 HRESULT STDMETHODCALLTYPE FlashAxContainer::ReleaseDC(HDC hDC)
320 ATLTRACE(_T("IOleInPlaceSiteWindowless::ReleaseDC"));
324 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRect(LPCRECT pRect, BOOL fErase)
326 // ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRect\n"));
328 bInvalidRect_ = true;
330 /* //Keep a list of dirty rectangles in order to be able to redraw only them
332 bDirtyRects_.push_back(DirtyRect(*pRect, fErase != 0));
335 bDirtyRects_.push_back(DirtyRect(true));
340 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRgn(HRGN hRGN, BOOL fErase)
342 ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRng\n"));
346 HRESULT STDMETHODCALLTYPE FlashAxContainer::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
348 ATLTRACE(_T("IOleInPlaceSiteWindowless::ScrollRect"));
352 HRESULT STDMETHODCALLTYPE FlashAxContainer::AdjustRect(LPRECT prc)
354 ATLTRACE(_T("IOleInPlaceSiteWindowless::AdjustRect"));
358 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
360 ATLTRACE(_T("IOleInPlaceSiteWindowless::OnDefWindowMessage"));
367 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnControlInfoChanged()
369 ATLTRACE(_T("IOleControlSite::OnControlInfoChanged"));
373 HRESULT STDMETHODCALLTYPE FlashAxContainer::LockInPlaceActive(BOOL fLock)
375 ATLTRACE(_T("IOleControlSite::LockInPlaceActive"));
379 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetExtendedControl(IDispatch** ppDisp)
381 ATLTRACE(_T("IOleControlSite::GetExtendedControl"));
385 return m_spOleObject.QueryInterface(ppDisp);
388 HRESULT STDMETHODCALLTYPE FlashAxContainer::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)
390 ATLTRACE(_T("IOleControlSite::TransformCoords"));
394 HRESULT STDMETHODCALLTYPE FlashAxContainer::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)
396 ATLTRACE(_T("IOleControlSite::TranslateAccelerator"));
400 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnFocus(BOOL fGotFocus)
402 bHaveFocus_ = fGotFocus;
406 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()
408 ATLTRACE(_T("IOleControlSite::ShowPropertyFrame"));
416 void STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)
418 ATLTRACE(_T("IAdviseSink::OnDataChange\n"));
421 void STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)
423 ATLTRACE(_T("IAdviseSink::OnViewChange\n"));
426 void STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk)
428 ATLTRACE(_T("IAdviseSink::OnRename\n"));
431 void STDMETHODCALLTYPE FlashAxContainer::OnSave()
433 ATLTRACE(_T("IAdviseSink::OnSave\n"));
436 void STDMETHODCALLTYPE FlashAxContainer::OnClose()
438 ATLTRACE(_T("IAdviseSink::OnClose\n"));
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);
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);
455 HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID riid, void** ppvObj)
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
461 ATLASSERT(ppvObj != NULL);
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))
474 m_lpDD4 = new IDirectDraw4Ptr;
475 hr = m_lpDD4->CreateInstance(CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER);
480 CASPAR_LOG(info) << print_() << " DirectDraw not installed. Running without DirectDraw.";
481 return E_NOINTERFACE;
484 if (m_lpDD4 && m_lpDD4->GetInterfacePtr())
486 *ppvObj = m_lpDD4->GetInterfacePtr();
492 //TODO: The fullscreen-consumer requires that ths does NOT return an ITimerService
493 hr = QueryInterface(riid, ppvObj);//E_NOINTERFACE;
502 HRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer *pReferenceTimer, ITimer **ppNewTimer)
504 ATLTRACE(_T("ITimerService::CreateTimer\n"));
505 if(pTimerHelper != 0)
510 pTimerHelper = new TimerHelper();
511 return QueryInterface(__uuidof(ITimer), (void**) ppNewTimer);
514 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer **ppTimer)
516 ATLTRACE(_T("ITimerService::GetNamedTimer"));
525 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer *pReferenceTimer)
527 ATLTRACE(_T("ITimerService::SetNamedTimerReference"));
534 HRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie)
536 ATLTRACE(_T("Timer::Advise\n"));
541 if(pTimerHelper != 0)
543 //static tbb::atomic<DWORD> NEXT_ID;
544 pTimerHelper->Setup(0, vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);
545 *pdwCookie = pTimerHelper->ID;
546 bHasNewTiming_ = true;
551 return E_OUTOFMEMORY;
554 HRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)
556 ATLTRACE(_T("Timer::Unadvice\n"));
557 if(pTimerHelper != 0)
559 pTimerHelper->pTimerSink = 0;
566 HRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)
568 ATLTRACE(_T("Timer::Freeze\n"));
572 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT *pvtime)
574 ATLTRACE(_T("Timer::GetTime\n"));
583 double FlashAxContainer::GetFPS() {
584 if(pTimerHelper != 0 && pTimerHelper->interval > 0)
585 return (1000.0 / static_cast<double>(pTimerHelper->interval));
590 bool FlashAxContainer::IsReadyToRender() const {
591 return bReadyToRender_;
594 void FlashAxContainer::EnterFullscreen()
596 if(m_spInPlaceObjectWindowless != 0)
599 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1), &result);
600 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(1, 1), &result);
604 void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)
606 ensure_gpf_handler_installed_for_thread("flash-player-thread");
607 std::wstring str(request);
608 if(str.find(L"DisplayedTemplate") != std::wstring::npos)
610 ATLTRACE(_T("ShockwaveFlash::DisplayedTemplate\n"));
611 bReadyToRender_ = true;
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;
618 else if(str.find(L"Activity") != std::wstring::npos)
620 CASPAR_LOG(debug) << print_() << L" [activity] " << str;
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;
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));
632 else if(str.find(L"OnNotify") != std::wstring::npos)
634 CASPAR_LOG(info) << print_() << L" [notification] " << str;
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));
642 else if(str.find(L"IsEmpty") != std::wstring::npos)
644 CASPAR_LOG(debug) << print_() << L" Empty.";
645 ATLTRACE(_T("ShockwaveFlash::IsEmpty\n"));
648 else if(str.find(L"OnError") != std::wstring::npos)
650 if (str.find(L"No template playing on layer") != std::wstring::npos)
651 CASPAR_LOG(info) << print_() << L" [info] " << str;
653 CASPAR_LOG(error) << print_() << L" [error] " << str;
655 else if(str.find(L"OnDebug") != std::wstring::npos)
657 CASPAR_LOG(debug) << print_() << L" [debug] " << str;
659 //else if(str.find(TEXT("OnTemplateDescription")) != std::wstring::npos)
661 // CASPAR_LOG(error) << print_() << L" TemplateDescription: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
663 //else if(str.find(TEXT("OnGetInfo")) != std::wstring::npos)
665 // CASPAR_LOG(error) << print_() << L" Info: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
669 // CASPAR_LOG(error) << print_() << L" Unknown: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
672 CComPtr<IShockwaveFlash> spFlash;
673 HRESULT hr = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);
674 if(hr == S_OK && spFlash)
676 hr = spFlash->SetReturnValue(L"<null/>");
680 void STDMETHODCALLTYPE FlashAxContainer::OnReadyStateChange(long newState)
683 bReadyToRender_ = true;
686 void FlashAxContainer::DestroyAxControl()
688 GetControllingUnknown()->AddRef();
690 if ((!m_spViewObject) == false)
691 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);
693 if ((!m_spOleObject) == false)
695 DispEventUnadvise(m_spOleObject, &DIID__IShockwaveFlashEvents);
696 m_spOleObject->Unadvise(m_dwOleObject);
697 m_spOleObject->Close(OLECLOSE_NOSAVE);
698 m_spOleObject->SetClientSite(NULL);
701 if ((!m_spUnknown) == false)
703 CComPtr<IObjectWithSite> spSite;
704 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
706 spSite->SetSite(NULL);
709 if ((!m_spViewObject) == false)
710 m_spViewObject.Release();
712 if ((!m_spInPlaceObjectWindowless) == false)
713 m_spInPlaceObjectWindowless.Release();
715 if ((!m_spOleObject) == false)
716 m_spOleObject.Release();
718 if ((!m_spUnknown) == false)
719 m_spUnknown.Release();
722 bool FlashAxContainer::CheckForFlashSupport()
725 return SUCCEEDED(CLSIDFromString((LPOLESTR)flashGUID_, &clsid));
728 HRESULT FlashAxContainer::CreateAxControl()
731 HRESULT hr = CLSIDFromString((LPOLESTR)flashGUID_, &clsid);
733 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), (void**)&m_spUnknown);
738 m_spUnknown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);
741 m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
742 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
744 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
745 m_spOleObject->SetClientSite(spClientSite);
749 CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);
751 hr = spPSI->InitNew();
753 if (FAILED(hr)) // If the initialization of the control failed...
755 // Clean up and return
756 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
757 m_spOleObject->SetClientSite(NULL);
760 m_spOleObject.Release();
761 m_spUnknown.Release();
765 //end Initialize object
767 if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
769 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
770 m_spOleObject->SetClientSite(spClientSite);
773 CComPtr<IShockwaveFlash> spFlash;
774 HRESULT hResultQuality;
775 HRESULT hr2 = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);
776 if(hr2 == S_OK && spFlash)
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");
783 if(SUCCEEDED(DispEventAdvise(spFlash, &DIID__IShockwaveFlashEvents)))
787 HRESULT hrView = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);
789 CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());
790 m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);
792 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
794 if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0)
796 //Initialize window to some dummy size
800 m_rcPos.bottom = 576;
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;
811 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
812 hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);
815 CComPtr<IObjectWithSite> spSite;
816 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
818 spSite->SetSite(GetControllingUnknown());
823 if (FAILED(hr) || m_spUnknown == NULL)
826 // We don't have a control or something failed so release
833 void FlashAxContainer::SetSize(size_t width, size_t height) {
834 if(m_spInPlaceObjectWindowless != 0)
838 m_rcPos.right = width;
839 m_rcPos.bottom = height;
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;
850 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
851 bInvalidRect_ = true;
855 HRESULT FlashAxContainer::QueryControl(REFIID iid, void** ppUnk)
857 ATLASSERT(ppUnk != NULL);
861 hr = m_spOleObject->QueryInterface(iid, ppUnk);
865 bool FlashAxContainer::DrawControl(HDC targetDC)
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_];
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);
884 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &(dirtyRect.rect));
885 hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);
888 bDirtyRects_.clear();
894 void FlashAxContainer::Tick()
898 DWORD time = pTimerHelper->Invoke(); // Tick flash
899 if(time - timerCount_ >= 400)
903 m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);
908 bool FlashAxContainer::FlashCall(const std::wstring& str, std::wstring& result2)
911 CComPtr<IShockwaveFlash> spFlash;
912 QueryControl(&spFlash);
913 CComBSTR request(str.c_str());
916 bCallSuccessful_ = false;
917 for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)
918 spFlash->CallFunction(request, &result);
923 return bCallSuccessful_;