EnumThemeColors() and EnumThemeSizes() actually do not return a single
[wine] / dlls / quartz / filtergraph.c
1 /*              DirectShow FilterGraph object (QUARTZ.DLL)
2  *
3  * Copyright 2002 Lionel Ulmer
4  * Copyright 2004 Christian Costa
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #include <stdarg.h>
26
27 #define COBJMACROS
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "dshow.h"
33 #include "wine/debug.h"
34 #include "quartz_private.h"
35 #define COM_NO_WINDOWS_H
36 #include "ole2.h"
37 #include "olectl.h"
38 #include "strmif.h"
39 #include "vfwmsgs.h"
40 #include "evcode.h"
41 #include "wine/unicode.h"
42
43
44 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45
46 typedef struct {
47     HWND hWnd;      /* Target window */
48     long msg;       /* User window message */
49     long instance;  /* User data */
50     int  disabled;  /* Disabled messages posting */
51 } WndNotify;
52
53 typedef struct {
54     long lEventCode;   /* Event code */
55     LONG_PTR lParam1;  /* Param1 */
56     LONG_PTR lParam2;  /* Param2 */
57 } Event;
58
59 /* messages ring implementation for queuing events (taken from winmm) */
60 #define EVENTS_RING_BUFFER_INCREMENT      64
61 typedef struct {
62     Event* messages;
63     int ring_buffer_size;
64     int msg_tosave;
65     int msg_toget;
66     CRITICAL_SECTION msg_crst;
67     HANDLE msg_event; /* Signaled for no empty queue */
68 } EventsQueue;
69
70 static int EventsQueue_Init(EventsQueue* omr)
71 {
72     omr->msg_toget = 0;
73     omr->msg_tosave = 0;
74     omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
75     omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
76     omr->messages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,omr->ring_buffer_size * sizeof(Event));
77
78     InitializeCriticalSection(&omr->msg_crst);
79     return TRUE;
80 }
81
82 static int EventsQueue_Destroy(EventsQueue* omr)
83 {
84     CloseHandle(omr->msg_event);
85     HeapFree(GetProcessHeap(),0,omr->messages);
86     DeleteCriticalSection(&omr->msg_crst);
87     return TRUE;
88 }
89
90 static int EventsQueue_PutEvent(EventsQueue* omr, Event* evt)
91 {
92     EnterCriticalSection(&omr->msg_crst);
93     if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
94     {
95         int old_ring_buffer_size = omr->ring_buffer_size;
96         omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
97         TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
98         omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
99         /* Now we need to rearrange the ring buffer so that the new
100            buffers just allocated are in between omr->msg_tosave and
101            omr->msg_toget.
102         */
103         if (omr->msg_tosave < omr->msg_toget)
104         {
105             memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
106                     &(omr->messages[omr->msg_toget]),
107                     sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
108                     );
109             omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
110         }
111     }
112     omr->messages[omr->msg_tosave] = *evt;
113     SetEvent(omr->msg_event);
114     omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
115     LeaveCriticalSection(&omr->msg_crst);
116     return TRUE;
117 }
118
119 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
120 {
121     if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
122         return FALSE;
123         
124     EnterCriticalSection(&omr->msg_crst);
125
126     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
127     {
128         LeaveCriticalSection(&omr->msg_crst);
129         return FALSE;
130     }
131
132     *evt = omr->messages[omr->msg_toget];
133     omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
134
135     /* Mark the buffer as empty if needed */
136     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
137         ResetEvent(omr->msg_event);
138
139     LeaveCriticalSection(&omr->msg_crst);
140     return TRUE;
141 }
142
143 typedef struct _IFilterGraphImpl {
144     const IGraphBuilderVtbl *IGraphBuilder_vtbl;
145     const IMediaControlVtbl *IMediaControl_vtbl;
146     const IMediaSeekingVtbl *IMediaSeeking_vtbl;
147     const IBasicAudioVtbl *IBasicAudio_vtbl;
148     const IBasicVideoVtbl *IBasicVideo_vtbl;
149     const IVideoWindowVtbl *IVideoWindow_vtbl;
150     const IMediaEventExVtbl *IMediaEventEx_vtbl;
151     const IMediaFilterVtbl *IMediaFilter_vtbl;
152     const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
153     const IGraphConfigVtbl *IGraphConfig_vtbl;
154     /* IAMGraphStreams */
155     /* IAMStats */
156     /* IBasicVideo2 */
157     /* IFilterChain */
158     /* IFilterGraph2 */
159     /* IFilterMapper2 */
160     /* IGraphVersion */
161     /* IMediaPosition */
162     /* IQueueCommand */
163     /* IRegisterServiceProvider */
164     /* IResourceMananger */
165     /* IServiceProvider */
166     /* IVideoFrameStep */
167
168     LONG ref;
169     IFilterMapper2 * pFilterMapper2;
170     IBaseFilter ** ppFiltersInGraph;
171     LPWSTR * pFilterNames;
172     int nFilters;
173     int filterCapacity;
174     long nameIndex;
175     EventsQueue evqueue;
176     HANDLE hEventCompletion;
177     int CompletionStatus;
178     WndNotify notif;
179     int nRenderers;
180     int EcCompleteCount;
181     int HandleEcComplete;
182     int HandleEcRepaint;
183     OAFilterState state;
184     CRITICAL_SECTION cs;
185 } IFilterGraphImpl;
186
187
188 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
189                                           REFIID riid,
190                                           LPVOID *ppvObj) {
191     TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
192     
193     if (IsEqualGUID(&IID_IUnknown, riid) ||
194         IsEqualGUID(&IID_IFilterGraph, riid) ||
195         IsEqualGUID(&IID_IGraphBuilder, riid)) {
196         *ppvObj = &(This->IGraphBuilder_vtbl);
197         TRACE("   returning IGraphBuilder interface (%p)\n", *ppvObj);
198     } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
199         *ppvObj = &(This->IMediaControl_vtbl);
200         TRACE("   returning IMediaControl interface (%p)\n", *ppvObj);
201     } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
202         *ppvObj = &(This->IMediaSeeking_vtbl);
203         TRACE("   returning IMediaSeeking interface (%p)\n", *ppvObj);
204     } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
205         *ppvObj = &(This->IBasicAudio_vtbl);
206         TRACE("   returning IBasicAudio interface (%p)\n", *ppvObj);
207     } else if (IsEqualGUID(&IID_IBasicVideo, riid)) {
208         *ppvObj = &(This->IBasicVideo_vtbl);
209         TRACE("   returning IBasicVideo interface (%p)\n", *ppvObj);
210     } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
211         *ppvObj = &(This->IVideoWindow_vtbl);
212         TRACE("   returning IVideoWindow interface (%p)\n", *ppvObj);
213     } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
214            IsEqualGUID(&IID_IMediaEventEx, riid)) {
215         *ppvObj = &(This->IMediaEventEx_vtbl);
216         TRACE("   returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
217     } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
218           IsEqualGUID(&IID_IPersist, riid)) {
219         *ppvObj = &(This->IMediaFilter_vtbl);
220         TRACE("   returning IMediaFilter interface (%p)\n", *ppvObj);
221     } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
222         *ppvObj = &(This->IMediaEventSink_vtbl);
223         TRACE("   returning IMediaEventSink interface (%p)\n", *ppvObj);
224     } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
225         *ppvObj = &(This->IGraphConfig_vtbl);
226         TRACE("   returning IGraphConfig interface (%p)\n", *ppvObj);
227     } else {
228         *ppvObj = NULL;
229         FIXME("unknown interface %s\n", debugstr_guid(riid));
230         return E_NOINTERFACE;
231     }
232
233     InterlockedIncrement(&This->ref);
234     return S_OK;
235 }
236
237 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) {
238     ULONG ref = InterlockedIncrement(&This->ref);
239
240     TRACE("(%p)->(): new ref = %ld\n", This, ref);
241     
242     return ref;
243 }
244
245 static ULONG Filtergraph_Release(IFilterGraphImpl *This) {
246     ULONG ref = InterlockedDecrement(&This->ref);
247     
248     TRACE("(%p)->(): new ref = %ld\n", This, ref);
249     
250     if (ref == 0) {
251         int i;
252         for (i = 0; i < This->nFilters; i++)
253            IBaseFilter_Release(This->ppFiltersInGraph[i]);
254         IFilterMapper2_Release(This->pFilterMapper2);
255         CloseHandle(This->hEventCompletion);
256         EventsQueue_Destroy(&This->evqueue);
257         DeleteCriticalSection(&This->cs);
258         HeapFree(GetProcessHeap(), 0, This->ppFiltersInGraph);
259         HeapFree(GetProcessHeap(), 0, This->pFilterNames);
260         HeapFree(GetProcessHeap(), 0, This);
261     }
262     return ref;
263 }
264
265
266 /*** IUnknown methods ***/
267 static HRESULT WINAPI Graphbuilder_QueryInterface(IGraphBuilder *iface,
268                                                   REFIID riid,
269                                                   LPVOID*ppvObj) {
270     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
271     
272     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
273     return Filtergraph_QueryInterface(This, riid, ppvObj);
274 }
275
276 static ULONG WINAPI Graphbuilder_AddRef(IGraphBuilder *iface) {
277     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
278     
279     TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
280     
281     return Filtergraph_AddRef(This);
282 }
283
284 static ULONG WINAPI Graphbuilder_Release(IGraphBuilder *iface) {
285     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
286     
287     TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
288
289     return Filtergraph_Release(This);
290 }
291
292 /*** IFilterGraph methods ***/
293 static HRESULT WINAPI Graphbuilder_AddFilter(IGraphBuilder *iface,
294                                              IBaseFilter *pFilter,
295                                              LPCWSTR pName) {
296     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
297     HRESULT hr;
298     int i,j;
299     WCHAR* wszFilterName = NULL;
300     int duplicate_name = FALSE;
301     
302     TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
303
304     wszFilterName = (WCHAR*) CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
305     
306     if (pName)
307     {
308         /* Check if name already exists */
309         for(i = 0; i < This->nFilters; i++)
310             if (!strcmpW(This->pFilterNames[i], pName))
311             {
312                 duplicate_name = TRUE;
313                 break;
314             }
315     }
316
317     /* If no name given or name already existing, generate one */
318     if (!pName || duplicate_name)
319     {
320         static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
321         static const WCHAR wszFmt2[] = {'%','0','4','d',0};
322
323         for (j = 0; j < 10000 ; j++)
324         {
325             /* Create name */
326             if (pName)
327                 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
328             else
329                 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
330             TRACE("Generated name %s\n", debugstr_w(wszFilterName));
331
332             /* Check if the generated name already exists */
333             for(i = 0; i < This->nFilters; i++)
334                 if (!strcmpW(This->pFilterNames[i], wszFilterName))
335                     break;
336
337             /* Compute next index and exit if generated name is suitable */
338             if (This->nameIndex++ == 10000)
339                 This->nameIndex = 1;
340             if (i == This->nFilters)
341                 break;
342         }
343         /* Unable to find a suitable name */
344         if (j == 10000)
345         {
346             CoTaskMemFree(wszFilterName);
347             return VFW_E_DUPLICATE_NAME;
348         }
349     }
350     else
351         memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
352
353     if (This->nFilters + 1 > This->filterCapacity)
354     {
355         int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
356         IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
357         LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
358         memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
359         memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
360         if (!This->filterCapacity)
361         {
362             CoTaskMemFree(This->ppFiltersInGraph);
363             CoTaskMemFree(This->pFilterNames);
364         }
365         This->ppFiltersInGraph = ppNewFilters;
366         This->pFilterNames = pNewNames;
367         This->filterCapacity = newCapacity;
368     }
369
370     hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
371
372     if (SUCCEEDED(hr))
373     {
374         IBaseFilter_AddRef(pFilter);
375         This->ppFiltersInGraph[This->nFilters] = pFilter;
376         This->pFilterNames[This->nFilters] = wszFilterName;
377         This->nFilters++;
378     }
379     else
380         CoTaskMemFree(wszFilterName);
381
382     if (SUCCEEDED(hr) && duplicate_name)
383         return VFW_S_DUPLICATE_NAME;
384         
385     return hr;
386 }
387
388 static HRESULT WINAPI Graphbuilder_RemoveFilter(IGraphBuilder *iface,
389                                                 IBaseFilter *pFilter) {
390     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
391     int i;
392     HRESULT hr = E_FAIL;
393
394     TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
395
396     /* FIXME: check graph is stopped */
397
398     for (i = 0; i < This->nFilters; i++)
399     {
400         if (This->ppFiltersInGraph[i] == pFilter)
401         {
402             /* FIXME: disconnect pins */
403             hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
404             if (SUCCEEDED(hr))
405             {
406                 IPin_Release(pFilter);
407                 CoTaskMemFree(This->pFilterNames[i]);
408                 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
409                 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
410                 This->nFilters--;
411                 return S_OK;
412             }
413             break;
414         }
415     }
416
417     return hr; /* FIXME: check this error code */
418 }
419
420 static HRESULT WINAPI Graphbuilder_EnumFilters(IGraphBuilder *iface,
421                                               IEnumFilters **ppEnum) {
422     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
423
424     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
425
426     return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
427 }
428
429 static HRESULT WINAPI Graphbuilder_FindFilterByName(IGraphBuilder *iface,
430                                                     LPCWSTR pName,
431                                                     IBaseFilter **ppFilter) {
432     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
433     int i;
434
435     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
436
437     *ppFilter = NULL;
438
439     for (i = 0; i < This->nFilters; i++)
440     {
441         if (!strcmpW(pName, This->pFilterNames[i]))
442         {
443             *ppFilter = This->ppFiltersInGraph[i];
444             IBaseFilter_AddRef(*ppFilter);
445             return S_OK;
446         }
447     }
448
449     return E_FAIL; /* FIXME: check this error code */
450 }
451
452 /* NOTE: despite the implication, it doesn't matter which
453  * way round you put in the input and output pins */
454 static HRESULT WINAPI Graphbuilder_ConnectDirect(IGraphBuilder *iface,
455                                                  IPin *ppinIn,
456                                                  IPin *ppinOut,
457                                                  const AM_MEDIA_TYPE *pmt) {
458     PIN_DIRECTION dir;
459     HRESULT hr;
460
461     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
462
463     TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
464
465     /* FIXME: check pins are in graph */
466
467     if (TRACE_ON(quartz))
468     {
469         PIN_INFO PinInfo;
470
471         hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
472         if (FAILED(hr))
473             return hr;
474
475         TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
476         IBaseFilter_Release(PinInfo.pFilter);
477
478         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
479         if (FAILED(hr))
480             return hr;
481
482         TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
483         IBaseFilter_Release(PinInfo.pFilter);
484     }
485
486     hr = IPin_QueryDirection(ppinIn, &dir);
487     if (SUCCEEDED(hr))
488     {
489         if (dir == PINDIR_INPUT)
490             hr = IPin_Connect(ppinOut, ppinIn, pmt);
491         else
492             hr = IPin_Connect(ppinIn, ppinOut, pmt);
493     }
494
495     return hr;
496 }
497
498 static HRESULT WINAPI Graphbuilder_Reconnect(IGraphBuilder *iface,
499                                              IPin *ppin) {
500     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
501     IPin *pConnectedTo = NULL;
502     HRESULT hr;
503     PIN_DIRECTION pindir;
504
505     IPin_QueryDirection(ppin, &pindir);
506     hr = IPin_ConnectedTo(ppin, &pConnectedTo);
507     if (FAILED(hr)) {
508         TRACE("Querying connected to failed: %lx\n", hr);
509         return hr; 
510     }
511     IPin_Disconnect(ppin);
512     IPin_Disconnect(pConnectedTo);
513     if (pindir == PINDIR_INPUT)
514         hr = IPin_Connect(pConnectedTo, ppin, NULL);
515     else
516         hr = IPin_Connect(ppin, pConnectedTo, NULL);
517     IPin_Release(pConnectedTo);
518     if (FAILED(hr))
519         ERR("Reconnecting pins failed, pins are not connected now..\n");
520     TRACE("(%p->%p) -- %p %p -> %lx\n", iface, This, ppin, pConnectedTo, hr);
521     return hr;
522 }
523
524 static HRESULT WINAPI Graphbuilder_Disconnect(IGraphBuilder *iface,
525                                               IPin *ppin) {
526     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
527
528     TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
529
530     return IPin_Disconnect(ppin);
531 }
532
533 static HRESULT WINAPI Graphbuilder_SetDefaultSyncSource(IGraphBuilder *iface) {
534     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
535
536     TRACE("(%p/%p)->(): stub !!!\n", iface, This);
537
538     return S_OK;
539 }
540
541 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
542 {
543     static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
544     static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
545     IPropertyBag * pPropBagCat = NULL;
546     HRESULT hr;
547
548     VariantInit(pvar);
549     V_VT(pvar) = VT_BSTR;
550
551     hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
552
553     if (SUCCEEDED(hr))
554         hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
555
556     if (SUCCEEDED(hr))
557         hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
558
559     if (SUCCEEDED(hr))
560         hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
561
562     if (SUCCEEDED(hr))
563         TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
564
565     if (pPropBagCat)
566         IPropertyBag_Release(pPropBagCat);
567
568     return hr;
569 }
570
571 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
572 {
573     HRESULT hr;
574     ULONG nb = 0;
575
576     TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
577     hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
578     if (hr == S_OK) {
579         /* Rendered input */
580     } else if (hr == S_FALSE) {
581         *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
582         hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
583         if (hr != S_OK) {
584             ERR("Error (%lx)\n", hr);
585         }
586     } else if (hr == E_NOTIMPL) {
587         /* Input connected to all outputs */
588         IEnumPins* penumpins;
589         IPin* ppin;
590         int i = 0;
591         TRACE("E_NOTIMPL\n");
592         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
593         if (FAILED(hr)) {
594             ERR("filter Enumpins failed (%lx)\n", hr);
595             return hr;
596         }
597         i = 0;
598         /* Count output pins */
599         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
600             PIN_DIRECTION pindir;
601             IPin_QueryDirection(ppin, &pindir);
602             if (pindir == PINDIR_OUTPUT)
603                 i++;
604             IPin_Release(ppin);
605         }
606         *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
607         /* Retrieve output pins */
608         IEnumPins_Reset(penumpins);
609         i = 0;
610         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
611             PIN_DIRECTION pindir;
612             IPin_QueryDirection(ppin, &pindir);
613             if (pindir == PINDIR_OUTPUT)
614                 (*pppins)[i++] = ppin;
615             else
616                 IPin_Release(ppin);
617         }
618         nb = i;
619         if (FAILED(hr)) {
620             ERR("Next failed (%lx)\n", hr);
621             return hr;
622         }
623         IEnumPins_Release(penumpins);
624     } else if (FAILED(hr)) {
625         ERR("Cannot get internal connection (%lx)\n", hr);
626         return hr;
627     }
628
629     *pnb = nb;
630     return S_OK;
631 }
632
633 /*** IGraphBuilder methods ***/
634 static HRESULT WINAPI Graphbuilder_Connect(IGraphBuilder *iface,
635                                            IPin *ppinOut,
636                                            IPin *ppinIn) {
637     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
638     HRESULT hr;
639     AM_MEDIA_TYPE* mt;
640     IEnumMediaTypes* penummt;
641     ULONG nbmt;
642     IEnumPins* penumpins;
643     IEnumMoniker* pEnumMoniker;
644     GUID tab[2];
645     ULONG nb;
646     IMoniker* pMoniker;
647     ULONG pin;
648     PIN_INFO PinInfo;
649     CLSID FilterCLSID;
650
651     TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
652
653     if (TRACE_ON(quartz))
654     {
655         hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
656         if (FAILED(hr))
657             return hr;
658
659         TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
660         IBaseFilter_Release(PinInfo.pFilter);
661
662         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
663         if (FAILED(hr))
664             return hr;
665
666         TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
667         IBaseFilter_Release(PinInfo.pFilter);
668     }
669
670     /* Try direct connection first */
671     hr = IPin_Connect(ppinOut, ppinIn, NULL);
672     if (SUCCEEDED(hr)) {
673         return S_OK;
674     }
675     TRACE("Direct connection failed, trying to insert other filters\n");
676
677     hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
678     if (FAILED(hr))
679        return hr;
680
681     hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
682     if (FAILED(hr))
683        return hr;
684
685     IBaseFilter_Release(PinInfo.pFilter);
686
687     /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream 
688      * filter to the minor mediatype of input pin of the renderer */
689     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
690     if (FAILED(hr)) {
691         ERR("EnumMediaTypes (%lx)\n", hr);
692         return hr;
693     }
694
695     hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
696     if (FAILED(hr)) {
697         ERR("IEnumMediaTypes_Next (%lx)\n", hr);
698         return hr;
699     }
700
701     if (!nbmt) {
702         ERR("No media type found!\n");
703         return S_OK;
704     }
705     TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
706     TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
707
708     /* Try to find a suitable filter that can connect to the pin to render */
709     tab[0] = mt->majortype;
710     tab[1] = mt->subtype;
711     hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
712     if (FAILED(hr)) {
713         ERR("Unable to enum filters (%lx)\n", hr);
714         return hr;
715     }
716     
717     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
718     {
719         VARIANT var;
720         GUID clsid;
721         IPin** ppins;
722         IPin* ppinfilter = NULL;
723         IBaseFilter* pfilter = NULL;
724
725         hr = GetFilterInfo(pMoniker, &clsid, &var);
726         IMoniker_Release(pMoniker);
727         if (FAILED(hr)) {
728             ERR("Unable to retrieve filter info (%lx)\n", hr);
729             goto error;
730         }
731
732         if (IsEqualGUID(&clsid, &FilterCLSID)) {
733             /* Skip filter (same as the one the output pin belongs to) */
734             goto error;
735         }
736
737         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
738         if (FAILED(hr)) {
739             ERR("Unable to create filter (%lx), trying next one\n", hr);
740             goto error;
741         }
742
743         hr = IGraphBuilder_AddFilter(iface, pfilter, NULL);
744         if (FAILED(hr)) {
745             ERR("Unable to add filter (%lx)\n", hr);
746             IBaseFilter_Release(pfilter);
747             pfilter = NULL;
748             goto error;
749         }
750
751         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
752         if (FAILED(hr)) {
753             ERR("Enumpins (%lx)\n", hr);
754             goto error;
755         }
756
757         hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
758         if (FAILED(hr)) {
759             ERR("Next (%lx)\n", hr);
760             goto error;
761         }
762         if (pin == 0) {
763             ERR("No Pin\n");
764             goto error;
765         }
766         IEnumPins_Release(penumpins);
767
768         hr = IPin_Connect(ppinOut, ppinfilter, NULL);
769         if (FAILED(hr)) {
770             TRACE("Cannot connect to filter (%lx), trying next one\n", hr);
771             goto error;
772         }
773         TRACE("Successfully connected to filter, follow chain...\n");
774
775         /* Render all output pins of the filter by calling IGraphBuilder_Render on each of them */
776         hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
777
778         if (SUCCEEDED(hr)) {
779             int i;
780             TRACE("pins to consider: %ld\n", nb);
781             for(i = 0; i < nb; i++) {
782                 TRACE("Processing pin %d\n", i);
783                 hr = IGraphBuilder_Connect(iface, ppins[i], ppinIn);
784                 if (FAILED(hr)) {
785                    TRACE("Cannot render pin %p (%lx)\n", ppinfilter, hr);
786                 }
787                 IPin_Release(ppins[i]);
788                 if (SUCCEEDED(hr)) break;
789             }
790             while (++i < nb) IPin_Release(ppins[i]);
791             CoTaskMemFree(ppins);
792             IBaseFilter_Release(pfilter);
793             IPin_Release(ppinfilter);
794             break;
795         }
796
797 error:
798         if (ppinfilter) IPin_Release(ppinfilter);
799         if (pfilter) {
800             IGraphBuilder_RemoveFilter(iface, pfilter);
801             IBaseFilter_Release(pfilter);
802         }
803     }
804
805     IEnumMediaTypes_Release(penummt);
806     DeleteMediaType(mt);
807     
808     return S_OK;
809 }
810
811 static HRESULT WINAPI Graphbuilder_Render(IGraphBuilder *iface,
812                                           IPin *ppinOut) {
813     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
814     IEnumMediaTypes* penummt;
815     AM_MEDIA_TYPE* mt;
816     ULONG nbmt;
817     HRESULT hr;
818
819     IEnumMoniker* pEnumMoniker;
820     GUID tab[2];
821     ULONG nb;
822     IMoniker* pMoniker;
823
824     TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
825
826     if (TRACE_ON(quartz))
827     {
828         PIN_INFO PinInfo;
829
830         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
831         if (FAILED(hr))
832             return hr;
833
834         TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
835         IBaseFilter_Release(PinInfo.pFilter);
836     }
837
838     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
839     if (FAILED(hr)) {
840         ERR("EnumMediaTypes (%lx)\n", hr);
841         return hr;
842     }
843
844     while(1)
845     {
846         hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
847         if (FAILED(hr)) {
848             ERR("IEnumMediaTypes_Next (%lx)\n", hr);
849             return hr;
850         }
851         if (!nbmt)
852             break;
853         TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
854         TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
855
856         /* Try to find a suitable renderer with the same media type */
857         tab[0] = mt->majortype;
858         tab[1] = GUID_NULL;
859         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL);
860         if (FAILED(hr)) {
861             ERR("Unable to enum filters (%lx)\n", hr);
862             return hr;
863         }
864
865         while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
866         {
867             VARIANT var;
868             GUID clsid;
869             IPin* ppinfilter;
870             IBaseFilter* pfilter = NULL;
871             IEnumPins* penumpins;
872             ULONG pin;
873
874             hr = GetFilterInfo(pMoniker, &clsid, &var);
875             IMoniker_Release(pMoniker);
876             if (FAILED(hr)) {
877                 ERR("Unable to retrieve filter info (%lx)\n", hr);
878                 goto error;
879             }
880
881             hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
882             if (FAILED(hr)) {
883                ERR("Unable to create filter (%lx), trying next one\n", hr);
884                goto error;
885             }
886
887             hr = IGraphBuilder_AddFilter(iface, pfilter, NULL);
888             if (FAILED(hr)) {
889                 ERR("Unable to add filter (%lx)\n", hr);
890                 pfilter = NULL;
891                 goto error;
892             }
893
894             hr = IBaseFilter_EnumPins(pfilter, &penumpins);
895             if (FAILED(hr)) {
896                 ERR("Splitter Enumpins (%lx)\n", hr);
897                 goto error;
898             }
899             hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
900             if (FAILED(hr)) {
901                ERR("Next (%lx)\n", hr);
902                goto error;
903             }
904             if (pin == 0) {
905                ERR("No Pin\n");
906                goto error;
907             }
908             IEnumPins_Release(penumpins);
909
910             /* Connect the pin to render to the renderer */
911             hr = IGraphBuilder_Connect(iface, ppinOut, ppinfilter);
912             if (FAILED(hr)) {
913                 TRACE("Unable to connect to renderer (%lx)\n", hr);
914                 goto error;
915             }
916             break;
917
918 error:
919             if (pfilter) {
920                 IGraphBuilder_RemoveFilter(iface, pfilter);
921                 IBaseFilter_Release(pfilter);
922             }
923         }
924        
925         DeleteMediaType(mt);
926         break;  
927     }
928
929     IEnumMediaTypes_Release(penummt);
930     
931     return S_OK;
932 }
933
934 static HRESULT WINAPI Graphbuilder_RenderFile(IGraphBuilder *iface,
935                                               LPCWSTR lpcwstrFile,
936                                               LPCWSTR lpcwstrPlayList) {
937     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
938     static const WCHAR string[] = {'R','e','a','d','e','r',0};
939     IBaseFilter* preader = NULL;
940     IBaseFilter* psplitter;
941     IPin* ppinreader;
942     IPin* ppinsplitter;
943     IEnumPins* penumpins;
944     ULONG pin;
945     HRESULT hr;
946     IEnumMoniker* pEnumMoniker;
947     GUID tab[2];
948     IPin** ppins;
949     ULONG nb;
950     IMoniker* pMoniker;
951     IFileSourceFilter* pfile = NULL;
952     AM_MEDIA_TYPE mt;
953     WCHAR* filename;
954
955     TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
956
957     hr = IGraphBuilder_AddSourceFilter(iface, lpcwstrFile, string, &preader);
958
959     /* Retrieve file media type */
960     if (SUCCEEDED(hr))
961         hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
962     if (SUCCEEDED(hr)) {
963         hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
964         IFileSourceFilter_Release(pfile);
965     }
966
967     if (SUCCEEDED(hr)) {
968         tab[0] = mt.majortype;
969         tab[1] = mt.subtype;
970         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
971     }
972
973     if (FAILED(hr))
974     {
975         if (preader) {
976              IGraphBuilder_RemoveFilter(iface, preader);
977              IBaseFilter_Release(preader);
978         }
979         return hr;
980     }
981
982     hr = E_FAIL;
983     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
984     {
985         VARIANT var;
986         GUID clsid;
987
988         hr = GetFilterInfo(pMoniker, &clsid, &var);
989         IMoniker_Release(pMoniker);
990         if (FAILED(hr)) {
991             ERR("Unable to retrieve filter info (%lx)\n", hr);
992             continue;
993         }
994
995         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter);
996         if (FAILED(hr)) {
997            ERR("Unable to create filter (%lx), trying next one\n", hr);
998            continue;
999         }
1000
1001         hr = IGraphBuilder_AddFilter(iface, psplitter, NULL);
1002         if (FAILED(hr)) {
1003             ERR("Unable add filter (%lx)\n", hr);
1004             return hr;
1005         }
1006
1007         /* Connect file source and splitter filters together */
1008         /* Make the splitter analyze incoming data */
1009         hr = IBaseFilter_EnumPins(preader, &penumpins);
1010         if (FAILED(hr)) {
1011             ERR("Enumpins (%lx)\n", hr);
1012             return hr;
1013         }
1014         hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin);
1015         if (FAILED(hr)) {
1016             ERR("Next (%lx)\n", hr);
1017             return hr;
1018         }
1019         if (pin == 0) {
1020             ERR("No Pin\n");
1021             return E_FAIL;
1022         }
1023         IEnumPins_Release(penumpins);
1024
1025         hr = IBaseFilter_EnumPins(psplitter, &penumpins);
1026         if (FAILED(hr)) {
1027             ERR("Splitter Enumpins (%lx)\n", hr);
1028             return hr;
1029         }
1030         hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin);
1031         if (FAILED(hr)) {
1032             ERR("Next (%lx)\n", hr);
1033             return hr;
1034         }
1035         if (pin == 0) {
1036             ERR("No Pin\n");
1037             return E_FAIL;
1038         }
1039         IEnumPins_Release(penumpins);
1040
1041         hr = IPin_Connect(ppinreader, ppinsplitter, NULL);
1042         if (FAILED(hr)) {
1043             IBaseFilter_Release(ppinsplitter);
1044             ppinsplitter = NULL;
1045             TRACE("Cannot connect to filter (%lx), trying next one\n", hr);
1046             break;
1047         }
1048         TRACE("Successfully connected to filter\n");
1049         break;
1050     }
1051
1052     /* Render all output pin of the splitter by calling IGraphBuilder_Render on each of them */
1053     if (SUCCEEDED(hr))
1054         hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb);
1055     
1056     if (SUCCEEDED(hr)) {
1057         int i;
1058         TRACE("pins to consider: %ld\n", nb);
1059         for(i = 0; i < nb; i++) {
1060             TRACE("Processing pin %d\n", i);
1061             hr = IGraphBuilder_Render(iface, ppins[i]);
1062             if (FAILED(hr)) {
1063                 ERR("Cannot render pin %p (%lx)\n", ppins[i], hr);
1064                 /* FIXME: We should clean created things properly */
1065                 break;
1066             }
1067         }
1068         CoTaskMemFree(ppins);
1069     }
1070     
1071     return hr;
1072 }
1073
1074 static HRESULT WINAPI Graphbuilder_AddSourceFilter(IGraphBuilder *iface,
1075                                                    LPCWSTR lpcwstrFileName,
1076                                                    LPCWSTR lpcwstrFilterName,
1077                                                    IBaseFilter **ppFilter) {
1078     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1079     HRESULT hr;
1080     IBaseFilter* preader;
1081     IFileSourceFilter* pfile = NULL;
1082     AM_MEDIA_TYPE mt;
1083     WCHAR* filename;
1084
1085     TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1086
1087     /* Instantiate a file source filter */ 
1088     hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1089     if (FAILED(hr)) {
1090         ERR("Unable to create file source filter (%lx)\n", hr);
1091         return hr;
1092     }
1093
1094     hr = IGraphBuilder_AddFilter(iface, preader, lpcwstrFilterName);
1095     if (FAILED(hr)) {
1096         ERR("Unable add filter (%lx)\n", hr);
1097         IBaseFilter_Release(preader);
1098         return hr;
1099     }
1100
1101     hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1102     if (FAILED(hr)) {
1103         ERR("Unable to get IFileSourceInterface (%lx)\n", hr);
1104         goto error;
1105     }
1106
1107     /* Load the file in the file source filter */
1108     hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1109     if (FAILED(hr)) {
1110         ERR("Load (%lx)\n", hr);
1111         goto error;
1112     }
1113     
1114     IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1115     if (FAILED(hr)) {
1116         ERR("GetCurFile (%lx)\n", hr);
1117         goto error;
1118     }
1119     TRACE("File %s\n", debugstr_w(filename));
1120     TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1121     TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1122
1123     if (ppFilter)
1124         *ppFilter = preader;
1125
1126     return S_OK;
1127     
1128 error:
1129     if (pfile)
1130         IFileSourceFilter_Release(pfile);
1131     IGraphBuilder_RemoveFilter(iface, preader);
1132     IBaseFilter_Release(preader);
1133        
1134     return hr;
1135 }
1136
1137 static HRESULT WINAPI Graphbuilder_SetLogFile(IGraphBuilder *iface,
1138                                               DWORD_PTR hFile) {
1139     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1140
1141     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) hFile);
1142
1143     return S_OK;
1144 }
1145
1146 static HRESULT WINAPI Graphbuilder_Abort(IGraphBuilder *iface) {
1147     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1148
1149     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1150
1151     return S_OK;
1152 }
1153
1154 static HRESULT WINAPI Graphbuilder_ShouldOperationContinue(IGraphBuilder *iface) {
1155     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1156
1157     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1158
1159     return S_OK;
1160 }
1161
1162
1163 static const IGraphBuilderVtbl IGraphBuilder_VTable =
1164 {
1165     Graphbuilder_QueryInterface,
1166     Graphbuilder_AddRef,
1167     Graphbuilder_Release,
1168     Graphbuilder_AddFilter,
1169     Graphbuilder_RemoveFilter,
1170     Graphbuilder_EnumFilters,
1171     Graphbuilder_FindFilterByName,
1172     Graphbuilder_ConnectDirect,
1173     Graphbuilder_Reconnect,
1174     Graphbuilder_Disconnect,
1175     Graphbuilder_SetDefaultSyncSource,
1176     Graphbuilder_Connect,
1177     Graphbuilder_Render,
1178     Graphbuilder_RenderFile,
1179     Graphbuilder_AddSourceFilter,
1180     Graphbuilder_SetLogFile,
1181     Graphbuilder_Abort,
1182     Graphbuilder_ShouldOperationContinue
1183 };
1184
1185 /*** IUnknown methods ***/
1186 static HRESULT WINAPI Mediacontrol_QueryInterface(IMediaControl *iface,
1187                                                   REFIID riid,
1188                                                   LPVOID*ppvObj) {
1189     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1190
1191     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1192
1193     return Filtergraph_QueryInterface(This, riid, ppvObj);
1194 }
1195
1196 static ULONG WINAPI Mediacontrol_AddRef(IMediaControl *iface) {
1197     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1198
1199     TRACE("(%p/%p)->()\n", This, iface);
1200
1201     return Filtergraph_AddRef(This);
1202 }
1203
1204 static ULONG WINAPI Mediacontrol_Release(IMediaControl *iface) {
1205     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1206
1207     TRACE("(%p/%p)->()\n", This, iface);
1208
1209     return Filtergraph_Release(This);
1210
1211 }
1212
1213 /*** IDispatch methods ***/
1214 static HRESULT WINAPI Mediacontrol_GetTypeInfoCount(IMediaControl *iface,
1215                                                     UINT*pctinfo) {
1216     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1217
1218     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1219
1220     return S_OK;
1221 }
1222
1223 static HRESULT WINAPI Mediacontrol_GetTypeInfo(IMediaControl *iface,
1224                                                UINT iTInfo,
1225                                                LCID lcid,
1226                                                ITypeInfo**ppTInfo) {
1227     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1228
1229     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1230
1231     return S_OK;
1232 }
1233
1234 static HRESULT WINAPI Mediacontrol_GetIDsOfNames(IMediaControl *iface,
1235                                                  REFIID riid,
1236                                                  LPOLESTR*rgszNames,
1237                                                  UINT cNames,
1238                                                  LCID lcid,
1239                                                  DISPID*rgDispId) {
1240     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1241
1242     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1243
1244     return S_OK;
1245 }
1246
1247 static HRESULT WINAPI Mediacontrol_Invoke(IMediaControl *iface,
1248                                           DISPID dispIdMember,
1249                                           REFIID riid,
1250                                           LCID lcid,
1251                                           WORD wFlags,
1252                                           DISPPARAMS*pDispParams,
1253                                           VARIANT*pVarResult,
1254                                           EXCEPINFO*pExepInfo,
1255                                           UINT*puArgErr) {
1256     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1257
1258     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1259
1260     return S_OK;
1261 }
1262
1263 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *);
1264
1265 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter)
1266 {
1267     HRESULT hr;
1268     IPin* pInputPin;
1269     IPin** ppPins;
1270     ULONG nb;
1271     ULONG i;
1272     PIN_INFO PinInfo;
1273
1274     TRACE("%p %p\n", pGraph, pOutputPin);
1275     PinInfo.pFilter = NULL;
1276
1277     hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1278
1279     if (SUCCEEDED(hr))
1280         hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1281
1282     if (SUCCEEDED(hr))
1283         hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1284
1285     if (SUCCEEDED(hr))
1286     {
1287         if (nb == 0)
1288         {
1289             TRACE("Reached a renderer\n");
1290             /* Count renderers for end of stream notification */
1291             pGraph->nRenderers++;
1292         }
1293         else
1294         {
1295             for(i = 0; i < nb; i++)
1296             {
1297                 /* Explore the graph downstream from this pin
1298                  * FIXME: We should prevent exploring from a pin more than once. This can happens when
1299                  * several input pins are connected to the same output (a MUX for instance). */
1300                 ExploreGraph(pGraph, ppPins[i], FoundFilter);
1301                 IPin_Release(ppPins[i]);
1302             }
1303
1304             CoTaskMemFree(ppPins);
1305         }
1306         TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1307         FoundFilter(PinInfo.pFilter);
1308     }
1309
1310     if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1311     return hr;
1312 }
1313
1314 static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
1315    return IBaseFilter_Run(pFilter, 0);
1316 }
1317
1318 static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
1319    return IBaseFilter_Pause(pFilter);
1320 }
1321
1322 static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
1323    return IBaseFilter_Stop(pFilter);
1324 }
1325
1326 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) {
1327     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1328     int i;
1329     IBaseFilter* pfilter;
1330     IEnumPins* pEnum;
1331     HRESULT hr;
1332     IPin* pPin;
1333     LONG dummy;
1334     PIN_DIRECTION dir;
1335     TRACE("(%p/%p)->()\n", This, iface);
1336
1337     /* Explorer the graph from source filters to renderers, determine renderers
1338      * number and run filters from renderers to source filters */
1339     This->nRenderers = 0;  
1340     ResetEvent(This->hEventCompletion);
1341
1342     for(i = 0; i < This->nFilters; i++)
1343     {
1344         BOOL source = TRUE;
1345         pfilter = This->ppFiltersInGraph[i];
1346         hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1347         if (hr != S_OK)
1348         {
1349             ERR("Enum pins failed %lx\n", hr);
1350             continue;
1351         }
1352         /* Check if it is a source filter */
1353         while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1354         {
1355             IPin_QueryDirection(pPin, &dir);
1356             IPin_Release(pPin);
1357             if (dir == PINDIR_INPUT)
1358             {
1359                 source = FALSE;
1360                 break;
1361             }
1362         }
1363         if (source == TRUE)
1364         {
1365             TRACE("Found a source filter %p\n", pfilter);
1366             IEnumPins_Reset(pEnum);
1367             while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1368             {
1369                 /* Explore the graph downstream from this pin */
1370                 ExploreGraph(This, pPin, FoundFilter);
1371                 IPin_Release(pPin);
1372             }
1373             FoundFilter(pfilter);
1374         }
1375         IEnumPins_Release(pEnum);
1376     }
1377
1378     return S_FALSE;
1379 }
1380
1381 /*** IMediaControl methods ***/
1382 static HRESULT WINAPI Mediacontrol_Run(IMediaControl *iface) {
1383     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1384     TRACE("(%p/%p)->()\n", This, iface);
1385
1386     if (This->state == State_Running) return S_OK;
1387
1388     EnterCriticalSection(&This->cs);
1389     SendFilterMessage(iface, SendRun);
1390     This->state = State_Running;
1391     LeaveCriticalSection(&This->cs);
1392     return S_FALSE;
1393 }
1394
1395 static HRESULT WINAPI Mediacontrol_Pause(IMediaControl *iface) {
1396     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1397     TRACE("(%p/%p)->()\n", This, iface);
1398
1399     if (This->state == State_Paused) return S_OK;
1400
1401     EnterCriticalSection(&This->cs);
1402     SendFilterMessage(iface, SendPause);
1403     This->state = State_Paused;
1404     LeaveCriticalSection(&This->cs);
1405     return S_FALSE;
1406 }
1407
1408 static HRESULT WINAPI Mediacontrol_Stop(IMediaControl *iface) {
1409     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1410     TRACE("(%p/%p)->()\n", This, iface);
1411
1412     if (This->state == State_Stopped) return S_OK;
1413
1414     EnterCriticalSection(&This->cs);
1415     if (This->state == State_Running) SendFilterMessage(iface, SendPause);
1416     SendFilterMessage(iface, SendStop);
1417     This->state = State_Stopped;
1418     LeaveCriticalSection(&This->cs);
1419     return S_FALSE;
1420 }
1421
1422 static HRESULT WINAPI Mediacontrol_GetState(IMediaControl *iface,
1423                                             LONG msTimeout,
1424                                             OAFilterState *pfs) {
1425     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1426
1427     TRACE("(%p/%p)->(%ld, %p): semi-stub !!!\n", This, iface, msTimeout, pfs);
1428
1429     EnterCriticalSection(&This->cs);
1430
1431     *pfs = This->state;
1432
1433     LeaveCriticalSection(&This->cs);
1434
1435     return S_OK;
1436 }
1437
1438 static HRESULT WINAPI Mediacontrol_RenderFile(IMediaControl *iface,
1439                                               BSTR strFilename) {
1440     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1441
1442     TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1443
1444     return S_OK;
1445 }
1446
1447 static HRESULT WINAPI Mediacontrol_AddSourceFilter(IMediaControl *iface,
1448                                                    BSTR strFilename,
1449                                                    IDispatch **ppUnk) {
1450     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1451
1452     TRACE("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1453
1454     return S_OK;
1455 }
1456
1457 static HRESULT WINAPI Mediacontrol_get_FilterCollection(IMediaControl *iface,
1458                                                         IDispatch **ppUnk) {
1459     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1460
1461     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1462
1463     return S_OK;
1464 }
1465
1466 static HRESULT WINAPI Mediacontrol_get_RegFilterCollection(IMediaControl *iface,
1467                                                            IDispatch **ppUnk) {
1468     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1469
1470     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1471
1472     return S_OK;
1473 }
1474
1475 static HRESULT WINAPI Mediacontrol_StopWhenReady(IMediaControl *iface) {
1476     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1477
1478     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1479
1480     return S_OK;
1481 }
1482
1483
1484 static const IMediaControlVtbl IMediaControl_VTable =
1485 {
1486     Mediacontrol_QueryInterface,
1487     Mediacontrol_AddRef,
1488     Mediacontrol_Release,
1489     Mediacontrol_GetTypeInfoCount,
1490     Mediacontrol_GetTypeInfo,
1491     Mediacontrol_GetIDsOfNames,
1492     Mediacontrol_Invoke,
1493     Mediacontrol_Run,
1494     Mediacontrol_Pause,
1495     Mediacontrol_Stop,
1496     Mediacontrol_GetState,
1497     Mediacontrol_RenderFile,
1498     Mediacontrol_AddSourceFilter,
1499     Mediacontrol_get_FilterCollection,
1500     Mediacontrol_get_RegFilterCollection,
1501     Mediacontrol_StopWhenReady
1502 };
1503
1504
1505 /*** IUnknown methods ***/
1506 static HRESULT WINAPI Mediaseeking_QueryInterface(IMediaSeeking *iface,
1507                                                   REFIID riid,
1508                                                   LPVOID*ppvObj) {
1509     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1510
1511     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1512
1513     return Filtergraph_QueryInterface(This, riid, ppvObj);
1514 }
1515
1516 static ULONG WINAPI Mediaseeking_AddRef(IMediaSeeking *iface) {
1517     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1518
1519     TRACE("(%p/%p)->()\n", This, iface);
1520
1521     return Filtergraph_AddRef(This);
1522 }
1523
1524 static ULONG WINAPI Mediaseeking_Release(IMediaSeeking *iface) {
1525     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1526
1527     TRACE("(%p/%p)->()\n", This, iface);
1528
1529     return Filtergraph_Release(This);
1530 }
1531
1532 /*** IMediaSeeking methods ***/
1533 static HRESULT WINAPI Mediaseeking_GetCapabilities(IMediaSeeking *iface,
1534                                                    DWORD *pCapabilities) {
1535     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1536
1537     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1538
1539     return S_OK;
1540 }
1541
1542 static HRESULT WINAPI Mediaseeking_CheckCapabilities(IMediaSeeking *iface,
1543                                                      DWORD *pCapabilities) {
1544     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1545
1546     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1547
1548     return S_OK;
1549 }
1550
1551 static HRESULT WINAPI Mediaseeking_IsFormatSupported(IMediaSeeking *iface,
1552                                                      const GUID *pFormat) {
1553     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1554
1555     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1556
1557     return S_OK;
1558 }
1559
1560 static HRESULT WINAPI Mediaseeking_QueryPreferredFormat(IMediaSeeking *iface,
1561                                                         GUID *pFormat) {
1562     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1563
1564     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1565
1566     return S_OK;
1567 }
1568
1569 static HRESULT WINAPI Mediaseeking_GetTimeFormat(IMediaSeeking *iface,
1570                                                  GUID *pFormat) {
1571     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1572
1573     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1574
1575     return S_OK;
1576 }
1577
1578 static HRESULT WINAPI Mediaseeking_IsUsingTimeFormat(IMediaSeeking *iface,
1579                                                      const GUID *pFormat) {
1580     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1581
1582     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1583
1584     return S_OK;
1585 }
1586
1587 static HRESULT WINAPI Mediaseeking_SetTimeFormat(IMediaSeeking *iface,
1588                                                  const GUID *pFormat) {
1589     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1590
1591     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1592
1593     return S_OK;
1594 }
1595
1596 static HRESULT WINAPI Mediaseeking_GetDuration(IMediaSeeking *iface,
1597                                                LONGLONG *pDuration) {
1598     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1599
1600     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDuration);
1601
1602     return S_OK;
1603 }
1604
1605 static HRESULT WINAPI Mediaseeking_GetStopPosition(IMediaSeeking *iface,
1606                                                    LONGLONG *pStop) {
1607     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1608
1609     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1610
1611     return S_OK;
1612 }
1613
1614 static HRESULT WINAPI Mediaseeking_GetCurrentPosition(IMediaSeeking *iface,
1615                                                       LONGLONG *pCurrent) {
1616     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1617
1618     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent);
1619
1620     return S_OK;
1621 }
1622
1623 static HRESULT WINAPI Mediaseeking_ConvertTimeFormat(IMediaSeeking *iface,
1624                                                      LONGLONG *pTarget,
1625                                                      const GUID *pTargetFormat,
1626                                                      LONGLONG Source,
1627                                                      const GUID *pSourceFormat) {
1628     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1629
1630     TRACE("(%p/%p)->(%p, %p, %lld, %p): stub !!!\n", This, iface, pTarget, pTargetFormat, Source, pSourceFormat);
1631
1632     return S_OK;
1633 }
1634
1635 static HRESULT WINAPI Mediaseeking_SetPositions(IMediaSeeking *iface,
1636                                                 LONGLONG *pCurrent,
1637                                                 DWORD dwCurrentFlags,
1638                                                 LONGLONG *pStop,
1639                                                 DWORD dwStopFlags) {
1640     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1641
1642     TRACE("(%p/%p)->(%p, %08lx, %p, %08lx): stub !!!\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1643
1644     return S_OK;
1645 }
1646
1647 static HRESULT WINAPI Mediaseeking_GetPositions(IMediaSeeking *iface,
1648                                                 LONGLONG *pCurrent,
1649                                                 LONGLONG *pStop) {
1650     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1651
1652     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pCurrent, pStop);
1653
1654     return S_OK;
1655 }
1656
1657 static HRESULT WINAPI Mediaseeking_GetAvailable(IMediaSeeking *iface,
1658                                                 LONGLONG *pEarliest,
1659                                                 LONGLONG *pLatest) {
1660     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1661
1662     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
1663
1664     return S_OK;
1665 }
1666
1667 static HRESULT WINAPI Mediaseeking_SetRate(IMediaSeeking *iface,
1668                                            double dRate) {
1669     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1670
1671     TRACE("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
1672
1673     return S_OK;
1674 }
1675
1676 static HRESULT WINAPI Mediaseeking_GetRate(IMediaSeeking *iface,
1677                                            double *pdRate) {
1678     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1679
1680     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
1681
1682     return S_OK;
1683 }
1684
1685 static HRESULT WINAPI Mediaseeking_GetPreroll(IMediaSeeking *iface,
1686                                               LONGLONG *pllPreroll) {
1687     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1688
1689     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
1690
1691     return S_OK;
1692 }
1693
1694
1695 static const IMediaSeekingVtbl IMediaSeeking_VTable =
1696 {
1697     Mediaseeking_QueryInterface,
1698     Mediaseeking_AddRef,
1699     Mediaseeking_Release,
1700     Mediaseeking_GetCapabilities,
1701     Mediaseeking_CheckCapabilities,
1702     Mediaseeking_IsFormatSupported,
1703     Mediaseeking_QueryPreferredFormat,
1704     Mediaseeking_GetTimeFormat,
1705     Mediaseeking_IsUsingTimeFormat,
1706     Mediaseeking_SetTimeFormat,
1707     Mediaseeking_GetDuration,
1708     Mediaseeking_GetStopPosition,
1709     Mediaseeking_GetCurrentPosition,
1710     Mediaseeking_ConvertTimeFormat,
1711     Mediaseeking_SetPositions,
1712     Mediaseeking_GetPositions,
1713     Mediaseeking_GetAvailable,
1714     Mediaseeking_SetRate,
1715     Mediaseeking_GetRate,
1716     Mediaseeking_GetPreroll
1717 };
1718
1719 /*** IUnknown methods ***/
1720 static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface,
1721                                                 REFIID riid,
1722                                                 LPVOID*ppvObj) {
1723     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1724
1725     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1726
1727     return Filtergraph_QueryInterface(This, riid, ppvObj);
1728 }
1729
1730 static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
1731     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1732
1733     TRACE("(%p/%p)->()\n", This, iface);
1734
1735     return Filtergraph_AddRef(This);
1736 }
1737
1738 static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
1739     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1740
1741     TRACE("(%p/%p)->()\n", This, iface);
1742
1743     return Filtergraph_Release(This);
1744 }
1745
1746 /*** IDispatch methods ***/
1747 static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface,
1748                                                   UINT*pctinfo) {
1749     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1750
1751     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1752
1753     return S_OK;
1754 }
1755
1756 static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface,
1757                                              UINT iTInfo,
1758                                              LCID lcid,
1759                                              ITypeInfo**ppTInfo) {
1760     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1761
1762     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1763
1764     return S_OK;
1765 }
1766
1767 static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface,
1768                                                REFIID riid,
1769                                                LPOLESTR*rgszNames,
1770                                                UINT cNames,
1771                                                LCID lcid,
1772                                                DISPID*rgDispId) {
1773     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1774
1775     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1776
1777     return S_OK;
1778 }
1779
1780 static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface,
1781                                         DISPID dispIdMember,
1782                                         REFIID riid,
1783                                         LCID lcid,
1784                                         WORD wFlags,
1785                                         DISPPARAMS*pDispParams,
1786                                         VARIANT*pVarResult,
1787                                         EXCEPINFO*pExepInfo,
1788                                         UINT*puArgErr) {
1789     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1790
1791     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1792
1793     return S_OK;
1794 }
1795
1796 /*** IBasicAudio methods ***/
1797 static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface,
1798                                             long lVolume) {
1799     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1800
1801     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lVolume);
1802
1803     return S_OK;
1804 }
1805
1806 static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface,
1807                                             long *plVolume) {
1808     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1809
1810     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plVolume);
1811
1812     return S_OK;
1813 }
1814
1815 static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface,
1816                                              long lBalance) {
1817     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1818
1819     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lBalance);
1820
1821     return S_OK;
1822 }
1823
1824 static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface,
1825                                              long *plBalance) {
1826     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1827
1828     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plBalance);
1829
1830     return S_OK;
1831 }
1832
1833 static const IBasicAudioVtbl IBasicAudio_VTable =
1834 {
1835     Basicaudio_QueryInterface,
1836     Basicaudio_AddRef,
1837     Basicaudio_Release,
1838     Basicaudio_GetTypeInfoCount,
1839     Basicaudio_GetTypeInfo,
1840     Basicaudio_GetIDsOfNames,
1841     Basicaudio_Invoke,
1842     Basicaudio_put_Volume,
1843     Basicaudio_get_Volume,
1844     Basicaudio_put_Balance,
1845     Basicaudio_get_Balance
1846 };
1847
1848 /*** IUnknown methods ***/
1849 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
1850                                                 REFIID riid,
1851                                                 LPVOID*ppvObj) {
1852     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1853
1854     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1855
1856     return Filtergraph_QueryInterface(This, riid, ppvObj);
1857 }
1858
1859 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
1860     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1861
1862     TRACE("(%p/%p)->()\n", This, iface);
1863
1864     return Filtergraph_AddRef(This);
1865 }
1866
1867 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
1868     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1869
1870     TRACE("(%p/%p)->()\n", This, iface);
1871
1872     return Filtergraph_Release(This);
1873 }
1874
1875 /*** IDispatch methods ***/
1876 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
1877                                                   UINT*pctinfo) {
1878     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1879
1880     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1881
1882     return S_OK;
1883 }
1884
1885 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
1886                                              UINT iTInfo,
1887                                              LCID lcid,
1888                                              ITypeInfo**ppTInfo) {
1889     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1890
1891     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1892
1893     return S_OK;
1894 }
1895
1896 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
1897                                                REFIID riid,
1898                                                LPOLESTR*rgszNames,
1899                                                UINT cNames,
1900                                                LCID lcid,
1901                                                DISPID*rgDispId) {
1902     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1903
1904     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1905
1906     return S_OK;
1907 }
1908
1909 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
1910                                         DISPID dispIdMember,
1911                                         REFIID riid,
1912                                         LCID lcid,
1913                                         WORD wFlags,
1914                                         DISPPARAMS*pDispParams,
1915                                         VARIANT*pVarResult,
1916                                         EXCEPINFO*pExepInfo,
1917                                         UINT*puArgErr) {
1918     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1919
1920     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1921
1922     return S_OK;
1923 }
1924
1925 /*** IBasicVideo methods ***/
1926 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
1927                                                      REFTIME *pAvgTimePerFrame) {
1928     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1929
1930     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
1931
1932     return S_OK;
1933 }
1934
1935 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
1936                                              long *pBitRate) {
1937     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1938
1939     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
1940
1941     return S_OK;
1942 }
1943
1944 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
1945                                                   long *pBitErrorRate) {
1946     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1947
1948     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
1949
1950     return S_OK;
1951 }
1952
1953 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
1954                                                 long *pVideoWidth) {
1955     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1956
1957     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoWidth);
1958
1959     return S_OK;
1960 }
1961
1962 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
1963                                                  long *pVideoHeight) {
1964     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1965
1966     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoHeight);
1967
1968     return S_OK;
1969 }
1970
1971 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1972                                                 long SourceLeft) {
1973     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1974
1975     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceLeft);
1976
1977     return S_OK;
1978 }
1979
1980 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1981                                                 long *pSourceLeft) {
1982     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1983
1984     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceLeft);
1985
1986     return S_OK;
1987 }
1988
1989 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1990                                                  long SourceWidth) {
1991     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1992
1993     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceWidth);
1994
1995     return S_OK;
1996 }
1997
1998 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1999                                                  long *pSourceWidth) {
2000     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2001
2002     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceWidth);
2003
2004     return S_OK;
2005 }
2006
2007 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
2008                                                long SourceTop) {
2009     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2010
2011     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceTop);
2012
2013     return S_OK;
2014 }
2015
2016 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
2017                                                long *pSourceTop) {
2018     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2019
2020     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceTop);
2021
2022     return S_OK;
2023 }
2024
2025 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
2026                                                   long SourceHeight) {
2027     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2028
2029     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceHeight);
2030
2031     return S_OK;
2032 }
2033
2034 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
2035                                                   long *pSourceHeight) {
2036     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2037
2038     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceHeight);
2039
2040     return S_OK;
2041 }
2042
2043 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
2044                                                      long DestinationLeft) {
2045     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2046
2047     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationLeft);
2048
2049     return S_OK;
2050 }
2051
2052 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
2053                                                      long *pDestinationLeft) {
2054     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2055
2056     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationLeft);
2057
2058     return S_OK;
2059 }
2060
2061 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
2062                                                       long DestinationWidth) {
2063     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2064
2065     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationWidth);
2066
2067     return S_OK;
2068 }
2069
2070 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
2071                                                       long *pDestinationWidth) {
2072     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2073
2074     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationWidth);
2075
2076     return S_OK;
2077 }
2078
2079 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
2080                                                     long DestinationTop) {
2081     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2082
2083     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationTop);
2084
2085     return S_OK;
2086 }
2087
2088 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
2089                                                     long *pDestinationTop) {
2090     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2091
2092     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationTop);
2093
2094     return S_OK;
2095 }
2096
2097 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
2098                                                        long DestinationHeight) {
2099     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2100
2101     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationHeight);
2102
2103     return S_OK;
2104 }
2105
2106 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
2107                                                        long *pDestinationHeight) {
2108     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2109
2110     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationHeight);
2111
2112     return S_OK;
2113 }
2114
2115 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
2116                                                    long Left,
2117                                                    long Top,
2118                                                    long Width,
2119                                                    long Height) {
2120     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2121
2122     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
2123
2124     return S_OK;
2125 }
2126
2127 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
2128                                                    long *pLeft,
2129                                                    long *pTop,
2130                                                    long *pWidth,
2131                                                    long *pHeight) {
2132     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2133
2134     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2135
2136     return S_OK;
2137 }
2138
2139 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
2140     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2141
2142     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2143
2144     return S_OK;
2145 }
2146
2147 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
2148                                                         long Left,
2149                                                         long Top,
2150                                                         long Width,
2151                                                         long Height) {
2152     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2153
2154     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
2155
2156     return S_OK;
2157 }
2158
2159 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
2160                                                         long *pLeft,
2161                                                         long *pTop,
2162                                                         long *pWidth,
2163                                                         long *pHeight) {
2164     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2165
2166     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2167
2168     return S_OK;
2169 }
2170
2171 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
2172     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2173
2174     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2175
2176     return S_OK;
2177 }
2178
2179 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
2180                                               long *pWidth,
2181                                               long *pHeight) {
2182     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2183
2184     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2185
2186     return S_OK;
2187 }
2188
2189 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
2190                                                         long StartIndex,
2191                                                         long Entries,
2192                                                         long *pRetrieved,
2193                                                         long *pPalette) {
2194     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2195
2196     TRACE("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
2197
2198     return S_OK;
2199 }
2200
2201 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
2202                                                  long *pBufferSize,
2203                                                  long *pDIBImage) {
2204     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2205
2206     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
2207
2208     return S_OK;
2209 }
2210
2211 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
2212     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2213
2214     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2215
2216     return S_OK;
2217 }
2218
2219 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
2220     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2221
2222     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2223
2224     return S_OK;
2225 }
2226
2227
2228 static const IBasicVideoVtbl IBasicVideo_VTable =
2229 {
2230     Basicvideo_QueryInterface,
2231     Basicvideo_AddRef,
2232     Basicvideo_Release,
2233     Basicvideo_GetTypeInfoCount,
2234     Basicvideo_GetTypeInfo,
2235     Basicvideo_GetIDsOfNames,
2236     Basicvideo_Invoke,
2237     Basicvideo_get_AvgTimePerFrame,
2238     Basicvideo_get_BitRate,
2239     Basicvideo_get_BitErrorRate,
2240     Basicvideo_get_VideoWidth,
2241     Basicvideo_get_VideoHeight,
2242     Basicvideo_put_SourceLeft,
2243     Basicvideo_get_SourceLeft,
2244     Basicvideo_put_SourceWidth,
2245     Basicvideo_get_SourceWidth,
2246     Basicvideo_put_SourceTop,
2247     Basicvideo_get_SourceTop,
2248     Basicvideo_put_SourceHeight,
2249     Basicvideo_get_SourceHeight,
2250     Basicvideo_put_DestinationLeft,
2251     Basicvideo_get_DestinationLeft,
2252     Basicvideo_put_DestinationWidth,
2253     Basicvideo_get_DestinationWidth,
2254     Basicvideo_put_DestinationTop,
2255     Basicvideo_get_DestinationTop,
2256     Basicvideo_put_DestinationHeight,
2257     Basicvideo_get_DestinationHeight,
2258     Basicvideo_SetSourcePosition,
2259     Basicvideo_GetSourcePosition,
2260     Basicvideo_SetDefaultSourcePosition,
2261     Basicvideo_SetDestinationPosition,
2262     Basicvideo_GetDestinationPosition,
2263     Basicvideo_SetDefaultDestinationPosition,
2264     Basicvideo_GetVideoSize,
2265     Basicvideo_GetVideoPaletteEntries,
2266     Basicvideo_GetCurrentImage,
2267     Basicvideo_IsUsingDefaultSource,
2268     Basicvideo_IsUsingDefaultDestination
2269 };
2270
2271
2272 /*** IUnknown methods ***/
2273 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
2274                                                  REFIID riid,
2275                                                  LPVOID*ppvObj) {
2276     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2277
2278     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2279
2280     return Filtergraph_QueryInterface(This, riid, ppvObj);
2281 }
2282
2283 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
2284     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2285
2286     TRACE("(%p/%p)->()\n", This, iface);
2287
2288     return Filtergraph_AddRef(This);
2289 }
2290
2291 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
2292     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2293
2294     TRACE("(%p/%p)->()\n", This, iface);
2295
2296     return Filtergraph_Release(This);
2297 }
2298
2299 /*** IDispatch methods ***/
2300 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
2301                                                    UINT*pctinfo) {
2302     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2303
2304     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
2305
2306     return S_OK;
2307 }
2308
2309 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
2310                                               UINT iTInfo,
2311                                               LCID lcid,
2312                                               ITypeInfo**ppTInfo) {
2313     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2314
2315     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
2316
2317     return S_OK;
2318 }
2319
2320 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
2321                                                 REFIID riid,
2322                                                 LPOLESTR*rgszNames,
2323                                                 UINT cNames,
2324                                                 LCID lcid,
2325                                                 DISPID*rgDispId) {
2326     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2327
2328     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2329
2330     return S_OK;
2331 }
2332
2333 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
2334                                          DISPID dispIdMember,
2335                                          REFIID riid,
2336                                          LCID lcid,
2337                                          WORD wFlags,
2338                                          DISPPARAMS*pDispParams,
2339                                          VARIANT*pVarResult,
2340                                          EXCEPINFO*pExepInfo,
2341                                          UINT*puArgErr) {
2342     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2343
2344     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2345
2346     return S_OK;
2347 }
2348
2349 /*** IVideoWindow methods ***/
2350 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
2351                                               BSTR strCaption) {
2352     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2353
2354     TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strCaption), strCaption);
2355
2356     return S_OK;
2357 }
2358
2359 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
2360                                               BSTR *strCaption) {
2361     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2362
2363     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, strCaption);
2364
2365     return S_OK;
2366 }
2367
2368 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
2369                                                   long WindowStyle) {
2370     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2371
2372     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyle);
2373
2374     return S_OK;
2375 }
2376
2377 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
2378                                                   long *WindowStyle) {
2379     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2380
2381     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyle);
2382
2383     return S_OK;
2384 }
2385
2386 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
2387                                                     long WindowStyleEx) {
2388     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2389
2390     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyleEx);
2391
2392     return S_OK;
2393 }
2394
2395 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
2396                                                     long *WindowStyleEx) {
2397     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2398
2399     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyleEx);
2400
2401     return S_OK;
2402 }
2403
2404 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
2405                                                long AutoShow) {
2406     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2407
2408     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, AutoShow);
2409
2410     return S_OK;
2411 }
2412
2413 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
2414                                                long *AutoShow) {
2415     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2416
2417     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, AutoShow);
2418
2419     return S_OK;
2420 }
2421
2422 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
2423                                                   long WindowState) {
2424     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2425
2426     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
2427
2428     return S_OK;
2429 }
2430
2431 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
2432                                                   long *WindowState) {
2433     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2434
2435     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
2436
2437     return S_OK;
2438 }
2439
2440 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
2441                                                         long BackgroundPalette) {
2442     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2443
2444     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
2445
2446     return S_OK;
2447 }
2448
2449 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
2450                                                         long *pBackgroundPalette) {
2451     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2452
2453     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
2454
2455     return S_OK;
2456 }
2457
2458 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
2459                                               long Visible) {
2460     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2461
2462     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Visible);
2463
2464     return S_OK;
2465 }
2466
2467 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
2468                                               long *pVisible) {
2469     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2470
2471     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVisible);
2472
2473     return S_OK;
2474 }
2475
2476 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
2477                                            long Left) {
2478     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2479
2480     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Left);
2481
2482     return S_OK;
2483 }
2484
2485 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
2486                                            long *pLeft) {
2487     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2488
2489     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pLeft);
2490
2491     return S_OK;
2492 }
2493
2494 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
2495                                             long Width) {
2496     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2497
2498     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Width);
2499
2500     return S_OK;
2501 }
2502
2503 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
2504                                             long *pWidth) {
2505     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2506
2507     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pWidth);
2508
2509     return S_OK;
2510 }
2511
2512 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
2513                                           long Top) {
2514     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2515
2516     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Top);
2517
2518     return S_OK;
2519 }
2520
2521 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
2522                                           long *pTop) {
2523     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2524
2525     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pTop);
2526
2527     return S_OK;
2528 }
2529
2530 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
2531                                              long Height) {
2532     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2533
2534     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Height);
2535
2536     return S_OK;
2537 }
2538
2539 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
2540                                              long *pHeight) {
2541     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2542
2543     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pHeight);
2544
2545     return S_OK;
2546 }
2547
2548 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
2549                                             OAHWND Owner) {
2550     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2551
2552     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
2553
2554     return S_OK;
2555 }
2556
2557 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
2558                                             OAHWND *Owner) {
2559     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2560
2561     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
2562
2563     return S_OK;
2564 }
2565
2566 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
2567                                                    OAHWND Drain) {
2568     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2569
2570     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Drain);
2571
2572     return S_OK;
2573 }
2574
2575 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
2576                                                    OAHWND *Drain) {
2577     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2578
2579     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Drain);
2580
2581     return S_OK;
2582 }
2583
2584 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
2585                                                   long *Color) {
2586     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2587
2588     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
2589
2590     return S_OK;
2591 }
2592
2593 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
2594                                                   long Color) {
2595     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2596
2597     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
2598
2599     return S_OK;
2600 }
2601
2602 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
2603                                                      long *FullScreenMode) {
2604     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2605
2606     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
2607
2608     return S_OK;
2609 }
2610
2611 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
2612                                                      long FullScreenMode) {
2613     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2614
2615     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
2616
2617     return S_OK;
2618 }
2619
2620 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
2621                                                       long Focus) {
2622     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2623
2624     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Focus);
2625
2626     return S_OK;
2627 }
2628
2629 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
2630                                                      OAHWND hwnd,
2631                                                      long uMsg,
2632                                                      LONG_PTR wParam,
2633                                                      LONG_PTR lParam) {
2634     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2635
2636     TRACE("(%p/%p)->(%08lx, %ld, %08lx, %08lx): stub !!!\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
2637
2638     return S_OK;
2639 }
2640
2641 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
2642                                                     long Left,
2643                                                     long Top,
2644                                                     long Width,
2645                                                     long Height) {
2646     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2647     
2648     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
2649
2650     return S_OK;
2651 }
2652
2653 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
2654                                                     long *pLeft,
2655                                                     long *pTop,
2656                                                     long *pWidth,
2657                                                     long *pHeight) {
2658     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2659
2660     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2661
2662     return S_OK;
2663 }
2664
2665 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
2666                                                        long *pWidth,
2667                                                        long *pHeight) {
2668     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2669
2670     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2671
2672     return S_OK;
2673 }
2674
2675 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
2676                                                        long *pWidth,
2677                                                        long *pHeight) {
2678     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2679
2680     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2681
2682     return S_OK;
2683 }
2684
2685 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
2686                                                      long *pLeft,
2687                                                      long *pTop,
2688                                                      long *pWidth,
2689                                                      long *pHeight) {
2690     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2691
2692     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2693
2694     return S_OK;
2695 }
2696
2697 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
2698                                              long HideCursor) {
2699     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2700
2701     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
2702
2703     return S_OK;
2704 }
2705
2706 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
2707                                                  long *CursorHidden) {
2708     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2709
2710     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
2711
2712     return S_OK;
2713 }
2714
2715
2716 static const IVideoWindowVtbl IVideoWindow_VTable =
2717 {
2718     Videowindow_QueryInterface,
2719     Videowindow_AddRef,
2720     Videowindow_Release,
2721     Videowindow_GetTypeInfoCount,
2722     Videowindow_GetTypeInfo,
2723     Videowindow_GetIDsOfNames,
2724     Videowindow_Invoke,
2725     Videowindow_put_Caption,
2726     Videowindow_get_Caption,
2727     Videowindow_put_WindowStyle,
2728     Videowindow_get_WindowStyle,
2729     Videowindow_put_WindowStyleEx,
2730     Videowindow_get_WindowStyleEx,
2731     Videowindow_put_AutoShow,
2732     Videowindow_get_AutoShow,
2733     Videowindow_put_WindowState,
2734     Videowindow_get_WindowState,
2735     Videowindow_put_BackgroundPalette,
2736     Videowindow_get_BackgroundPalette,
2737     Videowindow_put_Visible,
2738     Videowindow_get_Visible,
2739     Videowindow_put_Left,
2740     Videowindow_get_Left,
2741     Videowindow_put_Width,
2742     Videowindow_get_Width,
2743     Videowindow_put_Top,
2744     Videowindow_get_Top,
2745     Videowindow_put_Height,
2746     Videowindow_get_Height,
2747     Videowindow_put_Owner,
2748     Videowindow_get_Owner,
2749     Videowindow_put_MessageDrain,
2750     Videowindow_get_MessageDrain,
2751     Videowindow_get_BorderColor,
2752     Videowindow_put_BorderColor,
2753     Videowindow_get_FullScreenMode,
2754     Videowindow_put_FullScreenMode,
2755     Videowindow_SetWindowForeground,
2756     Videowindow_NotifyOwnerMessage,
2757     Videowindow_SetWindowPosition,
2758     Videowindow_GetWindowPosition,
2759     Videowindow_GetMinIdealImageSize,
2760     Videowindow_GetMaxIdealImageSize,
2761     Videowindow_GetRestorePosition,
2762     Videowindow_HideCursor,
2763     Videowindow_IsCursorHidden
2764 };
2765
2766
2767 /*** IUnknown methods ***/
2768 static HRESULT WINAPI Mediaevent_QueryInterface(IMediaEventEx *iface,
2769                                                 REFIID riid,
2770                                                 LPVOID*ppvObj) {
2771     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2772
2773     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2774
2775     return Filtergraph_QueryInterface(This, riid, ppvObj);
2776 }
2777
2778 static ULONG WINAPI Mediaevent_AddRef(IMediaEventEx *iface) {
2779     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2780
2781     TRACE("(%p/%p)->()\n", This, iface);
2782
2783     return Filtergraph_AddRef(This);
2784 }
2785
2786 static ULONG WINAPI Mediaevent_Release(IMediaEventEx *iface) {
2787     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2788
2789     TRACE("(%p/%p)->()\n", This, iface);
2790
2791     return Filtergraph_Release(This);
2792 }
2793
2794 /*** IDispatch methods ***/
2795 static HRESULT WINAPI Mediaevent_GetTypeInfoCount(IMediaEventEx *iface,
2796                                                   UINT*pctinfo) {
2797     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2798
2799     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
2800
2801     return S_OK;
2802 }
2803
2804 static HRESULT WINAPI Mediaevent_GetTypeInfo(IMediaEventEx *iface,
2805                                              UINT iTInfo,
2806                                              LCID lcid,
2807                                              ITypeInfo**ppTInfo) {
2808     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2809
2810     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
2811
2812     return S_OK;
2813 }
2814
2815 static HRESULT WINAPI Mediaevent_GetIDsOfNames(IMediaEventEx *iface,
2816                                                REFIID riid,
2817                                                LPOLESTR*rgszNames,
2818                                                UINT cNames,
2819                                                LCID lcid,
2820                                                DISPID*rgDispId) {
2821     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2822
2823     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2824
2825     return S_OK;
2826 }
2827
2828 static HRESULT WINAPI Mediaevent_Invoke(IMediaEventEx *iface,
2829                                         DISPID dispIdMember,
2830                                         REFIID riid,
2831                                         LCID lcid,
2832                                         WORD wFlags,
2833                                         DISPPARAMS*pDispParams,
2834                                         VARIANT*pVarResult,
2835                                         EXCEPINFO*pExepInfo,
2836                                         UINT*puArgErr) {
2837     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2838
2839     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2840
2841     return S_OK;
2842 }
2843
2844 /*** IMediaEvent methods ***/
2845 static HRESULT WINAPI Mediaevent_GetEventHandle(IMediaEventEx *iface,
2846                                                 OAEVENT *hEvent) {
2847     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2848
2849     TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
2850
2851     *hEvent = (OAEVENT)This->evqueue.msg_event;
2852
2853     return S_OK;
2854 }
2855
2856 static HRESULT WINAPI Mediaevent_GetEvent(IMediaEventEx *iface,
2857                                           long *lEventCode,
2858                                           LONG_PTR *lParam1,
2859                                           LONG_PTR *lParam2,
2860                                           long msTimeout) {
2861     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2862     Event evt;
2863
2864     TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
2865
2866     if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
2867     {
2868         *lEventCode = evt.lEventCode;
2869         *lParam1 = evt.lParam1;
2870         *lParam2 = evt.lParam2;
2871         return S_OK;
2872     }
2873
2874     *lEventCode = 0;
2875     return E_ABORT;
2876 }
2877
2878 static HRESULT WINAPI Mediaevent_WaitForCompletion(IMediaEventEx *iface,
2879                                                    long msTimeout,
2880                                                    long *pEvCode) {
2881     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2882
2883     TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
2884
2885     if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
2886     {
2887         *pEvCode = This->CompletionStatus;
2888         return S_OK;
2889     }
2890
2891     *pEvCode = 0;
2892     return E_ABORT;
2893 }
2894
2895 static HRESULT WINAPI Mediaevent_CancelDefaultHandling(IMediaEventEx *iface,
2896                                                        long lEvCode) {
2897     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2898
2899     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
2900
2901     if (lEvCode == EC_COMPLETE)
2902         This->HandleEcComplete = FALSE;
2903     else if (lEvCode == EC_REPAINT)
2904         This->HandleEcRepaint = FALSE;
2905     else
2906         return S_FALSE;
2907
2908     return S_OK;
2909 }
2910
2911 static HRESULT WINAPI Mediaevent_RestoreDefaultHandling(IMediaEventEx *iface,
2912                                                         long lEvCode) {
2913     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2914
2915     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
2916
2917     if (lEvCode == EC_COMPLETE)
2918         This->HandleEcComplete = TRUE;
2919     else if (lEvCode == EC_REPAINT)
2920         This->HandleEcRepaint = TRUE;
2921     else
2922         return S_FALSE;
2923
2924     return S_OK;
2925 }
2926
2927 static HRESULT WINAPI Mediaevent_FreeEventParams(IMediaEventEx *iface,
2928                                                  long lEvCode,
2929                                                  LONG_PTR lParam1,
2930                                                  LONG_PTR lParam2) {
2931     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2932
2933     TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
2934
2935     return S_OK;
2936 }
2937
2938 /*** IMediaEventEx methods ***/
2939 static HRESULT WINAPI Mediaevent_SetNotifyWindow(IMediaEventEx *iface,
2940                                                  OAHWND hwnd,
2941                                                  long lMsg,
2942                                                  LONG_PTR lInstanceData) {
2943     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2944
2945     TRACE("(%p/%p)->(%08lx, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
2946
2947     This->notif.hWnd = (HWND)hwnd;
2948     This->notif.msg = lMsg;
2949     This->notif.instance = (long) lInstanceData;
2950
2951     return S_OK;
2952 }
2953
2954 static HRESULT WINAPI Mediaevent_SetNotifyFlags(IMediaEventEx *iface,
2955                                                 long lNoNotifyFlags) {
2956     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2957
2958     TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
2959
2960     if ((lNoNotifyFlags != 0) || (lNoNotifyFlags != 1))
2961         return E_INVALIDARG;
2962
2963     This->notif.disabled = lNoNotifyFlags;
2964
2965     return S_OK;
2966 }
2967
2968 static HRESULT WINAPI Mediaevent_GetNotifyFlags(IMediaEventEx *iface,
2969                                                 long *lplNoNotifyFlags) {
2970     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2971
2972     TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
2973
2974     if (!lplNoNotifyFlags)
2975         return E_POINTER;
2976
2977     *lplNoNotifyFlags = This->notif.disabled;
2978
2979     return S_OK;
2980 }
2981
2982
2983 static const IMediaEventExVtbl IMediaEventEx_VTable =
2984 {
2985     Mediaevent_QueryInterface,
2986     Mediaevent_AddRef,
2987     Mediaevent_Release,
2988     Mediaevent_GetTypeInfoCount,
2989     Mediaevent_GetTypeInfo,
2990     Mediaevent_GetIDsOfNames,
2991     Mediaevent_Invoke,
2992     Mediaevent_GetEventHandle,
2993     Mediaevent_GetEvent,
2994     Mediaevent_WaitForCompletion,
2995     Mediaevent_CancelDefaultHandling,
2996     Mediaevent_RestoreDefaultHandling,
2997     Mediaevent_FreeEventParams,
2998     Mediaevent_SetNotifyWindow,
2999     Mediaevent_SetNotifyFlags,
3000     Mediaevent_GetNotifyFlags
3001 };
3002
3003
3004 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
3005 {
3006     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3007
3008     return Filtergraph_QueryInterface(This, riid, ppv);
3009 }
3010
3011 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
3012 {
3013     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3014
3015     return Filtergraph_AddRef(This);
3016 }
3017
3018 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
3019 {
3020     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3021
3022     return Filtergraph_Release(This);
3023 }
3024
3025 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
3026 {
3027     FIXME("(%p): stub\n", pClassID);
3028
3029     return E_NOTIMPL;
3030 }
3031
3032 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
3033 {
3034     FIXME("(): stub\n");
3035
3036     return E_NOTIMPL;
3037 }
3038
3039 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
3040 {
3041     FIXME("(): stub\n");
3042
3043     return E_NOTIMPL;
3044 }
3045
3046 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
3047 {
3048     FIXME("(%lld): stub\n", tStart);
3049
3050     return E_NOTIMPL;
3051 }
3052
3053 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
3054 {
3055     FIXME("(%ld, %p): stub\n", dwMsTimeout, pState);
3056
3057     return E_NOTIMPL;
3058 }
3059
3060 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
3061 {
3062     FIXME("(%p): stub\n", pClock);
3063
3064     return E_NOTIMPL;
3065 }
3066
3067 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
3068 {
3069     FIXME("(%p): stub\n", ppClock);
3070
3071     return E_NOTIMPL;
3072 }
3073
3074 static const IMediaFilterVtbl IMediaFilter_VTable =
3075 {
3076     MediaFilter_QueryInterface,
3077     MediaFilter_AddRef,
3078     MediaFilter_Release,
3079     MediaFilter_GetClassID,
3080     MediaFilter_Stop,
3081     MediaFilter_Pause,
3082     MediaFilter_Run,
3083     MediaFilter_GetState,
3084     MediaFilter_SetSyncSource,
3085     MediaFilter_GetSyncSource
3086 };
3087
3088 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
3089 {
3090     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
3091
3092     return Filtergraph_QueryInterface(This, riid, ppv);
3093 }
3094
3095 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
3096 {
3097     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
3098
3099     return Filtergraph_AddRef(This);
3100 }
3101
3102 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
3103 {
3104     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
3105
3106     return Filtergraph_Release(This);
3107 }
3108
3109 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
3110 {
3111     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
3112     Event evt;
3113
3114     TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
3115
3116     /* We need thread safety here, let's use the events queue's one */
3117     EnterCriticalSection(&This->evqueue.msg_crst);
3118
3119     if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
3120     {
3121         TRACE("Process EC_COMPLETE notification\n");
3122         if (++This->EcCompleteCount == This->nRenderers)
3123         {
3124             evt.lEventCode = EC_COMPLETE;
3125             evt.lParam1 = S_OK;
3126             evt.lParam2 = 0;
3127             TRACE("Send EC_COMPLETE to app\n");
3128             EventsQueue_PutEvent(&This->evqueue, &evt);
3129             if (!This->notif.disabled && This->notif.hWnd)
3130             {
3131                 TRACE("Send Window message\n");
3132                 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
3133             }
3134             This->CompletionStatus = EC_COMPLETE;
3135             SetEvent(This->hEventCompletion);
3136         }
3137     }
3138     else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
3139     {
3140         /* FIXME: Not handled yet */
3141     }
3142     else
3143     {
3144         evt.lEventCode = EventCode;
3145         evt.lParam1 = EventParam1;
3146         evt.lParam2 = EventParam2;
3147         EventsQueue_PutEvent(&This->evqueue, &evt);
3148         if (!This->notif.disabled && This->notif.hWnd)
3149             PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
3150     }
3151
3152     LeaveCriticalSection(&This->evqueue.msg_crst);
3153     return S_OK;
3154 }
3155
3156 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
3157 {
3158     MediaEventSink_QueryInterface,
3159     MediaEventSink_AddRef,
3160     MediaEventSink_Release,
3161     MediaEventSink_Notify
3162 };
3163
3164 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
3165 {
3166     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3167
3168     return Filtergraph_QueryInterface(This, riid, ppv);
3169 }
3170
3171 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
3172 {
3173     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
3174
3175     return Filtergraph_AddRef(This);
3176 }
3177
3178 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
3179 {
3180     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3181
3182     return Filtergraph_Release(This);
3183 }
3184
3185 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
3186                                             IPin* pOutputPin,
3187                                             IPin* pInputPin,
3188                                             const AM_MEDIA_TYPE* pmtFirstConnection,
3189                                             IBaseFilter* pUsingFilter,
3190                                             HANDLE hAbortEvent,
3191                                             DWORD dwFlags)
3192 {
3193     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3194
3195     FIXME("(%p)->(%p, %p, %p, %p, %p, %lx): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
3196     
3197     return E_NOTIMPL;
3198 }
3199
3200 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
3201                                               IGraphConfigCallback* pCallback,
3202                                               PVOID pvContext,
3203                                               DWORD dwFlags,
3204                                               HANDLE hAbortEvent)
3205 {
3206     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3207
3208     FIXME("(%p)->(%p, %p, %lx, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
3209     
3210     return E_NOTIMPL;
3211 }
3212
3213 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
3214                                                    IBaseFilter* pFilter)
3215 {
3216     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3217
3218     FIXME("(%p)->(%p): stub!\n", This, pFilter);
3219     
3220     return E_NOTIMPL;
3221 }
3222
3223 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
3224                                                   IEnumFilters** pEnum)
3225 {
3226     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3227
3228     FIXME("(%p)->(%p): stub!\n", This, pEnum);
3229     
3230     return E_NOTIMPL;
3231 }
3232
3233 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
3234                                                         IBaseFilter* pFilter)
3235 {
3236     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3237
3238     FIXME("(%p)->(%p): stub!\n", This, pFilter);
3239     
3240     return E_NOTIMPL;
3241 }
3242
3243 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
3244                                                REFERENCE_TIME* prtStart)
3245 {
3246     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3247
3248     FIXME("(%p)->(%p): stub!\n", This, prtStart);
3249     
3250     return E_NOTIMPL;
3251 }
3252
3253 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
3254                                                   IPin* pOutputPin,
3255                                                   IPinConnection* pConnection,
3256                                                   HANDLE hEventAbort)
3257 {
3258     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3259
3260     FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
3261     
3262     return E_NOTIMPL;
3263 }
3264
3265 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
3266                                                  IBaseFilter* pFilter,
3267                                                  DWORD dwFlags)
3268 {
3269     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3270
3271     FIXME("(%p)->(%p, %lx): stub!\n", This, pFilter, dwFlags);
3272     
3273     return E_NOTIMPL;
3274 }
3275
3276 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
3277                                                  IBaseFilter* pFilter,
3278                                                  DWORD* dwFlags)
3279 {
3280     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3281
3282     FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
3283     
3284     return E_NOTIMPL;
3285 }
3286
3287 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
3288                                                  IBaseFilter* pFilter,
3289                                                  DWORD dwFlags)
3290 {
3291     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
3292
3293     FIXME("(%p)->(%p, %lx): stub!\n", This, pFilter, dwFlags);
3294     
3295     return E_NOTIMPL;
3296 }
3297
3298 static const IGraphConfigVtbl IGraphConfig_VTable =
3299 {
3300     GraphConfig_QueryInterface,
3301     GraphConfig_AddRef,
3302     GraphConfig_Release,
3303     GraphConfig_Reconnect,
3304     GraphConfig_Reconfigure,
3305     GraphConfig_AddFilterToCache,
3306     GraphConfig_EnumCacheFilter,
3307     GraphConfig_RemoveFilterFromCache,
3308     GraphConfig_GetStartTime,
3309     GraphConfig_PushThroughData,
3310     GraphConfig_SetFilterFlags,
3311     GraphConfig_GetFilterFlags,
3312     GraphConfig_RemoveFilterEx
3313 };
3314
3315 /* This is the only function that actually creates a FilterGraph class... */
3316 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3317 {
3318     IFilterGraphImpl *fimpl;
3319     HRESULT hr;
3320
3321     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
3322
3323     if( pUnkOuter )
3324         return CLASS_E_NOAGGREGATION;
3325
3326     fimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(*fimpl));
3327     fimpl->IGraphBuilder_vtbl = &IGraphBuilder_VTable;
3328     fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
3329     fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
3330     fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
3331     fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
3332     fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
3333     fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
3334     fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
3335     fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
3336     fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
3337     fimpl->ref = 1;
3338     fimpl->ppFiltersInGraph = NULL;
3339     fimpl->pFilterNames = NULL;
3340     fimpl->nFilters = 0;
3341     fimpl->filterCapacity = 0;
3342     fimpl->nameIndex = 1;
3343     fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
3344     fimpl->HandleEcComplete = TRUE;
3345     fimpl->HandleEcRepaint = TRUE;
3346     fimpl->notif.hWnd = 0;
3347     fimpl->notif.disabled = FALSE;
3348     fimpl->nRenderers = 0;
3349     fimpl->EcCompleteCount = 0;
3350     fimpl->state = State_Stopped;
3351     EventsQueue_Init(&fimpl->evqueue);
3352     InitializeCriticalSection(&fimpl->cs);
3353
3354     hr = CoCreateInstance(&CLSID_FilterMapper, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
3355     if (FAILED(hr)) {
3356         ERR("Unable to create filter mapper (%lx)\n", hr);
3357         return hr;
3358     }
3359
3360     *ppObj = fimpl;
3361     return S_OK;
3362 }
3363
3364 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
3365 {
3366     FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
3367     return FilterGraph_create(pUnkOuter, ppObj);
3368 }