2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>
\r
4 * This file is part of CasparCG.
\r
6 * CasparCG is free software: you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation, either version 3 of the License, or
\r
9 * (at your option) any later version.
\r
11 * CasparCG is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
\r
21 #include "..\..\stdafx.h"
\r
23 #include "FlashAxContainer.h"
\r
24 #include "TimerHelper.h"
\r
26 #include <common/log/log.h>
\r
28 #if defined(_MSC_VER)
\r
29 #pragma warning (push, 2) // TODO
\r
32 using namespace ATL;
\r
34 namespace caspar { namespace flash {
\r
36 CComBSTR FlashAxContainer::flashGUID_(_T("{D27CDB6E-AE6D-11CF-96B8-444553540000}"));
\r
38 _ATL_FUNC_INFO fnInfoFlashCallEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };
\r
39 _ATL_FUNC_INFO fnInfoReadyStateChangeEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };
\r
41 FlashAxContainer::FlashAxContainer() : bInPlaceActive_(FALSE), pTimerHelper(0), bInvalidRect_(false), bReadyToRender_(false), bHasNewTiming_(false), m_lpDD4(0), timerCount_(0)
\r
44 FlashAxContainer::~FlashAxContainer()
\r
52 if(pTimerHelper != 0)
\r
53 delete pTimerHelper;
\r
60 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetSite(IUnknown* pUnkSite)
\r
62 ATLTRACE(_T("IObjectWithSite::SetSite\n"));
\r
63 HRESULT hr = IObjectWithSiteImpl<FlashAxContainer>::SetSite(pUnkSite);
\r
65 if (SUCCEEDED(hr) && m_spUnkSite)
\r
67 // Look for "outer" IServiceProvider
\r
68 hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices);
\r
69 ATLASSERT( !hr && _T("No ServiceProvider!") );
\r
72 if (pUnkSite == NULL)
\r
73 m_spServices.Release();
\r
81 HRESULT STDMETHODCALLTYPE FlashAxContainer::SaveObject()
\r
83 ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject"));
\r
86 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)
\r
88 /* if(*ppmk != NULL) {
\r
89 if(m_spMyMoniker == NULL) {
\r
90 ATL::CComObject<MyMoniker>* pMoniker = NULL;
\r
91 HRESULT hr = ATL::CComObject<MyMoniker>::CreateInstance(&pMoniker);
\r
93 m_spMyMoniker = pMoniker;
\r
96 if(m_spMyMoniker != NULL) {
\r
97 *ppmk = m_spMyMoniker;
\r
102 */ if(ppmk != NULL)
\r
107 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetContainer(IOleContainer** ppContainer)
\r
109 ATLTRACE(_T("IOleClientSite::GetContainer\n"));
\r
110 (*ppContainer) = NULL;
\r
111 return E_NOINTERFACE;
\r
114 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowObject()
\r
116 ATLTRACE(_T("IOleClientSite::ShowObject\n"));
\r
120 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnShowWindow(BOOL fShow)
\r
122 ATLTRACE(_T("IOleClientSite::OnShowWindow"));
\r
126 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestNewObjectLayout()
\r
128 ATLTRACE(_T("IOleClientSite::RequestNewObjectLayout"));
\r
132 ///////////////////
\r
134 ///////////////////
\r
135 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindow(HWND* pHwnd)
\r
137 ATLTRACE(_T("IOleInPlaceSite::GetWindow\n"));
\r
138 (*pHwnd) = NULL;//GetApplication()->GetMainWindow()->getHwnd();
\r
141 HRESULT STDMETHODCALLTYPE FlashAxContainer::ContextSensitiveHelp(BOOL fEnterMode)
\r
143 ATLTRACE(_T("IOleInPlaceSite::ContextSensitiveHelp"));
\r
147 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanInPlaceActivate()
\r
149 ATLTRACE(_T("IOleInPlaceSite::CanInPlaceActivate\n"));
\r
153 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivate()
\r
155 ATLTRACE(_T("IOleInPlaceSite::OnInPlaceActivate"));
\r
159 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIActivate()
\r
161 ATLTRACE(_T("IOleInPlaceSite::OnUIActivate\n"));
\r
166 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)
\r
168 ATLTRACE(_T("IOleInPlaceSite::GetWindowContext\n"));
\r
169 if (ppFrame != NULL)
\r
174 if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL)
\r
177 pFrameInfo->fMDIApp = FALSE;
\r
178 pFrameInfo->haccel = NULL;
\r
179 pFrameInfo->cAccelEntries = 0;
\r
180 pFrameInfo->hwndFrame = NULL;
\r
182 lprcPosRect->top = m_rcPos.top;
\r
183 lprcPosRect->left = m_rcPos.left;
\r
184 lprcPosRect->right = m_rcPos.right;
\r
185 lprcPosRect->bottom = m_rcPos.bottom;
\r
187 lprcClipRect->top = m_rcPos.top;
\r
188 lprcClipRect->left = m_rcPos.left;
\r
189 lprcClipRect->right = m_rcPos.right;
\r
190 lprcClipRect->bottom = m_rcPos.bottom;
\r
195 HRESULT STDMETHODCALLTYPE FlashAxContainer::Scroll(SIZE scrollExtant)
\r
197 ATLTRACE(_T("IOleInPlaceSite::Scroll"));
\r
201 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIDeactivate(BOOL fUndoable)
\r
203 ATLTRACE(_T("IOleInPlaceSite::OnUIDeactivate\n"));
\r
204 bUIActive_ = FALSE;
\r
208 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivate()
\r
210 ATLTRACE(_T("IOleInPlaceSite::OnInPlaceDeactivate\n"));
\r
211 bInPlaceActive_ = FALSE;
\r
212 m_spInPlaceObjectWindowless.Release();
\r
216 HRESULT STDMETHODCALLTYPE FlashAxContainer::DiscardUndoState()
\r
218 ATLTRACE(_T("IOleInPlaceSite::DiscardUndoState"));
\r
222 HRESULT STDMETHODCALLTYPE FlashAxContainer::DeactivateAndUndo()
\r
224 ATLTRACE(_T("IOleInPlaceSite::DeactivateAndUndo"));
\r
228 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnPosRectChange(LPCRECT lprcPosRect)
\r
230 ATLTRACE(_T("IOleInPlaceSite::OnPosRectChange"));
\r
235 /////////////////////
\r
236 // IOleInPlaceSiteEx
\r
237 /////////////////////
\r
238 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)
\r
240 // should only be called once the first time control is inplace-activated
\r
241 ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceActivateEx\n"));
\r
242 ATLASSERT(bInPlaceActive_ == FALSE);
\r
243 ATLASSERT(m_spInPlaceObjectWindowless == NULL);
\r
245 bInPlaceActive_ = TRUE;
\r
246 OleLockRunning(m_spOleObject, TRUE, FALSE);
\r
247 HRESULT hr = E_FAIL;
\r
248 if (dwFlags & ACTIVATE_WINDOWLESS)
\r
250 hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**) &m_spInPlaceObjectWindowless);
\r
252 if (m_spInPlaceObjectWindowless != NULL)
\r
253 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
\r
256 return (m_spInPlaceObjectWindowless != NULL) ? S_OK : E_FAIL;
\r
259 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivateEx(BOOL fNoRedraw)
\r
261 ATLTRACE(_T("IOleInPlaceSiteEx::OnInPlaceDeactivateEx\n"));
\r
262 bInPlaceActive_ = FALSE;
\r
263 m_spInPlaceObjectWindowless.Release();
\r
267 HRESULT STDMETHODCALLTYPE FlashAxContainer::RequestUIActivate()
\r
269 ATLTRACE(_T("IOleInPlaceSiteEx::RequestUIActivate\n"));
\r
274 /////////////////////////////
\r
275 // IOleInPlaceSiteWindowless
\r
276 /////////////////////////////
\r
277 HRESULT STDMETHODCALLTYPE FlashAxContainer::CanWindowlessActivate()
\r
279 ATLTRACE(_T("IOleInPlaceSiteWindowless::CanWindowlessActivate\n"));
\r
284 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetCapture()
\r
286 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetCapture\n"));
\r
287 return bCapture_ ? S_OK : S_FALSE;
\r
290 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetCapture(BOOL fCapture)
\r
292 ATLTRACE(_T("IOleInPlaceSiteWindowless::SetCapture\n"));
\r
293 bCapture_ = fCapture;
\r
297 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetFocus()
\r
299 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetFocus\n"));
\r
300 return bHaveFocus_ ? S_OK : S_FALSE;
\r
303 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetFocus(BOOL fGotFocus)
\r
305 ATLTRACE(_T("IOleInPlaceSiteWindowless::SetFocus\n"));
\r
306 bHaveFocus_ = fGotFocus;
\r
310 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)
\r
312 ATLTRACE(_T("IOleInPlaceSiteWindowless::GetDC"));
\r
316 HRESULT STDMETHODCALLTYPE FlashAxContainer::ReleaseDC(HDC hDC)
\r
318 ATLTRACE(_T("IOleInPlaceSiteWindowless::ReleaseDC"));
\r
322 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRect(LPCRECT pRect, BOOL fErase)
\r
324 // ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRect\n"));
\r
326 bInvalidRect_ = true;
\r
328 /* //Keep a list of dirty rectangles in order to be able to redraw only them
\r
329 if(pRect != NULL) {
\r
330 bDirtyRects_.push_back(DirtyRect(*pRect, fErase != 0));
\r
333 bDirtyRects_.push_back(DirtyRect(true));
\r
338 HRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRgn(HRGN hRGN, BOOL fErase)
\r
340 ATLTRACE(_T("IOleInPlaceSiteWindowless::InvalidateRng\n"));
\r
344 HRESULT STDMETHODCALLTYPE FlashAxContainer::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
\r
346 ATLTRACE(_T("IOleInPlaceSiteWindowless::ScrollRect"));
\r
350 HRESULT STDMETHODCALLTYPE FlashAxContainer::AdjustRect(LPRECT prc)
\r
352 ATLTRACE(_T("IOleInPlaceSiteWindowless::AdjustRect"));
\r
356 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
\r
358 ATLTRACE(_T("IOleInPlaceSiteWindowless::OnDefWindowMessage"));
\r
362 ///////////////////
\r
364 ///////////////////
\r
365 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnControlInfoChanged()
\r
367 ATLTRACE(_T("IOleControlSite::OnControlInfoChanged"));
\r
371 HRESULT STDMETHODCALLTYPE FlashAxContainer::LockInPlaceActive(BOOL fLock)
\r
373 ATLTRACE(_T("IOleControlSite::LockInPlaceActive"));
\r
377 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetExtendedControl(IDispatch** ppDisp)
\r
379 ATLTRACE(_T("IOleControlSite::GetExtendedControl"));
\r
381 if (ppDisp == NULL)
\r
383 return m_spOleObject.QueryInterface(ppDisp);
\r
386 HRESULT STDMETHODCALLTYPE FlashAxContainer::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)
\r
388 ATLTRACE(_T("IOleControlSite::TransformCoords"));
\r
392 HRESULT STDMETHODCALLTYPE FlashAxContainer::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)
\r
394 ATLTRACE(_T("IOleControlSite::TranslateAccelerator"));
\r
398 HRESULT STDMETHODCALLTYPE FlashAxContainer::OnFocus(BOOL fGotFocus)
\r
400 bHaveFocus_ = fGotFocus;
\r
404 HRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()
\r
406 ATLTRACE(_T("IOleControlSite::ShowPropertyFrame"));
\r
411 ///////////////////
\r
413 ///////////////////
\r
414 void STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)
\r
416 ATLTRACE(_T("IAdviseSink::OnDataChange\n"));
\r
419 void STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)
\r
421 ATLTRACE(_T("IAdviseSink::OnViewChange\n"));
\r
424 void STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk)
\r
426 ATLTRACE(_T("IAdviseSink::OnRename\n"));
\r
429 void STDMETHODCALLTYPE FlashAxContainer::OnSave()
\r
431 ATLTRACE(_T("IAdviseSink::OnSave\n"));
\r
434 void STDMETHODCALLTYPE FlashAxContainer::OnClose()
\r
436 ATLTRACE(_T("IAdviseSink::OnClose\n"));
\r
442 DEFINE_GUID2(CLSID_DirectDraw,0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35);
\r
443 DEFINE_GUID2(CLSID_DirectDraw7,0x3c305196,0x50db,0x11d3,0x9c,0xfe,0x00,0xc0,0x4f,0xd9,0x30,0xc5);
\r
445 DEFINE_GUID2(IID_IDirectDraw,0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
\r
446 DEFINE_GUID2(IID_IDirectDraw3,0x618f8ad4,0x8b7a,0x11d0,0x8f,0xcc,0x0,0xc0,0x4f,0xd9,0x18,0x9d);
\r
447 DEFINE_GUID2(IID_IDirectDraw4,0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5);
\r
448 DEFINE_GUID2(IID_IDirectDraw7,0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b);
\r
450 ///////////////////
\r
451 // IServiceProvider
\r
452 ///////////////////
\r
453 HRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService( REFGUID rsid, REFIID riid, void** ppvObj)
\r
455 // ATLTRACE(_T("IServiceProvider::QueryService\n"));
\r
456 //the flashcontrol asks for an interface {618F8AD4-8B7A-11D0-8FCC-00C04FD9189D}, this is IID for a DirectDraw3 object
\r
458 ATLASSERT(ppvObj != NULL);
\r
459 if (ppvObj == NULL)
\r
464 // Author: Makarov Igor
\r
465 // Transparent Flash Control in Plain C++
\r
466 // http://www.codeproject.com/KB/COM/flashcontrol.aspx
\r
467 if (IsEqualGUID(rsid, IID_IDirectDraw3))
\r
471 m_lpDD4 = new IDirectDraw4Ptr;
\r
472 hr = m_lpDD4->CreateInstance(CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER);
\r
477 CASPAR_LOG(info) << print_() << " DirectDraw not installed. Running without DirectDraw.";
\r
478 return E_NOINTERFACE;
\r
481 if (m_lpDD4 && m_lpDD4->GetInterfacePtr())
\r
483 *ppvObj = m_lpDD4->GetInterfacePtr();
\r
489 //TODO: The fullscreen-consumer requires that ths does NOT return an ITimerService
\r
490 hr = QueryInterface(riid, ppvObj);//E_NOINTERFACE;
\r
496 ///////////////////
\r
498 ///////////////////
\r
499 HRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer *pReferenceTimer, ITimer **ppNewTimer)
\r
501 ATLTRACE(_T("ITimerService::CreateTimer\n"));
\r
502 if(pTimerHelper != 0)
\r
504 delete pTimerHelper;
\r
507 pTimerHelper = new TimerHelper();
\r
508 return QueryInterface(__uuidof(ITimer), (void**) ppNewTimer);
\r
511 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer **ppTimer)
\r
513 ATLTRACE(_T("ITimerService::GetNamedTimer"));
\r
514 if(ppTimer == NULL)
\r
522 HRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer *pReferenceTimer)
\r
524 ATLTRACE(_T("ITimerService::SetNamedTimerReference"));
\r
531 HRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink *pTimerSink, DWORD *pdwCookie)
\r
533 ATLTRACE(_T("Timer::Advise\n"));
\r
538 if(pTimerHelper != 0)
\r
540 pTimerHelper->Setup(vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);
\r
541 *pdwCookie = pTimerHelper->ID;
\r
542 bHasNewTiming_ = true;
\r
547 return E_OUTOFMEMORY;
\r
550 HRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)
\r
552 ATLTRACE(_T("Timer::Unadvice\n"));
\r
553 if(pTimerHelper != 0)
\r
555 pTimerHelper->pTimerSink = 0;
\r
562 HRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)
\r
564 ATLTRACE(_T("Timer::Freeze\n"));
\r
568 HRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT *pvtime)
\r
570 ATLTRACE(_T("Timer::GetTime\n"));
\r
574 // return E_NOTIMPL;
\r
579 double FlashAxContainer::GetFPS() {
\r
580 if(pTimerHelper != 0 && pTimerHelper->interval > 0)
\r
581 return (1000.0 / static_cast<double>(pTimerHelper->interval));
\r
586 bool FlashAxContainer::IsReadyToRender() const {
\r
587 return bReadyToRender_;
\r
590 void FlashAxContainer::EnterFullscreen()
\r
592 if(m_spInPlaceObjectWindowless != 0)
\r
595 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1), &result);
\r
596 m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(1, 1), &result);
\r
600 void STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)
\r
602 std::wstring str(request);
\r
603 if(str.find(TEXT("DisplayedTemplate")) != std::wstring::npos)
\r
605 ATLTRACE(_T("ShockwaveFlash::DisplayedTemplate\n"));
\r
606 bReadyToRender_ = true;
\r
608 else if(str.find(TEXT("OnCommand")) != std::wstring::npos) {
\r
609 //this is how templatehost 1.8 reports that a command has been received
\r
610 CASPAR_LOG(info) << print_() << L" Command: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
\r
611 bCallSuccessful_ = true;
\r
613 else if(str.find(TEXT("Activity")) != std::wstring::npos)
\r
615 CASPAR_LOG(info) << print_() << L" Activity: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
\r
617 //this is how templatehost 1.7 reports that a command has been received
\r
618 if(str.find(TEXT("Command recieved")) != std::wstring::npos)
\r
619 bCallSuccessful_ = true;
\r
621 /*if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {
\r
622 std::wstring::size_type pos = str.find(TEXT('@'));
\r
623 if(pos != std::wstring::npos)
\r
624 pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));
\r
627 else if(str.find(TEXT("OnNotify")) != std::wstring::npos)
\r
629 CASPAR_LOG(info) << print_() << L" Notification: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
\r
631 //if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {
\r
632 // std::wstring::size_type pos = str.find(TEXT('@'));
\r
633 // if(pos != std::wstring::npos)
\r
634 // pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));
\r
637 else if(str.find(TEXT("IsEmpty")) != std::wstring::npos)
\r
639 CASPAR_LOG(info) << print_() << L" Empty.";
\r
640 ATLTRACE(_T("ShockwaveFlash::IsEmpty\n"));
\r
643 else if(str.find(TEXT("OnError")) != std::wstring::npos)
\r
645 CASPAR_LOG(error) << print_() << L" Error: \n-------------------------------------------\n" << str << L"\n-------------------------------------------";
\r
648 CComPtr<IShockwaveFlash> spFlash;
\r
649 HRESULT hr = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);
\r
650 if(hr == S_OK && spFlash)
\r
652 hr = spFlash->SetReturnValue(TEXT("<null/>"));
\r
656 void STDMETHODCALLTYPE FlashAxContainer::OnReadyStateChange(long newState)
\r
660 bReadyToRender_ = true;
\r
663 bReadyToRender_ = false;
\r
666 void FlashAxContainer::DestroyAxControl()
\r
668 GetControllingUnknown()->AddRef();
\r
670 if ((!m_spViewObject) == false)
\r
671 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);
\r
673 if ((!m_spOleObject) == false)
\r
675 DispEventUnadvise(m_spOleObject, &DIID__IShockwaveFlashEvents);
\r
676 m_spOleObject->Unadvise(m_dwOleObject);
\r
677 m_spOleObject->Close(OLECLOSE_NOSAVE);
\r
678 m_spOleObject->SetClientSite(NULL);
\r
681 if ((!m_spUnknown) == false)
\r
683 CComPtr<IObjectWithSite> spSite;
\r
684 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
\r
685 if (spSite != NULL)
\r
686 spSite->SetSite(NULL);
\r
689 if ((!m_spViewObject) == false)
\r
690 m_spViewObject.Release();
\r
692 if ((!m_spInPlaceObjectWindowless) == false)
\r
693 m_spInPlaceObjectWindowless.Release();
\r
695 if ((!m_spOleObject) == false)
\r
696 m_spOleObject.Release();
\r
698 if ((!m_spUnknown) == false)
\r
699 m_spUnknown.Release();
\r
702 bool FlashAxContainer::CheckForFlashSupport()
\r
705 return SUCCEEDED(CLSIDFromString((LPOLESTR)flashGUID_, &clsid));
\r
708 HRESULT FlashAxContainer::CreateAxControl()
\r
711 HRESULT hr = CLSIDFromString((LPOLESTR)flashGUID_, &clsid);
\r
713 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), (void**)&m_spUnknown);
\r
718 m_spUnknown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);
\r
721 m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
\r
722 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
\r
724 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
\r
725 m_spOleObject->SetClientSite(spClientSite);
\r
728 //Initialize control
\r
729 CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);
\r
731 hr = spPSI->InitNew();
\r
733 if (FAILED(hr)) // If the initialization of the control failed...
\r
735 // Clean up and return
\r
736 if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
\r
737 m_spOleObject->SetClientSite(NULL);
\r
739 m_dwMiscStatus = 0;
\r
740 m_spOleObject.Release();
\r
741 m_spUnknown.Release();
\r
745 //end Initialize object
\r
747 if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
\r
749 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
\r
750 m_spOleObject->SetClientSite(spClientSite);
\r
753 CComPtr<IShockwaveFlash> spFlash;
\r
754 HRESULT hResultQuality;
\r
755 HRESULT hr2 = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**) &spFlash);
\r
756 if(hr2 == S_OK && spFlash)
\r
758 if(FAILED(spFlash->put_WMode(TEXT("Transparent"))))
\r
759 CASPAR_LOG(warning) << print_() << L" Failed to set flash container to transparent mode.";
\r
760 //spFlash->put_WMode(TEXT("GPU"));
\r
761 hResultQuality = spFlash->put_Quality2(TEXT("Best"));
\r
763 if(SUCCEEDED(DispEventAdvise(spFlash, &DIID__IShockwaveFlashEvents)))
\r
767 HRESULT hrView = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);
\r
769 CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());
\r
770 m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);
\r
771 if (m_spViewObject)
\r
772 m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
\r
774 if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0)
\r
776 //Initialize window to some dummy size
\r
779 m_rcPos.right = 720;
\r
780 m_rcPos.bottom = 576;
\r
782 m_pxSize.cx = m_rcPos.right - m_rcPos.left;
\r
783 m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;
\r
784 AtlPixelToHiMetric(&m_pxSize, &m_hmSize);
\r
785 m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);
\r
786 m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);
\r
787 AtlHiMetricToPixel(&m_hmSize, &m_pxSize);
\r
788 m_rcPos.right = m_rcPos.left + m_pxSize.cx;
\r
789 m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;
\r
791 CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
\r
792 hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, NULL, &m_rcPos);
\r
795 CComPtr<IObjectWithSite> spSite;
\r
796 m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
\r
797 if (spSite != NULL)
\r
798 spSite->SetSite(GetControllingUnknown());
\r
803 if (FAILED(hr) || m_spUnknown == NULL)
\r
806 // We don't have a control or something failed so release
\r
813 void FlashAxContainer::SetFormat(const core::video_format_desc& fmtDesc) {
\r
814 if(m_spInPlaceObjectWindowless != 0)
\r
818 m_rcPos.right = fmtDesc.width;
\r
819 m_rcPos.bottom = fmtDesc.height;
\r
821 m_pxSize.cx = m_rcPos.right - m_rcPos.left;
\r
822 m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;
\r
823 AtlPixelToHiMetric(&m_pxSize, &m_hmSize);
\r
824 m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);
\r
825 m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);
\r
826 AtlHiMetricToPixel(&m_hmSize, &m_pxSize);
\r
827 m_rcPos.right = m_rcPos.left + m_pxSize.cx;
\r
828 m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;
\r
830 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
\r
831 bInvalidRect_ = true;
\r
835 HRESULT FlashAxContainer::QueryControl(REFIID iid, void** ppUnk)
\r
837 ATLASSERT(ppUnk != NULL);
\r
841 hr = m_spOleObject->QueryInterface(iid, ppUnk);
\r
845 bool FlashAxContainer::DrawControl(HDC targetDC)
\r
847 // ATLTRACE(_T("FlashAxContainer::DrawControl\n"));
\r
848 DVASPECTINFO aspectInfo = {sizeof(DVASPECTINFO), DVASPECTINFOFLAG_CANOPTIMIZE};
\r
851 hr = m_spViewObject->Draw(DVASPECT_CONTENT, -1, &aspectInfo, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);
\r
852 bInvalidRect_ = false;
\r
853 /* const video_format_desc& fmtDesc = video_format_desc::FormatDescriptions[format_];
\r
855 //Trying to redraw just the dirty rectangles. Doesn't seem to work when the movie uses "filters", such as glow, dropshadow etc.
\r
856 std::vector<flash::DirtyRect>::iterator it = bDirtyRects_.begin();
\r
857 std::vector<flash::DirtyRect>::iterator end = bDirtyRects_.end();
\r
858 for(; it != end; ++it) {
\r
859 flash::DirtyRect& dirtyRect = (*it);
\r
860 if(dirtyRect.bWhole || dirtyRect.rect.right >= fmtDesc.width || dirtyRect.rect.bottom >= fmtDesc.height) {
\r
861 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
\r
862 hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);
\r
866 m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &(dirtyRect.rect));
\r
867 hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);
\r
870 bDirtyRects_.clear();
\r
873 return (hr == S_OK);
\r
876 void FlashAxContainer::Tick()
\r
880 DWORD time = pTimerHelper->Invoke(); // Tick flash
\r
881 if(time - timerCount_ >= 400)
\r
883 timerCount_ = time;
\r
885 m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);
\r
890 bool FlashAxContainer::FlashCall(const std::wstring& str)
\r
893 CComPtr<IShockwaveFlash> spFlash;
\r
894 QueryControl(&spFlash);
\r
895 CComBSTR request(str.c_str());
\r
898 bCallSuccessful_ = false;
\r
899 for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)
\r
900 spFlash->CallFunction(request, &result);
\r
901 return bCallSuccessful_;
\r
904 } //namespace flash
\r