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