qcap: Implement a stubbed SmartTee filter.
[wine/multimedia.git] / dlls / qcap / smartteefilter.c
blobbf68398f0fd2515942fef7e20a39ccfbe477f287
1 /*
2 * Implementation of the SmartTee filter
4 * Copyright 2015 Damjan Jovanovic
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wtypes.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "dshow.h"
32 #include "qcap_main.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
38 typedef struct {
39 IUnknown IUnknown_iface;
40 IUnknown *outerUnknown;
41 BaseFilter filter;
42 BaseInputPin *input;
43 BaseOutputPin *capture;
44 BaseOutputPin *preview;
45 } SmartTeeFilter;
47 static inline SmartTeeFilter *impl_from_IUnknown(IUnknown *iface)
49 return CONTAINING_RECORD(iface, SmartTeeFilter, IUnknown_iface);
52 static inline SmartTeeFilter *impl_from_BaseFilter(BaseFilter *filter)
54 return CONTAINING_RECORD(filter, SmartTeeFilter, filter);
57 static inline SmartTeeFilter *impl_from_IBaseFilter(IBaseFilter *iface)
59 BaseFilter *filter = CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface);
60 return impl_from_BaseFilter(filter);
63 static inline SmartTeeFilter *impl_from_BasePin(BasePin *pin)
65 return impl_from_IBaseFilter(pin->pinInfo.pFilter);
68 static inline SmartTeeFilter *impl_from_IPin(IPin *iface)
70 BasePin *bp = CONTAINING_RECORD(iface, BasePin, IPin_iface);
71 return impl_from_IBaseFilter(bp->pinInfo.pFilter);
74 static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
76 SmartTeeFilter *This = impl_from_IUnknown(iface);
77 if (IsEqualIID(riid, &IID_IUnknown)) {
78 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
79 *ppv = &This->IUnknown_iface;
80 } else if (IsEqualIID(riid, &IID_IPersist)) {
81 TRACE("(%p)->(IID_IPersist, %p)\n", This, ppv);
82 *ppv = &This->filter.IBaseFilter_iface;
83 } else if (IsEqualIID(riid, &IID_IMediaFilter)) {
84 TRACE("(%p)->(IID_IMediaFilter, %p)\n", This, ppv);
85 *ppv = &This->filter.IBaseFilter_iface;
86 } else if (IsEqualIID(riid, &IID_IBaseFilter)) {
87 TRACE("(%p)->(IID_IBaseFilter, %p)\n", This, ppv);
88 *ppv = &This->filter.IBaseFilter_iface;
89 } else {
90 FIXME("(%p): no interface for %s\n", This, debugstr_guid(riid));
91 *ppv = NULL;
92 return E_NOINTERFACE;
94 IUnknown_AddRef((IUnknown*)*ppv);
95 return S_OK;
98 static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
100 SmartTeeFilter *This = impl_from_IUnknown(iface);
101 return BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);
104 static ULONG WINAPI Unknown_Release(IUnknown *iface)
106 SmartTeeFilter *This = impl_from_IUnknown(iface);
107 ULONG ref = BaseFilterImpl_Release(&This->filter.IBaseFilter_iface);
109 TRACE("(%p)->() ref=%d\n", This, ref);
111 if (!ref) {
112 if(This->input)
113 BaseInputPinImpl_Release(&This->input->pin.IPin_iface);
114 if(This->capture)
115 BaseOutputPinImpl_Release(&This->capture->pin.IPin_iface);
116 if(This->preview)
117 BaseOutputPinImpl_Release(&This->preview->pin.IPin_iface);
118 CoTaskMemFree(This);
120 return ref;
123 static const IUnknownVtbl UnknownVtbl = {
124 Unknown_QueryInterface,
125 Unknown_AddRef,
126 Unknown_Release
129 static HRESULT WINAPI SmartTeeFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
131 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
132 return IUnknown_QueryInterface(This->outerUnknown, riid, ppv);
135 static ULONG WINAPI SmartTeeFilter_AddRef(IBaseFilter *iface)
137 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
138 return IUnknown_AddRef(This->outerUnknown);
141 static ULONG WINAPI SmartTeeFilter_Release(IBaseFilter *iface)
143 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
144 return IUnknown_Release(This->outerUnknown);
147 static HRESULT WINAPI SmartTeeFilter_Stop(IBaseFilter *iface)
149 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
150 FIXME("(%p): stub\n", This);
151 return E_NOTIMPL;
154 static HRESULT WINAPI SmartTeeFilter_Pause(IBaseFilter *iface)
156 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
157 FIXME("(%p): stub\n", This);
158 return E_NOTIMPL;
161 static HRESULT WINAPI SmartTeeFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
163 FIXME("(%p, %x%08x): stub\n", iface, (ULONG)(tStart >> 32), (ULONG)tStart);
164 return E_NOTIMPL;
167 static HRESULT WINAPI SmartTeeFilter_FindPin(IBaseFilter *iface, LPCWSTR Id, IPin **ppPin)
169 SmartTeeFilter *This = impl_from_IBaseFilter(iface);
170 FIXME("(%p)->(%s, %p): stub\n", This, debugstr_w(Id), ppPin);
171 return VFW_E_NOT_FOUND;
174 static const IBaseFilterVtbl SmartTeeFilterVtbl = {
175 SmartTeeFilter_QueryInterface,
176 SmartTeeFilter_AddRef,
177 SmartTeeFilter_Release,
178 BaseFilterImpl_GetClassID,
179 SmartTeeFilter_Stop,
180 SmartTeeFilter_Pause,
181 SmartTeeFilter_Run,
182 BaseFilterImpl_GetState,
183 BaseFilterImpl_SetSyncSource,
184 BaseFilterImpl_GetSyncSource,
185 BaseFilterImpl_EnumPins,
186 SmartTeeFilter_FindPin,
187 BaseFilterImpl_QueryFilterInfo,
188 BaseFilterImpl_JoinFilterGraph,
189 BaseFilterImpl_QueryVendorInfo
192 static IPin* WINAPI SmartTeeFilter_GetPin(BaseFilter *iface, int pos)
194 SmartTeeFilter *This = impl_from_BaseFilter(iface);
195 IPin *ret;
197 TRACE("(%p)->(%d)\n", This, pos);
199 switch(pos) {
200 case 0:
201 ret = &This->input->pin.IPin_iface;
202 break;
203 case 1:
204 ret = &This->capture->pin.IPin_iface;
205 break;
206 case 2:
207 ret = &This->preview->pin.IPin_iface;
208 break;
209 default:
210 TRACE("No pin %d\n", pos);
211 return NULL;
214 IPin_AddRef(ret);
215 return ret;
218 static LONG WINAPI SmartTeeFilter_GetPinCount(BaseFilter *iface)
220 return 3;
222 static const BaseFilterFuncTable SmartTeeFilterFuncs = {
223 SmartTeeFilter_GetPin,
224 SmartTeeFilter_GetPinCount
227 static ULONG WINAPI SmartTeeFilterInput_AddRef(IPin *iface)
229 SmartTeeFilter *This = impl_from_IPin(iface);
230 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
233 static ULONG WINAPI SmartTeeFilterInput_Release(IPin *iface)
235 SmartTeeFilter *This = impl_from_IPin(iface);
236 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
240 static const IPinVtbl SmartTeeFilterInputVtbl = {
241 BaseInputPinImpl_QueryInterface,
242 SmartTeeFilterInput_AddRef,
243 SmartTeeFilterInput_Release,
244 BaseInputPinImpl_Connect,
245 BaseInputPinImpl_ReceiveConnection,
246 BasePinImpl_Disconnect,
247 BasePinImpl_ConnectedTo,
248 BasePinImpl_ConnectionMediaType,
249 BasePinImpl_QueryPinInfo,
250 BasePinImpl_QueryDirection,
251 BasePinImpl_QueryId,
252 BasePinImpl_QueryAccept,
253 BasePinImpl_EnumMediaTypes,
254 BasePinImpl_QueryInternalConnections,
255 BaseInputPinImpl_EndOfStream,
256 BaseInputPinImpl_BeginFlush,
257 BaseInputPinImpl_EndFlush,
258 BaseInputPinImpl_NewSegment
261 static HRESULT WINAPI SmartTeeFilterInput_CheckMediaType(BasePin *base, const AM_MEDIA_TYPE *pmt)
263 SmartTeeFilter *This = impl_from_BasePin(base);
264 FIXME("(%p, AM_MEDIA_TYPE(%p)): stub\n", This, pmt);
265 dump_AM_MEDIA_TYPE(pmt);
266 return E_NOTIMPL;
269 static LONG WINAPI SmartTeeFilterInput_GetMediaTypeVersion(BasePin *base)
271 return 0;
274 static HRESULT WINAPI SmartTeeFilterInput_GetMediaType(BasePin *base, int iPosition, AM_MEDIA_TYPE *amt)
276 SmartTeeFilter *This = impl_from_BasePin(base);
277 FIXME("(%p)->(%d, %p): stub\n", This, iPosition, amt);
278 return S_FALSE;
281 static HRESULT WINAPI SmartTeeFilterInput_Receive(BaseInputPin *base, IMediaSample *pSample)
283 SmartTeeFilter *This = impl_from_BasePin(&base->pin);
284 FIXME("(%p)->(%p): stub\n", This, pSample);
285 return E_NOTIMPL;
288 static const BaseInputPinFuncTable SmartTeeFilterInputFuncs = {
290 SmartTeeFilterInput_CheckMediaType,
291 NULL,
292 SmartTeeFilterInput_GetMediaTypeVersion,
293 SmartTeeFilterInput_GetMediaType
295 SmartTeeFilterInput_Receive
298 static ULONG WINAPI SmartTeeFilterCapture_AddRef(IPin *iface)
300 SmartTeeFilter *This = impl_from_IPin(iface);
301 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
304 static ULONG WINAPI SmartTeeFilterCapture_Release(IPin *iface)
306 SmartTeeFilter *This = impl_from_IPin(iface);
307 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
310 static const IPinVtbl SmartTeeFilterCaptureVtbl = {
311 BaseOutputPinImpl_QueryInterface,
312 SmartTeeFilterCapture_AddRef,
313 SmartTeeFilterCapture_Release,
314 BaseOutputPinImpl_Connect,
315 BaseOutputPinImpl_ReceiveConnection,
316 BaseOutputPinImpl_Disconnect,
317 BasePinImpl_ConnectedTo,
318 BasePinImpl_ConnectionMediaType,
319 BasePinImpl_QueryPinInfo,
320 BasePinImpl_QueryDirection,
321 BasePinImpl_QueryId,
322 BasePinImpl_QueryAccept,
323 BasePinImpl_EnumMediaTypes,
324 BasePinImpl_QueryInternalConnections,
325 BaseOutputPinImpl_EndOfStream,
326 BaseOutputPinImpl_BeginFlush,
327 BaseOutputPinImpl_EndFlush,
328 BasePinImpl_NewSegment
331 static LONG WINAPI SmartTeeFilterCapture_GetMediaTypeVersion(BasePin *base)
333 SmartTeeFilter *This = impl_from_BasePin(base);
334 TRACE("(%p)\n", This);
335 return 0;
338 static HRESULT WINAPI SmartTeeFilterCapture_GetMediaType(BasePin *base, int iPosition, AM_MEDIA_TYPE *amt)
340 SmartTeeFilter *This = impl_from_BasePin(base);
341 FIXME("(%p, %d, %p): stub\n", This, iPosition, amt);
342 return E_NOTIMPL;
345 static HRESULT WINAPI SmartTeeFilterCapture_DecideBufferSize(BaseOutputPin *base, IMemAllocator *alloc,
346 ALLOCATOR_PROPERTIES *ppropInputRequest)
348 SmartTeeFilter *This = impl_from_BasePin(&base->pin);
349 FIXME("(%p, %p, %p): stub\n", This, alloc, ppropInputRequest);
350 return E_NOTIMPL;
353 static HRESULT WINAPI SmartTeeFilterCapture_BreakConnect(BaseOutputPin *base)
355 SmartTeeFilter *This = impl_from_BasePin(&base->pin);
356 FIXME("(%p): stub\n", This);
357 return E_NOTIMPL;
360 static const BaseOutputPinFuncTable SmartTeeFilterCaptureFuncs = {
362 NULL,
363 BaseOutputPinImpl_AttemptConnection,
364 SmartTeeFilterCapture_GetMediaTypeVersion,
365 SmartTeeFilterCapture_GetMediaType
367 SmartTeeFilterCapture_DecideBufferSize,
368 BaseOutputPinImpl_DecideAllocator,
369 SmartTeeFilterCapture_BreakConnect
372 static ULONG WINAPI SmartTeeFilterPreview_AddRef(IPin *iface)
374 SmartTeeFilter *This = impl_from_IPin(iface);
375 return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
378 static ULONG WINAPI SmartTeeFilterPreview_Release(IPin *iface)
380 SmartTeeFilter *This = impl_from_IPin(iface);
381 return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
384 static const IPinVtbl SmartTeeFilterPreviewVtbl = {
385 BaseOutputPinImpl_QueryInterface,
386 SmartTeeFilterPreview_AddRef,
387 SmartTeeFilterPreview_Release,
388 BaseOutputPinImpl_Connect,
389 BaseOutputPinImpl_ReceiveConnection,
390 BaseOutputPinImpl_Disconnect,
391 BasePinImpl_ConnectedTo,
392 BasePinImpl_ConnectionMediaType,
393 BasePinImpl_QueryPinInfo,
394 BasePinImpl_QueryDirection,
395 BasePinImpl_QueryId,
396 BasePinImpl_QueryAccept,
397 BasePinImpl_EnumMediaTypes,
398 BasePinImpl_QueryInternalConnections,
399 BaseOutputPinImpl_EndOfStream,
400 BaseOutputPinImpl_BeginFlush,
401 BaseOutputPinImpl_EndFlush,
402 BasePinImpl_NewSegment
405 static LONG WINAPI SmartTeeFilterPreview_GetMediaTypeVersion(BasePin *base)
407 SmartTeeFilter *This = impl_from_BasePin(base);
408 TRACE("(%p)\n", This);
409 return 0;
412 static HRESULT WINAPI SmartTeeFilterPreview_GetMediaType(BasePin *base, int iPosition, AM_MEDIA_TYPE *amt)
414 SmartTeeFilter *This = impl_from_BasePin(base);
415 FIXME("(%p, %d, %p): stub\n", This, iPosition, amt);
416 return E_NOTIMPL;
419 static HRESULT WINAPI SmartTeeFilterPreview_DecideBufferSize(BaseOutputPin *base, IMemAllocator *alloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
421 SmartTeeFilter *This = impl_from_BasePin(&base->pin);
422 FIXME("(%p, %p, %p): stub\n", This, alloc, ppropInputRequest);
423 return E_NOTIMPL;
426 static HRESULT WINAPI SmartTeeFilterPreview_BreakConnect(BaseOutputPin *base)
428 SmartTeeFilter *This = impl_from_BasePin(&base->pin);
429 FIXME("(%p): stub\n", This);
430 return E_NOTIMPL;
433 static const BaseOutputPinFuncTable SmartTeeFilterPreviewFuncs = {
435 NULL,
436 BaseOutputPinImpl_AttemptConnection,
437 SmartTeeFilterPreview_GetMediaTypeVersion,
438 SmartTeeFilterPreview_GetMediaType
440 SmartTeeFilterPreview_DecideBufferSize,
441 BaseOutputPinImpl_DecideAllocator,
442 SmartTeeFilterPreview_BreakConnect
444 IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
446 PIN_INFO inputPinInfo = {NULL, PINDIR_INPUT, {'I','n','p','u','t',0}};
447 PIN_INFO capturePinInfo = {NULL, PINDIR_OUTPUT, {'C','a','p','t','u','r','e',0}};
448 PIN_INFO previewPinInfo = {NULL, PINDIR_OUTPUT, {'P','r','e','v','i','e','w',0}};
449 HRESULT hr;
450 SmartTeeFilter *This = NULL;
452 TRACE("(%p, %p)\n", outer, phr);
454 This = CoTaskMemAlloc(sizeof(*This));
455 if (This == NULL) {
456 hr = E_OUTOFMEMORY;
457 goto end;
459 memset(This, 0, sizeof(*This));
460 This->IUnknown_iface.lpVtbl = &UnknownVtbl;
461 if (outer)
462 This->outerUnknown = outer;
463 else
464 This->outerUnknown = &This->IUnknown_iface;
466 BaseFilter_Init(&This->filter, &SmartTeeFilterVtbl, &CLSID_SmartTee,
467 (DWORD_PTR)(__FILE__ ": SmartTeeFilter.csFilter"), &SmartTeeFilterFuncs);
469 inputPinInfo.pFilter = &This->filter.IBaseFilter_iface;
470 hr = BaseInputPin_Construct(&SmartTeeFilterInputVtbl, sizeof(BaseInputPin), &inputPinInfo,
471 &SmartTeeFilterInputFuncs, &This->filter.csFilter, NULL, (IPin**)&This->input);
472 if (FAILED(hr))
473 goto end;
475 capturePinInfo.pFilter = &This->filter.IBaseFilter_iface;
476 hr = BaseOutputPin_Construct(&SmartTeeFilterCaptureVtbl, sizeof(BaseOutputPin), &capturePinInfo,
477 &SmartTeeFilterCaptureFuncs, &This->filter.csFilter, (IPin**)&This->capture);
478 if (FAILED(hr))
479 goto end;
481 previewPinInfo.pFilter = &This->filter.IBaseFilter_iface;
482 hr = BaseOutputPin_Construct(&SmartTeeFilterPreviewVtbl, sizeof(BaseOutputPin), &previewPinInfo,
483 &SmartTeeFilterPreviewFuncs, &This->filter.csFilter, (IPin**)&This->preview);
485 end:
486 *phr = hr;
487 if (SUCCEEDED(hr)) {
488 if (outer)
489 return &This->IUnknown_iface;
490 else
491 return (IUnknown*)&This->filter.IBaseFilter_iface;
492 } else {
493 if (This)
494 IBaseFilter_Release(&This->filter.IBaseFilter_iface);
495 return NULL;