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