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