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 ICaptureGraphBuilder2 ICaptureGraphBuilder2_iface;
58 ICaptureGraphBuilder ICaptureGraphBuilder_iface;
60 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 CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder_iface);
72 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2 *iface)
74 return CONTAINING_RECORD(iface, CaptureGraphImpl, ICaptureGraphBuilder2_iface);
78 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
81 CaptureGraphImpl * pCapture = NULL;
83 TRACE("(%p, %p)\n", pUnkOuter, phr);
85 *phr = CLASS_E_NOAGGREGATION;
92 pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
95 pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
96 pCapture->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
98 pCapture->mygraph = NULL;
99 InitializeCriticalSection(&pCapture->csFilter);
100 pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
102 ObjectRefCount(TRUE);
104 return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
107 static HRESULT WINAPI
108 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
112 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
114 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
117 if (IsEqualIID(riid, &IID_IUnknown))
118 *ppv = &This->ICaptureGraphBuilder2_iface;
119 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
120 *ppv = &This->ICaptureGraphBuilder_iface;
121 else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
122 *ppv = &This->ICaptureGraphBuilder2_iface;
126 IUnknown_AddRef((IUnknown *)(*ppv));
127 TRACE ("-- Interface = %p\n", *ppv);
131 TRACE ("-- Interface: E_NOINTERFACE\n");
132 return E_NOINTERFACE;
136 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
138 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
139 DWORD ref = InterlockedIncrement(&This->ref);
141 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
145 static ULONG WINAPI fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
147 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
148 DWORD ref = InterlockedDecrement(&This->ref);
150 TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
154 This->csFilter.DebugInfo->Spare[0] = 0;
155 DeleteCriticalSection(&This->csFilter);
157 IGraphBuilder_Release(This->mygraph);
159 ObjectRefCount(FALSE);
164 static HRESULT WINAPI
165 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
168 /* The graph builder will automatically create a filter graph if you don't call
169 this method. If you call this method after the graph builder has created its
170 own filter graph, the call will fail. */
172 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
174 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
183 IGraphBuilder_AddRef(This->mygraph);
184 if (SUCCEEDED(IGraphBuilder_QueryInterface(This->mygraph,
185 &IID_IMediaEvent, (LPVOID *)&pmev)))
187 IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
188 IMediaEvent_Release(pmev);
193 static HRESULT WINAPI
194 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
197 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
199 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
204 *pfg = This->mygraph;
207 TRACE("(%p) Getting NULL filtergraph\n", iface);
211 IGraphBuilder_AddRef(This->mygraph);
213 TRACE("(%p) return filtergraph %p\n", iface, *pfg);
217 static HRESULT WINAPI
218 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
222 IFileSinkFilter **ppSink)
224 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
226 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
227 debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
232 static HRESULT WINAPI
233 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
234 const GUID *pCategory,
240 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
242 FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
243 debugstr_guid(pCategory), debugstr_guid(pType),
244 pf, debugstr_guid(riid), ppint);
246 return IBaseFilter_QueryInterface(pf, riid, ppint);
247 /* Looks for the specified interface on the filter, upstream and
248 * downstream from the filter, and, optionally, only on the output
249 * pin of the given category.
253 static HRESULT WINAPI
254 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
255 const GUID *pCategory,
258 IBaseFilter *pfCompressor,
259 IBaseFilter *pfRenderer)
261 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
263 IPin *pin_out = NULL;
266 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
267 debugstr_guid(pCategory), debugstr_guid(pType),
268 pSource, pfCompressor, pfRenderer);
271 FIXME("Intermediate streams not supported yet\n");
275 FIXME("Need a capture graph\n");
279 ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
282 ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
285 IPin_Release(pin_in);
289 /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
290 hr = IGraphBuilder_Connect(This->mygraph, pin_in, pin_out);
291 IPin_Release(pin_in);
292 IPin_Release(pin_out);
296 static HRESULT WINAPI
297 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
298 const GUID *pCategory,
300 IBaseFilter *pFilter,
301 REFERENCE_TIME *pstart,
302 REFERENCE_TIME *pstop,
306 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
308 FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
309 debugstr_guid(pCategory), debugstr_guid(pType),
310 pFilter, pstart, pstop, wStartCookie, wStopCookie);
315 static HRESULT WINAPI
316 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
320 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
322 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
323 debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
328 static HRESULT WINAPI
329 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
333 IAMCopyCaptureFileProgress *pCallback)
335 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
337 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
338 debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
339 fAllowEscAbort, pCallback);
344 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
347 PIN_DIRECTION pindir;
349 IPin_QueryDirection(pin, &pindir);
350 if (pindir != direction)
352 TRACE("No match, wrong direction\n");
356 if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
358 IPin_Release(partner);
359 TRACE("No match, %p already connected to %p\n", pin, partner);
364 FIXME("Ignoring category/type\n");
366 TRACE("Match made in heaven\n");
371 static HRESULT WINAPI
372 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
374 PIN_DIRECTION pindir,
375 const GUID *pCategory,
382 IEnumPins *enumpins = NULL;
384 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
386 TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
387 pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
388 fUnconnected, num, ppPin);
392 hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
393 if (hr == E_NOINTERFACE)
395 IBaseFilter *filter = NULL;
398 hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
399 if (hr == E_NOINTERFACE)
401 WARN("Input not filter or pin?!\n");
405 hr = IBaseFilter_EnumPins(filter, &enumpins);
408 WARN("Could not enumerate\n");
412 IEnumPins_Reset(enumpins);
416 hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
417 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
420 IEnumPins_Reset(enumpins);
427 TRACE("Testing match\n");
428 if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
433 IEnumPins_Release(enumpins);
437 WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
441 else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
451 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
453 fnCaptureGraphBuilder2_QueryInterface,
454 fnCaptureGraphBuilder2_AddRef,
455 fnCaptureGraphBuilder2_Release,
456 fnCaptureGraphBuilder2_SetFilterGraph,
457 fnCaptureGraphBuilder2_GetFilterGraph,
458 fnCaptureGraphBuilder2_SetOutputFileName,
459 fnCaptureGraphBuilder2_FindInterface,
460 fnCaptureGraphBuilder2_RenderStream,
461 fnCaptureGraphBuilder2_ControlStream,
462 fnCaptureGraphBuilder2_AllocCapFile,
463 fnCaptureGraphBuilder2_CopyCaptureFile,
464 fnCaptureGraphBuilder2_FindPin
468 static HRESULT WINAPI
469 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
470 REFIID riid, LPVOID * ppv)
472 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
473 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
474 return ICaptureGraphBuilder2_QueryInterface(&This->ICaptureGraphBuilder2_iface, riid, ppv);
478 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
480 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
481 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
482 return ICaptureGraphBuilder2_AddRef(&This->ICaptureGraphBuilder2_iface);
486 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
488 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
489 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
490 return ICaptureGraphBuilder2_Release(&This->ICaptureGraphBuilder2_iface);
493 static HRESULT WINAPI
494 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
497 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
498 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
499 return ICaptureGraphBuilder2_SetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
502 static HRESULT WINAPI
503 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
506 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
507 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
508 return ICaptureGraphBuilder2_GetFiltergraph(&This->ICaptureGraphBuilder2_iface, pfg);
511 static HRESULT WINAPI
512 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
513 const GUID *pType, LPCOLESTR lpstrFile,
514 IBaseFilter **ppf, IFileSinkFilter **ppSink)
516 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
517 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
518 return ICaptureGraphBuilder2_SetOutputFileName(&This->ICaptureGraphBuilder2_iface, pType,
519 lpstrFile, ppf, ppSink);
522 static HRESULT WINAPI
523 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
524 const GUID *pCategory, IBaseFilter *pf,
525 REFIID riid, void **ppint)
527 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
528 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
529 return ICaptureGraphBuilder2_FindInterface(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
533 static HRESULT WINAPI
534 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
535 const GUID *pCategory, IUnknown *pSource,
536 IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
538 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
539 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
540 return ICaptureGraphBuilder2_RenderStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
541 pSource, pfCompressor, pfRenderer);
544 static HRESULT WINAPI
545 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
546 const GUID *pCategory, IBaseFilter *pFilter,
547 REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
548 WORD wStartCookie, WORD wStopCookie)
550 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
551 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
552 return ICaptureGraphBuilder2_ControlStream(&This->ICaptureGraphBuilder2_iface, pCategory, NULL,
553 pFilter, pstart, pstop, wStartCookie, wStopCookie);
556 static HRESULT WINAPI
557 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
558 LPCOLESTR lpstr, DWORDLONG dwlSize)
560 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
561 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
562 return ICaptureGraphBuilder2_AllocCapFile(&This->ICaptureGraphBuilder2_iface, lpstr, dwlSize);
565 static HRESULT WINAPI
566 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
567 LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
569 IAMCopyCaptureFileProgress *pCallback)
571 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
572 TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
573 return ICaptureGraphBuilder2_CopyCaptureFile(&This->ICaptureGraphBuilder2_iface, lpwstrOld,
574 lpwstrNew, fAllowEscAbort, pCallback);
577 static const ICaptureGraphBuilderVtbl builder_Vtbl =
579 fnCaptureGraphBuilder_QueryInterface,
580 fnCaptureGraphBuilder_AddRef,
581 fnCaptureGraphBuilder_Release,
582 fnCaptureGraphBuilder_SetFiltergraph,
583 fnCaptureGraphBuilder_GetFiltergraph,
584 fnCaptureGraphBuilder_SetOutputFileName,
585 fnCaptureGraphBuilder_FindInterface,
586 fnCaptureGraphBuilder_RenderStream,
587 fnCaptureGraphBuilder_ControlStream,
588 fnCaptureGraphBuilder_AllocCapFile,
589 fnCaptureGraphBuilder_CopyCaptureFile