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