user32: Prefer loading color cursors in LoadImage.
[wine.git] / dlls / qcap / capturegraph.c
blob7cec77ee3bdf1b78e8d914a443d26d354e71b829
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
20 #include "config.h"
22 #include <stdio.h>
23 #include <stdarg.h>
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winerror.h"
33 #include "objbase.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "control.h"
38 #include "vfwmsgs.h"
40 *#include "amvideo.h"
41 *#include "mmreg.h"
42 *#include "dshow.h"
43 *#include "ddraw.h"
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;
59 LONG ref;
60 IGraphBuilder *mygraph;
61 CRITICAL_SECTION csFilter;
62 } CaptureGraphImpl;
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,
79 HRESULT *phr)
81 CaptureGraphImpl * pCapture = NULL;
83 TRACE("(%p, %p)\n", pUnkOuter, phr);
85 *phr = CLASS_E_NOAGGREGATION;
86 if (pUnkOuter)
88 return NULL;
90 *phr = E_OUTOFMEMORY;
92 pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
93 if (pCapture)
95 pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl;
96 pCapture->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl;
97 pCapture->ref = 1;
98 pCapture->mygraph = NULL;
99 InitializeCriticalSection(&pCapture->csFilter);
100 pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
101 *phr = S_OK;
102 ObjectRefCount(TRUE);
104 return (IUnknown *)&pCapture->ICaptureGraphBuilder_iface;
107 static HRESULT WINAPI
108 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
109 REFIID riid,
110 LPVOID * ppv)
112 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
114 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
116 *ppv = NULL;
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;
124 if (*ppv)
126 IUnknown_AddRef((IUnknown *)(*ppv));
127 TRACE ("-- Interface = %p\n", *ppv);
128 return S_OK;
131 TRACE ("-- Interface: E_NOINTERFACE\n");
132 return E_NOINTERFACE;
135 static ULONG WINAPI
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);
142 return ref;
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);
152 if (!ref)
154 This->csFilter.DebugInfo->Spare[0] = 0;
155 DeleteCriticalSection(&This->csFilter);
156 if (This->mygraph)
157 IGraphBuilder_Release(This->mygraph);
158 CoTaskMemFree(This);
159 ObjectRefCount(FALSE);
161 return ref;
164 static HRESULT WINAPI
165 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
166 IGraphBuilder *pfg)
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. */
171 IMediaEvent *pmev;
172 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
174 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
176 if (This->mygraph)
177 return E_UNEXPECTED;
179 if (!pfg)
180 return E_POINTER;
182 This->mygraph = 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);
190 return S_OK;
193 static HRESULT WINAPI
194 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
195 IGraphBuilder **pfg)
197 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
199 TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
201 if (!pfg)
202 return E_POINTER;
204 *pfg = This->mygraph;
205 if (!This->mygraph)
207 TRACE("(%p) Getting NULL filtergraph\n", iface);
208 return E_UNEXPECTED;
211 IGraphBuilder_AddRef(This->mygraph);
213 TRACE("(%p) return filtergraph %p\n", iface, *pfg);
214 return S_OK;
217 static HRESULT WINAPI
218 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
219 const GUID *pType,
220 LPCOLESTR lpstrFile,
221 IBaseFilter **ppf,
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);
229 return E_NOTIMPL;
232 static HRESULT WINAPI
233 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
234 const GUID *pCategory,
235 const GUID *pType,
236 IBaseFilter *pf,
237 REFIID riid,
238 void **ppint)
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,
256 const GUID *pType,
257 IUnknown *pSource,
258 IBaseFilter *pfCompressor,
259 IBaseFilter *pfRenderer)
261 CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
262 IPin *pin_in = NULL;
263 IPin *pin_out = NULL;
264 HRESULT hr;
266 FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
267 debugstr_guid(pCategory), debugstr_guid(pType),
268 pSource, pfCompressor, pfRenderer);
270 if (pfCompressor)
271 FIXME("Intermediate streams not supported yet\n");
273 if (!This->mygraph)
275 FIXME("Need a capture graph\n");
276 return E_UNEXPECTED;
279 ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
280 if (!pin_in)
281 return E_FAIL;
282 ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
283 if (!pin_out)
285 IPin_Release(pin_in);
286 return E_FAIL;
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);
293 return hr;
296 static HRESULT WINAPI
297 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
298 const GUID *pCategory,
299 const GUID *pType,
300 IBaseFilter *pFilter,
301 REFERENCE_TIME *pstart,
302 REFERENCE_TIME *pstop,
303 WORD wStartCookie,
304 WORD wStopCookie)
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);
312 return E_NOTIMPL;
315 static HRESULT WINAPI
316 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
317 LPCOLESTR lpwstr,
318 DWORDLONG dwlSize)
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));
325 return E_NOTIMPL;
328 static HRESULT WINAPI
329 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
330 LPOLESTR lpwstrOld,
331 LPOLESTR lpwstrNew,
332 int fAllowEscAbort,
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);
341 return E_NOTIMPL;
344 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
346 IPin *partner;
347 PIN_DIRECTION pindir;
349 IPin_QueryDirection(pin, &pindir);
350 if (pindir != direction)
352 TRACE("No match, wrong direction\n");
353 return FALSE;
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);
360 return FALSE;
363 if (cat || type)
364 FIXME("Ignoring category/type\n");
366 TRACE("Match made in heaven\n");
368 return TRUE;
371 static HRESULT WINAPI
372 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
373 IUnknown *pSource,
374 PIN_DIRECTION pindir,
375 const GUID *pCategory,
376 const GUID *pType,
377 BOOL fUnconnected,
378 INT num,
379 IPin **ppPin)
381 HRESULT hr;
382 IEnumPins *enumpins = NULL;
383 IPin *pin;
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);
390 pin = NULL;
392 hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
393 if (hr == E_NOINTERFACE)
395 IBaseFilter *filter = NULL;
396 int numcurrent = 0;
398 hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
399 if (hr == E_NOINTERFACE)
401 WARN("Input not filter or pin?!\n");
402 return E_FAIL;
405 hr = IBaseFilter_EnumPins(filter, &enumpins);
406 if (FAILED(hr))
408 WARN("Could not enumerate\n");
409 return hr;
412 IEnumPins_Reset(enumpins);
414 while (1)
416 hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
417 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
419 numcurrent = 0;
420 IEnumPins_Reset(enumpins);
421 pin = NULL;
422 continue;
425 if (hr != S_OK)
426 break;
427 TRACE("Testing match\n");
428 if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
429 break;
430 IPin_Release(pin);
431 pin = NULL;
433 IEnumPins_Release(enumpins);
435 if (hr != S_OK)
437 WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
438 return E_FAIL;
441 else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
443 IPin_Release(pin);
444 return E_FAIL;
447 *ppPin = pin;
448 return S_OK;
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);
477 static ULONG WINAPI
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);
485 static ULONG WINAPI
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,
495 IGraphBuilder *pfg)
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,
504 IGraphBuilder **pfg)
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,
530 pf, riid, ppint);
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,
568 int fAllowEscAbort,
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