winex11: Mirror the client rectangle if necessary for update_window_zorder.
[wine/multimedia.git] / dlls / quartz / nullrenderer.c
blobb82be2f8ba3466967b6eb9e0c3d3895241aba7a4
1 /*
2 * Null Renderer (Promiscuous, not rendering anything at all!)
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 #include "quartz_private.h"
27 #include "control_private.h"
28 #include "pin.h"
30 #include "uuids.h"
31 #include "vfwmsgs.h"
32 #include "amvideo.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "dshow.h"
36 #include "evcode.h"
37 #include "strmif.h"
38 #include "ddraw.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
46 static const WCHAR wcsAltInputPinName[] = {'I','n',0};
48 static const IBaseFilterVtbl NullRenderer_Vtbl;
49 static const IUnknownVtbl IInner_VTable;
50 static const IPinVtbl NullRenderer_InputPin_Vtbl;
52 typedef struct NullRendererImpl
54 const IBaseFilterVtbl * lpVtbl;
55 const IUnknownVtbl * IInner_vtbl;
56 IUnknown *seekthru_unk;
58 LONG refCount;
59 CRITICAL_SECTION csFilter;
60 FILTER_STATE state;
61 REFERENCE_TIME rtStreamStart;
62 IReferenceClock * pClock;
63 FILTER_INFO filterInfo;
65 BaseInputPin *pInputPin;
66 IUnknown * pUnkOuter;
67 BOOL bUnkOuterValid;
68 BOOL bAggregatable;
69 } NullRendererImpl;
71 static HRESULT WINAPI NullRenderer_Receive(IPin *iface, IMediaSample * pSample)
73 BaseInputPin *pin = (BaseInputPin*)iface;
74 NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter);
75 HRESULT hr = S_OK;
76 REFERENCE_TIME start, stop;
78 TRACE("%p %p\n", iface, pSample);
80 if (SUCCEEDED(IMediaSample_GetTime(pSample, &start, &stop)))
81 MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, start);
82 EnterCriticalSection(&This->csFilter);
83 if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
84 hr = S_FALSE;
85 LeaveCriticalSection(&This->csFilter);
87 return hr;
90 static HRESULT WINAPI NullRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
92 TRACE("Not a stub!\n");
93 return S_OK;
96 HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
98 HRESULT hr;
99 PIN_INFO piInput;
100 NullRendererImpl * pNullRenderer;
102 TRACE("(%p, %p)\n", pUnkOuter, ppv);
104 *ppv = NULL;
106 pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
107 pNullRenderer->pUnkOuter = pUnkOuter;
108 pNullRenderer->bUnkOuterValid = FALSE;
109 pNullRenderer->bAggregatable = FALSE;
110 pNullRenderer->IInner_vtbl = &IInner_VTable;
112 pNullRenderer->lpVtbl = &NullRenderer_Vtbl;
113 pNullRenderer->refCount = 1;
114 InitializeCriticalSection(&pNullRenderer->csFilter);
115 pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter");
116 pNullRenderer->state = State_Stopped;
117 pNullRenderer->pClock = NULL;
118 ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO));
120 /* construct input pin */
121 piInput.dir = PINDIR_INPUT;
122 piInput.pFilter = (IBaseFilter *)pNullRenderer;
123 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
125 hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_CheckMediaType, NullRenderer_Receive, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
127 if (SUCCEEDED(hr))
129 ISeekingPassThru *passthru;
130 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pNullRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pNullRenderer->seekthru_unk);
131 if (FAILED(hr)) {
132 IUnknown_Release((IUnknown*)pNullRenderer);
133 return hr;
135 IUnknown_QueryInterface(pNullRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
136 ISeekingPassThru_Init(passthru, TRUE, (IPin*)pNullRenderer->pInputPin);
137 ISeekingPassThru_Release(passthru);
138 *ppv = pNullRenderer;
140 else
142 pNullRenderer->csFilter.DebugInfo->Spare[0] = 0;
143 DeleteCriticalSection(&pNullRenderer->csFilter);
144 CoTaskMemFree(pNullRenderer);
147 return hr;
150 static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
152 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
153 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
155 if (This->bAggregatable)
156 This->bUnkOuterValid = TRUE;
158 *ppv = NULL;
160 if (IsEqualIID(riid, &IID_IUnknown))
161 *ppv = &This->IInner_vtbl;
162 else if (IsEqualIID(riid, &IID_IPersist))
163 *ppv = This;
164 else if (IsEqualIID(riid, &IID_IMediaFilter))
165 *ppv = This;
166 else if (IsEqualIID(riid, &IID_IBaseFilter))
167 *ppv = This;
168 else if (IsEqualIID(riid, &IID_IMediaSeeking))
169 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
171 if (*ppv)
173 IUnknown_AddRef((IUnknown *)(*ppv));
174 return S_OK;
177 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
178 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
180 return E_NOINTERFACE;
183 static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface)
185 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
186 ULONG refCount = InterlockedIncrement(&This->refCount);
188 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
190 return refCount;
193 static ULONG WINAPI NullRendererInner_Release(IUnknown * iface)
195 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
196 ULONG refCount = InterlockedDecrement(&This->refCount);
198 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
200 if (!refCount)
202 IPin *pConnectedTo;
204 if (This->pClock)
205 IReferenceClock_Release(This->pClock);
207 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
209 IPin_Disconnect(pConnectedTo);
210 IPin_Release(pConnectedTo);
212 IPin_Disconnect((IPin *)This->pInputPin);
213 IPin_Release((IPin *)This->pInputPin);
215 This->lpVtbl = NULL;
216 if (This->seekthru_unk)
217 IUnknown_Release(This->seekthru_unk);
219 This->csFilter.DebugInfo->Spare[0] = 0;
220 DeleteCriticalSection(&This->csFilter);
222 TRACE("Destroying Null Renderer\n");
223 CoTaskMemFree(This);
224 return 0;
226 else
227 return refCount;
230 static const IUnknownVtbl IInner_VTable =
232 NullRendererInner_QueryInterface,
233 NullRendererInner_AddRef,
234 NullRendererInner_Release
237 static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
239 NullRendererImpl *This = (NullRendererImpl *)iface;
241 if (This->bAggregatable)
242 This->bUnkOuterValid = TRUE;
244 if (This->pUnkOuter)
246 if (This->bAggregatable)
247 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
249 if (IsEqualIID(riid, &IID_IUnknown))
251 HRESULT hr;
253 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
254 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
255 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
256 This->bAggregatable = TRUE;
257 return hr;
260 *ppv = NULL;
261 return E_NOINTERFACE;
264 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
267 static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
269 NullRendererImpl *This = (NullRendererImpl *)iface;
271 if (This->pUnkOuter && This->bUnkOuterValid)
272 return IUnknown_AddRef(This->pUnkOuter);
273 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
276 static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface)
278 NullRendererImpl *This = (NullRendererImpl *)iface;
280 if (This->pUnkOuter && This->bUnkOuterValid)
281 return IUnknown_Release(This->pUnkOuter);
282 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
285 /** IPersist methods **/
287 static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
289 NullRendererImpl *This = (NullRendererImpl *)iface;
291 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
293 *pClsid = CLSID_NullRenderer;
295 return S_OK;
298 /** IMediaFilter methods **/
300 static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
302 NullRendererImpl *This = (NullRendererImpl *)iface;
304 TRACE("(%p/%p)->()\n", This, iface);
306 EnterCriticalSection(&This->csFilter);
308 This->state = State_Stopped;
309 MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk);
311 LeaveCriticalSection(&This->csFilter);
313 return S_OK;
316 static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
318 NullRendererImpl *This = (NullRendererImpl *)iface;
320 TRACE("(%p/%p)->()\n", This, iface);
322 EnterCriticalSection(&This->csFilter);
324 if (This->state == State_Stopped)
325 This->pInputPin->end_of_stream = 0;
326 This->state = State_Paused;
328 LeaveCriticalSection(&This->csFilter);
330 return S_OK;
333 static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
335 NullRendererImpl *This = (NullRendererImpl *)iface;
337 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
339 EnterCriticalSection(&This->csFilter);
341 This->rtStreamStart = tStart;
342 This->state = State_Running;
343 This->pInputPin->end_of_stream = 0;
345 LeaveCriticalSection(&This->csFilter);
347 return S_OK;
350 static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
352 NullRendererImpl *This = (NullRendererImpl *)iface;
354 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
356 EnterCriticalSection(&This->csFilter);
358 *pState = This->state;
360 LeaveCriticalSection(&This->csFilter);
362 return S_OK;
365 static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
367 NullRendererImpl *This = (NullRendererImpl *)iface;
369 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
371 EnterCriticalSection(&This->csFilter);
373 if (This->pClock)
374 IReferenceClock_Release(This->pClock);
375 This->pClock = pClock;
376 if (This->pClock)
377 IReferenceClock_AddRef(This->pClock);
379 LeaveCriticalSection(&This->csFilter);
381 return S_OK;
384 static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
386 NullRendererImpl *This = (NullRendererImpl *)iface;
388 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
390 EnterCriticalSection(&This->csFilter);
392 *ppClock = This->pClock;
393 if (This->pClock)
394 IReferenceClock_AddRef(This->pClock);
396 LeaveCriticalSection(&This->csFilter);
398 return S_OK;
401 /** IBaseFilter implementation **/
403 static IPin* WINAPI NullRenderer_GetPin(IBaseFilter *iface, int pos)
405 NullRendererImpl *This = (NullRendererImpl *)iface;
407 if (pos >= 1 || pos < 0)
408 return NULL;
410 IPin_AddRef((IPin *)This->pInputPin);
411 return (IPin *)This->pInputPin;
414 static LONG WINAPI NullRenderer_GetPinCount(IBaseFilter *iface)
416 return 1;
419 static LONG WINAPI NullRenderer_GetPinVersion(IBaseFilter *iface)
421 /* Our pins are static, not changing so setting static tick count is ok */
422 return 0;
425 static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
427 NullRendererImpl *This = (NullRendererImpl *)iface;
429 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
431 return EnumPins_Construct(iface, NullRenderer_GetPin, NullRenderer_GetPinCount, NullRenderer_GetPinVersion, ppEnum);
434 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
436 NullRendererImpl *This = (NullRendererImpl *)iface;
438 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
440 if (!Id || !ppPin)
441 return E_POINTER;
443 if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName))
445 *ppPin = (IPin *)This->pInputPin;
446 IPin_AddRef(*ppPin);
447 return S_OK;
449 *ppPin = NULL;
450 return VFW_E_NOT_FOUND;
453 static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
455 NullRendererImpl *This = (NullRendererImpl *)iface;
457 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
459 strcpyW(pInfo->achName, This->filterInfo.achName);
460 pInfo->pGraph = This->filterInfo.pGraph;
462 if (pInfo->pGraph)
463 IFilterGraph_AddRef(pInfo->pGraph);
465 return S_OK;
468 static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
470 NullRendererImpl *This = (NullRendererImpl *)iface;
472 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
474 EnterCriticalSection(&This->csFilter);
476 if (pName)
477 strcpyW(This->filterInfo.achName, pName);
478 else
479 *This->filterInfo.achName = '\0';
480 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
482 LeaveCriticalSection(&This->csFilter);
484 return S_OK;
487 static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
489 NullRendererImpl *This = (NullRendererImpl *)iface;
490 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
491 return E_NOTIMPL;
494 static const IBaseFilterVtbl NullRenderer_Vtbl =
496 NullRenderer_QueryInterface,
497 NullRenderer_AddRef,
498 NullRenderer_Release,
499 NullRenderer_GetClassID,
500 NullRenderer_Stop,
501 NullRenderer_Pause,
502 NullRenderer_Run,
503 NullRenderer_GetState,
504 NullRenderer_SetSyncSource,
505 NullRenderer_GetSyncSource,
506 NullRenderer_EnumPins,
507 NullRenderer_FindPin,
508 NullRenderer_QueryFilterInfo,
509 NullRenderer_JoinFilterGraph,
510 NullRenderer_QueryVendorInfo
513 static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
515 BaseInputPin* This = (BaseInputPin*)iface;
516 IMediaEventSink* pEventSink;
517 NullRendererImpl *pNull;
518 IFilterGraph *graph;
519 HRESULT hr = S_OK;
521 TRACE("(%p/%p)->()\n", This, iface);
523 BaseInputPinImpl_EndOfStream(iface);
524 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
525 graph = pNull->filterInfo.pGraph;
526 if (graph)
528 hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
529 if (SUCCEEDED(hr))
531 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
532 IMediaEventSink_Release(pEventSink);
535 MediaSeekingPassThru_EOS(pNull->seekthru_unk);
537 return hr;
540 static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
542 BaseInputPin* This = (BaseInputPin*)iface;
543 NullRendererImpl *pNull;
544 HRESULT hr = S_OK;
546 TRACE("(%p/%p)->()\n", This, iface);
548 hr = BaseInputPinImpl_EndOfStream(iface);
549 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
550 MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk);
551 return hr;
554 static const IPinVtbl NullRenderer_InputPin_Vtbl =
556 BaseInputPinImpl_QueryInterface,
557 BasePinImpl_AddRef,
558 BaseInputPinImpl_Release,
559 BaseInputPinImpl_Connect,
560 BaseInputPinImpl_ReceiveConnection,
561 BasePinImpl_Disconnect,
562 BasePinImpl_ConnectedTo,
563 BasePinImpl_ConnectionMediaType,
564 BasePinImpl_QueryPinInfo,
565 BasePinImpl_QueryDirection,
566 BasePinImpl_QueryId,
567 BaseInputPinImpl_QueryAccept,
568 BasePinImpl_EnumMediaTypes,
569 BasePinImpl_QueryInternalConnections,
570 NullRenderer_InputPin_EndOfStream,
571 BaseInputPinImpl_BeginFlush,
572 NullRenderer_InputPin_EndFlush,
573 BaseInputPinImpl_NewSegment