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