Overlay icons for .lnk files with a small arrow in the lower left
[wine] / dlls / qcap / capturegraph.c
1 /* Capture Graph Builder, Minimal edition
2  *
3  * Copyright 2005 Maarten Lankhorst
4  * Copyright 2005 Rolf Kalbermatter
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdarg.h>
24
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "uuids.h"
34
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "control.h"
38 /*
39  *#include "amvideo.h"
40  *#include "mmreg.h"
41  *#include "vfwmsgs.h"
42  *#include "dshow.h"
43  *#include "ddraw.h"
44  */
45 #include "qcap_main.h"
46
47 #include "wine/unicode.h"
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
51
52 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
53
54 /***********************************************************************
55 *   ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
56 */
57 typedef struct CaptureGraphImpl
58 {
59     const ICaptureGraphBuilder2Vtbl * lpVtbl2;
60     const ICaptureGraphBuilderVtbl * lpVtbl;
61     DWORD ref;
62     IGraphBuilder *mygraph;
63
64     CRITICAL_SECTION csFilter;
65 } CaptureGraphImpl;
66
67 static const ICaptureGraphBuilderVtbl builder_Vtbl;
68 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
69
70 #define _ICaptureGraphBuilder_Offset ((int)(&(((CaptureGraphImpl*)0)->lpVtbl)))
71 #define _ICOM_THIS_From_ICaptureGraphBuilder(class, name) class* This = (class*)(((char*)name)-_ICaptureGraphBuilder_Offset)
72
73 #define _ICaptureGraphBuilder2_Offset ((int)(&(((CaptureGraphImpl*)0)->lpVtbl2)))
74 #define _ICOM_THIS_From_ICaptureGraphBuilder2(class, name) class* This = (class*)(((char*)name)-_ICaptureGraphBuilder2_Offset)
75
76 /*
77   converts This to an interface pointer
78 */
79 #define _IUnknown_(This)                (IUnknown*)&(This->lpVtbl2)
80 #define _ICaptureGraphBuilder_(This)    (ICaptureGraphBuilder*)&(This->lpVtbl)
81 #define _ICaptureGraphBuilder2_(This)   (ICaptureGraphBuilder2*)&(This->lpVtbl2)
82
83
84 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
85                                                     HRESULT *phr)
86 {
87     CaptureGraphImpl * pCapture = NULL;
88
89     TRACE("(%p, %p)\n", pUnkOuter, phr);
90
91     *phr = CLASS_E_NOAGGREGATION;
92     if (pUnkOuter)
93     {
94         return NULL;
95     }
96     *phr = E_OUTOFMEMORY;
97
98     pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
99     if (pCapture)
100     {
101         pCapture->lpVtbl2 = &builder2_Vtbl;
102         pCapture->lpVtbl = &builder_Vtbl;
103         pCapture->ref = 1;
104         pCapture->mygraph = NULL;
105         InitializeCriticalSection(&pCapture->csFilter);
106         *phr = S_OK;
107     }
108     return (IUnknown *)pCapture;
109 }
110
111 static HRESULT WINAPI
112 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
113                                       REFIID riid,
114                                       LPVOID * ppv)
115 {
116     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
117
118     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
119
120     *ppv = NULL;
121     if (IsEqualIID(riid, &IID_IUnknown))
122         *ppv = _IUnknown_(This);
123     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
124         *ppv = _ICaptureGraphBuilder_(This);
125     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
126         *ppv = _ICaptureGraphBuilder2_(This);
127
128     if (*ppv)
129     {
130         IUnknown_AddRef((IUnknown *)(*ppv));
131         TRACE ("-- Interface = %p\n", *ppv);
132         return S_OK;
133     }
134
135     TRACE ("-- Interface: E_NOINTERFACE\n");
136     return E_NOINTERFACE;
137 }
138
139 static ULONG WINAPI
140 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
141 {
142     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
143     DWORD ref = InterlockedIncrement(&This->ref);
144
145     TRACE("(%p/%p)->() AddRef from %ld\n", This, iface, ref - 1);
146     return ref;
147 }
148
149 static ULONG WINAPI
150 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
151 {
152     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
153     DWORD ref = InterlockedDecrement(&This->ref);
154
155     TRACE("(%p/%p)->() Release from %ld\n", This, iface, ref + 1);
156
157     if (!ref)
158     {
159         FIXME("Release IGraphFilter or w/e\n");
160         DeleteCriticalSection(&This->csFilter);
161         This->lpVtbl = NULL;
162         This->lpVtbl2 = NULL;
163         if (This->mygraph != NULL)
164             IGraphBuilder_Release((IGraphBuilder *)This->mygraph);
165         CoTaskMemFree(This);
166         return 0;
167     }
168     else
169         return ref;
170 }
171
172 static HRESULT WINAPI
173 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
174                                       IGraphBuilder *pfg)
175 {
176 /* The graph builder will automatically create a filter graph if you don't call
177    this method. If you call this method after the graph builder has created its
178    own filter graph, the call will fail. */
179     IMediaEvent *pmev;
180     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
181
182     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
183
184     if (!This->mygraph)
185         return E_UNEXPECTED;
186
187     if (!pfg)
188         return E_POINTER;
189
190     This->mygraph = pfg;
191     IGraphBuilder_AddRef((IGraphBuilder *)This->mygraph);
192     if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph,
193                                           &IID_IMediaEvent, (LPVOID *)&pmev)))
194     {
195         IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
196         IMediaEvent_Release(pmev);
197     }
198     return S_OK;
199 }
200
201 static HRESULT WINAPI
202 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
203                                       IGraphBuilder **pfg)
204 {
205     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
206
207     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
208
209     if (!pfg)
210         return E_POINTER;
211
212     *pfg = This->mygraph;
213     if (!This->mygraph)
214     {
215         TRACE("(%p) Getting NULL filtergraph\n", iface);
216         return E_UNEXPECTED;
217     }
218
219     IGraphBuilder_AddRef((IGraphBuilder *)This->mygraph);
220    
221     TRACE("(%p) return filtergraph %p\n", iface, *pfg);
222     return S_OK;
223 }
224
225 static HRESULT WINAPI
226 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
227                                          const GUID *pType,
228                                          LPCOLESTR lpstrFile,
229                                          IBaseFilter **ppf,
230                                          IFileSinkFilter **ppSink)
231 {
232     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
233
234     FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
235           debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
236
237     return E_NOTIMPL;
238 }
239
240 static HRESULT WINAPI
241 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
242                                      const GUID *pCategory,
243                                      const GUID *pType,
244                                      IBaseFilter *pf,
245                                      REFIID riid,
246                                      void **ppint)
247 {
248     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
249
250     FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
251           debugstr_guid(pCategory), debugstr_guid(pType),
252           pf, debugstr_guid(riid), ppint);
253
254     return IBaseFilter_QueryInterface(pf, riid, ppint);
255     /* Looks for the specified interface on the filter, upstream and
256      * downstream from the filter, and, optionally, only on the output
257      * pin of the given category.
258      */
259 }
260
261 static HRESULT WINAPI
262 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
263                                     const GUID *pCategory,
264                                     const GUID *pType,
265                                     IUnknown *pSource,
266                                     IBaseFilter *pfCompressor,
267                                     IBaseFilter *pfRenderer)
268 {
269     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
270
271     FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
272           debugstr_guid(pCategory), debugstr_guid(pType),
273           pSource, pfCompressor, pfRenderer);
274
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI
279 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
280                                      const GUID *pCategory,
281                                      const GUID *pType,
282                                      IBaseFilter *pFilter,
283                                      REFERENCE_TIME *pstart,
284                                      REFERENCE_TIME *pstop,
285                                      WORD wStartCookie,
286                                      WORD wStopCookie)
287 {
288     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
289
290     FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
291           debugstr_guid(pCategory), debugstr_guid(pType),
292           pFilter, pstart, pstop, wStartCookie, wStopCookie);
293
294     return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI
298 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
299                                     LPCOLESTR lpwstr,
300                                     DWORDLONG dwlSize)
301 {
302     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
303
304     FIXME("(%p/%p)->(%s, %lld) Stub!\n", This, iface,
305           debugstr_w(lpwstr), dwlSize);
306
307     return E_NOTIMPL;
308 }
309
310 static HRESULT WINAPI
311 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
312                                        LPOLESTR lpwstrOld,
313                                        LPOLESTR lpwstrNew,
314                                        int fAllowEscAbort,
315                                        IAMCopyCaptureFileProgress *pCallback)
316 {
317     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
318
319     FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
320           debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
321           fAllowEscAbort, pCallback);
322
323     return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI
327 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
328                                IUnknown *pSource,
329                                PIN_DIRECTION pindir,
330                                const GUID *pCategory,
331                                const GUID *pType,
332                                BOOL fUnconnected,
333                                int num,
334                                IPin **ppPin)
335 {
336     _ICOM_THIS_From_ICaptureGraphBuilder2(CaptureGraphImpl, iface);
337
338     FIXME("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p) Stub!\n", This, iface,
339           pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
340           fUnconnected, num, ppPin);
341
342     return E_NOTIMPL;
343 }
344
345 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
346 {   
347     fnCaptureGraphBuilder2_QueryInterface,
348     fnCaptureGraphBuilder2_AddRef,
349     fnCaptureGraphBuilder2_Release,
350     fnCaptureGraphBuilder2_SetFilterGraph,
351     fnCaptureGraphBuilder2_GetFilterGraph,
352     fnCaptureGraphBuilder2_SetOutputFileName,
353     fnCaptureGraphBuilder2_FindInterface,
354     fnCaptureGraphBuilder2_RenderStream,
355     fnCaptureGraphBuilder2_ControlStream,
356     fnCaptureGraphBuilder2_AllocCapFile,
357     fnCaptureGraphBuilder2_CopyCaptureFile,
358     fnCaptureGraphBuilder2_FindPin
359 };
360
361
362 static HRESULT WINAPI
363 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
364                                      REFIID riid, LPVOID * ppv)
365 {
366     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
367
368     return IUnknown_QueryInterface(_ICaptureGraphBuilder2_(This), riid, ppv);
369 }
370
371 static ULONG WINAPI
372 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
373 {
374     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
375
376     return IUnknown_AddRef(_ICaptureGraphBuilder2_(This));
377 }
378
379 static ULONG WINAPI
380 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
381 {
382     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
383
384     return IUnknown_Release(_ICaptureGraphBuilder2_(This));
385 }
386
387 static HRESULT WINAPI
388 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
389                                      IGraphBuilder *pfg)
390 {
391     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
392
393     return ICaptureGraphBuilder2_SetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
394 }
395
396 static HRESULT WINAPI
397 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
398                                      IGraphBuilder **pfg)
399 {
400     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
401
402     return ICaptureGraphBuilder2_GetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
403 }
404
405 static HRESULT WINAPI
406 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
407                                         const GUID *pType, LPCOLESTR lpstrFile,
408                                         IBaseFilter **ppf, IFileSinkFilter **ppSink)
409 {
410     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
411
412     return ICaptureGraphBuilder2_SetOutputFileName(_ICaptureGraphBuilder2_(This),
413                                                    pType, lpstrFile, ppf, ppSink);
414 }
415
416 static HRESULT WINAPI
417 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
418                                     const GUID *pCategory, IBaseFilter *pf,
419                                     REFIID riid, void **ppint)
420 {
421     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
422
423     return ICaptureGraphBuilder2_FindInterface(_ICaptureGraphBuilder2_(This),
424                                                pCategory, NULL, pf, riid, ppint);
425 }
426
427 static HRESULT WINAPI
428 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
429                                    const GUID *pCategory, IUnknown *pSource,
430                                    IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
431 {
432     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
433
434     return ICaptureGraphBuilder2_RenderStream(_ICaptureGraphBuilder2_(This),
435                                               pCategory, NULL, pSource,
436                                               pfCompressor, pfRenderer);
437 }
438
439 static HRESULT WINAPI
440 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
441                                     const GUID *pCategory, IBaseFilter *pFilter,
442                                     REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
443                                     WORD wStartCookie, WORD wStopCookie)
444 {
445     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
446
447     return ICaptureGraphBuilder2_ControlStream(_ICaptureGraphBuilder2_(This),
448                                                pCategory, NULL, pFilter, pstart, 
449                                                pstop, wStartCookie, wStopCookie);
450 }
451
452 static HRESULT WINAPI
453 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
454                                    LPCOLESTR lpstr, DWORDLONG dwlSize)
455 {
456     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
457
458     return ICaptureGraphBuilder2_AllocCapFile(_ICaptureGraphBuilder2_(This),
459                                               lpstr, dwlSize);
460 }
461
462 static HRESULT WINAPI
463 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
464                                       LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
465                                       int fAllowEscAbort,
466                                       IAMCopyCaptureFileProgress *pCallback)
467 {
468     _ICOM_THIS_From_ICaptureGraphBuilder(CaptureGraphImpl, iface);
469
470     return ICaptureGraphBuilder2_CopyCaptureFile(_ICaptureGraphBuilder2_(This),
471                                                  lpwstrOld, lpwstrNew,
472                                                  fAllowEscAbort, pCallback);
473 }
474
475 static const ICaptureGraphBuilderVtbl builder_Vtbl =
476 {   
477    fnCaptureGraphBuilder_QueryInterface,
478    fnCaptureGraphBuilder_AddRef,
479    fnCaptureGraphBuilder_Release,
480    fnCaptureGraphBuilder_SetFiltergraph,
481    fnCaptureGraphBuilder_GetFiltergraph,
482    fnCaptureGraphBuilder_SetOutputFileName,
483    fnCaptureGraphBuilder_FindInterface,
484    fnCaptureGraphBuilder_RenderStream,
485    fnCaptureGraphBuilder_ControlStream,
486    fnCaptureGraphBuilder_AllocCapFile,
487    fnCaptureGraphBuilder_CopyCaptureFile
488 };