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
44 #include "qcap_main.h"
46 #include "wine/unicode.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
51 /***********************************************************************
52 * ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
54 typedef struct CaptureGraphImpl
56 const ICaptureGraphBuilder2Vtbl * lpVtbl2;
57 const ICaptureGraphBuilderVtbl * lpVtbl;
59 IGraphBuilder *mygraph;
61 CRITICAL_SECTION csFilter;
64 static const ICaptureGraphBuilderVtbl builder_Vtbl;
65 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
67 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder( ICaptureGraphBuilder *iface )
69 return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl));
72 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2( ICaptureGraphBuilder2 *iface )
74 return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl2));
78 converts This to an interface pointer
80 #define _IUnknown_(This) (IUnknown*)&(This->lpVtbl2)
81 #define _ICaptureGraphBuilder_(This) (ICaptureGraphBuilder*)&(This->lpVtbl)
82 #define _ICaptureGraphBuilder2_(This) (ICaptureGraphBuilder2*)&(This->lpVtbl2)
85 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
88 CaptureGraphImpl * pCapture = NULL;
90 TRACE("(%p, %p)\n", pUnkOuter, phr);
92 *phr = CLASS_E_NOAGGREGATION;
99 pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
102 pCapture->lpVtbl2 = &builder2_Vtbl;
103 pCapture->lpVtbl = &builder_Vtbl;
105 pCapture->mygraph = NULL;
106 InitializeCriticalSection(&pCapture->csFilter);
107 pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
109 ObjectRefCount(TRUE);
111 return (IUnknown *)pCapture;
114 static HRESULT WINAPI
115 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
119 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
121 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
124 if (IsEqualIID(riid, &IID_IUnknown))
125 *ppv = _IUnknown_(This);
126 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
127 *ppv = _ICaptureGraphBuilder_(This);
128 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
129 *ppv = _ICaptureGraphBuilder2_(This);
133 IUnknown_AddRef((IUnknown *)(*ppv));
134 TRACE ("-- Interface = %p\n", *ppv);
138 TRACE ("-- Interface: E_NOINTERFACE\n");
139 return E_NOINTERFACE;
143 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
145 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
146 DWORD ref = InterlockedIncrement(&This->ref);
148 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
153 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
155 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
156 DWORD ref = InterlockedDecrement(&This->ref);
158 TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
162 FIXME("Release IGraphFilter or w/e\n");
163 This->csFilter.DebugInfo->Spare[0] = 0;
164 DeleteCriticalSection(&This->csFilter);
166 This->lpVtbl2 = NULL;
167 if (This->mygraph != NULL)
168 IGraphBuilder_Release(This->mygraph);
170 ObjectRefCount(FALSE);
175 static HRESULT WINAPI
176 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
179 /* The graph builder will automatically create a filter graph if you don't call
180 this method. If you call this method after the graph builder has created its
181 own filter graph, the call will fail. */
183 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
185 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
194 IGraphBuilder_AddRef(This->mygraph);
195 if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph,
196 &IID_IMediaEvent, (LPVOID *)&pmev)))
198 IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
199 IMediaEvent_Release(pmev);
204 static HRESULT WINAPI
205 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
208 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
210 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
215 *pfg = This->mygraph;
218 TRACE("(%p) Getting NULL filtergraph\n", iface);
222 IGraphBuilder_AddRef(This->mygraph);
224 TRACE("(%p) return filtergraph %p\n", iface, *pfg);
228 static HRESULT WINAPI
229 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
233 IFileSinkFilter **ppSink)
235 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
237 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
238 debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
243 static HRESULT WINAPI
244 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
245 const GUID *pCategory,
251 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
253 FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
254 debugstr_guid(pCategory), debugstr_guid(pType),
255 pf, debugstr_guid(riid), ppint);
257 return IBaseFilter_QueryInterface(pf, riid, ppint);
258 /* Looks for the specified interface on the filter, upstream and
259 * downstream from the filter, and, optionally, only on the output
260 * pin of the given category.
264 static HRESULT WINAPI
265 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
266 const GUID *pCategory,
269 IBaseFilter *pfCompressor,
270 IBaseFilter *pfRenderer)
272 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
274 IPin *pin_out = NULL;
277 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
278 debugstr_guid(pCategory), debugstr_guid(pType),
279 pSource, pfCompressor, pfRenderer);
282 FIXME("Intermediate streams not supported yet\n");
286 FIXME("Need a capture graph\n");
290 ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
293 ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
296 IPin_Release(pin_in);
300 /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
301 hr = IFilterGraph2_Connect(This->mygraph, pin_in, pin_out);
302 IPin_Release(pin_in);
303 IPin_Release(pin_out);
307 static HRESULT WINAPI
308 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
309 const GUID *pCategory,
311 IBaseFilter *pFilter,
312 REFERENCE_TIME *pstart,
313 REFERENCE_TIME *pstop,
317 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
319 FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
320 debugstr_guid(pCategory), debugstr_guid(pType),
321 pFilter, pstart, pstop, wStartCookie, wStopCookie);
326 static HRESULT WINAPI
327 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
331 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
333 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
334 debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
339 static HRESULT WINAPI
340 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
344 IAMCopyCaptureFileProgress *pCallback)
346 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
348 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
349 debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
350 fAllowEscAbort, pCallback);
355 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
358 PIN_DIRECTION pindir;
360 IPin_QueryDirection(pin, &pindir);
361 if (pindir != direction)
363 TRACE("No match, wrong direction\n");
367 if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
369 IPin_Release(partner);
370 TRACE("No match, %p already connected to %p\n", pin, partner);
375 FIXME("Ignoring category/type\n");
377 TRACE("Match made in heaven\n");
382 static HRESULT WINAPI
383 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
385 PIN_DIRECTION pindir,
386 const GUID *pCategory,
393 IEnumPins *enumpins = NULL;
395 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
397 TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
398 pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
399 fUnconnected, num, ppPin);
403 hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
404 if (hr == E_NOINTERFACE)
406 IBaseFilter *filter = NULL;
409 hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
410 if (hr == E_NOINTERFACE)
412 WARN("Input not filter or pin?!\n");
416 hr = IBaseFilter_EnumPins(filter, &enumpins);
419 WARN("Could not enumerate\n");
423 IEnumPins_Reset(enumpins);
427 hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
428 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
431 IEnumPins_Reset(enumpins);
438 TRACE("Testing match\n");
439 if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
444 IEnumPins_Release(enumpins);
448 WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
452 else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
462 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
464 fnCaptureGraphBuilder2_QueryInterface,
465 fnCaptureGraphBuilder2_AddRef,
466 fnCaptureGraphBuilder2_Release,
467 fnCaptureGraphBuilder2_SetFilterGraph,
468 fnCaptureGraphBuilder2_GetFilterGraph,
469 fnCaptureGraphBuilder2_SetOutputFileName,
470 fnCaptureGraphBuilder2_FindInterface,
471 fnCaptureGraphBuilder2_RenderStream,
472 fnCaptureGraphBuilder2_ControlStream,
473 fnCaptureGraphBuilder2_AllocCapFile,
474 fnCaptureGraphBuilder2_CopyCaptureFile,
475 fnCaptureGraphBuilder2_FindPin
479 static HRESULT WINAPI
480 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
481 REFIID riid, LPVOID * ppv)
483 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
484 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
485 return IUnknown_QueryInterface(_ICaptureGraphBuilder2_(This), riid, ppv);
489 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
491 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
492 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
493 return IUnknown_AddRef(_ICaptureGraphBuilder2_(This));
497 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
499 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
500 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
501 return IUnknown_Release(_ICaptureGraphBuilder2_(This));
504 static HRESULT WINAPI
505 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
508 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
509 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
510 return ICaptureGraphBuilder2_SetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
513 static HRESULT WINAPI
514 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
517 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
518 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
519 return ICaptureGraphBuilder2_GetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
522 static HRESULT WINAPI
523 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
524 const GUID *pType, LPCOLESTR lpstrFile,
525 IBaseFilter **ppf, IFileSinkFilter **ppSink)
527 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
528 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
529 return ICaptureGraphBuilder2_SetOutputFileName(_ICaptureGraphBuilder2_(This),
530 pType, lpstrFile, ppf, ppSink);
533 static HRESULT WINAPI
534 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
535 const GUID *pCategory, IBaseFilter *pf,
536 REFIID riid, void **ppint)
538 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
539 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
540 return ICaptureGraphBuilder2_FindInterface(_ICaptureGraphBuilder2_(This),
541 pCategory, NULL, pf, riid, ppint);
544 static HRESULT WINAPI
545 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
546 const GUID *pCategory, IUnknown *pSource,
547 IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
549 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
550 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
551 return ICaptureGraphBuilder2_RenderStream(_ICaptureGraphBuilder2_(This),
552 pCategory, NULL, pSource,
553 pfCompressor, pfRenderer);
556 static HRESULT WINAPI
557 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
558 const GUID *pCategory, IBaseFilter *pFilter,
559 REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
560 WORD wStartCookie, WORD wStopCookie)
562 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
563 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
564 return ICaptureGraphBuilder2_ControlStream(_ICaptureGraphBuilder2_(This),
565 pCategory, NULL, pFilter, pstart,
566 pstop, wStartCookie, wStopCookie);
569 static HRESULT WINAPI
570 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
571 LPCOLESTR lpstr, DWORDLONG dwlSize)
573 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
574 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
575 return ICaptureGraphBuilder2_AllocCapFile(_ICaptureGraphBuilder2_(This),
579 static HRESULT WINAPI
580 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
581 LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
583 IAMCopyCaptureFileProgress *pCallback)
585 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
586 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
587 return ICaptureGraphBuilder2_CopyCaptureFile(_ICaptureGraphBuilder2_(This),
588 lpwstrOld, lpwstrNew,
589 fAllowEscAbort, pCallback);
592 static const ICaptureGraphBuilderVtbl builder_Vtbl =
594 fnCaptureGraphBuilder_QueryInterface,
595 fnCaptureGraphBuilder_AddRef,
596 fnCaptureGraphBuilder_Release,
597 fnCaptureGraphBuilder_SetFiltergraph,
598 fnCaptureGraphBuilder_GetFiltergraph,
599 fnCaptureGraphBuilder_SetOutputFileName,
600 fnCaptureGraphBuilder_FindInterface,
601 fnCaptureGraphBuilder_RenderStream,
602 fnCaptureGraphBuilder_ControlStream,
603 fnCaptureGraphBuilder_AllocCapFile,
604 fnCaptureGraphBuilder_CopyCaptureFile