1 /* Capture Graph Builder, Minimal edition
3 * Copyright 2005 Maarten Lankhorst
4 * Copyright 2005 Rolf Kalbermatter
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
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
45 #include "qcap_main.h"
47 #include "wine/unicode.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
52 /***********************************************************************
53 * ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
55 typedef struct CaptureGraphImpl
57 const ICaptureGraphBuilder2Vtbl * lpVtbl2;
58 const ICaptureGraphBuilderVtbl * lpVtbl;
60 IGraphBuilder *mygraph;
62 CRITICAL_SECTION csFilter;
65 static const ICaptureGraphBuilderVtbl builder_Vtbl;
66 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
68 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder( ICaptureGraphBuilder *iface )
70 return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl));
73 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2( ICaptureGraphBuilder2 *iface )
75 return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl2));
79 converts This to an interface pointer
81 #define _IUnknown_(This) (&(This)->lpVtbl2)
82 #define _ICaptureGraphBuilder_(This) (&(This)->lpVtbl)
83 #define _ICaptureGraphBuilder2_(This) ((ICaptureGraphBuilder2*)&(This)->lpVtbl2)
86 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
89 CaptureGraphImpl * pCapture = NULL;
91 TRACE("(%p, %p)\n", pUnkOuter, phr);
93 *phr = CLASS_E_NOAGGREGATION;
100 pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
103 pCapture->lpVtbl2 = &builder2_Vtbl;
104 pCapture->lpVtbl = &builder_Vtbl;
106 pCapture->mygraph = NULL;
107 InitializeCriticalSection(&pCapture->csFilter);
108 pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
110 ObjectRefCount(TRUE);
112 return (IUnknown *)pCapture;
115 static HRESULT WINAPI
116 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
120 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
122 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
125 if (IsEqualIID(riid, &IID_IUnknown))
126 *ppv = _IUnknown_(This);
127 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
128 *ppv = _ICaptureGraphBuilder_(This);
129 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
130 *ppv = _ICaptureGraphBuilder2_(This);
134 IUnknown_AddRef((IUnknown *)(*ppv));
135 TRACE ("-- Interface = %p\n", *ppv);
139 TRACE ("-- Interface: E_NOINTERFACE\n");
140 return E_NOINTERFACE;
144 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
146 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
147 DWORD ref = InterlockedIncrement(&This->ref);
149 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
154 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
156 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
157 DWORD ref = InterlockedDecrement(&This->ref);
159 TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
163 FIXME("Release IGraphFilter or w/e\n");
164 This->csFilter.DebugInfo->Spare[0] = 0;
165 DeleteCriticalSection(&This->csFilter);
167 This->lpVtbl2 = NULL;
168 if (This->mygraph != NULL)
169 IGraphBuilder_Release(This->mygraph);
171 ObjectRefCount(FALSE);
176 static HRESULT WINAPI
177 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
180 /* The graph builder will automatically create a filter graph if you don't call
181 this method. If you call this method after the graph builder has created its
182 own filter graph, the call will fail. */
184 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
186 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
195 IGraphBuilder_AddRef(This->mygraph);
196 if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph,
197 &IID_IMediaEvent, (LPVOID *)&pmev)))
199 IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
200 IMediaEvent_Release(pmev);
205 static HRESULT WINAPI
206 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
209 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
211 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
216 *pfg = This->mygraph;
219 TRACE("(%p) Getting NULL filtergraph\n", iface);
223 IGraphBuilder_AddRef(This->mygraph);
225 TRACE("(%p) return filtergraph %p\n", iface, *pfg);
229 static HRESULT WINAPI
230 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
234 IFileSinkFilter **ppSink)
236 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
238 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
239 debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
244 static HRESULT WINAPI
245 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
246 const GUID *pCategory,
252 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
254 FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
255 debugstr_guid(pCategory), debugstr_guid(pType),
256 pf, debugstr_guid(riid), ppint);
258 return IBaseFilter_QueryInterface(pf, riid, ppint);
259 /* Looks for the specified interface on the filter, upstream and
260 * downstream from the filter, and, optionally, only on the output
261 * pin of the given category.
265 static HRESULT WINAPI
266 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
267 const GUID *pCategory,
270 IBaseFilter *pfCompressor,
271 IBaseFilter *pfRenderer)
273 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
275 IPin *pin_out = NULL;
278 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
279 debugstr_guid(pCategory), debugstr_guid(pType),
280 pSource, pfCompressor, pfRenderer);
283 FIXME("Intermediate streams not supported yet\n");
287 FIXME("Need a capture graph\n");
291 ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
294 ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
297 IPin_Release(pin_in);
301 /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
302 hr = IFilterGraph2_Connect(This->mygraph, pin_in, pin_out);
303 IPin_Release(pin_in);
304 IPin_Release(pin_out);
308 static HRESULT WINAPI
309 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
310 const GUID *pCategory,
312 IBaseFilter *pFilter,
313 REFERENCE_TIME *pstart,
314 REFERENCE_TIME *pstop,
318 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
320 FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
321 debugstr_guid(pCategory), debugstr_guid(pType),
322 pFilter, pstart, pstop, wStartCookie, wStopCookie);
327 static HRESULT WINAPI
328 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
332 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
334 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
335 debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
340 static HRESULT WINAPI
341 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
345 IAMCopyCaptureFileProgress *pCallback)
347 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
349 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
350 debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
351 fAllowEscAbort, pCallback);
356 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
359 PIN_DIRECTION pindir;
361 IPin_QueryDirection(pin, &pindir);
362 if (pindir != direction)
364 TRACE("No match, wrong direction\n");
368 if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
370 IPin_Release(partner);
371 TRACE("No match, %p already connected to %p\n", pin, partner);
376 FIXME("Ignoring category/type\n");
378 TRACE("Match made in heaven\n");
383 static HRESULT WINAPI
384 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
386 PIN_DIRECTION pindir,
387 const GUID *pCategory,
394 IEnumPins *enumpins = NULL;
396 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
398 TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
399 pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
400 fUnconnected, num, ppPin);
404 hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
405 if (hr == E_NOINTERFACE)
407 IBaseFilter *filter = NULL;
410 hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
411 if (hr == E_NOINTERFACE)
413 WARN("Input not filter or pin?!\n");
417 hr = IBaseFilter_EnumPins(filter, &enumpins);
420 WARN("Could not enumerate\n");
424 IEnumPins_Reset(enumpins);
428 hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
429 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
432 IEnumPins_Reset(enumpins);
439 TRACE("Testing match\n");
440 if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
445 IEnumPins_Release(enumpins);
449 WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
453 else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
463 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
465 fnCaptureGraphBuilder2_QueryInterface,
466 fnCaptureGraphBuilder2_AddRef,
467 fnCaptureGraphBuilder2_Release,
468 fnCaptureGraphBuilder2_SetFilterGraph,
469 fnCaptureGraphBuilder2_GetFilterGraph,
470 fnCaptureGraphBuilder2_SetOutputFileName,
471 fnCaptureGraphBuilder2_FindInterface,
472 fnCaptureGraphBuilder2_RenderStream,
473 fnCaptureGraphBuilder2_ControlStream,
474 fnCaptureGraphBuilder2_AllocCapFile,
475 fnCaptureGraphBuilder2_CopyCaptureFile,
476 fnCaptureGraphBuilder2_FindPin
480 static HRESULT WINAPI
481 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
482 REFIID riid, LPVOID * ppv)
484 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
485 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
486 return IUnknown_QueryInterface(_ICaptureGraphBuilder2_(This), riid, ppv);
490 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
492 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
493 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
494 return IUnknown_AddRef(_ICaptureGraphBuilder2_(This));
498 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
500 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
501 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
502 return IUnknown_Release(_ICaptureGraphBuilder2_(This));
505 static HRESULT WINAPI
506 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
509 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
510 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
511 return ICaptureGraphBuilder2_SetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
514 static HRESULT WINAPI
515 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
518 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
519 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
520 return ICaptureGraphBuilder2_GetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
523 static HRESULT WINAPI
524 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
525 const GUID *pType, LPCOLESTR lpstrFile,
526 IBaseFilter **ppf, IFileSinkFilter **ppSink)
528 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
529 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
530 return ICaptureGraphBuilder2_SetOutputFileName(_ICaptureGraphBuilder2_(This),
531 pType, lpstrFile, ppf, ppSink);
534 static HRESULT WINAPI
535 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
536 const GUID *pCategory, IBaseFilter *pf,
537 REFIID riid, void **ppint)
539 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
540 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
541 return ICaptureGraphBuilder2_FindInterface(_ICaptureGraphBuilder2_(This),
542 pCategory, NULL, pf, riid, ppint);
545 static HRESULT WINAPI
546 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
547 const GUID *pCategory, IUnknown *pSource,
548 IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
550 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
551 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
552 return ICaptureGraphBuilder2_RenderStream(_ICaptureGraphBuilder2_(This),
553 pCategory, NULL, pSource,
554 pfCompressor, pfRenderer);
557 static HRESULT WINAPI
558 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
559 const GUID *pCategory, IBaseFilter *pFilter,
560 REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
561 WORD wStartCookie, WORD wStopCookie)
563 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
564 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
565 return ICaptureGraphBuilder2_ControlStream(_ICaptureGraphBuilder2_(This),
566 pCategory, NULL, pFilter, pstart,
567 pstop, wStartCookie, wStopCookie);
570 static HRESULT WINAPI
571 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
572 LPCOLESTR lpstr, DWORDLONG dwlSize)
574 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
575 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
576 return ICaptureGraphBuilder2_AllocCapFile(_ICaptureGraphBuilder2_(This),
580 static HRESULT WINAPI
581 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
582 LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
584 IAMCopyCaptureFileProgress *pCallback)
586 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
587 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
588 return ICaptureGraphBuilder2_CopyCaptureFile(_ICaptureGraphBuilder2_(This),
589 lpwstrOld, lpwstrNew,
590 fAllowEscAbort, pCallback);
593 static const ICaptureGraphBuilderVtbl builder_Vtbl =
595 fnCaptureGraphBuilder_QueryInterface,
596 fnCaptureGraphBuilder_AddRef,
597 fnCaptureGraphBuilder_Release,
598 fnCaptureGraphBuilder_SetFiltergraph,
599 fnCaptureGraphBuilder_GetFiltergraph,
600 fnCaptureGraphBuilder_SetOutputFileName,
601 fnCaptureGraphBuilder_FindInterface,
602 fnCaptureGraphBuilder_RenderStream,
603 fnCaptureGraphBuilder_ControlStream,
604 fnCaptureGraphBuilder_AllocCapFile,
605 fnCaptureGraphBuilder_CopyCaptureFile