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
;
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 CONTAINING_RECORD(iface
, CaptureGraphImpl
, ICaptureGraphBuilder_iface
);
73 static inline CaptureGraphImpl
*impl_from_ICaptureGraphBuilder2(ICaptureGraphBuilder2
*iface
)
75 return CONTAINING_RECORD(iface
, CaptureGraphImpl
, ICaptureGraphBuilder2_iface
);
79 IUnknown
* CALLBACK
QCAP_createCaptureGraphBuilder2(IUnknown
*pUnkOuter
,
82 CaptureGraphImpl
* pCapture
= NULL
;
84 TRACE("(%p, %p)\n", pUnkOuter
, phr
);
86 *phr
= CLASS_E_NOAGGREGATION
;
93 pCapture
= CoTaskMemAlloc(sizeof(CaptureGraphImpl
));
96 pCapture
->ICaptureGraphBuilder2_iface
.lpVtbl
= &builder2_Vtbl
;
97 pCapture
->ICaptureGraphBuilder_iface
.lpVtbl
= &builder_Vtbl
;
99 pCapture
->mygraph
= NULL
;
100 InitializeCriticalSection(&pCapture
->csFilter
);
101 pCapture
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": CaptureGraphImpl.csFilter");
103 ObjectRefCount(TRUE
);
105 return (IUnknown
*)&pCapture
->ICaptureGraphBuilder_iface
;
108 static HRESULT WINAPI
109 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2
* iface
,
113 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
115 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, debugstr_guid(riid
), ppv
);
118 if (IsEqualIID(riid
, &IID_IUnknown
))
119 *ppv
= &This
->ICaptureGraphBuilder2_iface
;
120 else if (IsEqualIID(riid
, &IID_ICaptureGraphBuilder
))
121 *ppv
= &This
->ICaptureGraphBuilder_iface
;
122 else if (IsEqualIID(riid
, &IID_ICaptureGraphBuilder2
))
123 *ppv
= &This
->ICaptureGraphBuilder2_iface
;
127 IUnknown_AddRef((IUnknown
*)(*ppv
));
128 TRACE ("-- Interface = %p\n", *ppv
);
132 TRACE ("-- Interface: E_NOINTERFACE\n");
133 return E_NOINTERFACE
;
137 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2
* iface
)
139 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
140 DWORD ref
= InterlockedIncrement(&This
->ref
);
142 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, ref
- 1);
147 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2
* iface
)
149 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
150 DWORD ref
= InterlockedDecrement(&This
->ref
);
152 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, ref
+ 1);
156 FIXME("Release IGraphFilter or w/e\n");
157 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
158 DeleteCriticalSection(&This
->csFilter
);
159 if (This
->mygraph
!= NULL
)
160 IGraphBuilder_Release(This
->mygraph
);
162 ObjectRefCount(FALSE
);
167 static HRESULT WINAPI
168 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2
* iface
,
171 /* The graph builder will automatically create a filter graph if you don't call
172 this method. If you call this method after the graph builder has created its
173 own filter graph, the call will fail. */
175 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
177 TRACE("(%p/%p)->(%p)\n", This
, iface
, pfg
);
186 IGraphBuilder_AddRef(This
->mygraph
);
187 if (SUCCEEDED(IGraphBuilder_QueryInterface(This
->mygraph
,
188 &IID_IMediaEvent
, (LPVOID
*)&pmev
)))
190 IMediaEvent_CancelDefaultHandling(pmev
, EC_REPAINT
);
191 IMediaEvent_Release(pmev
);
196 static HRESULT WINAPI
197 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2
* iface
,
200 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
202 TRACE("(%p/%p)->(%p)\n", This
, iface
, pfg
);
207 *pfg
= This
->mygraph
;
210 TRACE("(%p) Getting NULL filtergraph\n", iface
);
214 IGraphBuilder_AddRef(This
->mygraph
);
216 TRACE("(%p) return filtergraph %p\n", iface
, *pfg
);
220 static HRESULT WINAPI
221 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2
* iface
,
225 IFileSinkFilter
**ppSink
)
227 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
229 FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This
, iface
,
230 debugstr_guid(pType
), debugstr_w(lpstrFile
), ppf
, ppSink
);
235 static HRESULT WINAPI
236 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2
* iface
,
237 const GUID
*pCategory
,
243 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
245 FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This
, iface
,
246 debugstr_guid(pCategory
), debugstr_guid(pType
),
247 pf
, debugstr_guid(riid
), ppint
);
249 return IBaseFilter_QueryInterface(pf
, riid
, ppint
);
250 /* Looks for the specified interface on the filter, upstream and
251 * downstream from the filter, and, optionally, only on the output
252 * pin of the given category.
256 static HRESULT WINAPI
257 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2
* iface
,
258 const GUID
*pCategory
,
261 IBaseFilter
*pfCompressor
,
262 IBaseFilter
*pfRenderer
)
264 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
266 IPin
*pin_out
= NULL
;
269 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This
, iface
,
270 debugstr_guid(pCategory
), debugstr_guid(pType
),
271 pSource
, pfCompressor
, pfRenderer
);
274 FIXME("Intermediate streams not supported yet\n");
278 FIXME("Need a capture graph\n");
282 ICaptureGraphBuilder2_FindPin(iface
, pSource
, PINDIR_OUTPUT
, pCategory
, pType
, TRUE
, 0, &pin_in
);
285 ICaptureGraphBuilder2_FindPin(iface
, (IUnknown
*)pfRenderer
, PINDIR_INPUT
, pCategory
, pType
, TRUE
, 0, &pin_out
);
288 IPin_Release(pin_in
);
292 /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
293 hr
= IGraphBuilder_Connect(This
->mygraph
, pin_in
, pin_out
);
294 IPin_Release(pin_in
);
295 IPin_Release(pin_out
);
299 static HRESULT WINAPI
300 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2
* iface
,
301 const GUID
*pCategory
,
303 IBaseFilter
*pFilter
,
304 REFERENCE_TIME
*pstart
,
305 REFERENCE_TIME
*pstop
,
309 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
311 FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This
, iface
,
312 debugstr_guid(pCategory
), debugstr_guid(pType
),
313 pFilter
, pstart
, pstop
, wStartCookie
, wStopCookie
);
318 static HRESULT WINAPI
319 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2
* iface
,
323 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
325 FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This
, iface
,
326 debugstr_w(lpwstr
), wine_dbgstr_longlong(dwlSize
));
331 static HRESULT WINAPI
332 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2
* iface
,
336 IAMCopyCaptureFileProgress
*pCallback
)
338 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
340 FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This
, iface
,
341 debugstr_w(lpwstrOld
), debugstr_w(lpwstrNew
),
342 fAllowEscAbort
, pCallback
);
347 static BOOL
pin_matches(IPin
*pin
, PIN_DIRECTION direction
, const GUID
*cat
, const GUID
*type
, BOOL unconnected
)
350 PIN_DIRECTION pindir
;
352 IPin_QueryDirection(pin
, &pindir
);
353 if (pindir
!= direction
)
355 TRACE("No match, wrong direction\n");
359 if (unconnected
&& IPin_ConnectedTo(pin
, &partner
) == S_OK
)
361 IPin_Release(partner
);
362 TRACE("No match, %p already connected to %p\n", pin
, partner
);
367 FIXME("Ignoring category/type\n");
369 TRACE("Match made in heaven\n");
374 static HRESULT WINAPI
375 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2
* iface
,
377 PIN_DIRECTION pindir
,
378 const GUID
*pCategory
,
385 IEnumPins
*enumpins
= NULL
;
387 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder2(iface
);
389 TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This
, iface
,
390 pSource
, pindir
, debugstr_guid(pCategory
), debugstr_guid(pType
),
391 fUnconnected
, num
, ppPin
);
395 hr
= IUnknown_QueryInterface(pSource
, &IID_IPin
, (void**)&pin
);
396 if (hr
== E_NOINTERFACE
)
398 IBaseFilter
*filter
= NULL
;
401 hr
= IUnknown_QueryInterface(pSource
, &IID_IBaseFilter
, (void**)&filter
);
402 if (hr
== E_NOINTERFACE
)
404 WARN("Input not filter or pin?!\n");
408 hr
= IBaseFilter_EnumPins(filter
, &enumpins
);
411 WARN("Could not enumerate\n");
415 IEnumPins_Reset(enumpins
);
419 hr
= IEnumPins_Next(enumpins
, 1, &pin
, NULL
);
420 if (hr
== VFW_E_ENUM_OUT_OF_SYNC
)
423 IEnumPins_Reset(enumpins
);
430 TRACE("Testing match\n");
431 if (pin_matches(pin
, pindir
, pCategory
, pType
, fUnconnected
) && numcurrent
++ == num
)
436 IEnumPins_Release(enumpins
);
440 WARN("Could not find %s pin # %d\n", (pindir
== PINDIR_OUTPUT
? "output" : "input"), numcurrent
);
444 else if (!pin_matches(pin
, pindir
, pCategory
, pType
, fUnconnected
))
454 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl
=
456 fnCaptureGraphBuilder2_QueryInterface
,
457 fnCaptureGraphBuilder2_AddRef
,
458 fnCaptureGraphBuilder2_Release
,
459 fnCaptureGraphBuilder2_SetFilterGraph
,
460 fnCaptureGraphBuilder2_GetFilterGraph
,
461 fnCaptureGraphBuilder2_SetOutputFileName
,
462 fnCaptureGraphBuilder2_FindInterface
,
463 fnCaptureGraphBuilder2_RenderStream
,
464 fnCaptureGraphBuilder2_ControlStream
,
465 fnCaptureGraphBuilder2_AllocCapFile
,
466 fnCaptureGraphBuilder2_CopyCaptureFile
,
467 fnCaptureGraphBuilder2_FindPin
471 static HRESULT WINAPI
472 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder
* iface
,
473 REFIID riid
, LPVOID
* ppv
)
475 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
476 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
477 return ICaptureGraphBuilder2_QueryInterface(&This
->ICaptureGraphBuilder2_iface
, riid
, ppv
);
481 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder
* iface
)
483 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
484 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
485 return ICaptureGraphBuilder2_AddRef(&This
->ICaptureGraphBuilder2_iface
);
489 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder
* iface
)
491 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
492 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
493 return ICaptureGraphBuilder2_Release(&This
->ICaptureGraphBuilder2_iface
);
496 static HRESULT WINAPI
497 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder
* iface
,
500 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
501 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
502 return ICaptureGraphBuilder2_SetFiltergraph(&This
->ICaptureGraphBuilder2_iface
, pfg
);
505 static HRESULT WINAPI
506 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder
* iface
,
509 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
510 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
511 return ICaptureGraphBuilder2_GetFiltergraph(&This
->ICaptureGraphBuilder2_iface
, pfg
);
514 static HRESULT WINAPI
515 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder
* iface
,
516 const GUID
*pType
, LPCOLESTR lpstrFile
,
517 IBaseFilter
**ppf
, IFileSinkFilter
**ppSink
)
519 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
520 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
521 return ICaptureGraphBuilder2_SetOutputFileName(&This
->ICaptureGraphBuilder2_iface
, pType
,
522 lpstrFile
, ppf
, ppSink
);
525 static HRESULT WINAPI
526 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder
* iface
,
527 const GUID
*pCategory
, IBaseFilter
*pf
,
528 REFIID riid
, void **ppint
)
530 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
531 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
532 return ICaptureGraphBuilder2_FindInterface(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
536 static HRESULT WINAPI
537 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder
* iface
,
538 const GUID
*pCategory
, IUnknown
*pSource
,
539 IBaseFilter
*pfCompressor
, IBaseFilter
*pfRenderer
)
541 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
542 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
543 return ICaptureGraphBuilder2_RenderStream(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
544 pSource
, pfCompressor
, pfRenderer
);
547 static HRESULT WINAPI
548 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder
* iface
,
549 const GUID
*pCategory
, IBaseFilter
*pFilter
,
550 REFERENCE_TIME
*pstart
, REFERENCE_TIME
*pstop
,
551 WORD wStartCookie
, WORD wStopCookie
)
553 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
554 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
555 return ICaptureGraphBuilder2_ControlStream(&This
->ICaptureGraphBuilder2_iface
, pCategory
, NULL
,
556 pFilter
, pstart
, pstop
, wStartCookie
, wStopCookie
);
559 static HRESULT WINAPI
560 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder
* iface
,
561 LPCOLESTR lpstr
, DWORDLONG dwlSize
)
563 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
564 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
565 return ICaptureGraphBuilder2_AllocCapFile(&This
->ICaptureGraphBuilder2_iface
, lpstr
, dwlSize
);
568 static HRESULT WINAPI
569 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder
* iface
,
570 LPOLESTR lpwstrOld
, LPOLESTR lpwstrNew
,
572 IAMCopyCaptureFileProgress
*pCallback
)
574 CaptureGraphImpl
*This
= impl_from_ICaptureGraphBuilder(iface
);
575 TRACE("%p --> Forwarding to v2 (%p)\n", iface
, This
);
576 return ICaptureGraphBuilder2_CopyCaptureFile(&This
->ICaptureGraphBuilder2_iface
, lpwstrOld
,
577 lpwstrNew
, fAllowEscAbort
, pCallback
);
580 static const ICaptureGraphBuilderVtbl builder_Vtbl
=
582 fnCaptureGraphBuilder_QueryInterface
,
583 fnCaptureGraphBuilder_AddRef
,
584 fnCaptureGraphBuilder_Release
,
585 fnCaptureGraphBuilder_SetFiltergraph
,
586 fnCaptureGraphBuilder_GetFiltergraph
,
587 fnCaptureGraphBuilder_SetOutputFileName
,
588 fnCaptureGraphBuilder_FindInterface
,
589 fnCaptureGraphBuilder_RenderStream
,
590 fnCaptureGraphBuilder_ControlStream
,
591 fnCaptureGraphBuilder_AllocCapFile
,
592 fnCaptureGraphBuilder_CopyCaptureFile