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