quartz: Reset EcCompleteCount before starting filters.
[wine/wine64.git] / dlls / quartz / filtergraph.c
blob1c0acc743fe3b6df9cd6195edd63da3df8a124ab
1 /* DirectShow FilterGraph object (QUARTZ.DLL)
3 * Copyright 2002 Lionel Ulmer
4 * Copyright 2004 Christian Costa
6 * This file contains the (internal) driver registration functions,
7 * driver enumeration APIs and DirectDraw creation functions.
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include <stdarg.h>
27 #define COBJMACROS
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 #include "ole2.h"
36 #include "olectl.h"
37 #include "strmif.h"
38 #include "vfwmsgs.h"
39 #include "evcode.h"
40 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 typedef struct {
46 HWND hWnd; /* Target window */
47 long msg; /* User window message */
48 long instance; /* User data */
49 int disabled; /* Disabled messages posting */
50 } WndNotify;
52 typedef struct {
53 long lEventCode; /* Event code */
54 LONG_PTR lParam1; /* Param1 */
55 LONG_PTR lParam2; /* Param2 */
56 } Event;
58 /* messages ring implementation for queuing events (taken from winmm) */
59 #define EVENTS_RING_BUFFER_INCREMENT 64
60 typedef struct {
61 Event* messages;
62 int ring_buffer_size;
63 int msg_tosave;
64 int msg_toget;
65 CRITICAL_SECTION msg_crst;
66 HANDLE msg_event; /* Signaled for no empty queue */
67 } EventsQueue;
69 static int EventsQueue_Init(EventsQueue* omr)
71 omr->msg_toget = 0;
72 omr->msg_tosave = 0;
73 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
74 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
75 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
76 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
78 InitializeCriticalSection(&omr->msg_crst);
79 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
80 return TRUE;
83 static int EventsQueue_Destroy(EventsQueue* omr)
85 CloseHandle(omr->msg_event);
86 CoTaskMemFree(omr->messages);
87 omr->msg_crst.DebugInfo->Spare[0] = 0;
88 DeleteCriticalSection(&omr->msg_crst);
89 return TRUE;
92 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
94 EnterCriticalSection(&omr->msg_crst);
95 if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
97 int old_ring_buffer_size = omr->ring_buffer_size;
98 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
99 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
100 omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
101 /* Now we need to rearrange the ring buffer so that the new
102 buffers just allocated are in between omr->msg_tosave and
103 omr->msg_toget.
105 if (omr->msg_tosave < omr->msg_toget)
107 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
108 &(omr->messages[omr->msg_toget]),
109 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
111 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
114 omr->messages[omr->msg_tosave] = *evt;
115 SetEvent(omr->msg_event);
116 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
117 LeaveCriticalSection(&omr->msg_crst);
118 return TRUE;
121 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
123 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
124 return FALSE;
126 EnterCriticalSection(&omr->msg_crst);
128 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
130 LeaveCriticalSection(&omr->msg_crst);
131 return FALSE;
134 *evt = omr->messages[omr->msg_toget];
135 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
137 /* Mark the buffer as empty if needed */
138 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
139 ResetEvent(omr->msg_event);
141 LeaveCriticalSection(&omr->msg_crst);
142 return TRUE;
145 #define MAX_ITF_CACHE_ENTRIES 3
146 typedef struct _ITF_CACHE_ENTRY {
147 const IID* riid;
148 IBaseFilter* filter;
149 IUnknown* iface;
150 } ITF_CACHE_ENTRY;
152 typedef struct _IFilterGraphImpl {
153 const IFilterGraph2Vtbl *IFilterGraph2_vtbl;
154 const IMediaControlVtbl *IMediaControl_vtbl;
155 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
156 const IBasicAudioVtbl *IBasicAudio_vtbl;
157 const IBasicVideoVtbl *IBasicVideo_vtbl;
158 const IVideoWindowVtbl *IVideoWindow_vtbl;
159 const IMediaEventExVtbl *IMediaEventEx_vtbl;
160 const IMediaFilterVtbl *IMediaFilter_vtbl;
161 const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
162 const IGraphConfigVtbl *IGraphConfig_vtbl;
163 const IMediaPositionVtbl *IMediaPosition_vtbl;
164 const IUnknownVtbl * IInner_vtbl;
165 /* IAMGraphStreams */
166 /* IAMStats */
167 /* IBasicVideo2 */
168 /* IFilterChain */
169 /* IFilterMapper2 */
170 /* IGraphVersion */
171 /* IQueueCommand */
172 /* IRegisterServiceProvider */
173 /* IResourceMananger */
174 /* IServiceProvider */
175 /* IVideoFrameStep */
177 LONG ref;
178 IFilterMapper2 * pFilterMapper2;
179 IBaseFilter ** ppFiltersInGraph;
180 LPWSTR * pFilterNames;
181 int nFilters;
182 int filterCapacity;
183 long nameIndex;
184 IReferenceClock *refClock;
185 EventsQueue evqueue;
186 HANDLE hEventCompletion;
187 int CompletionStatus;
188 WndNotify notif;
189 int nRenderers;
190 int EcCompleteCount;
191 int HandleEcComplete;
192 int HandleEcRepaint;
193 int HandleEcClockChanged;
194 OAFilterState state;
195 CRITICAL_SECTION cs;
196 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
197 int nItfCacheEntries;
198 IUnknown * pUnkOuter;
199 BOOL bUnkOuterValid;
200 BOOL bAggregatable;
201 GUID timeformatseek;
202 LONGLONG start_time;
203 LONGLONG position;
204 } IFilterGraphImpl;
206 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
207 REFIID riid, LPVOID * ppv);
208 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This);
209 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This);
211 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
212 REFIID riid,
213 LPVOID *ppvObj) {
214 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
215 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
217 if (This->bAggregatable)
218 This->bUnkOuterValid = TRUE;
220 if (IsEqualGUID(&IID_IUnknown, riid)) {
221 *ppvObj = &(This->IInner_vtbl);
222 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
223 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
224 IsEqualGUID(&IID_IFilterGraph2, riid) ||
225 IsEqualGUID(&IID_IGraphBuilder, riid)) {
226 *ppvObj = &(This->IFilterGraph2_vtbl);
227 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
228 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
229 *ppvObj = &(This->IMediaControl_vtbl);
230 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
231 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
232 *ppvObj = &(This->IMediaSeeking_vtbl);
233 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
234 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
235 *ppvObj = &(This->IBasicAudio_vtbl);
236 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
237 } else if (IsEqualGUID(&IID_IBasicVideo, riid)) {
238 *ppvObj = &(This->IBasicVideo_vtbl);
239 TRACE(" returning IBasicVideo interface (%p)\n", *ppvObj);
240 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
241 *ppvObj = &(This->IVideoWindow_vtbl);
242 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
243 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
244 IsEqualGUID(&IID_IMediaEventEx, riid)) {
245 *ppvObj = &(This->IMediaEventEx_vtbl);
246 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
247 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
248 IsEqualGUID(&IID_IPersist, riid)) {
249 *ppvObj = &(This->IMediaFilter_vtbl);
250 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
251 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
252 *ppvObj = &(This->IMediaEventSink_vtbl);
253 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
254 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
255 *ppvObj = &(This->IGraphConfig_vtbl);
256 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
257 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
258 *ppvObj = &(This->IMediaPosition_vtbl);
259 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
260 } else {
261 *ppvObj = NULL;
262 FIXME("unknown interface %s\n", debugstr_guid(riid));
263 return E_NOINTERFACE;
266 IUnknown_AddRef((IUnknown *)(*ppvObj));
267 return S_OK;
270 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) {
271 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
272 ULONG ref = InterlockedIncrement(&This->ref);
274 TRACE("(%p)->(): new ref = %d\n", This, ref);
276 return ref;
279 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) {
280 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
281 ULONG ref = InterlockedDecrement(&This->ref);
283 TRACE("(%p)->(): new ref = %d\n", This, ref);
285 if (ref == 0) {
286 int i;
288 IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl));
289 if (This->refClock)
290 IReferenceClock_Release(This->refClock);
292 while (This->nFilters)
293 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]);
295 for (i = 0; i < This->nItfCacheEntries; i++)
297 if (This->ItfCacheEntries[i].iface)
298 IUnknown_Release(This->ItfCacheEntries[i].iface);
300 IFilterMapper2_Release(This->pFilterMapper2);
301 CloseHandle(This->hEventCompletion);
302 EventsQueue_Destroy(&This->evqueue);
303 This->cs.DebugInfo->Spare[0] = 0;
304 DeleteCriticalSection(&This->cs);
305 CoTaskMemFree(This->ppFiltersInGraph);
306 CoTaskMemFree(This->pFilterNames);
307 CoTaskMemFree(This);
309 return ref;
313 /*** IUnknown methods ***/
314 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface,
315 REFIID riid,
316 LPVOID*ppvObj) {
317 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
319 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
320 return Filtergraph_QueryInterface(This, riid, ppvObj);
323 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) {
324 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
326 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
328 return Filtergraph_AddRef(This);
331 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) {
332 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
334 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
336 return Filtergraph_Release(This);
339 /*** IFilterGraph methods ***/
340 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
341 IBaseFilter *pFilter,
342 LPCWSTR pName) {
343 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
344 HRESULT hr;
345 int i,j;
346 WCHAR* wszFilterName = NULL;
347 int duplicate_name = FALSE;
349 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
351 if (!pFilter)
352 return E_POINTER;
354 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
356 if (pName)
358 /* Check if name already exists */
359 for(i = 0; i < This->nFilters; i++)
360 if (!strcmpW(This->pFilterNames[i], pName))
362 duplicate_name = TRUE;
363 break;
367 /* If no name given or name already existing, generate one */
368 if (!pName || duplicate_name)
370 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
371 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
373 for (j = 0; j < 10000 ; j++)
375 /* Create name */
376 if (pName)
377 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
378 else
379 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
380 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
382 /* Check if the generated name already exists */
383 for(i = 0; i < This->nFilters; i++)
384 if (!strcmpW(This->pFilterNames[i], wszFilterName))
385 break;
387 /* Compute next index and exit if generated name is suitable */
388 if (This->nameIndex++ == 10000)
389 This->nameIndex = 1;
390 if (i == This->nFilters)
391 break;
393 /* Unable to find a suitable name */
394 if (j == 10000)
396 CoTaskMemFree(wszFilterName);
397 return VFW_E_DUPLICATE_NAME;
400 else
401 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
403 if (This->nFilters + 1 > This->filterCapacity)
405 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
406 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
407 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
408 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
409 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
410 if (This->filterCapacity)
412 CoTaskMemFree(This->ppFiltersInGraph);
413 CoTaskMemFree(This->pFilterNames);
415 This->ppFiltersInGraph = ppNewFilters;
416 This->pFilterNames = pNewNames;
417 This->filterCapacity = newCapacity;
420 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
422 if (SUCCEEDED(hr))
424 IBaseFilter_AddRef(pFilter);
425 This->ppFiltersInGraph[This->nFilters] = pFilter;
426 This->pFilterNames[This->nFilters] = wszFilterName;
427 This->nFilters++;
428 IBaseFilter_SetSyncSource(pFilter, This->refClock);
430 else
431 CoTaskMemFree(wszFilterName);
433 if (SUCCEEDED(hr) && duplicate_name)
434 return VFW_S_DUPLICATE_NAME;
436 return hr;
439 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface,
440 IBaseFilter *pFilter) {
441 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
442 int i;
443 HRESULT hr = E_FAIL;
445 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
447 /* FIXME: check graph is stopped */
449 for (i = 0; i < This->nFilters; i++)
451 if (This->ppFiltersInGraph[i] == pFilter)
453 IEnumPins *penumpins;
454 IBaseFilter_Stop(pFilter);
455 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
456 if (SUCCEEDED(hr)) {
457 IPin *ppin;
458 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) {
459 IPin *victim = NULL;
460 HRESULT h;
461 IPin_ConnectedTo(ppin, &victim);
462 if (victim)
464 h = IPin_Disconnect(victim);
465 TRACE("Disconnect other side: %08x\n", h);
466 if (h == VFW_E_NOT_STOPPED)
468 PIN_INFO pinfo;
469 IPin_QueryPinInfo(victim, &pinfo);
470 IBaseFilter_Stop(pinfo.pFilter);
471 IBaseFilter_Release(pinfo.pFilter);
472 h = IPin_Disconnect(victim);
473 TRACE("Disconnect retry: %08x\n", h);
475 IPin_Release(victim);
477 h = IPin_Disconnect(ppin);
478 TRACE("Disconnect 2: %08x\n", h);
480 IEnumPins_Release(penumpins);
483 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
484 if (SUCCEEDED(hr))
486 IBaseFilter_SetSyncSource(pFilter, NULL);
487 IBaseFilter_Release(pFilter);
488 CoTaskMemFree(This->pFilterNames[i]);
489 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
490 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
491 This->nFilters--;
492 /* Invalidate interfaces in the cache */
493 for (i = 0; i < This->nItfCacheEntries; i++)
494 if (pFilter == This->ItfCacheEntries[i].filter)
496 IUnknown_Release(This->ItfCacheEntries[i].iface);
497 This->ItfCacheEntries[i].iface = NULL;
498 This->ItfCacheEntries[i].filter = NULL;
500 return S_OK;
502 break;
506 return hr; /* FIXME: check this error code */
509 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface,
510 IEnumFilters **ppEnum) {
511 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
513 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
515 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
518 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
519 LPCWSTR pName,
520 IBaseFilter **ppFilter) {
521 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
522 int i;
524 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
526 if (!ppFilter)
527 return E_POINTER;
529 for (i = 0; i < This->nFilters; i++)
531 if (!strcmpW(pName, This->pFilterNames[i]))
533 *ppFilter = This->ppFiltersInGraph[i];
534 IBaseFilter_AddRef(*ppFilter);
535 return S_OK;
539 *ppFilter = NULL;
540 return VFW_E_NOT_FOUND;
543 /* NOTE: despite the implication, it doesn't matter which
544 * way round you put in the input and output pins */
545 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface,
546 IPin *ppinIn,
547 IPin *ppinOut,
548 const AM_MEDIA_TYPE *pmt) {
549 PIN_DIRECTION dir;
550 HRESULT hr;
552 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
554 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
556 /* FIXME: check pins are in graph */
558 if (TRACE_ON(quartz))
560 PIN_INFO PinInfo;
562 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
563 if (FAILED(hr))
564 return hr;
566 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
567 IBaseFilter_Release(PinInfo.pFilter);
569 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
570 if (FAILED(hr))
571 return hr;
573 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
574 IBaseFilter_Release(PinInfo.pFilter);
577 hr = IPin_QueryDirection(ppinIn, &dir);
578 if (SUCCEEDED(hr))
580 if (dir == PINDIR_INPUT)
581 hr = IPin_Connect(ppinOut, ppinIn, pmt);
582 else
583 hr = IPin_Connect(ppinIn, ppinOut, pmt);
586 return hr;
589 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface,
590 IPin *ppin) {
591 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
592 IPin *pConnectedTo = NULL;
593 HRESULT hr;
594 PIN_DIRECTION pindir;
596 IPin_QueryDirection(ppin, &pindir);
597 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
598 if (FAILED(hr)) {
599 TRACE("Querying connected to failed: %x\n", hr);
600 return hr;
602 IPin_Disconnect(ppin);
603 IPin_Disconnect(pConnectedTo);
604 if (pindir == PINDIR_INPUT)
605 hr = IPin_Connect(pConnectedTo, ppin, NULL);
606 else
607 hr = IPin_Connect(ppin, pConnectedTo, NULL);
608 IPin_Release(pConnectedTo);
609 if (FAILED(hr))
610 ERR("Reconnecting pins failed, pins are not connected now..\n");
611 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
612 return hr;
615 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface,
616 IPin *ppin) {
617 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
619 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
621 return IPin_Disconnect(ppin);
624 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) {
625 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
626 IReferenceClock *pClock = NULL;
627 HRESULT hr;
629 TRACE("(%p/%p)->() semi-stub\n", iface, This);
631 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
633 if (SUCCEEDED(hr))
635 hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock);
636 IReferenceClock_Release(pClock);
639 return hr;
642 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
644 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
645 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
646 IPropertyBag * pPropBagCat = NULL;
647 HRESULT hr;
649 VariantInit(pvar);
650 V_VT(pvar) = VT_BSTR;
652 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
654 if (SUCCEEDED(hr))
655 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
657 if (SUCCEEDED(hr))
658 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
660 if (SUCCEEDED(hr))
661 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
663 if (SUCCEEDED(hr))
664 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
666 if (pPropBagCat)
667 IPropertyBag_Release(pPropBagCat);
669 return hr;
672 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
674 HRESULT hr;
675 ULONG nb = 0;
677 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
678 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
679 if (hr == S_OK) {
680 /* Rendered input */
681 } else if (hr == S_FALSE) {
682 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
683 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
684 if (hr != S_OK) {
685 ERR("Error (%x)\n", hr);
687 } else if (hr == E_NOTIMPL) {
688 /* Input connected to all outputs */
689 IEnumPins* penumpins;
690 IPin* ppin;
691 int i = 0;
692 TRACE("E_NOTIMPL\n");
693 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
694 if (FAILED(hr)) {
695 ERR("filter Enumpins failed (%x)\n", hr);
696 return hr;
698 i = 0;
699 /* Count output pins */
700 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
701 PIN_DIRECTION pindir;
702 IPin_QueryDirection(ppin, &pindir);
703 if (pindir == PINDIR_OUTPUT)
704 i++;
705 IPin_Release(ppin);
707 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
708 /* Retrieve output pins */
709 IEnumPins_Reset(penumpins);
710 i = 0;
711 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
712 PIN_DIRECTION pindir;
713 IPin_QueryDirection(ppin, &pindir);
714 if (pindir == PINDIR_OUTPUT)
715 (*pppins)[i++] = ppin;
716 else
717 IPin_Release(ppin);
719 IEnumPins_Release(penumpins);
720 nb = i;
721 if (FAILED(hr)) {
722 ERR("Next failed (%x)\n", hr);
723 return hr;
725 } else if (FAILED(hr)) {
726 ERR("Cannot get internal connection (%x)\n", hr);
727 return hr;
730 *pnb = nb;
731 return S_OK;
734 /*** IGraphBuilder methods ***/
735 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface,
736 IPin *ppinOut,
737 IPin *ppinIn) {
738 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
739 HRESULT hr;
740 AM_MEDIA_TYPE* mt;
741 IEnumMediaTypes* penummt;
742 ULONG nbmt;
743 IEnumPins* penumpins;
744 IEnumMoniker* pEnumMoniker;
745 GUID tab[2];
746 ULONG nb;
747 IMoniker* pMoniker;
748 ULONG pin;
749 PIN_INFO PinInfo;
750 CLSID FilterCLSID;
752 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
754 if (TRACE_ON(quartz))
756 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
757 if (FAILED(hr))
758 return hr;
760 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
761 IBaseFilter_Release(PinInfo.pFilter);
763 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
764 if (FAILED(hr))
765 return hr;
767 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
768 IBaseFilter_Release(PinInfo.pFilter);
771 /* Try direct connection first */
772 hr = IPin_Connect(ppinOut, ppinIn, NULL);
773 if (SUCCEEDED(hr)) {
774 return S_OK;
776 TRACE("Direct connection failed, trying to insert other filters\n");
778 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
779 if (FAILED(hr))
780 return hr;
782 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
783 IBaseFilter_Release(PinInfo.pFilter);
784 if (FAILED(hr))
785 return hr;
787 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
788 * filter to the minor mediatype of input pin of the renderer */
789 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
790 if (FAILED(hr)) {
791 ERR("EnumMediaTypes (%x)\n", hr);
792 return hr;
795 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
796 if (FAILED(hr)) {
797 ERR("IEnumMediaTypes_Next (%x)\n", hr);
798 return hr;
801 if (!nbmt) {
802 ERR("No media type found!\n");
803 return S_OK;
805 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
806 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
808 /* Try to find a suitable filter that can connect to the pin to render */
809 tab[0] = mt->majortype;
810 tab[1] = mt->subtype;
811 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
812 if (FAILED(hr)) {
813 ERR("Unable to enum filters (%x)\n", hr);
814 return hr;
817 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
819 VARIANT var;
820 GUID clsid;
821 IPin** ppins;
822 IPin* ppinfilter = NULL;
823 IBaseFilter* pfilter = NULL;
825 hr = GetFilterInfo(pMoniker, &clsid, &var);
826 IMoniker_Release(pMoniker);
827 if (FAILED(hr)) {
828 ERR("Unable to retrieve filter info (%x)\n", hr);
829 goto error;
832 if (IsEqualGUID(&clsid, &FilterCLSID)) {
833 /* Skip filter (same as the one the output pin belongs to) */
834 goto error;
837 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
838 if (FAILED(hr)) {
839 ERR("Unable to create filter (%x), trying next one\n", hr);
840 goto error;
843 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
844 if (FAILED(hr)) {
845 ERR("Unable to add filter (%x)\n", hr);
846 IBaseFilter_Release(pfilter);
847 pfilter = NULL;
848 goto error;
851 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
852 if (FAILED(hr)) {
853 ERR("Enumpins (%x)\n", hr);
854 goto error;
857 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
858 IEnumPins_Release(penumpins);
860 if (FAILED(hr)) {
861 ERR("Next (%x)\n", hr);
862 goto error;
864 if (pin == 0) {
865 ERR("No Pin\n");
866 goto error;
869 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
870 if (FAILED(hr)) {
871 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
872 goto error;
874 TRACE("Successfully connected to filter, follow chain...\n");
876 /* Render all output pins of the filter by calling IFilterGraph2_Render on each of them */
877 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
879 if (SUCCEEDED(hr)) {
880 int i;
881 if (nb == 0) {
882 IPin_Disconnect(ppinOut);
883 goto error;
885 TRACE("pins to consider: %d\n", nb);
886 for(i = 0; i < nb; i++) {
887 TRACE("Processing pin %d\n", i);
888 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
889 if (FAILED(hr)) {
890 TRACE("Cannot render pin %p (%x)\n", ppinfilter, hr);
892 IPin_Release(ppins[i]);
893 if (SUCCEEDED(hr)) break;
895 while (++i < nb) IPin_Release(ppins[i]);
896 CoTaskMemFree(ppins);
897 IPin_Release(ppinfilter);
898 IBaseFilter_Release(pfilter);
899 break;
902 error:
903 if (ppinfilter) IPin_Release(ppinfilter);
904 if (pfilter) {
905 IFilterGraph2_RemoveFilter(iface, pfilter);
906 IBaseFilter_Release(pfilter);
910 IEnumMediaTypes_Release(penummt);
911 DeleteMediaType(mt);
913 return S_OK;
916 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface,
917 IPin *ppinOut) {
918 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
919 IEnumMediaTypes* penummt;
920 AM_MEDIA_TYPE* mt;
921 ULONG nbmt;
922 HRESULT hr;
924 IEnumMoniker* pEnumMoniker;
925 GUID tab[2];
926 ULONG nb;
927 IMoniker* pMoniker;
929 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
931 if (TRACE_ON(quartz))
933 PIN_INFO PinInfo;
935 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
936 if (FAILED(hr))
937 return hr;
939 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
940 IBaseFilter_Release(PinInfo.pFilter);
943 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
944 if (FAILED(hr)) {
945 ERR("EnumMediaTypes (%x)\n", hr);
946 return hr;
949 while(1)
951 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
952 if (FAILED(hr)) {
953 ERR("IEnumMediaTypes_Next (%x)\n", hr);
954 return hr;
956 if (!nbmt)
957 break;
958 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
959 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
961 /* Try to find a suitable renderer with the same media type */
962 tab[0] = mt->majortype;
963 tab[1] = GUID_NULL;
964 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL);
965 if (FAILED(hr)) {
966 ERR("Unable to enum filters (%x)\n", hr);
967 return hr;
970 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
972 VARIANT var;
973 GUID clsid;
974 IPin* ppinfilter;
975 IBaseFilter* pfilter = NULL;
976 IEnumPins* penumpins;
977 ULONG pin;
979 hr = GetFilterInfo(pMoniker, &clsid, &var);
980 IMoniker_Release(pMoniker);
981 if (FAILED(hr)) {
982 ERR("Unable to retrieve filter info (%x)\n", hr);
983 goto error;
986 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
987 if (FAILED(hr)) {
988 ERR("Unable to create filter (%x), trying next one\n", hr);
989 goto error;
992 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
993 if (FAILED(hr)) {
994 ERR("Unable to add filter (%x)\n", hr);
995 IBaseFilter_Release(pfilter);
996 pfilter = NULL;
997 goto error;
1000 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1001 if (FAILED(hr)) {
1002 ERR("Splitter Enumpins (%x)\n", hr);
1003 goto error;
1005 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1006 IEnumPins_Release(penumpins);
1007 if (FAILED(hr)) {
1008 ERR("Next (%x)\n", hr);
1009 goto error;
1011 if (pin == 0) {
1012 ERR("No Pin\n");
1013 goto error;
1016 /* Connect the pin to render to the renderer */
1017 hr = IFilterGraph2_Connect(iface, ppinOut, ppinfilter);
1018 if (FAILED(hr)) {
1019 TRACE("Unable to connect to renderer (%x)\n", hr);
1020 IPin_Release(ppinfilter);
1021 goto error;
1023 IPin_Release(ppinfilter);
1024 IBaseFilter_Release(pfilter);
1025 pfilter = NULL;
1026 break;
1028 error:
1029 if (pfilter) {
1030 IFilterGraph2_RemoveFilter(iface, pfilter);
1031 IBaseFilter_Release(pfilter);
1035 DeleteMediaType(mt);
1036 break;
1039 IEnumMediaTypes_Release(penummt);
1041 return S_OK;
1044 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface,
1045 LPCWSTR lpcwstrFile,
1046 LPCWSTR lpcwstrPlayList) {
1047 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1048 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1049 IBaseFilter* preader = NULL;
1050 IBaseFilter* psplitter = NULL;
1051 IPin* ppinreader = NULL;
1052 IPin* ppinsplitter = NULL;
1053 IEnumPins* penumpins;
1054 ULONG pin;
1055 HRESULT hr;
1056 IEnumMoniker* pEnumMoniker = NULL;
1057 GUID tab[2];
1058 IPin** ppins = NULL;
1059 ULONG nb;
1060 IMoniker* pMoniker;
1061 IFileSourceFilter* pfile = NULL;
1062 AM_MEDIA_TYPE mt;
1063 WCHAR* filename;
1065 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1067 if (lpcwstrPlayList != NULL)
1068 return E_INVALIDARG;
1070 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1072 /* Retrieve file media type */
1073 if (SUCCEEDED(hr))
1074 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1075 if (SUCCEEDED(hr)) {
1076 hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1077 IFileSourceFilter_Release(pfile);
1080 if (SUCCEEDED(hr))
1081 hr = IBaseFilter_EnumPins(preader, &penumpins);
1082 if (SUCCEEDED(hr)) {
1083 hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin);
1084 IEnumPins_Release(penumpins);
1087 if (SUCCEEDED(hr)) {
1088 tab[0] = mt.majortype;
1089 tab[1] = mt.subtype;
1090 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1093 if (FAILED(hr))
1095 if (ppinreader)
1096 IPin_Release(ppinreader);
1097 if (pEnumMoniker)
1098 IEnumMoniker_Release(pEnumMoniker);
1099 if (preader) {
1100 IFilterGraph2_RemoveFilter(iface, preader);
1101 IBaseFilter_Release(preader);
1103 return hr;
1106 hr = VFW_E_CANNOT_RENDER;
1107 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1109 VARIANT var;
1110 GUID clsid;
1112 hr = GetFilterInfo(pMoniker, &clsid, &var);
1113 IMoniker_Release(pMoniker);
1114 if (FAILED(hr)) {
1115 ERR("Unable to retrieve filter info (%x)\n", hr);
1116 continue;
1119 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter);
1120 if (FAILED(hr)) {
1121 ERR("Unable to create filter (%x), trying next one\n", hr);
1122 continue;
1125 hr = IFilterGraph2_AddFilter(iface, psplitter, V_UNION(&var, bstrVal));
1126 if (FAILED(hr)) {
1127 ERR("Unable add filter (%x)\n", hr);
1128 IBaseFilter_Release(psplitter);
1129 continue;
1132 /* Connect file source and splitter filters together */
1133 /* Make the splitter analyze incoming data */
1135 hr = IBaseFilter_EnumPins(psplitter, &penumpins);
1136 if (SUCCEEDED(hr)) {
1137 hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin);
1138 IEnumPins_Release(penumpins);
1141 if (SUCCEEDED(hr))
1142 hr = IPin_Connect(ppinreader, ppinsplitter, NULL);
1144 /* Make sure there's some output pins in the filter */
1145 if (SUCCEEDED(hr))
1146 hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb);
1147 if (SUCCEEDED(hr)) {
1148 if(nb == 0) {
1149 IPin_Disconnect(ppinreader);
1150 TRACE("No output pins found in filter\n");
1151 hr = VFW_E_CANNOT_RENDER;
1155 if (ppinsplitter)
1156 IPin_Release(ppinsplitter);
1157 ppinsplitter = NULL;
1159 if (SUCCEEDED(hr)) {
1160 TRACE("Successfully connected to filter\n");
1161 break;
1164 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1166 if (ppins) {
1167 CoTaskMemFree(ppins);
1168 ppins = NULL;
1170 IFilterGraph2_RemoveFilter(iface, psplitter);
1171 IBaseFilter_Release(psplitter);
1172 psplitter = NULL;
1175 /* Render all output pin of the splitter by calling IFilterGraph2_Render on each of them */
1176 if (SUCCEEDED(hr)) {
1177 int partial = 0;
1178 int i;
1179 TRACE("pins to consider: %d\n", nb);
1180 for(i = 0; i < nb; i++) {
1181 TRACE("Processing pin %d\n", i);
1182 hr = IFilterGraph2_Render(iface, ppins[i]);
1183 if (FAILED(hr)) {
1184 ERR("Cannot render pin %p (%x)\n", ppins[i], hr);
1185 partial = 1;
1187 IPin_Release(ppins[i]);
1189 CoTaskMemFree(ppins);
1191 hr = (partial ? VFW_S_PARTIAL_RENDER : S_OK);
1194 IPin_Release(ppinreader);
1195 IBaseFilter_Release(preader);
1196 if (psplitter)
1197 IBaseFilter_Release(psplitter);
1199 return hr;
1202 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface,
1203 LPCWSTR lpcwstrFileName,
1204 LPCWSTR lpcwstrFilterName,
1205 IBaseFilter **ppFilter) {
1206 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1207 HRESULT hr;
1208 IBaseFilter* preader;
1209 IFileSourceFilter* pfile = NULL;
1210 AM_MEDIA_TYPE mt;
1211 WCHAR* filename;
1213 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1215 /* Instantiate a file source filter */
1216 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1217 if (FAILED(hr)) {
1218 ERR("Unable to create file source filter (%x)\n", hr);
1219 return hr;
1222 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1223 if (FAILED(hr)) {
1224 ERR("Unable add filter (%x)\n", hr);
1225 IBaseFilter_Release(preader);
1226 return hr;
1229 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1230 if (FAILED(hr)) {
1231 ERR("Unable to get IFileSourceInterface (%x)\n", hr);
1232 goto error;
1235 /* Load the file in the file source filter */
1236 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1237 if (FAILED(hr)) {
1238 ERR("Load (%x)\n", hr);
1239 goto error;
1242 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1243 if (FAILED(hr)) {
1244 ERR("GetCurFile (%x)\n", hr);
1245 goto error;
1247 TRACE("File %s\n", debugstr_w(filename));
1248 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1249 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1251 if (ppFilter)
1252 *ppFilter = preader;
1253 IFileSourceFilter_Release(pfile);
1255 return S_OK;
1257 error:
1258 if (pfile)
1259 IFileSourceFilter_Release(pfile);
1260 IFilterGraph2_RemoveFilter(iface, preader);
1261 IBaseFilter_Release(preader);
1263 return hr;
1266 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface,
1267 DWORD_PTR hFile) {
1268 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1270 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1272 return S_OK;
1275 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) {
1276 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1278 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1280 return S_OK;
1283 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) {
1284 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1286 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1288 return S_OK;
1291 /*** IFilterGraph2 methods ***/
1292 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1293 IMoniker *pMoniker,
1294 IBindCtx *pCtx,
1295 LPCWSTR lpcwstrFilterName,
1296 IBaseFilter **ppFilter) {
1297 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1299 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1301 return S_OK;
1304 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface,
1305 IPin *ppin,
1306 const AM_MEDIA_TYPE *pmt) {
1307 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1309 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1311 return S_OK;
1314 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface,
1315 IPin *pPinOut,
1316 DWORD dwFlags,
1317 DWORD *pvContext) {
1318 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1320 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1322 return S_OK;
1326 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1328 FilterGraph2_QueryInterface,
1329 FilterGraph2_AddRef,
1330 FilterGraph2_Release,
1331 FilterGraph2_AddFilter,
1332 FilterGraph2_RemoveFilter,
1333 FilterGraph2_EnumFilters,
1334 FilterGraph2_FindFilterByName,
1335 FilterGraph2_ConnectDirect,
1336 FilterGraph2_Reconnect,
1337 FilterGraph2_Disconnect,
1338 FilterGraph2_SetDefaultSyncSource,
1339 FilterGraph2_Connect,
1340 FilterGraph2_Render,
1341 FilterGraph2_RenderFile,
1342 FilterGraph2_AddSourceFilter,
1343 FilterGraph2_SetLogFile,
1344 FilterGraph2_Abort,
1345 FilterGraph2_ShouldOperationContinue,
1346 FilterGraph2_AddSourceFilterForMoniker,
1347 FilterGraph2_ReconnectEx,
1348 FilterGraph2_RenderEx
1351 /*** IUnknown methods ***/
1352 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface,
1353 REFIID riid,
1354 LPVOID*ppvObj) {
1355 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1357 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1359 return Filtergraph_QueryInterface(This, riid, ppvObj);
1362 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) {
1363 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1365 TRACE("(%p/%p)->()\n", This, iface);
1367 return Filtergraph_AddRef(This);
1370 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) {
1371 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1373 TRACE("(%p/%p)->()\n", This, iface);
1375 return Filtergraph_Release(This);
1379 /*** IDispatch methods ***/
1380 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface,
1381 UINT*pctinfo) {
1382 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1384 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1386 return S_OK;
1389 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface,
1390 UINT iTInfo,
1391 LCID lcid,
1392 ITypeInfo**ppTInfo) {
1393 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1395 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1397 return S_OK;
1400 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface,
1401 REFIID riid,
1402 LPOLESTR*rgszNames,
1403 UINT cNames,
1404 LCID lcid,
1405 DISPID*rgDispId) {
1406 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1408 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1410 return S_OK;
1413 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
1414 DISPID dispIdMember,
1415 REFIID riid,
1416 LCID lcid,
1417 WORD wFlags,
1418 DISPPARAMS*pDispParams,
1419 VARIANT*pVarResult,
1420 EXCEPINFO*pExepInfo,
1421 UINT*puArgErr) {
1422 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1424 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1426 return S_OK;
1429 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *);
1431 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter)
1433 HRESULT hr;
1434 IPin* pInputPin;
1435 IPin** ppPins;
1436 ULONG nb;
1437 ULONG i;
1438 PIN_INFO PinInfo;
1440 TRACE("%p %p\n", pGraph, pOutputPin);
1441 PinInfo.pFilter = NULL;
1443 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1445 if (SUCCEEDED(hr))
1447 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1448 if (SUCCEEDED(hr))
1449 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1450 IPin_Release(pInputPin);
1453 if (SUCCEEDED(hr))
1455 if (nb == 0)
1457 TRACE("Reached a renderer\n");
1458 /* Count renderers for end of stream notification */
1459 pGraph->nRenderers++;
1461 else
1463 for(i = 0; i < nb; i++)
1465 /* Explore the graph downstream from this pin
1466 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1467 * several input pins are connected to the same output (a MUX for instance). */
1468 ExploreGraph(pGraph, ppPins[i], FoundFilter);
1469 IPin_Release(ppPins[i]);
1472 CoTaskMemFree(ppPins);
1474 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1476 FoundFilter(PinInfo.pFilter);
1479 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1480 return hr;
1483 static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
1484 LONGLONG time = 0;
1485 IReferenceClock *clock = NULL;
1487 IBaseFilter_GetSyncSource(pFilter, &clock);
1488 if (clock)
1490 IReferenceClock_GetTime(clock, &time);
1491 if (time)
1492 /* Add 50 ms */
1493 time += 500000;
1494 if (time < 0)
1495 time = 0;
1496 IReferenceClock_Release(clock);
1499 return IBaseFilter_Run(pFilter, time);
1502 static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
1503 return IBaseFilter_Pause(pFilter);
1506 static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
1507 return IBaseFilter_Stop(pFilter);
1510 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) {
1511 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1512 int i;
1513 IBaseFilter* pfilter;
1514 IEnumPins* pEnum;
1515 HRESULT hr;
1516 IPin* pPin;
1517 DWORD dummy;
1518 PIN_DIRECTION dir;
1519 TRACE("(%p/%p)->()\n", This, iface);
1521 /* Explorer the graph from source filters to renderers, determine renderers
1522 * number and run filters from renderers to source filters */
1523 This->nRenderers = 0;
1524 ResetEvent(This->hEventCompletion);
1526 for(i = 0; i < This->nFilters; i++)
1528 BOOL source = TRUE;
1529 pfilter = This->ppFiltersInGraph[i];
1530 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1531 if (hr != S_OK)
1533 ERR("Enum pins failed %x\n", hr);
1534 continue;
1536 /* Check if it is a source filter */
1537 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1539 IPin_QueryDirection(pPin, &dir);
1540 IPin_Release(pPin);
1541 if (dir == PINDIR_INPUT)
1543 source = FALSE;
1544 break;
1547 if (source)
1549 TRACE("Found a source filter %p\n", pfilter);
1550 IEnumPins_Reset(pEnum);
1551 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1553 /* Explore the graph downstream from this pin */
1554 ExploreGraph(This, pPin, FoundFilter);
1555 IPin_Release(pPin);
1557 FoundFilter(pfilter);
1559 IEnumPins_Release(pEnum);
1562 return S_FALSE;
1565 /*** IMediaControl methods ***/
1566 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
1567 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1568 TRACE("(%p/%p)->()\n", This, iface);
1570 if (This->state == State_Running) return S_OK;
1572 EnterCriticalSection(&This->cs);
1573 if (This->state == State_Stopped)
1574 This->EcCompleteCount = 0;
1576 if (This->refClock)
1578 IReferenceClock_GetTime(This->refClock, &This->start_time);
1579 This->start_time += 500000;
1581 else This->position = This->start_time = 0;
1583 SendFilterMessage(iface, SendRun);
1584 This->state = State_Running;
1585 LeaveCriticalSection(&This->cs);
1586 return S_FALSE;
1589 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
1590 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1591 TRACE("(%p/%p)->()\n", This, iface);
1593 if (This->state == State_Paused) return S_OK;
1595 EnterCriticalSection(&This->cs);
1596 if (This->state == State_Stopped)
1597 This->EcCompleteCount = 0;
1599 if (This->state == State_Running && This->refClock)
1601 LONGLONG time = This->start_time;
1602 IReferenceClock_GetTime(This->refClock, &time);
1603 This->position += time - This->start_time;
1606 SendFilterMessage(iface, SendPause);
1607 This->state = State_Paused;
1608 LeaveCriticalSection(&This->cs);
1609 return S_FALSE;
1612 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
1613 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1614 TRACE("(%p/%p)->()\n", This, iface);
1616 if (This->state == State_Stopped) return S_OK;
1618 EnterCriticalSection(&This->cs);
1619 if (This->state == State_Running && This->refClock)
1621 LONGLONG time = This->start_time;
1622 IReferenceClock_GetTime(This->refClock, &time);
1623 This->position += time - This->start_time;
1626 if (This->state == State_Running) SendFilterMessage(iface, SendPause);
1627 SendFilterMessage(iface, SendStop);
1628 This->state = State_Stopped;
1629 LeaveCriticalSection(&This->cs);
1630 return S_OK;
1633 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
1634 LONG msTimeout,
1635 OAFilterState *pfs) {
1636 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1638 TRACE("(%p/%p)->(%d, %p): semi-stub !!!\n", This, iface, msTimeout, pfs);
1640 EnterCriticalSection(&This->cs);
1642 *pfs = This->state;
1644 LeaveCriticalSection(&This->cs);
1646 return S_OK;
1649 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface,
1650 BSTR strFilename) {
1651 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1653 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1655 return S_OK;
1658 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface,
1659 BSTR strFilename,
1660 IDispatch **ppUnk) {
1661 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1663 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1665 return S_OK;
1668 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface,
1669 IDispatch **ppUnk) {
1670 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1672 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1674 return S_OK;
1677 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface,
1678 IDispatch **ppUnk) {
1679 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1681 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1683 return S_OK;
1686 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) {
1687 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1689 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1691 return S_OK;
1695 static const IMediaControlVtbl IMediaControl_VTable =
1697 MediaControl_QueryInterface,
1698 MediaControl_AddRef,
1699 MediaControl_Release,
1700 MediaControl_GetTypeInfoCount,
1701 MediaControl_GetTypeInfo,
1702 MediaControl_GetIDsOfNames,
1703 MediaControl_Invoke,
1704 MediaControl_Run,
1705 MediaControl_Pause,
1706 MediaControl_Stop,
1707 MediaControl_GetState,
1708 MediaControl_RenderFile,
1709 MediaControl_AddSourceFilter,
1710 MediaControl_get_FilterCollection,
1711 MediaControl_get_RegFilterCollection,
1712 MediaControl_StopWhenReady
1716 /*** IUnknown methods ***/
1717 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface,
1718 REFIID riid,
1719 LPVOID*ppvObj) {
1720 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1722 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1724 return Filtergraph_QueryInterface(This, riid, ppvObj);
1727 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) {
1728 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1730 TRACE("(%p/%p)->()\n", This, iface);
1732 return Filtergraph_AddRef(This);
1735 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) {
1736 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1738 TRACE("(%p/%p)->()\n", This, iface);
1740 return Filtergraph_Release(This);
1743 typedef HRESULT WINAPI (*fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
1745 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
1746 BOOL allnotimpl = TRUE;
1747 int i;
1748 IBaseFilter* pfilter;
1749 IEnumPins* pEnum;
1750 HRESULT hr, hr_return = S_OK;
1751 IPin* pPin;
1752 DWORD dummy;
1753 PIN_DIRECTION dir;
1755 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
1756 /* Send a message to all renderers, they are responsible for broadcasting it further */
1758 for(i = 0; i < This->nFilters; i++)
1760 BOOL renderer = TRUE;
1761 pfilter = This->ppFiltersInGraph[i];
1762 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1763 if (hr != S_OK)
1765 ERR("Enum pins failed %x\n", hr);
1766 continue;
1768 /* Check if it is a source filter */
1769 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1771 IPin_QueryDirection(pPin, &dir);
1772 IPin_Release(pPin);
1773 if (dir != PINDIR_INPUT)
1775 renderer = FALSE;
1776 break;
1779 IEnumPins_Release(pEnum);
1780 if (renderer)
1782 IMediaSeeking *seek = NULL;
1783 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
1784 if (!seek)
1785 continue;
1787 hr = FoundSeek(This, seek, arg);
1789 IMediaSeeking_Release(seek);
1790 if (hr_return != E_NOTIMPL)
1791 allnotimpl = FALSE;
1792 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && !FAILED(hr_return)))
1793 hr_return = hr;
1797 if (allnotimpl)
1798 return E_NOTIMPL;
1799 return hr_return;
1802 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
1804 HRESULT hr;
1805 DWORD caps = 0;
1807 hr = IMediaSeeking_GetCapabilities(seek, &caps);
1808 if (FAILED(hr))
1809 return hr;
1811 /* Only add common capabilities everything supports */
1812 *(DWORD*)pcaps &= caps;
1814 return hr;
1817 /*** IMediaSeeking methods ***/
1818 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface,
1819 DWORD *pCapabilities) {
1820 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1821 HRESULT hr;
1822 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
1824 if (!pCapabilities)
1825 return E_POINTER;
1827 EnterCriticalSection(&This->cs);
1828 *pCapabilities = 0xffffffff;
1830 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
1831 LeaveCriticalSection(&This->cs);
1833 return hr;
1836 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface,
1837 DWORD *pCapabilities) {
1838 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1839 DWORD originalcaps;
1840 HRESULT hr;
1841 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
1843 if (!pCapabilities)
1844 return E_POINTER;
1846 EnterCriticalSection(&This->cs);
1847 originalcaps = *pCapabilities;
1848 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
1849 LeaveCriticalSection(&This->cs);
1851 if (FAILED(hr))
1852 return hr;
1854 if (!*pCapabilities)
1855 return E_FAIL;
1856 if (*pCapabilities != originalcaps)
1857 return S_FALSE;
1858 return S_OK;
1861 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface,
1862 const GUID *pFormat) {
1863 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1865 if (!pFormat)
1866 return E_POINTER;
1868 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
1870 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
1872 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
1873 return S_FALSE;
1876 return S_OK;
1879 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface,
1880 GUID *pFormat) {
1881 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1883 if (!pFormat)
1884 return E_POINTER;
1886 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
1887 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
1889 return S_OK;
1892 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface,
1893 GUID *pFormat) {
1894 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1896 if (!pFormat)
1897 return E_POINTER;
1899 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
1900 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
1902 return S_OK;
1905 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface,
1906 const GUID *pFormat) {
1907 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1909 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
1910 if (!pFormat)
1911 return E_POINTER;
1913 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
1914 return S_FALSE;
1916 return S_OK;
1919 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface,
1920 const GUID *pFormat) {
1921 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1923 if (!pFormat)
1924 return E_POINTER;
1926 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
1928 if (This->state != State_Stopped)
1929 return VFW_E_WRONG_STATE;
1931 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
1933 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
1934 return E_INVALIDARG;
1937 return S_OK;
1940 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
1942 HRESULT hr;
1943 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
1945 hr = IMediaSeeking_GetDuration(seek, &duration);
1946 if (FAILED(hr))
1947 return hr;
1949 /* FIXME: Minimum or maximum duration? Assuming minimum */
1950 if (duration > 0 && *pdur < duration)
1951 *pdur = duration;
1953 return hr;
1956 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface,
1957 LONGLONG *pDuration) {
1958 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1959 HRESULT hr;
1961 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
1963 if (!pDuration)
1964 return E_POINTER;
1966 EnterCriticalSection(&This->cs);
1967 *pDuration = -1;
1968 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
1969 LeaveCriticalSection(&This->cs);
1971 TRACE("--->%08x\n", hr);
1972 return hr;
1975 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
1976 LONGLONG *pStop) {
1977 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1979 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1981 return S_OK;
1984 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
1985 LONGLONG *pCurrent) {
1986 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1987 LONGLONG time = 0;
1989 if (!pCurrent)
1990 return E_POINTER;
1992 EnterCriticalSection(&This->cs);
1993 if (This->state == State_Running && This->refClock)
1995 IReferenceClock_GetTime(This->refClock, &time);
1996 if (time)
1997 time += This->position - This->start_time;
1998 if (time < This->position)
1999 time = This->position;
2000 *pCurrent = time;
2002 else
2003 *pCurrent = This->position;
2004 LeaveCriticalSection(&This->cs);
2005 TRACE("Time: %lld.%03lld\n", *pCurrent / 10000000, (*pCurrent / 10000)%1000);
2007 return S_OK;
2010 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
2011 LONGLONG *pTarget,
2012 const GUID *pTargetFormat,
2013 LONGLONG Source,
2014 const GUID *pSourceFormat) {
2015 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2017 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2018 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2020 return S_OK;
2023 struct pos_args {
2024 LONGLONG* current, *stop;
2025 DWORD curflags, stopflags;
2028 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2030 struct pos_args *args = (void*)pargs;
2032 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2035 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
2036 LONGLONG *pCurrent,
2037 DWORD dwCurrentFlags,
2038 LONGLONG *pStop,
2039 DWORD dwStopFlags) {
2040 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2041 HRESULT hr = S_OK;
2042 FILTER_STATE state;
2043 struct pos_args args;
2045 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2047 EnterCriticalSection(&This->cs);
2048 state = This->state;
2049 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2051 if ((dwCurrentFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2052 This->position = *pCurrent;
2053 else if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2054 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2056 if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2057 FIXME("Stop position not handled yet!\n");
2059 args.current = pCurrent;
2060 args.stop = pStop;
2061 args.curflags = dwCurrentFlags;
2062 args.stopflags = dwStopFlags;
2063 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2064 LeaveCriticalSection(&This->cs);
2066 return hr;
2069 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
2070 LONGLONG *pCurrent,
2071 LONGLONG *pStop) {
2072 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2073 HRESULT hr;
2075 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2076 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2077 if (SUCCEEDED(hr))
2078 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2080 return hr;
2083 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
2084 LONGLONG *pEarliest,
2085 LONGLONG *pLatest) {
2086 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2088 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2090 return S_OK;
2093 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
2094 double dRate) {
2095 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2097 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2099 return S_OK;
2102 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
2103 double *pdRate) {
2104 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2106 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2108 return S_OK;
2111 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
2112 LONGLONG *pllPreroll) {
2113 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2115 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2117 return S_OK;
2121 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2123 MediaSeeking_QueryInterface,
2124 MediaSeeking_AddRef,
2125 MediaSeeking_Release,
2126 MediaSeeking_GetCapabilities,
2127 MediaSeeking_CheckCapabilities,
2128 MediaSeeking_IsFormatSupported,
2129 MediaSeeking_QueryPreferredFormat,
2130 MediaSeeking_GetTimeFormat,
2131 MediaSeeking_IsUsingTimeFormat,
2132 MediaSeeking_SetTimeFormat,
2133 MediaSeeking_GetDuration,
2134 MediaSeeking_GetStopPosition,
2135 MediaSeeking_GetCurrentPosition,
2136 MediaSeeking_ConvertTimeFormat,
2137 MediaSeeking_SetPositions,
2138 MediaSeeking_GetPositions,
2139 MediaSeeking_GetAvailable,
2140 MediaSeeking_SetRate,
2141 MediaSeeking_GetRate,
2142 MediaSeeking_GetPreroll
2145 /*** IUnknown methods ***/
2146 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
2147 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2149 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2151 return Filtergraph_QueryInterface(This, riid, ppvObj);
2154 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
2155 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2157 TRACE("(%p/%p)->()\n", This, iface);
2159 return Filtergraph_AddRef(This);
2162 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
2163 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2165 TRACE("(%p/%p)->()\n", This, iface);
2167 return Filtergraph_Release(This);
2170 /*** IDispatch methods ***/
2171 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2172 FIXME("(%p) stub!\n", iface);
2173 return E_NOTIMPL;
2176 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2177 FIXME("(%p) stub!\n", iface);
2178 return E_NOTIMPL;
2181 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2182 FIXME("(%p) stub!\n", iface);
2183 return E_NOTIMPL;
2186 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2187 FIXME("(%p) stub!\n", iface);
2188 return E_NOTIMPL;
2191 /*** IMediaPosition methods ***/
2192 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
2193 FIXME("(%p)->(%p) stub!\n", iface, plength);
2194 return E_NOTIMPL;
2197 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
2198 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
2203 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2204 return E_NOTIMPL;
2207 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
2208 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2209 return E_NOTIMPL;
2212 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
2213 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2214 return E_NOTIMPL;
2217 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2218 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2219 return E_NOTIMPL;
2222 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2223 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2224 return E_NOTIMPL;
2227 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
2228 FIXME("(%p)->(%f) stub!\n", iface, dRate);
2229 return E_NOTIMPL;
2232 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
2233 FIXME("(%p)->(%p) stub!\n", iface, pdRate);
2234 return E_NOTIMPL;
2237 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2238 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2239 return E_NOTIMPL;
2242 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2243 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2244 return E_NOTIMPL;
2248 static const IMediaPositionVtbl IMediaPosition_VTable =
2250 MediaPosition_QueryInterface,
2251 MediaPosition_AddRef,
2252 MediaPosition_Release,
2253 MediaPosition_GetTypeInfoCount,
2254 MediaPosition_GetTypeInfo,
2255 MediaPosition_GetIDsOfNames,
2256 MediaPosition_Invoke,
2257 MediaPosition_get_Duration,
2258 MediaPosition_put_CurrentPosition,
2259 MediaPosition_get_CurrentPosition,
2260 MediaPosition_get_StopTime,
2261 MediaPosition_put_StopTime,
2262 MediaPosition_get_PrerollTime,
2263 MediaPosition_put_PrerollTime,
2264 MediaPosition_put_Rate,
2265 MediaPosition_get_Rate,
2266 MediaPosition_CanSeekForward,
2267 MediaPosition_CanSeekBackward
2270 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2272 HRESULT hr = E_NOINTERFACE;
2273 int i;
2274 int entry;
2276 /* Check if the interface type is already registered */
2277 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2278 if (riid == pGraph->ItfCacheEntries[entry].riid)
2280 if (pGraph->ItfCacheEntries[entry].iface)
2282 /* Return the interface if available */
2283 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2284 return S_OK;
2286 break;
2289 if (entry >= MAX_ITF_CACHE_ENTRIES)
2291 FIXME("Not enough space to store interface in the cache\n");
2292 return E_OUTOFMEMORY;
2295 /* Find a filter supporting the requested interface */
2296 for (i = 0; i < pGraph->nFilters; i++)
2298 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2299 if (hr == S_OK)
2301 pGraph->ItfCacheEntries[entry].riid = riid;
2302 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2303 pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
2304 if (entry >= pGraph->nItfCacheEntries)
2305 pGraph->nItfCacheEntries++;
2306 return S_OK;
2308 if (hr != E_NOINTERFACE)
2309 return hr;
2312 return hr;
2315 /*** IUnknown methods ***/
2316 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
2317 REFIID riid,
2318 LPVOID*ppvObj) {
2319 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2321 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2323 return Filtergraph_QueryInterface(This, riid, ppvObj);
2326 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
2327 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2329 TRACE("(%p/%p)->()\n", This, iface);
2331 return Filtergraph_AddRef(This);
2334 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
2335 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2337 TRACE("(%p/%p)->()\n", This, iface);
2339 return Filtergraph_Release(This);
2342 /*** IDispatch methods ***/
2343 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
2344 UINT*pctinfo) {
2345 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2346 IBasicAudio* pBasicAudio;
2347 HRESULT hr;
2349 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2351 EnterCriticalSection(&This->cs);
2353 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2355 if (hr == S_OK)
2356 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2358 LeaveCriticalSection(&This->cs);
2360 return hr;
2363 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2364 UINT iTInfo,
2365 LCID lcid,
2366 ITypeInfo**ppTInfo) {
2367 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2368 IBasicAudio* pBasicAudio;
2369 HRESULT hr;
2371 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2373 EnterCriticalSection(&This->cs);
2375 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2377 if (hr == S_OK)
2378 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2380 LeaveCriticalSection(&This->cs);
2382 return hr;
2385 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2386 REFIID riid,
2387 LPOLESTR*rgszNames,
2388 UINT cNames,
2389 LCID lcid,
2390 DISPID*rgDispId) {
2391 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2392 IBasicAudio* pBasicAudio;
2393 HRESULT hr;
2395 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2397 EnterCriticalSection(&This->cs);
2399 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2401 if (hr == S_OK)
2402 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2404 LeaveCriticalSection(&This->cs);
2406 return hr;
2409 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2410 DISPID dispIdMember,
2411 REFIID riid,
2412 LCID lcid,
2413 WORD wFlags,
2414 DISPPARAMS*pDispParams,
2415 VARIANT*pVarResult,
2416 EXCEPINFO*pExepInfo,
2417 UINT*puArgErr) {
2418 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2419 IBasicAudio* pBasicAudio;
2420 HRESULT hr;
2422 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2424 EnterCriticalSection(&This->cs);
2426 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2428 if (hr == S_OK)
2429 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2431 LeaveCriticalSection(&This->cs);
2433 return hr;
2436 /*** IBasicAudio methods ***/
2437 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2438 long lVolume) {
2439 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2440 IBasicAudio* pBasicAudio;
2441 HRESULT hr;
2443 TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2445 EnterCriticalSection(&This->cs);
2447 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2449 if (hr == S_OK)
2450 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2452 LeaveCriticalSection(&This->cs);
2454 return hr;
2457 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2458 long *plVolume) {
2459 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2460 IBasicAudio* pBasicAudio;
2461 HRESULT hr;
2463 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2465 EnterCriticalSection(&This->cs);
2467 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2469 if (hr == S_OK)
2470 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2472 LeaveCriticalSection(&This->cs);
2474 return hr;
2477 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2478 long lBalance) {
2479 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2480 IBasicAudio* pBasicAudio;
2481 HRESULT hr;
2483 TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2485 EnterCriticalSection(&This->cs);
2487 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2489 if (hr == S_OK)
2490 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2492 LeaveCriticalSection(&This->cs);
2494 return hr;
2497 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2498 long *plBalance) {
2499 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2500 IBasicAudio* pBasicAudio;
2501 HRESULT hr;
2503 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2505 EnterCriticalSection(&This->cs);
2507 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2509 if (hr == S_OK)
2510 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2512 LeaveCriticalSection(&This->cs);
2514 return hr;
2517 static const IBasicAudioVtbl IBasicAudio_VTable =
2519 BasicAudio_QueryInterface,
2520 BasicAudio_AddRef,
2521 BasicAudio_Release,
2522 BasicAudio_GetTypeInfoCount,
2523 BasicAudio_GetTypeInfo,
2524 BasicAudio_GetIDsOfNames,
2525 BasicAudio_Invoke,
2526 BasicAudio_put_Volume,
2527 BasicAudio_get_Volume,
2528 BasicAudio_put_Balance,
2529 BasicAudio_get_Balance
2532 /*** IUnknown methods ***/
2533 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface,
2534 REFIID riid,
2535 LPVOID*ppvObj) {
2536 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2538 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2540 return Filtergraph_QueryInterface(This, riid, ppvObj);
2543 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) {
2544 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2546 TRACE("(%p/%p)->()\n", This, iface);
2548 return Filtergraph_AddRef(This);
2551 static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) {
2552 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2554 TRACE("(%p/%p)->()\n", This, iface);
2556 return Filtergraph_Release(This);
2559 /*** IDispatch methods ***/
2560 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface,
2561 UINT*pctinfo) {
2562 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2563 IBasicVideo* pBasicVideo;
2564 HRESULT hr;
2566 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2568 EnterCriticalSection(&This->cs);
2570 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2572 if (hr == S_OK)
2573 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2575 LeaveCriticalSection(&This->cs);
2577 return hr;
2580 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface,
2581 UINT iTInfo,
2582 LCID lcid,
2583 ITypeInfo**ppTInfo) {
2584 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2585 IBasicVideo* pBasicVideo;
2586 HRESULT hr;
2588 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2590 EnterCriticalSection(&This->cs);
2592 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2594 if (hr == S_OK)
2595 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2597 LeaveCriticalSection(&This->cs);
2599 return hr;
2602 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface,
2603 REFIID riid,
2604 LPOLESTR*rgszNames,
2605 UINT cNames,
2606 LCID lcid,
2607 DISPID*rgDispId) {
2608 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2609 IBasicVideo* pBasicVideo;
2610 HRESULT hr;
2612 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2614 EnterCriticalSection(&This->cs);
2616 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2618 if (hr == S_OK)
2619 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
2621 LeaveCriticalSection(&This->cs);
2623 return hr;
2626 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface,
2627 DISPID dispIdMember,
2628 REFIID riid,
2629 LCID lcid,
2630 WORD wFlags,
2631 DISPPARAMS*pDispParams,
2632 VARIANT*pVarResult,
2633 EXCEPINFO*pExepInfo,
2634 UINT*puArgErr) {
2635 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2636 IBasicVideo* pBasicVideo;
2637 HRESULT hr;
2639 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2641 EnterCriticalSection(&This->cs);
2643 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2645 if (hr == S_OK)
2646 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2648 LeaveCriticalSection(&This->cs);
2650 return hr;
2653 /*** IBasicVideo methods ***/
2654 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface,
2655 REFTIME *pAvgTimePerFrame) {
2656 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2657 IBasicVideo* pBasicVideo;
2658 HRESULT hr;
2660 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
2662 EnterCriticalSection(&This->cs);
2664 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2666 if (hr == S_OK)
2667 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
2669 LeaveCriticalSection(&This->cs);
2671 return hr;
2674 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface,
2675 long *pBitRate) {
2676 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2677 IBasicVideo* pBasicVideo;
2678 HRESULT hr;
2680 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
2682 EnterCriticalSection(&This->cs);
2684 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2686 if (hr == S_OK)
2687 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
2689 LeaveCriticalSection(&This->cs);
2691 return hr;
2694 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface,
2695 long *pBitErrorRate) {
2696 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2697 IBasicVideo* pBasicVideo;
2698 HRESULT hr;
2700 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
2702 EnterCriticalSection(&This->cs);
2704 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2706 if (hr == S_OK)
2707 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
2709 LeaveCriticalSection(&This->cs);
2711 return hr;
2714 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface,
2715 long *pVideoWidth) {
2716 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2717 IBasicVideo* pBasicVideo;
2718 HRESULT hr;
2720 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
2722 EnterCriticalSection(&This->cs);
2724 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2726 if (hr == S_OK)
2727 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
2729 LeaveCriticalSection(&This->cs);
2731 return hr;
2734 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface,
2735 long *pVideoHeight) {
2736 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2737 IBasicVideo* pBasicVideo;
2738 HRESULT hr;
2740 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
2742 EnterCriticalSection(&This->cs);
2744 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2746 if (hr == S_OK)
2747 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
2749 LeaveCriticalSection(&This->cs);
2751 return hr;
2754 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface,
2755 long SourceLeft) {
2756 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2757 IBasicVideo* pBasicVideo;
2758 HRESULT hr;
2760 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
2762 EnterCriticalSection(&This->cs);
2764 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2766 if (hr == S_OK)
2767 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
2769 LeaveCriticalSection(&This->cs);
2771 return hr;
2774 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface,
2775 long *pSourceLeft) {
2776 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2777 IBasicVideo* pBasicVideo;
2778 HRESULT hr;
2780 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
2782 EnterCriticalSection(&This->cs);
2784 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2786 if (hr == S_OK)
2787 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
2789 LeaveCriticalSection(&This->cs);
2791 return hr;
2794 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface,
2795 long SourceWidth) {
2796 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2797 IBasicVideo* pBasicVideo;
2798 HRESULT hr;
2800 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
2802 EnterCriticalSection(&This->cs);
2804 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2806 if (hr == S_OK)
2807 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
2809 LeaveCriticalSection(&This->cs);
2811 return hr;
2814 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface,
2815 long *pSourceWidth) {
2816 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2817 IBasicVideo* pBasicVideo;
2818 HRESULT hr;
2820 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
2822 EnterCriticalSection(&This->cs);
2824 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2826 if (hr == S_OK)
2827 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
2829 LeaveCriticalSection(&This->cs);
2831 return hr;
2834 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface,
2835 long SourceTop) {
2836 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2837 IBasicVideo* pBasicVideo;
2838 HRESULT hr;
2840 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
2842 EnterCriticalSection(&This->cs);
2844 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2846 if (hr == S_OK)
2847 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
2849 LeaveCriticalSection(&This->cs);
2851 return hr;
2854 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface,
2855 long *pSourceTop) {
2856 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2857 IBasicVideo* pBasicVideo;
2858 HRESULT hr;
2860 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
2862 EnterCriticalSection(&This->cs);
2864 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2866 if (hr == S_OK)
2867 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
2869 LeaveCriticalSection(&This->cs);
2871 return hr;
2874 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface,
2875 long SourceHeight) {
2876 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2877 IBasicVideo* pBasicVideo;
2878 HRESULT hr;
2880 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
2882 EnterCriticalSection(&This->cs);
2884 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2886 if (hr == S_OK)
2887 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
2889 LeaveCriticalSection(&This->cs);
2891 return hr;
2894 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface,
2895 long *pSourceHeight) {
2896 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2897 IBasicVideo* pBasicVideo;
2898 HRESULT hr;
2900 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
2902 EnterCriticalSection(&This->cs);
2904 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2906 if (hr == S_OK)
2907 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
2909 LeaveCriticalSection(&This->cs);
2911 return hr;
2914 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface,
2915 long DestinationLeft) {
2916 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2917 IBasicVideo* pBasicVideo;
2918 HRESULT hr;
2920 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
2922 EnterCriticalSection(&This->cs);
2924 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2926 if (hr == S_OK)
2927 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
2929 LeaveCriticalSection(&This->cs);
2931 return hr;
2934 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface,
2935 long *pDestinationLeft) {
2936 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2937 IBasicVideo* pBasicVideo;
2938 HRESULT hr;
2940 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
2942 EnterCriticalSection(&This->cs);
2944 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2946 if (hr == S_OK)
2947 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
2949 LeaveCriticalSection(&This->cs);
2951 return hr;
2954 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface,
2955 long DestinationWidth) {
2956 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2957 IBasicVideo* pBasicVideo;
2958 HRESULT hr;
2960 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
2962 EnterCriticalSection(&This->cs);
2964 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2966 if (hr == S_OK)
2967 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
2969 LeaveCriticalSection(&This->cs);
2971 return hr;
2974 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface,
2975 long *pDestinationWidth) {
2976 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2977 IBasicVideo* pBasicVideo;
2978 HRESULT hr;
2980 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
2982 EnterCriticalSection(&This->cs);
2984 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2986 if (hr == S_OK)
2987 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
2989 LeaveCriticalSection(&This->cs);
2991 return hr;
2994 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface,
2995 long DestinationTop) {
2996 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2997 IBasicVideo* pBasicVideo;
2998 HRESULT hr;
3000 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
3002 EnterCriticalSection(&This->cs);
3004 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3006 if (hr == S_OK)
3007 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3009 LeaveCriticalSection(&This->cs);
3011 return hr;
3014 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface,
3015 long *pDestinationTop) {
3016 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3017 IBasicVideo* pBasicVideo;
3018 HRESULT hr;
3020 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3022 EnterCriticalSection(&This->cs);
3024 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3026 if (hr == S_OK)
3027 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3029 LeaveCriticalSection(&This->cs);
3031 return hr;
3034 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface,
3035 long DestinationHeight) {
3036 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3037 IBasicVideo* pBasicVideo;
3038 HRESULT hr;
3040 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
3042 EnterCriticalSection(&This->cs);
3044 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3046 if (hr == S_OK)
3047 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3049 LeaveCriticalSection(&This->cs);
3051 return hr;
3054 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface,
3055 long *pDestinationHeight) {
3056 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3057 IBasicVideo* pBasicVideo;
3058 HRESULT hr;
3060 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3062 EnterCriticalSection(&This->cs);
3064 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3066 if (hr == S_OK)
3067 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3069 LeaveCriticalSection(&This->cs);
3071 return hr;
3074 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface,
3075 long Left,
3076 long Top,
3077 long Width,
3078 long Height) {
3079 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3080 IBasicVideo* pBasicVideo;
3081 HRESULT hr;
3083 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3085 EnterCriticalSection(&This->cs);
3087 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3089 if (hr == S_OK)
3090 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3092 LeaveCriticalSection(&This->cs);
3094 return hr;
3097 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface,
3098 long *pLeft,
3099 long *pTop,
3100 long *pWidth,
3101 long *pHeight) {
3102 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3103 IBasicVideo* pBasicVideo;
3104 HRESULT hr;
3106 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3108 EnterCriticalSection(&This->cs);
3110 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3112 if (hr == S_OK)
3113 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3115 LeaveCriticalSection(&This->cs);
3117 return hr;
3120 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) {
3121 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3122 IBasicVideo* pBasicVideo;
3123 HRESULT hr;
3125 TRACE("(%p/%p)->()\n", This, iface);
3127 EnterCriticalSection(&This->cs);
3129 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3131 if (hr == S_OK)
3132 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3134 LeaveCriticalSection(&This->cs);
3136 return hr;
3139 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface,
3140 long Left,
3141 long Top,
3142 long Width,
3143 long Height) {
3144 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3145 IBasicVideo* pBasicVideo;
3146 HRESULT hr;
3148 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3150 EnterCriticalSection(&This->cs);
3152 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3154 if (hr == S_OK)
3155 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3157 LeaveCriticalSection(&This->cs);
3159 return hr;
3162 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface,
3163 long *pLeft,
3164 long *pTop,
3165 long *pWidth,
3166 long *pHeight) {
3167 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3168 IBasicVideo* pBasicVideo;
3169 HRESULT hr;
3171 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3173 EnterCriticalSection(&This->cs);
3175 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3177 if (hr == S_OK)
3178 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3180 LeaveCriticalSection(&This->cs);
3182 return hr;
3185 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
3186 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3187 IBasicVideo* pBasicVideo;
3188 HRESULT hr;
3190 TRACE("(%p/%p)->()\n", This, iface);
3192 EnterCriticalSection(&This->cs);
3194 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3196 if (hr == S_OK)
3197 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3199 LeaveCriticalSection(&This->cs);
3201 return hr;
3204 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface,
3205 long *pWidth,
3206 long *pHeight) {
3207 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3208 IBasicVideo* pBasicVideo;
3209 HRESULT hr;
3211 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3213 EnterCriticalSection(&This->cs);
3215 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3217 if (hr == S_OK)
3218 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3220 LeaveCriticalSection(&This->cs);
3222 return hr;
3225 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface,
3226 long StartIndex,
3227 long Entries,
3228 long *pRetrieved,
3229 long *pPalette) {
3230 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3231 IBasicVideo* pBasicVideo;
3232 HRESULT hr;
3234 TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3236 EnterCriticalSection(&This->cs);
3238 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3240 if (hr == S_OK)
3241 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3243 LeaveCriticalSection(&This->cs);
3245 return hr;
3248 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface,
3249 long *pBufferSize,
3250 long *pDIBImage) {
3251 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3252 IBasicVideo* pBasicVideo;
3253 HRESULT hr;
3255 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3257 EnterCriticalSection(&This->cs);
3259 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3261 if (hr == S_OK)
3262 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3264 LeaveCriticalSection(&This->cs);
3266 return hr;
3269 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) {
3270 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3271 IBasicVideo* pBasicVideo;
3272 HRESULT hr;
3274 TRACE("(%p/%p)->()\n", This, iface);
3276 EnterCriticalSection(&This->cs);
3278 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3280 if (hr == S_OK)
3281 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3283 LeaveCriticalSection(&This->cs);
3285 return hr;
3288 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) {
3289 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3290 IBasicVideo* pBasicVideo;
3291 HRESULT hr;
3293 TRACE("(%p/%p)->()\n", This, iface);
3295 EnterCriticalSection(&This->cs);
3297 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3299 if (hr == S_OK)
3300 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3302 LeaveCriticalSection(&This->cs);
3304 return hr;
3308 static const IBasicVideoVtbl IBasicVideo_VTable =
3310 BasicVideo_QueryInterface,
3311 BasicVideo_AddRef,
3312 BasicVideo_Release,
3313 BasicVideo_GetTypeInfoCount,
3314 BasicVideo_GetTypeInfo,
3315 BasicVideo_GetIDsOfNames,
3316 BasicVideo_Invoke,
3317 BasicVideo_get_AvgTimePerFrame,
3318 BasicVideo_get_BitRate,
3319 BasicVideo_get_BitErrorRate,
3320 BasicVideo_get_VideoWidth,
3321 BasicVideo_get_VideoHeight,
3322 BasicVideo_put_SourceLeft,
3323 BasicVideo_get_SourceLeft,
3324 BasicVideo_put_SourceWidth,
3325 BasicVideo_get_SourceWidth,
3326 BasicVideo_put_SourceTop,
3327 BasicVideo_get_SourceTop,
3328 BasicVideo_put_SourceHeight,
3329 BasicVideo_get_SourceHeight,
3330 BasicVideo_put_DestinationLeft,
3331 BasicVideo_get_DestinationLeft,
3332 BasicVideo_put_DestinationWidth,
3333 BasicVideo_get_DestinationWidth,
3334 BasicVideo_put_DestinationTop,
3335 BasicVideo_get_DestinationTop,
3336 BasicVideo_put_DestinationHeight,
3337 BasicVideo_get_DestinationHeight,
3338 BasicVideo_SetSourcePosition,
3339 BasicVideo_GetSourcePosition,
3340 BasicVideo_SetDefaultSourcePosition,
3341 BasicVideo_SetDestinationPosition,
3342 BasicVideo_GetDestinationPosition,
3343 BasicVideo_SetDefaultDestinationPosition,
3344 BasicVideo_GetVideoSize,
3345 BasicVideo_GetVideoPaletteEntries,
3346 BasicVideo_GetCurrentImage,
3347 BasicVideo_IsUsingDefaultSource,
3348 BasicVideo_IsUsingDefaultDestination
3352 /*** IUnknown methods ***/
3353 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3354 REFIID riid,
3355 LPVOID*ppvObj) {
3356 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3358 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3360 return Filtergraph_QueryInterface(This, riid, ppvObj);
3363 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3364 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3366 TRACE("(%p/%p)->()\n", This, iface);
3368 return Filtergraph_AddRef(This);
3371 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3372 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3374 TRACE("(%p/%p)->()\n", This, iface);
3376 return Filtergraph_Release(This);
3379 /*** IDispatch methods ***/
3380 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3381 UINT*pctinfo) {
3382 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3383 IVideoWindow* pVideoWindow;
3384 HRESULT hr;
3386 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3388 EnterCriticalSection(&This->cs);
3390 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3392 if (hr == S_OK)
3393 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3395 LeaveCriticalSection(&This->cs);
3397 return hr;
3400 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3401 UINT iTInfo,
3402 LCID lcid,
3403 ITypeInfo**ppTInfo) {
3404 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3405 IVideoWindow* pVideoWindow;
3406 HRESULT hr;
3408 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3410 EnterCriticalSection(&This->cs);
3412 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3414 if (hr == S_OK)
3415 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3417 LeaveCriticalSection(&This->cs);
3419 return hr;
3422 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3423 REFIID riid,
3424 LPOLESTR*rgszNames,
3425 UINT cNames,
3426 LCID lcid,
3427 DISPID*rgDispId) {
3428 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3429 IVideoWindow* pVideoWindow;
3430 HRESULT hr;
3432 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3434 EnterCriticalSection(&This->cs);
3436 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3438 if (hr == S_OK)
3439 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3441 LeaveCriticalSection(&This->cs);
3443 return hr;
3446 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3447 DISPID dispIdMember,
3448 REFIID riid,
3449 LCID lcid,
3450 WORD wFlags,
3451 DISPPARAMS*pDispParams,
3452 VARIANT*pVarResult,
3453 EXCEPINFO*pExepInfo,
3454 UINT*puArgErr) {
3455 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3456 IVideoWindow* pVideoWindow;
3457 HRESULT hr;
3459 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3461 EnterCriticalSection(&This->cs);
3463 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3465 if (hr == S_OK)
3466 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3468 LeaveCriticalSection(&This->cs);
3470 return hr;
3474 /*** IVideoWindow methods ***/
3475 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3476 BSTR strCaption) {
3477 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3478 IVideoWindow* pVideoWindow;
3479 HRESULT hr;
3481 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3483 EnterCriticalSection(&This->cs);
3485 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3487 if (hr == S_OK)
3488 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3490 LeaveCriticalSection(&This->cs);
3492 return hr;
3495 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3496 BSTR *strCaption) {
3497 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3498 IVideoWindow* pVideoWindow;
3499 HRESULT hr;
3501 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3503 EnterCriticalSection(&This->cs);
3505 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3507 if (hr == S_OK)
3508 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3510 LeaveCriticalSection(&This->cs);
3512 return hr;
3515 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3516 long WindowStyle) {
3517 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3518 IVideoWindow* pVideoWindow;
3519 HRESULT hr;
3521 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3523 EnterCriticalSection(&This->cs);
3525 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3527 if (hr == S_OK)
3528 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3530 LeaveCriticalSection(&This->cs);
3532 return hr;
3535 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3536 long *WindowStyle) {
3537 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3538 IVideoWindow* pVideoWindow;
3539 HRESULT hr;
3541 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3543 EnterCriticalSection(&This->cs);
3545 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3547 if (hr == S_OK)
3548 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3550 LeaveCriticalSection(&This->cs);
3552 return hr;
3555 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3556 long WindowStyleEx) {
3557 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3558 IVideoWindow* pVideoWindow;
3559 HRESULT hr;
3561 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3563 EnterCriticalSection(&This->cs);
3565 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3567 if (hr == S_OK)
3568 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3570 LeaveCriticalSection(&This->cs);
3572 return hr;
3575 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3576 long *WindowStyleEx) {
3577 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3578 IVideoWindow* pVideoWindow;
3579 HRESULT hr;
3581 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3583 EnterCriticalSection(&This->cs);
3585 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3587 if (hr == S_OK)
3588 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
3590 LeaveCriticalSection(&This->cs);
3592 return hr;
3595 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
3596 long AutoShow) {
3597 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3598 IVideoWindow* pVideoWindow;
3599 HRESULT hr;
3601 TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
3603 EnterCriticalSection(&This->cs);
3605 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3607 if (hr == S_OK)
3608 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
3610 LeaveCriticalSection(&This->cs);
3612 return hr;
3615 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
3616 long *AutoShow) {
3617 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3618 IVideoWindow* pVideoWindow;
3619 HRESULT hr;
3621 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
3623 EnterCriticalSection(&This->cs);
3625 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3627 if (hr == S_OK)
3628 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
3630 LeaveCriticalSection(&This->cs);
3632 return hr;
3635 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
3636 long WindowState) {
3637 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3638 IVideoWindow* pVideoWindow;
3639 HRESULT hr;
3641 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
3643 EnterCriticalSection(&This->cs);
3645 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3647 if (hr == S_OK)
3648 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
3650 LeaveCriticalSection(&This->cs);
3652 return hr;
3655 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
3656 long *WindowState) {
3657 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3658 IVideoWindow* pVideoWindow;
3659 HRESULT hr;
3661 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
3663 EnterCriticalSection(&This->cs);
3665 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3667 if (hr == S_OK)
3668 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
3670 LeaveCriticalSection(&This->cs);
3672 return hr;
3675 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
3676 long BackgroundPalette) {
3677 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3678 IVideoWindow* pVideoWindow;
3679 HRESULT hr;
3681 TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
3683 EnterCriticalSection(&This->cs);
3685 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3687 if (hr == S_OK)
3688 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
3690 LeaveCriticalSection(&This->cs);
3692 return hr;
3695 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
3696 long *pBackgroundPalette) {
3697 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3698 IVideoWindow* pVideoWindow;
3699 HRESULT hr;
3701 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
3703 EnterCriticalSection(&This->cs);
3705 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3707 if (hr == S_OK)
3708 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
3710 LeaveCriticalSection(&This->cs);
3712 return hr;
3715 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
3716 long Visible) {
3717 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3718 IVideoWindow* pVideoWindow;
3719 HRESULT hr;
3721 TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
3723 EnterCriticalSection(&This->cs);
3725 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3727 if (hr == S_OK)
3728 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
3730 LeaveCriticalSection(&This->cs);
3732 return hr;
3735 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
3736 long *pVisible) {
3737 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3738 IVideoWindow* pVideoWindow;
3739 HRESULT hr;
3741 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
3743 EnterCriticalSection(&This->cs);
3745 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3747 if (hr == S_OK)
3748 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
3750 LeaveCriticalSection(&This->cs);
3752 return hr;
3755 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
3756 long Left) {
3757 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3758 IVideoWindow* pVideoWindow;
3759 HRESULT hr;
3761 TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
3763 EnterCriticalSection(&This->cs);
3765 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3767 if (hr == S_OK)
3768 hr = IVideoWindow_put_Left(pVideoWindow, Left);
3770 LeaveCriticalSection(&This->cs);
3772 return hr;
3775 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
3776 long *pLeft) {
3777 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3778 IVideoWindow* pVideoWindow;
3779 HRESULT hr;
3781 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
3783 EnterCriticalSection(&This->cs);
3785 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3787 if (hr == S_OK)
3788 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
3790 LeaveCriticalSection(&This->cs);
3792 return hr;
3795 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
3796 long Width) {
3797 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3798 IVideoWindow* pVideoWindow;
3799 HRESULT hr;
3801 TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
3803 EnterCriticalSection(&This->cs);
3805 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3807 if (hr == S_OK)
3808 hr = IVideoWindow_put_Width(pVideoWindow, Width);
3810 LeaveCriticalSection(&This->cs);
3812 return hr;
3815 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
3816 long *pWidth) {
3817 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3818 IVideoWindow* pVideoWindow;
3819 HRESULT hr;
3821 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
3823 EnterCriticalSection(&This->cs);
3825 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3827 if (hr == S_OK)
3828 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
3830 LeaveCriticalSection(&This->cs);
3832 return hr;
3835 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
3836 long Top) {
3837 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3838 IVideoWindow* pVideoWindow;
3839 HRESULT hr;
3841 TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
3843 EnterCriticalSection(&This->cs);
3845 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3847 if (hr == S_OK)
3848 hr = IVideoWindow_put_Top(pVideoWindow, Top);
3850 LeaveCriticalSection(&This->cs);
3852 return hr;
3855 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
3856 long *pTop) {
3857 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3858 IVideoWindow* pVideoWindow;
3859 HRESULT hr;
3861 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
3863 EnterCriticalSection(&This->cs);
3865 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3867 if (hr == S_OK)
3868 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
3870 LeaveCriticalSection(&This->cs);
3872 return hr;
3875 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
3876 long Height) {
3877 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3878 IVideoWindow* pVideoWindow;
3879 HRESULT hr;
3881 TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
3883 EnterCriticalSection(&This->cs);
3885 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3887 if (hr == S_OK)
3888 hr = IVideoWindow_put_Height(pVideoWindow, Height);
3890 LeaveCriticalSection(&This->cs);
3892 return hr;
3895 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
3896 long *pHeight) {
3897 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3898 IVideoWindow* pVideoWindow;
3899 HRESULT hr;
3901 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
3903 EnterCriticalSection(&This->cs);
3905 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3907 if (hr == S_OK)
3908 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
3910 LeaveCriticalSection(&This->cs);
3912 return hr;
3915 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
3916 OAHWND Owner) {
3917 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3918 IVideoWindow* pVideoWindow;
3919 HRESULT hr;
3921 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
3923 EnterCriticalSection(&This->cs);
3925 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3927 if (hr == S_OK)
3928 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
3930 LeaveCriticalSection(&This->cs);
3932 return hr;
3935 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
3936 OAHWND *Owner) {
3937 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3938 IVideoWindow* pVideoWindow;
3939 HRESULT hr;
3941 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
3943 EnterCriticalSection(&This->cs);
3945 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3947 if (hr == S_OK)
3948 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
3950 LeaveCriticalSection(&This->cs);
3952 return hr;
3955 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
3956 OAHWND Drain) {
3957 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3958 IVideoWindow* pVideoWindow;
3959 HRESULT hr;
3961 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
3963 EnterCriticalSection(&This->cs);
3965 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3967 if (hr == S_OK)
3968 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
3970 LeaveCriticalSection(&This->cs);
3972 return hr;
3975 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
3976 OAHWND *Drain) {
3977 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3978 IVideoWindow* pVideoWindow;
3979 HRESULT hr;
3981 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
3983 EnterCriticalSection(&This->cs);
3985 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3987 if (hr == S_OK)
3988 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
3990 LeaveCriticalSection(&This->cs);
3992 return hr;
3995 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
3996 long *Color) {
3997 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3998 IVideoWindow* pVideoWindow;
3999 HRESULT hr;
4001 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4003 EnterCriticalSection(&This->cs);
4005 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4007 if (hr == S_OK)
4008 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4010 LeaveCriticalSection(&This->cs);
4012 return hr;
4015 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
4016 long Color) {
4017 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4018 IVideoWindow* pVideoWindow;
4019 HRESULT hr;
4021 TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
4023 EnterCriticalSection(&This->cs);
4025 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4027 if (hr == S_OK)
4028 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4030 LeaveCriticalSection(&This->cs);
4032 return hr;
4035 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
4036 long *FullScreenMode) {
4037 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4038 IVideoWindow* pVideoWindow;
4039 HRESULT hr;
4041 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4043 EnterCriticalSection(&This->cs);
4045 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4047 if (hr == S_OK)
4048 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4050 LeaveCriticalSection(&This->cs);
4052 return hr;
4055 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
4056 long FullScreenMode) {
4057 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4058 IVideoWindow* pVideoWindow;
4059 HRESULT hr;
4061 TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
4063 EnterCriticalSection(&This->cs);
4065 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4067 if (hr == S_OK)
4068 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4070 LeaveCriticalSection(&This->cs);
4072 return hr;
4075 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
4076 long Focus) {
4077 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4078 IVideoWindow* pVideoWindow;
4079 HRESULT hr;
4081 TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
4083 EnterCriticalSection(&This->cs);
4085 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4087 if (hr == S_OK)
4088 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4090 LeaveCriticalSection(&This->cs);
4092 return hr;
4095 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
4096 OAHWND hwnd,
4097 long uMsg,
4098 LONG_PTR wParam,
4099 LONG_PTR lParam) {
4100 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4101 IVideoWindow* pVideoWindow;
4102 HRESULT hr;
4104 TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
4106 EnterCriticalSection(&This->cs);
4108 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4110 if (hr == S_OK)
4111 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4113 LeaveCriticalSection(&This->cs);
4115 return hr;
4118 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
4119 long Left,
4120 long Top,
4121 long Width,
4122 long Height) {
4123 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4124 IVideoWindow* pVideoWindow;
4125 HRESULT hr;
4127 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
4129 EnterCriticalSection(&This->cs);
4131 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4133 if (hr == S_OK)
4134 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4136 LeaveCriticalSection(&This->cs);
4138 return hr;
4141 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
4142 long *pLeft,
4143 long *pTop,
4144 long *pWidth,
4145 long *pHeight) {
4146 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4147 IVideoWindow* pVideoWindow;
4148 HRESULT hr;
4150 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4152 EnterCriticalSection(&This->cs);
4154 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4156 if (hr == S_OK)
4157 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4159 LeaveCriticalSection(&This->cs);
4161 return hr;
4164 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
4165 long *pWidth,
4166 long *pHeight) {
4167 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4168 IVideoWindow* pVideoWindow;
4169 HRESULT hr;
4171 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4173 EnterCriticalSection(&This->cs);
4175 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4177 if (hr == S_OK)
4178 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4180 LeaveCriticalSection(&This->cs);
4182 return hr;
4185 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
4186 long *pWidth,
4187 long *pHeight) {
4188 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4189 IVideoWindow* pVideoWindow;
4190 HRESULT hr;
4192 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4194 EnterCriticalSection(&This->cs);
4196 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4198 if (hr == S_OK)
4199 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4201 LeaveCriticalSection(&This->cs);
4203 return hr;
4206 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
4207 long *pLeft,
4208 long *pTop,
4209 long *pWidth,
4210 long *pHeight) {
4211 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4212 IVideoWindow* pVideoWindow;
4213 HRESULT hr;
4215 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4217 EnterCriticalSection(&This->cs);
4219 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4221 if (hr == S_OK)
4222 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4224 LeaveCriticalSection(&This->cs);
4226 return hr;
4229 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
4230 long HideCursor) {
4231 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4232 IVideoWindow* pVideoWindow;
4233 HRESULT hr;
4235 TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
4237 EnterCriticalSection(&This->cs);
4239 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4241 if (hr == S_OK)
4242 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4244 LeaveCriticalSection(&This->cs);
4246 return hr;
4249 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
4250 long *CursorHidden) {
4251 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4252 IVideoWindow* pVideoWindow;
4253 HRESULT hr;
4255 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4257 EnterCriticalSection(&This->cs);
4259 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4261 if (hr == S_OK)
4262 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4264 LeaveCriticalSection(&This->cs);
4266 return hr;
4270 static const IVideoWindowVtbl IVideoWindow_VTable =
4272 VideoWindow_QueryInterface,
4273 VideoWindow_AddRef,
4274 VideoWindow_Release,
4275 VideoWindow_GetTypeInfoCount,
4276 VideoWindow_GetTypeInfo,
4277 VideoWindow_GetIDsOfNames,
4278 VideoWindow_Invoke,
4279 VideoWindow_put_Caption,
4280 VideoWindow_get_Caption,
4281 VideoWindow_put_WindowStyle,
4282 VideoWindow_get_WindowStyle,
4283 VideoWindow_put_WindowStyleEx,
4284 VideoWindow_get_WindowStyleEx,
4285 VideoWindow_put_AutoShow,
4286 VideoWindow_get_AutoShow,
4287 VideoWindow_put_WindowState,
4288 VideoWindow_get_WindowState,
4289 VideoWindow_put_BackgroundPalette,
4290 VideoWindow_get_BackgroundPalette,
4291 VideoWindow_put_Visible,
4292 VideoWindow_get_Visible,
4293 VideoWindow_put_Left,
4294 VideoWindow_get_Left,
4295 VideoWindow_put_Width,
4296 VideoWindow_get_Width,
4297 VideoWindow_put_Top,
4298 VideoWindow_get_Top,
4299 VideoWindow_put_Height,
4300 VideoWindow_get_Height,
4301 VideoWindow_put_Owner,
4302 VideoWindow_get_Owner,
4303 VideoWindow_put_MessageDrain,
4304 VideoWindow_get_MessageDrain,
4305 VideoWindow_get_BorderColor,
4306 VideoWindow_put_BorderColor,
4307 VideoWindow_get_FullScreenMode,
4308 VideoWindow_put_FullScreenMode,
4309 VideoWindow_SetWindowForeground,
4310 VideoWindow_NotifyOwnerMessage,
4311 VideoWindow_SetWindowPosition,
4312 VideoWindow_GetWindowPosition,
4313 VideoWindow_GetMinIdealImageSize,
4314 VideoWindow_GetMaxIdealImageSize,
4315 VideoWindow_GetRestorePosition,
4316 VideoWindow_HideCursor,
4317 VideoWindow_IsCursorHidden
4321 /*** IUnknown methods ***/
4322 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
4323 REFIID riid,
4324 LPVOID*ppvObj) {
4325 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4327 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4329 return Filtergraph_QueryInterface(This, riid, ppvObj);
4332 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
4333 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4335 TRACE("(%p/%p)->()\n", This, iface);
4337 return Filtergraph_AddRef(This);
4340 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
4341 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4343 TRACE("(%p/%p)->()\n", This, iface);
4345 return Filtergraph_Release(This);
4348 /*** IDispatch methods ***/
4349 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4350 UINT*pctinfo) {
4351 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4353 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4355 return S_OK;
4358 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4359 UINT iTInfo,
4360 LCID lcid,
4361 ITypeInfo**ppTInfo) {
4362 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4364 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4366 return S_OK;
4369 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4370 REFIID riid,
4371 LPOLESTR*rgszNames,
4372 UINT cNames,
4373 LCID lcid,
4374 DISPID*rgDispId) {
4375 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4377 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4379 return S_OK;
4382 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4383 DISPID dispIdMember,
4384 REFIID riid,
4385 LCID lcid,
4386 WORD wFlags,
4387 DISPPARAMS*pDispParams,
4388 VARIANT*pVarResult,
4389 EXCEPINFO*pExepInfo,
4390 UINT*puArgErr) {
4391 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4393 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4395 return S_OK;
4398 /*** IMediaEvent methods ***/
4399 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4400 OAEVENT *hEvent) {
4401 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4403 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4405 *hEvent = (OAEVENT)This->evqueue.msg_event;
4407 return S_OK;
4410 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4411 long *lEventCode,
4412 LONG_PTR *lParam1,
4413 LONG_PTR *lParam2,
4414 long msTimeout) {
4415 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4416 Event evt;
4418 TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4420 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4422 *lEventCode = evt.lEventCode;
4423 *lParam1 = evt.lParam1;
4424 *lParam2 = evt.lParam2;
4425 return S_OK;
4428 *lEventCode = 0;
4429 return E_ABORT;
4432 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4433 long msTimeout,
4434 long *pEvCode) {
4435 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4437 TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4439 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4441 *pEvCode = This->CompletionStatus;
4442 return S_OK;
4445 *pEvCode = 0;
4446 return E_ABORT;
4449 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4450 long lEvCode) {
4451 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4453 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4455 if (lEvCode == EC_COMPLETE)
4456 This->HandleEcComplete = FALSE;
4457 else if (lEvCode == EC_REPAINT)
4458 This->HandleEcRepaint = FALSE;
4459 else if (lEvCode == EC_CLOCK_CHANGED)
4460 This->HandleEcClockChanged = FALSE;
4461 else
4462 return S_FALSE;
4464 return S_OK;
4467 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4468 long lEvCode) {
4469 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4471 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4473 if (lEvCode == EC_COMPLETE)
4474 This->HandleEcComplete = TRUE;
4475 else if (lEvCode == EC_REPAINT)
4476 This->HandleEcRepaint = TRUE;
4477 else if (lEvCode == EC_CLOCK_CHANGED)
4478 This->HandleEcClockChanged = TRUE;
4479 else
4480 return S_FALSE;
4482 return S_OK;
4485 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4486 long lEvCode,
4487 LONG_PTR lParam1,
4488 LONG_PTR lParam2) {
4489 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4491 TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4493 return S_OK;
4496 /*** IMediaEventEx methods ***/
4497 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4498 OAHWND hwnd,
4499 long lMsg,
4500 LONG_PTR lInstanceData) {
4501 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4503 TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4505 This->notif.hWnd = (HWND)hwnd;
4506 This->notif.msg = lMsg;
4507 This->notif.instance = (long) lInstanceData;
4509 return S_OK;
4512 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4513 long lNoNotifyFlags) {
4514 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4516 TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4518 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4519 return E_INVALIDARG;
4521 This->notif.disabled = lNoNotifyFlags;
4523 return S_OK;
4526 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4527 long *lplNoNotifyFlags) {
4528 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4530 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4532 if (!lplNoNotifyFlags)
4533 return E_POINTER;
4535 *lplNoNotifyFlags = This->notif.disabled;
4537 return S_OK;
4541 static const IMediaEventExVtbl IMediaEventEx_VTable =
4543 MediaEvent_QueryInterface,
4544 MediaEvent_AddRef,
4545 MediaEvent_Release,
4546 MediaEvent_GetTypeInfoCount,
4547 MediaEvent_GetTypeInfo,
4548 MediaEvent_GetIDsOfNames,
4549 MediaEvent_Invoke,
4550 MediaEvent_GetEventHandle,
4551 MediaEvent_GetEvent,
4552 MediaEvent_WaitForCompletion,
4553 MediaEvent_CancelDefaultHandling,
4554 MediaEvent_RestoreDefaultHandling,
4555 MediaEvent_FreeEventParams,
4556 MediaEvent_SetNotifyWindow,
4557 MediaEvent_SetNotifyFlags,
4558 MediaEvent_GetNotifyFlags
4562 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4564 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4566 return Filtergraph_QueryInterface(This, riid, ppv);
4569 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4571 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4573 return Filtergraph_AddRef(This);
4576 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4578 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4580 return Filtergraph_Release(This);
4583 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4585 FIXME("(%p): stub\n", pClassID);
4587 return E_NOTIMPL;
4590 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
4592 FIXME("(): stub\n");
4594 return E_NOTIMPL;
4597 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
4599 FIXME("(): stub\n");
4601 return E_NOTIMPL;
4604 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
4606 FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
4608 return E_NOTIMPL;
4611 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
4613 FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
4615 return E_NOTIMPL;
4618 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
4620 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4621 HRESULT hr = S_OK;
4622 int i;
4624 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
4626 EnterCriticalSection(&This->cs);
4628 for (i = 0;i < This->nFilters;i++)
4630 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
4631 if (FAILED(hr))
4632 break;
4635 if (FAILED(hr))
4637 for(;i >= 0;i--)
4638 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
4640 else
4642 if (This->refClock)
4643 IReferenceClock_Release(This->refClock);
4644 This->refClock = pClock;
4645 if (This->refClock)
4646 IReferenceClock_AddRef(This->refClock);
4648 if (This->HandleEcClockChanged)
4650 IMediaEventSink *pEventSink;
4651 HRESULT eshr;
4653 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
4654 if (SUCCEEDED(eshr))
4656 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
4657 IMediaEventSink_Release(pEventSink);
4662 LeaveCriticalSection(&This->cs);
4664 return hr;
4667 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
4669 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4671 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
4673 if (!ppClock)
4674 return E_POINTER;
4676 EnterCriticalSection(&This->cs);
4678 *ppClock = This->refClock;
4679 if (*ppClock)
4680 IReferenceClock_AddRef(*ppClock);
4682 LeaveCriticalSection(&This->cs);
4684 return S_OK;
4687 static const IMediaFilterVtbl IMediaFilter_VTable =
4689 MediaFilter_QueryInterface,
4690 MediaFilter_AddRef,
4691 MediaFilter_Release,
4692 MediaFilter_GetClassID,
4693 MediaFilter_Stop,
4694 MediaFilter_Pause,
4695 MediaFilter_Run,
4696 MediaFilter_GetState,
4697 MediaFilter_SetSyncSource,
4698 MediaFilter_GetSyncSource
4701 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
4703 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4705 return Filtergraph_QueryInterface(This, riid, ppv);
4708 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
4710 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4712 return Filtergraph_AddRef(This);
4715 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
4717 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4719 return Filtergraph_Release(This);
4722 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
4724 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4725 Event evt;
4727 TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
4729 /* We need thread safety here, let's use the events queue's one */
4730 EnterCriticalSection(&This->evqueue.msg_crst);
4732 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
4734 TRACE("Process EC_COMPLETE notification\n");
4735 if (++This->EcCompleteCount == This->nRenderers)
4737 evt.lEventCode = EC_COMPLETE;
4738 evt.lParam1 = S_OK;
4739 evt.lParam2 = 0;
4740 TRACE("Send EC_COMPLETE to app\n");
4741 EventsQueue_PutEvent(&This->evqueue, &evt);
4742 if (!This->notif.disabled && This->notif.hWnd)
4744 TRACE("Send Window message\n");
4745 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4747 This->CompletionStatus = EC_COMPLETE;
4748 SetEvent(This->hEventCompletion);
4751 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
4753 /* FIXME: Not handled yet */
4755 else
4757 evt.lEventCode = EventCode;
4758 evt.lParam1 = EventParam1;
4759 evt.lParam2 = EventParam2;
4760 EventsQueue_PutEvent(&This->evqueue, &evt);
4761 if (!This->notif.disabled && This->notif.hWnd)
4762 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4765 LeaveCriticalSection(&This->evqueue.msg_crst);
4766 return S_OK;
4769 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
4771 MediaEventSink_QueryInterface,
4772 MediaEventSink_AddRef,
4773 MediaEventSink_Release,
4774 MediaEventSink_Notify
4777 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
4779 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4781 return Filtergraph_QueryInterface(This, riid, ppv);
4784 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
4786 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4788 return Filtergraph_AddRef(This);
4791 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
4793 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4795 return Filtergraph_Release(This);
4798 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
4799 IPin* pOutputPin,
4800 IPin* pInputPin,
4801 const AM_MEDIA_TYPE* pmtFirstConnection,
4802 IBaseFilter* pUsingFilter,
4803 HANDLE hAbortEvent,
4804 DWORD dwFlags)
4806 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4808 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
4810 return E_NOTIMPL;
4813 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
4814 IGraphConfigCallback* pCallback,
4815 PVOID pvContext,
4816 DWORD dwFlags,
4817 HANDLE hAbortEvent)
4819 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4821 FIXME("(%p)->(%p, %p, %x, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
4823 return E_NOTIMPL;
4826 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
4827 IBaseFilter* pFilter)
4829 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4831 FIXME("(%p)->(%p): stub!\n", This, pFilter);
4833 return E_NOTIMPL;
4836 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
4837 IEnumFilters** pEnum)
4839 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4841 FIXME("(%p)->(%p): stub!\n", This, pEnum);
4843 return E_NOTIMPL;
4846 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
4847 IBaseFilter* pFilter)
4849 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4851 FIXME("(%p)->(%p): stub!\n", This, pFilter);
4853 return E_NOTIMPL;
4856 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
4857 REFERENCE_TIME* prtStart)
4859 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4861 FIXME("(%p)->(%p): stub!\n", This, prtStart);
4863 return E_NOTIMPL;
4866 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
4867 IPin* pOutputPin,
4868 IPinConnection* pConnection,
4869 HANDLE hEventAbort)
4871 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4873 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
4875 return E_NOTIMPL;
4878 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
4879 IBaseFilter* pFilter,
4880 DWORD dwFlags)
4882 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4884 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4886 return E_NOTIMPL;
4889 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
4890 IBaseFilter* pFilter,
4891 DWORD* dwFlags)
4893 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4895 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
4897 return E_NOTIMPL;
4900 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
4901 IBaseFilter* pFilter,
4902 DWORD dwFlags)
4904 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4906 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4908 return E_NOTIMPL;
4911 static const IGraphConfigVtbl IGraphConfig_VTable =
4913 GraphConfig_QueryInterface,
4914 GraphConfig_AddRef,
4915 GraphConfig_Release,
4916 GraphConfig_Reconnect,
4917 GraphConfig_Reconfigure,
4918 GraphConfig_AddFilterToCache,
4919 GraphConfig_EnumCacheFilter,
4920 GraphConfig_RemoveFilterFromCache,
4921 GraphConfig_GetStartTime,
4922 GraphConfig_PushThroughData,
4923 GraphConfig_SetFilterFlags,
4924 GraphConfig_GetFilterFlags,
4925 GraphConfig_RemoveFilterEx
4928 static const IUnknownVtbl IInner_VTable =
4930 FilterGraphInner_QueryInterface,
4931 FilterGraphInner_AddRef,
4932 FilterGraphInner_Release
4935 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
4936 REFIID riid,
4937 LPVOID * ppv) {
4938 if (This->bAggregatable)
4939 This->bUnkOuterValid = TRUE;
4941 if (This->pUnkOuter)
4943 if (This->bAggregatable)
4944 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
4946 if (IsEqualIID(riid, &IID_IUnknown))
4948 HRESULT hr;
4950 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4951 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4952 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4953 This->bAggregatable = TRUE;
4954 return hr;
4957 *ppv = NULL;
4958 return E_NOINTERFACE;
4961 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4964 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This) {
4965 if (This->pUnkOuter && This->bUnkOuterValid)
4966 return IUnknown_AddRef(This->pUnkOuter);
4967 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4970 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This) {
4971 if (This->pUnkOuter && This->bUnkOuterValid)
4972 return IUnknown_Release(This->pUnkOuter);
4973 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4976 /* This is the only function that actually creates a FilterGraph class... */
4977 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4979 IFilterGraphImpl *fimpl;
4980 HRESULT hr;
4982 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
4984 *ppObj = NULL;
4986 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
4987 fimpl->pUnkOuter = pUnkOuter;
4988 fimpl->bUnkOuterValid = FALSE;
4989 fimpl->bAggregatable = FALSE;
4990 fimpl->IInner_vtbl = &IInner_VTable;
4991 fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable;
4992 fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
4993 fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
4994 fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
4995 fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
4996 fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
4997 fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
4998 fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
4999 fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
5000 fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
5001 fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
5002 fimpl->ref = 1;
5003 fimpl->ppFiltersInGraph = NULL;
5004 fimpl->pFilterNames = NULL;
5005 fimpl->nFilters = 0;
5006 fimpl->filterCapacity = 0;
5007 fimpl->nameIndex = 1;
5008 fimpl->refClock = NULL;
5009 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5010 fimpl->HandleEcComplete = TRUE;
5011 fimpl->HandleEcRepaint = TRUE;
5012 fimpl->HandleEcClockChanged = TRUE;
5013 fimpl->notif.hWnd = 0;
5014 fimpl->notif.disabled = FALSE;
5015 fimpl->nRenderers = 0;
5016 fimpl->EcCompleteCount = 0;
5017 fimpl->state = State_Stopped;
5018 EventsQueue_Init(&fimpl->evqueue);
5019 InitializeCriticalSection(&fimpl->cs);
5020 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5021 fimpl->nItfCacheEntries = 0;
5022 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5023 fimpl->start_time = fimpl->position = 0;
5025 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
5026 if (FAILED(hr)) {
5027 ERR("Unable to create filter mapper (%x)\n", hr);
5028 return hr;
5030 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
5032 *ppObj = fimpl;
5033 return S_OK;
5036 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5038 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5039 return FilterGraph_create(pUnkOuter, ppObj);