push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / quartz / nullrenderer.c
blobd871e679db73e8ab75e14793d544f03911a4a528
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};
47 static const IBaseFilterVtbl NullRenderer_Vtbl;
48 static const IUnknownVtbl IInner_VTable;
49 static const IPinVtbl NullRenderer_InputPin_Vtbl;
51 typedef struct NullRendererImpl
53 const IBaseFilterVtbl * lpVtbl;
54 const IUnknownVtbl * IInner_vtbl;
56 LONG refCount;
57 CRITICAL_SECTION csFilter;
58 FILTER_STATE state;
59 REFERENCE_TIME rtStreamStart;
60 IReferenceClock * pClock;
61 FILTER_INFO filterInfo;
63 InputPin *pInputPin;
64 IPin ** ppPins;
65 IUnknown * pUnkOuter;
66 BOOL bUnkOuterValid;
67 BOOL bAggregatable;
68 MediaSeekingImpl mediaSeeking;
69 } NullRendererImpl;
71 static const IMemInputPinVtbl MemInputPin_Vtbl =
73 MemInputPin_QueryInterface,
74 MemInputPin_AddRef,
75 MemInputPin_Release,
76 MemInputPin_GetAllocator,
77 MemInputPin_NotifyAllocator,
78 MemInputPin_GetAllocatorRequirements,
79 MemInputPin_Receive,
80 MemInputPin_ReceiveMultiple,
81 MemInputPin_ReceiveCanBlock
84 static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
86 LPBYTE pbSrcStream = NULL;
87 long cbSrcStream = 0;
88 REFERENCE_TIME tStart, tStop;
89 HRESULT hr;
91 TRACE("%p %p\n", iface, pSample);
93 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
94 if (FAILED(hr))
96 ERR("Cannot get pointer to sample data (%x)\n", hr);
97 return hr;
100 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
101 if (FAILED(hr))
102 ERR("Cannot get sample time (%x)\n", hr);
104 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
106 TRACE("val %p %ld\n", pbSrcStream, cbSrcStream);
108 return S_OK;
111 static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
113 TRACE("Not a stub!\n");
114 return S_OK;
117 static inline NullRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
119 return (NullRendererImpl *)((char*)iface - FIELD_OFFSET(NullRendererImpl, mediaSeeking.lpVtbl));
122 static HRESULT WINAPI NullRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
124 NullRendererImpl *This = impl_from_IMediaSeeking(iface);
126 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
129 static ULONG WINAPI NullRendererImpl_Seeking_AddRef(IMediaSeeking * iface)
131 NullRendererImpl *This = impl_from_IMediaSeeking(iface);
133 return IUnknown_AddRef((IUnknown *)This);
136 static ULONG WINAPI NullRendererImpl_Seeking_Release(IMediaSeeking * iface)
138 NullRendererImpl *This = impl_from_IMediaSeeking(iface);
140 return IUnknown_Release((IUnknown *)This);
143 static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl =
145 NullRendererImpl_Seeking_QueryInterface,
146 NullRendererImpl_Seeking_AddRef,
147 NullRendererImpl_Seeking_Release,
148 MediaSeekingImpl_GetCapabilities,
149 MediaSeekingImpl_CheckCapabilities,
150 MediaSeekingImpl_IsFormatSupported,
151 MediaSeekingImpl_QueryPreferredFormat,
152 MediaSeekingImpl_GetTimeFormat,
153 MediaSeekingImpl_IsUsingTimeFormat,
154 MediaSeekingImpl_SetTimeFormat,
155 MediaSeekingImpl_GetDuration,
156 MediaSeekingImpl_GetStopPosition,
157 MediaSeekingImpl_GetCurrentPosition,
158 MediaSeekingImpl_ConvertTimeFormat,
159 MediaSeekingImpl_SetPositions,
160 MediaSeekingImpl_GetPositions,
161 MediaSeekingImpl_GetAvailable,
162 MediaSeekingImpl_SetRate,
163 MediaSeekingImpl_GetRate,
164 MediaSeekingImpl_GetPreroll
167 static HRESULT NullRendererImpl_Change(IBaseFilter *iface)
169 TRACE("(%p)\n", iface);
170 return S_OK;
173 HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
175 HRESULT hr;
176 PIN_INFO piInput;
177 NullRendererImpl * pNullRenderer;
179 TRACE("(%p, %p)\n", pUnkOuter, ppv);
181 *ppv = NULL;
183 pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
184 pNullRenderer->pUnkOuter = pUnkOuter;
185 pNullRenderer->bUnkOuterValid = FALSE;
186 pNullRenderer->bAggregatable = FALSE;
187 pNullRenderer->IInner_vtbl = &IInner_VTable;
189 pNullRenderer->lpVtbl = &NullRenderer_Vtbl;
190 pNullRenderer->refCount = 1;
191 InitializeCriticalSection(&pNullRenderer->csFilter);
192 pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter");
193 pNullRenderer->state = State_Stopped;
194 pNullRenderer->pClock = NULL;
195 ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO));
197 pNullRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
199 /* construct input pin */
200 piInput.dir = PINDIR_INPUT;
201 piInput.pFilter = (IBaseFilter *)pNullRenderer;
202 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
204 hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, (IPin **)&pNullRenderer->pInputPin);
206 if (SUCCEEDED(hr))
208 pNullRenderer->ppPins[0] = (IPin *)pNullRenderer->pInputPin;
209 MediaSeekingImpl_Init((IBaseFilter*)pNullRenderer, NullRendererImpl_Change, NullRendererImpl_Change, NullRendererImpl_Change, &pNullRenderer->mediaSeeking, &pNullRenderer->csFilter);
210 pNullRenderer->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl;
212 *ppv = (LPVOID)pNullRenderer;
214 else
216 CoTaskMemFree(pNullRenderer->ppPins);
217 pNullRenderer->csFilter.DebugInfo->Spare[0] = 0;
218 DeleteCriticalSection(&pNullRenderer->csFilter);
219 CoTaskMemFree(pNullRenderer);
222 return hr;
225 static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
227 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
228 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
230 if (This->bAggregatable)
231 This->bUnkOuterValid = TRUE;
233 *ppv = NULL;
235 if (IsEqualIID(riid, &IID_IUnknown))
236 *ppv = (LPVOID)&(This->IInner_vtbl);
237 else if (IsEqualIID(riid, &IID_IPersist))
238 *ppv = (LPVOID)This;
239 else if (IsEqualIID(riid, &IID_IMediaFilter))
240 *ppv = (LPVOID)This;
241 else if (IsEqualIID(riid, &IID_IBaseFilter))
242 *ppv = (LPVOID)This;
243 else if (IsEqualIID(riid, &IID_IMediaSeeking))
244 *ppv = &This->mediaSeeking;
246 if (*ppv)
248 IUnknown_AddRef((IUnknown *)(*ppv));
249 return S_OK;
252 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
253 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
255 return E_NOINTERFACE;
258 static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface)
260 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
261 ULONG refCount = InterlockedIncrement(&This->refCount);
263 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
265 return refCount;
268 static ULONG WINAPI NullRendererInner_Release(IUnknown * iface)
270 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
271 ULONG refCount = InterlockedDecrement(&This->refCount);
273 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
275 if (!refCount)
277 IPin *pConnectedTo;
279 if (This->pClock)
280 IReferenceClock_Release(This->pClock);
282 if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
284 IPin_Disconnect(pConnectedTo);
285 IPin_Release(pConnectedTo);
287 IPin_Disconnect(This->ppPins[0]);
288 IPin_Release(This->ppPins[0]);
290 CoTaskMemFree(This->ppPins);
291 This->lpVtbl = NULL;
293 This->csFilter.DebugInfo->Spare[0] = 0;
294 DeleteCriticalSection(&This->csFilter);
296 TRACE("Destroying Null Renderer\n");
297 CoTaskMemFree(This);
298 return 0;
300 else
301 return refCount;
304 static const IUnknownVtbl IInner_VTable =
306 NullRendererInner_QueryInterface,
307 NullRendererInner_AddRef,
308 NullRendererInner_Release
311 static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
313 NullRendererImpl *This = (NullRendererImpl *)iface;
315 if (This->bAggregatable)
316 This->bUnkOuterValid = TRUE;
318 if (This->pUnkOuter)
320 if (This->bAggregatable)
321 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
323 if (IsEqualIID(riid, &IID_IUnknown))
325 HRESULT hr;
327 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
328 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
329 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
330 This->bAggregatable = TRUE;
331 return hr;
334 *ppv = NULL;
335 return E_NOINTERFACE;
338 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
341 static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
343 NullRendererImpl *This = (NullRendererImpl *)iface;
345 if (This->pUnkOuter && This->bUnkOuterValid)
346 return IUnknown_AddRef(This->pUnkOuter);
347 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
350 static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface)
352 NullRendererImpl *This = (NullRendererImpl *)iface;
354 if (This->pUnkOuter && This->bUnkOuterValid)
355 return IUnknown_Release(This->pUnkOuter);
356 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
359 /** IPersist methods **/
361 static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
363 NullRendererImpl *This = (NullRendererImpl *)iface;
365 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
367 *pClsid = CLSID_NullRenderer;
369 return S_OK;
372 /** IMediaFilter methods **/
374 static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
376 NullRendererImpl *This = (NullRendererImpl *)iface;
378 TRACE("(%p/%p)->()\n", This, iface);
380 EnterCriticalSection(&This->csFilter);
382 This->state = State_Stopped;
384 LeaveCriticalSection(&This->csFilter);
386 return S_OK;
389 static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
391 NullRendererImpl *This = (NullRendererImpl *)iface;
393 TRACE("(%p/%p)->()\n", This, iface);
395 EnterCriticalSection(&This->csFilter);
397 if (This->state == State_Stopped)
398 This->pInputPin->end_of_stream = 0;
399 This->state = State_Paused;
401 LeaveCriticalSection(&This->csFilter);
403 return S_OK;
406 static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
408 NullRendererImpl *This = (NullRendererImpl *)iface;
410 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
412 EnterCriticalSection(&This->csFilter);
414 This->rtStreamStart = tStart;
415 This->state = State_Running;
416 This->pInputPin->end_of_stream = 0;
418 LeaveCriticalSection(&This->csFilter);
420 return S_OK;
423 static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
425 NullRendererImpl *This = (NullRendererImpl *)iface;
427 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
429 EnterCriticalSection(&This->csFilter);
431 *pState = This->state;
433 LeaveCriticalSection(&This->csFilter);
435 return S_OK;
438 static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
440 NullRendererImpl *This = (NullRendererImpl *)iface;
442 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
444 EnterCriticalSection(&This->csFilter);
446 if (This->pClock)
447 IReferenceClock_Release(This->pClock);
448 This->pClock = pClock;
449 if (This->pClock)
450 IReferenceClock_AddRef(This->pClock);
452 LeaveCriticalSection(&This->csFilter);
454 return S_OK;
457 static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
459 NullRendererImpl *This = (NullRendererImpl *)iface;
461 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
463 EnterCriticalSection(&This->csFilter);
465 *ppClock = This->pClock;
466 IReferenceClock_AddRef(This->pClock);
468 LeaveCriticalSection(&This->csFilter);
470 return S_OK;
473 /** IBaseFilter implementation **/
475 static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
477 ENUMPINDETAILS epd;
478 NullRendererImpl *This = (NullRendererImpl *)iface;
480 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
482 epd.cPins = 1; /* input pin */
483 epd.ppPins = This->ppPins;
484 return IEnumPinsImpl_Construct(&epd, ppEnum);
487 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
489 NullRendererImpl *This = (NullRendererImpl *)iface;
491 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
493 FIXME("NullRenderer::FindPin(...)\n");
495 /* FIXME: critical section */
497 return E_NOTIMPL;
500 static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
502 NullRendererImpl *This = (NullRendererImpl *)iface;
504 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
506 strcpyW(pInfo->achName, This->filterInfo.achName);
507 pInfo->pGraph = This->filterInfo.pGraph;
509 if (pInfo->pGraph)
510 IFilterGraph_AddRef(pInfo->pGraph);
512 return S_OK;
515 static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
517 NullRendererImpl *This = (NullRendererImpl *)iface;
519 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
521 EnterCriticalSection(&This->csFilter);
523 if (pName)
524 strcpyW(This->filterInfo.achName, pName);
525 else
526 *This->filterInfo.achName = '\0';
527 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
529 LeaveCriticalSection(&This->csFilter);
531 return S_OK;
534 static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
536 NullRendererImpl *This = (NullRendererImpl *)iface;
537 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
538 return E_NOTIMPL;
541 static const IBaseFilterVtbl NullRenderer_Vtbl =
543 NullRenderer_QueryInterface,
544 NullRenderer_AddRef,
545 NullRenderer_Release,
546 NullRenderer_GetClassID,
547 NullRenderer_Stop,
548 NullRenderer_Pause,
549 NullRenderer_Run,
550 NullRenderer_GetState,
551 NullRenderer_SetSyncSource,
552 NullRenderer_GetSyncSource,
553 NullRenderer_EnumPins,
554 NullRenderer_FindPin,
555 NullRenderer_QueryFilterInfo,
556 NullRenderer_JoinFilterGraph,
557 NullRenderer_QueryVendorInfo
560 static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
562 InputPin* This = (InputPin*)iface;
563 IMediaEventSink* pEventSink;
564 HRESULT hr;
566 TRACE("(%p/%p)->()\n", This, iface);
568 InputPin_EndOfStream(iface);
569 hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
570 if (SUCCEEDED(hr))
572 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
573 IMediaEventSink_Release(pEventSink);
576 return hr;
579 static const IPinVtbl NullRenderer_InputPin_Vtbl =
581 InputPin_QueryInterface,
582 IPinImpl_AddRef,
583 InputPin_Release,
584 InputPin_Connect,
585 InputPin_ReceiveConnection,
586 IPinImpl_Disconnect,
587 IPinImpl_ConnectedTo,
588 IPinImpl_ConnectionMediaType,
589 IPinImpl_QueryPinInfo,
590 IPinImpl_QueryDirection,
591 IPinImpl_QueryId,
592 IPinImpl_QueryAccept,
593 IPinImpl_EnumMediaTypes,
594 IPinImpl_QueryInternalConnections,
595 NullRenderer_InputPin_EndOfStream,
596 InputPin_BeginFlush,
597 InputPin_EndFlush,
598 InputPin_NewSegment