push 7f8c39dca3a5819e8ef115eebf7abed537de3a22
[wine/hacks.git] / dlls / quartz / filtergraph.c
blob9f6f79a756bc9f01c0af05075a80380a57c4bd34
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 "winreg.h"
33 #include "shlwapi.h"
34 #include "dshow.h"
35 #include "wine/debug.h"
36 #include "quartz_private.h"
37 #include "ole2.h"
38 #include "olectl.h"
39 #include "strmif.h"
40 #include "vfwmsgs.h"
41 #include "evcode.h"
42 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
47 typedef struct {
48 HWND hWnd; /* Target window */
49 long msg; /* User window message */
50 long instance; /* User data */
51 int disabled; /* Disabled messages posting */
52 } WndNotify;
54 typedef struct {
55 long lEventCode; /* Event code */
56 LONG_PTR lParam1; /* Param1 */
57 LONG_PTR lParam2; /* Param2 */
58 } Event;
60 /* messages ring implementation for queuing events (taken from winmm) */
61 #define EVENTS_RING_BUFFER_INCREMENT 64
62 typedef struct {
63 Event* messages;
64 int ring_buffer_size;
65 int msg_tosave;
66 int msg_toget;
67 CRITICAL_SECTION msg_crst;
68 HANDLE msg_event; /* Signaled for no empty queue */
69 } EventsQueue;
71 static int EventsQueue_Init(EventsQueue* omr)
73 omr->msg_toget = 0;
74 omr->msg_tosave = 0;
75 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
76 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
77 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
78 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
80 InitializeCriticalSection(&omr->msg_crst);
81 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
82 return TRUE;
85 static int EventsQueue_Destroy(EventsQueue* omr)
87 CloseHandle(omr->msg_event);
88 CoTaskMemFree(omr->messages);
89 omr->msg_crst.DebugInfo->Spare[0] = 0;
90 DeleteCriticalSection(&omr->msg_crst);
91 return TRUE;
94 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
96 EnterCriticalSection(&omr->msg_crst);
97 if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
99 int old_ring_buffer_size = omr->ring_buffer_size;
100 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
101 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
102 omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
103 /* Now we need to rearrange the ring buffer so that the new
104 buffers just allocated are in between omr->msg_tosave and
105 omr->msg_toget.
107 if (omr->msg_tosave < omr->msg_toget)
109 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
110 &(omr->messages[omr->msg_toget]),
111 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
113 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
116 omr->messages[omr->msg_tosave] = *evt;
117 SetEvent(omr->msg_event);
118 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
119 LeaveCriticalSection(&omr->msg_crst);
120 return TRUE;
123 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
125 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
126 return FALSE;
128 EnterCriticalSection(&omr->msg_crst);
130 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
132 LeaveCriticalSection(&omr->msg_crst);
133 return FALSE;
136 *evt = omr->messages[omr->msg_toget];
137 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
139 /* Mark the buffer as empty if needed */
140 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
141 ResetEvent(omr->msg_event);
143 LeaveCriticalSection(&omr->msg_crst);
144 return TRUE;
147 #define MAX_ITF_CACHE_ENTRIES 3
148 typedef struct _ITF_CACHE_ENTRY {
149 const IID* riid;
150 IBaseFilter* filter;
151 IUnknown* iface;
152 } ITF_CACHE_ENTRY;
154 typedef struct _IFilterGraphImpl {
155 const IFilterGraph2Vtbl *IFilterGraph2_vtbl;
156 const IMediaControlVtbl *IMediaControl_vtbl;
157 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
158 const IBasicAudioVtbl *IBasicAudio_vtbl;
159 const IBasicVideo2Vtbl *IBasicVideo_vtbl;
160 const IVideoWindowVtbl *IVideoWindow_vtbl;
161 const IMediaEventExVtbl *IMediaEventEx_vtbl;
162 const IMediaFilterVtbl *IMediaFilter_vtbl;
163 const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
164 const IGraphConfigVtbl *IGraphConfig_vtbl;
165 const IMediaPositionVtbl *IMediaPosition_vtbl;
166 const IUnknownVtbl * IInner_vtbl;
167 /* IAMGraphStreams */
168 /* IAMStats */
169 /* IFilterChain */
170 /* IFilterMapper2 */
171 /* IGraphVersion */
172 /* IQueueCommand */
173 /* IRegisterServiceProvider */
174 /* IResourceMananger */
175 /* IServiceProvider */
176 /* IVideoFrameStep */
178 LONG ref;
179 IFilterMapper2 * pFilterMapper2;
180 IBaseFilter ** ppFiltersInGraph;
181 LPWSTR * pFilterNames;
182 int nFilters;
183 int filterCapacity;
184 long nameIndex;
185 IReferenceClock *refClock;
186 EventsQueue evqueue;
187 HANDLE hEventCompletion;
188 int CompletionStatus;
189 WndNotify notif;
190 int nRenderers;
191 int EcCompleteCount;
192 int HandleEcComplete;
193 int HandleEcRepaint;
194 int HandleEcClockChanged;
195 OAFilterState state;
196 CRITICAL_SECTION cs;
197 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
198 int nItfCacheEntries;
199 IUnknown * pUnkOuter;
200 BOOL bUnkOuterValid;
201 BOOL bAggregatable;
202 GUID timeformatseek;
203 LONGLONG start_time;
204 LONGLONG position;
205 LONGLONG stop_position;
206 } IFilterGraphImpl;
208 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
209 REFIID riid, LPVOID * ppv);
210 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This);
211 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This);
213 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
214 REFIID riid,
215 LPVOID *ppvObj) {
216 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
217 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
219 if (This->bAggregatable)
220 This->bUnkOuterValid = TRUE;
222 if (IsEqualGUID(&IID_IUnknown, riid)) {
223 *ppvObj = &(This->IInner_vtbl);
224 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
225 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
226 IsEqualGUID(&IID_IFilterGraph2, riid) ||
227 IsEqualGUID(&IID_IGraphBuilder, riid)) {
228 *ppvObj = &(This->IFilterGraph2_vtbl);
229 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
230 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
231 *ppvObj = &(This->IMediaControl_vtbl);
232 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
233 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
234 *ppvObj = &(This->IMediaSeeking_vtbl);
235 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
236 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
237 *ppvObj = &(This->IBasicAudio_vtbl);
238 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
239 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
240 IsEqualGUID(&IID_IBasicVideo2, riid)) {
241 *ppvObj = &(This->IBasicVideo_vtbl);
242 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
243 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
244 *ppvObj = &(This->IVideoWindow_vtbl);
245 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
246 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
247 IsEqualGUID(&IID_IMediaEventEx, riid)) {
248 *ppvObj = &(This->IMediaEventEx_vtbl);
249 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
250 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
251 IsEqualGUID(&IID_IPersist, riid)) {
252 *ppvObj = &(This->IMediaFilter_vtbl);
253 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
254 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
255 *ppvObj = &(This->IMediaEventSink_vtbl);
256 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
257 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
258 *ppvObj = &(This->IGraphConfig_vtbl);
259 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
260 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
261 *ppvObj = &(This->IMediaPosition_vtbl);
262 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
263 } else {
264 *ppvObj = NULL;
265 FIXME("unknown interface %s\n", debugstr_guid(riid));
266 return E_NOINTERFACE;
269 IUnknown_AddRef((IUnknown *)(*ppvObj));
270 return S_OK;
273 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) {
274 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
275 ULONG ref = InterlockedIncrement(&This->ref);
277 TRACE("(%p)->(): new ref = %d\n", This, ref);
279 return ref;
282 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface)
284 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
285 ULONG ref = InterlockedDecrement(&This->ref);
287 TRACE("(%p)->(): new ref = %d\n", This, ref);
289 if (ref == 0) {
290 int i;
292 IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl));
294 while (This->nFilters)
295 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]);
297 if (This->refClock)
298 IReferenceClock_Release(This->refClock);
300 for (i = 0; i < This->nItfCacheEntries; i++)
302 if (This->ItfCacheEntries[i].iface)
303 IUnknown_Release(This->ItfCacheEntries[i].iface);
305 IFilterMapper2_Release(This->pFilterMapper2);
306 CloseHandle(This->hEventCompletion);
307 EventsQueue_Destroy(&This->evqueue);
308 This->cs.DebugInfo->Spare[0] = 0;
309 DeleteCriticalSection(&This->cs);
310 CoTaskMemFree(This->ppFiltersInGraph);
311 CoTaskMemFree(This->pFilterNames);
312 CoTaskMemFree(This);
314 return ref;
318 /*** IUnknown methods ***/
319 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface,
320 REFIID riid,
321 LPVOID*ppvObj) {
322 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
324 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
325 return Filtergraph_QueryInterface(This, riid, ppvObj);
328 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) {
329 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
331 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
333 return Filtergraph_AddRef(This);
336 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) {
337 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
339 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
341 return Filtergraph_Release(This);
344 /*** IFilterGraph methods ***/
345 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
346 IBaseFilter *pFilter,
347 LPCWSTR pName) {
348 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
349 HRESULT hr;
350 int i,j;
351 WCHAR* wszFilterName = NULL;
352 int duplicate_name = FALSE;
354 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
356 if (!pFilter)
357 return E_POINTER;
359 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
361 if (pName)
363 /* Check if name already exists */
364 for(i = 0; i < This->nFilters; i++)
365 if (!strcmpW(This->pFilterNames[i], pName))
367 duplicate_name = TRUE;
368 break;
372 /* If no name given or name already existing, generate one */
373 if (!pName || duplicate_name)
375 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
376 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
378 for (j = 0; j < 10000 ; j++)
380 /* Create name */
381 if (pName)
382 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
383 else
384 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
385 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
387 /* Check if the generated name already exists */
388 for(i = 0; i < This->nFilters; i++)
389 if (!strcmpW(This->pFilterNames[i], wszFilterName))
390 break;
392 /* Compute next index and exit if generated name is suitable */
393 if (This->nameIndex++ == 10000)
394 This->nameIndex = 1;
395 if (i == This->nFilters)
396 break;
398 /* Unable to find a suitable name */
399 if (j == 10000)
401 CoTaskMemFree(wszFilterName);
402 return VFW_E_DUPLICATE_NAME;
405 else
406 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
408 if (This->nFilters + 1 > This->filterCapacity)
410 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
411 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
412 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
413 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
414 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
415 if (This->filterCapacity)
417 CoTaskMemFree(This->ppFiltersInGraph);
418 CoTaskMemFree(This->pFilterNames);
420 This->ppFiltersInGraph = ppNewFilters;
421 This->pFilterNames = pNewNames;
422 This->filterCapacity = newCapacity;
425 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
427 if (SUCCEEDED(hr))
429 IBaseFilter_AddRef(pFilter);
430 This->ppFiltersInGraph[This->nFilters] = pFilter;
431 This->pFilterNames[This->nFilters] = wszFilterName;
432 This->nFilters++;
433 IBaseFilter_SetSyncSource(pFilter, This->refClock);
435 else
436 CoTaskMemFree(wszFilterName);
438 if (SUCCEEDED(hr) && duplicate_name)
439 return VFW_S_DUPLICATE_NAME;
441 return hr;
444 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
446 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
447 int i;
448 HRESULT hr = E_FAIL;
450 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
452 /* FIXME: check graph is stopped */
454 for (i = 0; i < This->nFilters; i++)
456 if (This->ppFiltersInGraph[i] == pFilter)
458 IEnumPins *penumpins = NULL;
459 FILTER_STATE state;
461 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
462 IBaseFilter_GetState(pFilter, 0, &state);
463 if (state == State_Running)
464 IBaseFilter_Pause(pFilter);
465 if (state != State_Stopped)
466 IBaseFilter_Stop(pFilter);
468 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
469 if (SUCCEEDED(hr)) {
470 IPin *ppin;
471 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
473 IPin *victim = NULL;
474 HRESULT h;
475 IPin_ConnectedTo(ppin, &victim);
476 if (victim)
478 h = IPin_Disconnect(victim);
479 TRACE("Disconnect other side: %08x\n", h);
480 if (h == VFW_E_NOT_STOPPED)
482 PIN_INFO pinfo;
483 IPin_QueryPinInfo(victim, &pinfo);
485 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
486 if (state == State_Running)
487 IBaseFilter_Pause(pinfo.pFilter);
488 IBaseFilter_Stop(pinfo.pFilter);
489 IBaseFilter_Release(pinfo.pFilter);
490 h = IPin_Disconnect(victim);
491 TRACE("Disconnect retry: %08x\n", h);
493 IPin_Release(victim);
495 h = IPin_Disconnect(ppin);
496 TRACE("Disconnect 2: %08x\n", h);
498 IEnumPins_Release(penumpins);
501 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
502 if (SUCCEEDED(hr))
504 IBaseFilter_SetSyncSource(pFilter, NULL);
505 IBaseFilter_Release(pFilter);
506 CoTaskMemFree(This->pFilterNames[i]);
507 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
508 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
509 This->nFilters--;
510 /* Invalidate interfaces in the cache */
511 for (i = 0; i < This->nItfCacheEntries; i++)
512 if (pFilter == This->ItfCacheEntries[i].filter)
514 IUnknown_Release(This->ItfCacheEntries[i].iface);
515 This->ItfCacheEntries[i].iface = NULL;
516 This->ItfCacheEntries[i].filter = NULL;
518 return S_OK;
520 break;
524 return hr; /* FIXME: check this error code */
527 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface,
528 IEnumFilters **ppEnum) {
529 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
531 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
533 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
536 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
537 LPCWSTR pName,
538 IBaseFilter **ppFilter) {
539 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
540 int i;
542 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
544 if (!ppFilter)
545 return E_POINTER;
547 for (i = 0; i < This->nFilters; i++)
549 if (!strcmpW(pName, This->pFilterNames[i]))
551 *ppFilter = This->ppFiltersInGraph[i];
552 IBaseFilter_AddRef(*ppFilter);
553 return S_OK;
557 *ppFilter = NULL;
558 return VFW_E_NOT_FOUND;
561 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
562 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
564 static HRESULT WINAPI CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
566 #if 1
567 HRESULT hr;
568 PIN_INFO info_out, info_in;
570 hr = IPin_QueryPinInfo(out, &info_out);
571 if (FAILED(hr))
572 return hr;
573 if (info_out.dir != PINDIR_OUTPUT)
575 IBaseFilter_Release(info_out.pFilter);
576 return E_UNEXPECTED;
579 hr = IPin_QueryPinInfo(in, &info_in);
580 if (SUCCEEDED(hr))
581 IBaseFilter_Release(info_in.pFilter);
582 if (FAILED(hr))
583 goto out;
584 if (info_in.dir != PINDIR_INPUT)
586 hr = E_UNEXPECTED;
587 goto out;
590 if (info_out.pFilter == info_in.pFilter)
591 hr = VFW_E_CIRCULAR_GRAPH;
592 else
594 IEnumPins *enumpins;
595 IPin *test;
597 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
598 if (FAILED(hr))
599 goto out;
601 IEnumPins_Reset(enumpins);
602 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
604 PIN_DIRECTION dir = PINDIR_OUTPUT;
605 IPin_QueryDirection(test, &dir);
606 if (dir == PINDIR_INPUT)
608 IPin *victim = NULL;
609 IPin_ConnectedTo(test, &victim);
610 if (victim)
612 hr = CheckCircularConnection(This, victim, in);
613 IPin_Release(victim);
614 if (FAILED(hr))
616 IPin_Release(test);
617 break;
621 IPin_Release(test);
623 IEnumPins_Release(enumpins);
626 out:
627 IBaseFilter_Release(info_out.pFilter);
628 if (FAILED(hr))
629 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
630 return hr;
631 #else
632 /* Debugging filtergraphs not enabled */
633 return S_OK;
634 #endif
638 /* NOTE: despite the implication, it doesn't matter which
639 * way round you put in the input and output pins */
640 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface,
641 IPin *ppinIn,
642 IPin *ppinOut,
643 const AM_MEDIA_TYPE *pmt) {
644 PIN_DIRECTION dir;
645 HRESULT hr;
647 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
649 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
651 /* FIXME: check pins are in graph */
653 if (TRACE_ON(quartz))
655 PIN_INFO PinInfo;
657 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
658 if (FAILED(hr))
659 return hr;
661 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
662 IBaseFilter_Release(PinInfo.pFilter);
664 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
665 if (FAILED(hr))
666 return hr;
668 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
669 IBaseFilter_Release(PinInfo.pFilter);
672 hr = IPin_QueryDirection(ppinIn, &dir);
673 if (SUCCEEDED(hr))
675 if (dir == PINDIR_INPUT)
677 hr = CheckCircularConnection(This, ppinOut, ppinIn);
678 if (SUCCEEDED(hr))
679 hr = IPin_Connect(ppinOut, ppinIn, pmt);
681 else
683 hr = CheckCircularConnection(This, ppinIn, ppinOut);
684 if (SUCCEEDED(hr))
685 hr = IPin_Connect(ppinIn, ppinOut, pmt);
689 return hr;
692 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface,
693 IPin *ppin) {
694 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
695 IPin *pConnectedTo = NULL;
696 HRESULT hr;
697 PIN_DIRECTION pindir;
699 IPin_QueryDirection(ppin, &pindir);
700 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
701 if (FAILED(hr)) {
702 TRACE("Querying connected to failed: %x\n", hr);
703 return hr;
705 IPin_Disconnect(ppin);
706 IPin_Disconnect(pConnectedTo);
707 if (pindir == PINDIR_INPUT)
708 hr = IPin_Connect(pConnectedTo, ppin, NULL);
709 else
710 hr = IPin_Connect(ppin, pConnectedTo, NULL);
711 IPin_Release(pConnectedTo);
712 if (FAILED(hr))
713 ERR("Reconnecting pins failed, pins are not connected now..\n");
714 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
715 return hr;
718 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
720 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
722 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
724 return IPin_Disconnect(ppin);
727 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) {
728 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
729 IReferenceClock *pClock = NULL;
730 HRESULT hr;
732 TRACE("(%p/%p)->() semi-stub\n", iface, This);
734 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
736 if (SUCCEEDED(hr))
738 hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock);
739 IReferenceClock_Release(pClock);
742 return hr;
745 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
747 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
748 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
749 IPropertyBag * pPropBagCat = NULL;
750 HRESULT hr;
752 VariantInit(pvar);
753 V_VT(pvar) = VT_BSTR;
755 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
757 if (SUCCEEDED(hr))
758 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
760 if (SUCCEEDED(hr))
761 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
763 if (SUCCEEDED(hr))
764 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
766 if (SUCCEEDED(hr))
767 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
769 if (pPropBagCat)
770 IPropertyBag_Release(pPropBagCat);
772 return hr;
775 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
777 HRESULT hr;
778 ULONG nb = 0;
780 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
781 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
782 if (hr == S_OK) {
783 /* Rendered input */
784 } else if (hr == S_FALSE) {
785 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
786 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
787 if (hr != S_OK) {
788 ERR("Error (%x)\n", hr);
790 } else if (hr == E_NOTIMPL) {
791 /* Input connected to all outputs */
792 IEnumPins* penumpins;
793 IPin* ppin;
794 int i = 0;
795 TRACE("E_NOTIMPL\n");
796 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
797 if (FAILED(hr)) {
798 ERR("filter Enumpins failed (%x)\n", hr);
799 return hr;
801 i = 0;
802 /* Count output pins */
803 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
804 PIN_DIRECTION pindir;
805 IPin_QueryDirection(ppin, &pindir);
806 if (pindir == PINDIR_OUTPUT)
807 i++;
808 IPin_Release(ppin);
810 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
811 /* Retrieve output pins */
812 IEnumPins_Reset(penumpins);
813 i = 0;
814 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
815 PIN_DIRECTION pindir;
816 IPin_QueryDirection(ppin, &pindir);
817 if (pindir == PINDIR_OUTPUT)
818 (*pppins)[i++] = ppin;
819 else
820 IPin_Release(ppin);
822 IEnumPins_Release(penumpins);
823 nb = i;
824 if (FAILED(hr)) {
825 ERR("Next failed (%x)\n", hr);
826 return hr;
828 } else if (FAILED(hr)) {
829 ERR("Cannot get internal connection (%x)\n", hr);
830 return hr;
833 *pnb = nb;
834 return S_OK;
837 /*** IGraphBuilder methods ***/
838 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
840 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
841 HRESULT hr;
842 AM_MEDIA_TYPE* mt;
843 IEnumMediaTypes* penummt;
844 ULONG nbmt;
845 IEnumPins* penumpins;
846 IEnumMoniker* pEnumMoniker;
847 GUID tab[2];
848 ULONG nb;
849 IMoniker* pMoniker;
850 ULONG pin;
851 PIN_INFO PinInfo;
852 CLSID FilterCLSID;
853 PIN_DIRECTION dir;
855 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
857 if (TRACE_ON(quartz))
859 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
860 if (FAILED(hr))
861 return hr;
863 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
864 IBaseFilter_Release(PinInfo.pFilter);
866 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
867 if (FAILED(hr))
868 return hr;
870 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
871 IBaseFilter_Release(PinInfo.pFilter);
874 hr = IPin_QueryDirection(ppinOut, &dir);
875 if (FAILED(hr))
876 return hr;
878 if (dir == PINDIR_INPUT)
880 IPin *temp;
882 temp = ppinIn;
883 ppinIn = ppinOut;
884 ppinOut = temp;
887 hr = CheckCircularConnection(This, ppinOut, ppinIn);
888 if (FAILED(hr))
889 return hr;
891 /* Try direct connection first */
892 hr = IPin_Connect(ppinOut, ppinIn, NULL);
893 if (SUCCEEDED(hr)) {
894 return S_OK;
896 TRACE("Direct connection failed, trying to render using extra filters\n");
898 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
899 if (FAILED(hr))
900 return hr;
902 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
903 IBaseFilter_Release(PinInfo.pFilter);
904 if (FAILED(hr))
905 return hr;
907 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
908 * filter to the minor mediatype of input pin of the renderer */
909 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
910 if (FAILED(hr)) {
911 WARN("EnumMediaTypes (%x)\n", hr);
912 return hr;
915 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
916 if (FAILED(hr)) {
917 WARN("IEnumMediaTypes_Next (%x)\n", hr);
918 return hr;
921 if (!nbmt)
923 WARN("No media type found!\n");
924 return S_OK;
926 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
927 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
929 /* Try to find a suitable filter that can connect to the pin to render */
930 tab[0] = mt->majortype;
931 tab[1] = mt->subtype;
932 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
933 if (FAILED(hr)) {
934 WARN("Unable to enum filters (%x)\n", hr);
935 return hr;
938 hr = VFW_E_CANNOT_RENDER;
939 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
941 VARIANT var;
942 GUID clsid;
943 IPin** ppins;
944 IPin* ppinfilter = NULL;
945 IBaseFilter* pfilter = NULL;
947 hr = GetFilterInfo(pMoniker, &clsid, &var);
948 IMoniker_Release(pMoniker);
949 if (FAILED(hr)) {
950 WARN("Unable to retrieve filter info (%x)\n", hr);
951 goto error;
954 if (IsEqualGUID(&clsid, &FilterCLSID)) {
955 /* Skip filter (same as the one the output pin belongs to) */
956 goto error;
959 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
960 if (FAILED(hr)) {
961 WARN("Unable to create filter (%x), trying next one\n", hr);
962 goto error;
965 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
966 if (FAILED(hr)) {
967 WARN("Unable to add filter (%x)\n", hr);
968 IBaseFilter_Release(pfilter);
969 pfilter = NULL;
970 goto error;
973 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
974 if (FAILED(hr)) {
975 WARN("Enumpins (%x)\n", hr);
976 goto error;
979 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
980 IEnumPins_Release(penumpins);
982 if (FAILED(hr)) {
983 WARN("Obtaining next pin: (%x)\n", hr);
984 goto error;
986 if (pin == 0) {
987 WARN("Cannot use this filter: no pins\n");
988 goto error;
991 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
992 if (FAILED(hr)) {
993 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
994 goto error;
996 TRACE("Successfully connected to filter, follow chain...\n");
998 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
999 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1001 if (SUCCEEDED(hr)) {
1002 int i;
1003 if (nb == 0) {
1004 IPin_Disconnect(ppinfilter);
1005 IPin_Disconnect(ppinOut);
1006 goto error;
1008 TRACE("pins to consider: %d\n", nb);
1009 for(i = 0; i < nb; i++)
1011 LPWSTR pinname = NULL;
1013 TRACE("Processing pin %d\n", i);
1015 hr = IPin_QueryId(ppins[i], &pinname);
1016 if (SUCCEEDED(hr))
1018 if (pinname[0] == '~')
1020 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1021 hr = E_FAIL;
1023 else
1024 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1025 CoTaskMemFree(pinname);
1028 if (FAILED(hr)) {
1029 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1031 IPin_Release(ppins[i]);
1032 if (SUCCEEDED(hr)) break;
1034 while (++i < nb) IPin_Release(ppins[i]);
1035 CoTaskMemFree(ppins);
1036 IPin_Release(ppinfilter);
1037 IBaseFilter_Release(pfilter);
1038 if (FAILED(hr))
1040 IPin_Disconnect(ppinfilter);
1041 IPin_Disconnect(ppinOut);
1042 IFilterGraph2_RemoveFilter(iface, pfilter);
1043 continue;
1045 break;
1048 error:
1049 if (ppinfilter) IPin_Release(ppinfilter);
1050 if (pfilter) {
1051 IFilterGraph2_RemoveFilter(iface, pfilter);
1052 IBaseFilter_Release(pfilter);
1056 IEnumMediaTypes_Release(penummt);
1057 DeleteMediaType(mt);
1059 TRACE("--> %08x\n", hr);
1060 return SUCCEEDED(hr) ? S_OK : hr;
1063 static HRESULT WINAPI FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1065 /* This pin has been connected now, try to call render on all pins that aren't connected */
1066 IPin *to = NULL;
1067 PIN_INFO info;
1068 IEnumPins *enumpins = NULL;
1069 BOOL renderany = FALSE;
1070 BOOL renderall = TRUE;
1072 IPin_QueryPinInfo(ppinOut, &info);
1074 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1075 /* Don't need to hold a reference, IEnumPins does */
1076 IBaseFilter_Release(info.pFilter);
1078 IEnumPins_Reset(enumpins);
1079 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1081 PIN_DIRECTION dir = PINDIR_INPUT;
1083 IPin_QueryDirection(to, &dir);
1085 if (dir == PINDIR_OUTPUT)
1087 IPin *out = NULL;
1089 IPin_ConnectedTo(to, &out);
1090 if (!out)
1092 HRESULT hr;
1093 hr = IFilterGraph2_Render((IFilterGraph2 *)&This->IFilterGraph2_vtbl, to);
1094 if (SUCCEEDED(hr))
1095 renderany = TRUE;
1096 else
1097 renderall = FALSE;
1099 else
1100 IPin_Release(out);
1103 IPin_Release(to);
1106 IEnumPins_Release(enumpins);
1108 if (renderall)
1109 return S_OK;
1111 if (renderany)
1112 return VFW_S_PARTIAL_RENDER;
1114 return VFW_E_CANNOT_RENDER;
1117 /* Ogg hates me if I create a direct rendering method
1119 * It can only connect to a pin properly once, so use a recursive method that does
1121 * +----+ --- (PIN 1) (Render is called on this pin)
1122 * | |
1123 * +----+ --- (PIN 2)
1125 * Enumerate possible renderers that EXACTLY match the requested type
1127 * If none is available, try to add intermediate filters that can connect to the input pin
1128 * then call Render on that intermediate pin's output pins
1129 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1130 * and another filter that can connect to the input pin is tried
1131 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1132 * It's recursive, but fun!
1135 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1137 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1138 IEnumMediaTypes* penummt;
1139 AM_MEDIA_TYPE* mt;
1140 ULONG nbmt;
1141 HRESULT hr;
1143 IEnumMoniker* pEnumMoniker;
1144 GUID tab[4];
1145 ULONG nb;
1146 IMoniker* pMoniker;
1147 INT x;
1149 BOOL final = FALSE;
1151 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1153 if (TRACE_ON(quartz))
1155 PIN_INFO PinInfo;
1157 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1158 if (FAILED(hr))
1159 return hr;
1161 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1162 IBaseFilter_Release(PinInfo.pFilter);
1165 /* Try to find out if there is a renderer for the specified subtype already, and use that
1167 EnterCriticalSection(&This->cs);
1168 for (x = 0; x < This->nFilters; ++x)
1170 IEnumPins *enumpins = NULL;
1171 IPin *pin = NULL;
1173 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1175 if (FAILED(hr) || !enumpins)
1176 continue;
1178 IEnumPins_Reset(enumpins);
1179 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1181 IPin *to = NULL;
1182 PIN_DIRECTION dir = PINDIR_OUTPUT;
1184 IPin_QueryDirection(pin, &dir);
1185 if (dir != PINDIR_INPUT)
1187 IPin_Release(pin);
1188 continue;
1190 IPin_ConnectedTo(pin, &to);
1192 if (to == NULL)
1194 hr = IPin_Connect(ppinOut, pin, NULL);
1195 if (SUCCEEDED(hr))
1197 TRACE("Connected succesfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1198 IPin_Release(pin);
1200 hr = FilterGraph2_RenderRecurse(This, pin);
1201 if (FAILED(hr))
1203 IPin_Disconnect(ppinOut);
1204 IPin_Disconnect(pin);
1205 continue;
1207 IEnumPins_Release(enumpins);
1208 LeaveCriticalSection(&This->cs);
1209 return hr;
1211 WARN("Could not connect!\n");
1213 else
1214 IPin_Release(to);
1216 IPin_Release(pin);
1218 IEnumPins_Release(enumpins);
1221 LeaveCriticalSection(&This->cs);
1223 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1224 if (FAILED(hr)) {
1225 WARN("EnumMediaTypes (%x)\n", hr);
1226 return hr;
1229 IEnumMediaTypes_Reset(penummt);
1231 /* Looks like no existing renderer of the kind exists
1232 * Try adding new ones
1234 tab[0] = tab[1] = GUID_NULL;
1235 while (SUCCEEDED(hr))
1237 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1238 if (FAILED(hr)) {
1239 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1240 break;
1242 if (!nbmt && !final)
1244 final = TRUE;
1245 tab[0] = tab[1] = GUID_NULL;
1246 IEnumMediaTypes_Reset(penummt);
1247 continue;
1249 else if (!nbmt)
1251 hr = VFW_E_CANNOT_RENDER;
1252 break;
1254 else
1256 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1257 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1259 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1260 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[0], &mt->majortype))
1262 DeleteMediaType(mt);
1263 continue;
1266 /* Try to find a suitable renderer with the same media type */
1267 tab[0] = mt->majortype;
1268 tab[1] = mt->subtype;
1269 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, !final, FALSE, 0, NULL, NULL, NULL);
1270 if (FAILED(hr))
1272 WARN("Unable to enum filters (%x)\n", hr);
1273 break;
1276 hr = E_FAIL;
1278 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1280 VARIANT var;
1281 GUID clsid;
1282 IPin* ppinfilter;
1283 IBaseFilter* pfilter = NULL;
1284 IEnumPins* penumpins;
1285 ULONG pin;
1287 hr = GetFilterInfo(pMoniker, &clsid, &var);
1288 IMoniker_Release(pMoniker);
1289 if (FAILED(hr)) {
1290 WARN("Unable to retrieve filter info (%x)\n", hr);
1291 goto error;
1294 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1295 if (FAILED(hr))
1297 WARN("Unable to create filter (%x), trying next one\n", hr);
1298 goto error;
1301 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1302 if (FAILED(hr)) {
1303 WARN("Unable to add filter (%x)\n", hr);
1304 IBaseFilter_Release(pfilter);
1305 pfilter = NULL;
1306 goto error;
1309 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1310 if (FAILED(hr)) {
1311 WARN("Splitter Enumpins (%x)\n", hr);
1312 goto error;
1314 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1315 IEnumPins_Release(penumpins);
1316 if (FAILED(hr)) {
1317 WARN("Next (%x)\n", hr);
1318 goto error;
1320 if (pin == 0) {
1321 WARN("No Pin\n");
1322 hr = E_FAIL;
1323 goto error;
1326 /* Connect the pin to the "Renderer" */
1327 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1328 IPin_Release(ppinfilter);
1330 if (FAILED(hr)) {
1331 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1332 goto error;
1334 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1335 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1336 if (FAILED(hr)) {
1337 WARN("Unable to connect recursively (%x)\n", hr);
1338 goto error;
1340 IBaseFilter_Release(pfilter);
1341 break;
1343 error:
1344 if (pfilter) {
1345 IFilterGraph2_RemoveFilter(iface, pfilter);
1346 IBaseFilter_Release(pfilter);
1348 if (!FAILED(hr)) DebugBreak();
1351 if (nbmt)
1352 DeleteMediaType(mt);
1353 if (SUCCEEDED(hr))
1354 break;
1355 hr = S_OK;
1358 IEnumMediaTypes_Release(penummt);
1359 return hr;
1362 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface,
1363 LPCWSTR lpcwstrFile,
1364 LPCWSTR lpcwstrPlayList)
1366 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1367 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1368 IBaseFilter* preader = NULL;
1369 IPin* ppinreader = NULL;
1370 IEnumPins* penumpins = NULL;
1371 HRESULT hr;
1372 BOOL partial = FALSE;
1373 HRESULT any = FALSE;
1375 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1377 if (lpcwstrPlayList != NULL)
1378 return E_INVALIDARG;
1380 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1381 if (FAILED(hr))
1382 return hr;
1384 if (SUCCEEDED(hr))
1385 hr = IBaseFilter_EnumPins(preader, &penumpins);
1386 if (SUCCEEDED(hr))
1388 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1390 PIN_DIRECTION dir;
1392 IPin_QueryDirection(ppinreader, &dir);
1393 if (dir == PINDIR_OUTPUT)
1395 INT i;
1397 hr = IFilterGraph2_Render(iface, ppinreader);
1398 ERR("Render %08x\n", hr);
1400 for (i = 0; i < This->nFilters; ++i)
1401 FIXME("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1403 if (SUCCEEDED(hr))
1404 any = TRUE;
1405 if (hr != S_OK)
1406 partial = TRUE;
1408 IPin_Release(ppinreader);
1410 IEnumPins_Release(penumpins);
1412 if (!any)
1413 hr = VFW_E_CANNOT_RENDER;
1414 else if (partial)
1415 hr = VFW_S_PARTIAL_RENDER;
1416 else
1417 hr = S_OK;
1419 IBaseFilter_Release(preader);
1421 TRACE("--> %08x\n", hr);
1422 return hr;
1425 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1426 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1428 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1429 HRESULT hr = S_OK;
1430 HKEY extkey;
1431 LONG lRet;
1433 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
1434 hr = HRESULT_FROM_WIN32(lRet);
1436 if (SUCCEEDED(hr))
1438 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
1439 WCHAR *ext = PathFindExtensionW(pszFileName);
1440 WCHAR clsid_key[39];
1441 GUID clsid;
1442 DWORD size = sizeof(clsid_key);
1443 HKEY pathkey;
1445 if (!ext)
1447 CloseHandle(extkey);
1448 return E_FAIL;
1451 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
1452 hr = HRESULT_FROM_WIN32(lRet);
1453 CloseHandle(extkey);
1454 if (FAILED(hr))
1455 return hr;
1457 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
1458 hr = HRESULT_FROM_WIN32(lRet);
1459 CloseHandle(pathkey);
1460 if (FAILED(hr))
1461 return hr;
1463 CLSIDFromString(clsid_key, &clsid);
1465 TRACE("CLSID: %s\n", debugstr_guid(&clsid));
1466 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1467 if (SUCCEEDED(hr))
1469 IFileSourceFilter *source = NULL;
1470 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1471 if (SUCCEEDED(hr))
1472 IFileSourceFilter_Release(source);
1473 else
1474 IBaseFilter_Release(*filter);
1477 if (FAILED(hr))
1478 *filter = NULL;
1479 return hr;
1482 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface,
1483 LPCWSTR lpcwstrFileName,
1484 LPCWSTR lpcwstrFilterName,
1485 IBaseFilter **ppFilter) {
1486 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1487 HRESULT hr;
1488 IBaseFilter* preader;
1489 IFileSourceFilter* pfile = NULL;
1490 AM_MEDIA_TYPE mt;
1491 WCHAR* filename;
1493 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1495 /* Try from file name first, then fall back to default asynchronous reader */
1496 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1498 if (FAILED(hr))
1499 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1500 if (FAILED(hr)) {
1501 ERR("Unable to create file source filter (%x)\n", hr);
1502 return hr;
1505 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1506 if (FAILED(hr)) {
1507 ERR("Unable add filter (%x)\n", hr);
1508 IBaseFilter_Release(preader);
1509 return hr;
1512 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1513 if (FAILED(hr)) {
1514 ERR("Unable to get IFileSourceInterface (%x)\n", hr);
1515 goto error;
1518 /* Load the file in the file source filter */
1519 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1520 if (FAILED(hr)) {
1521 ERR("Load (%x)\n", hr);
1522 goto error;
1525 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1526 if (FAILED(hr)) {
1527 ERR("GetCurFile (%x)\n", hr);
1528 goto error;
1531 TRACE("File %s\n", debugstr_w(filename));
1532 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1533 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1535 if (ppFilter)
1536 *ppFilter = preader;
1537 IFileSourceFilter_Release(pfile);
1539 return S_OK;
1541 error:
1542 if (pfile)
1543 IFileSourceFilter_Release(pfile);
1544 IFilterGraph2_RemoveFilter(iface, preader);
1545 IBaseFilter_Release(preader);
1547 return hr;
1550 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface,
1551 DWORD_PTR hFile) {
1552 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1554 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1556 return S_OK;
1559 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) {
1560 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1562 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1564 return S_OK;
1567 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) {
1568 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1570 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1572 return S_OK;
1575 /*** IFilterGraph2 methods ***/
1576 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1577 IMoniker *pMoniker,
1578 IBindCtx *pCtx,
1579 LPCWSTR lpcwstrFilterName,
1580 IBaseFilter **ppFilter) {
1581 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1583 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1585 return S_OK;
1588 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface,
1589 IPin *ppin,
1590 const AM_MEDIA_TYPE *pmt) {
1591 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1593 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1595 return S_OK;
1598 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface,
1599 IPin *pPinOut,
1600 DWORD dwFlags,
1601 DWORD *pvContext) {
1602 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1604 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1606 return S_OK;
1610 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1612 FilterGraph2_QueryInterface,
1613 FilterGraph2_AddRef,
1614 FilterGraph2_Release,
1615 FilterGraph2_AddFilter,
1616 FilterGraph2_RemoveFilter,
1617 FilterGraph2_EnumFilters,
1618 FilterGraph2_FindFilterByName,
1619 FilterGraph2_ConnectDirect,
1620 FilterGraph2_Reconnect,
1621 FilterGraph2_Disconnect,
1622 FilterGraph2_SetDefaultSyncSource,
1623 FilterGraph2_Connect,
1624 FilterGraph2_Render,
1625 FilterGraph2_RenderFile,
1626 FilterGraph2_AddSourceFilter,
1627 FilterGraph2_SetLogFile,
1628 FilterGraph2_Abort,
1629 FilterGraph2_ShouldOperationContinue,
1630 FilterGraph2_AddSourceFilterForMoniker,
1631 FilterGraph2_ReconnectEx,
1632 FilterGraph2_RenderEx
1635 /*** IUnknown methods ***/
1636 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface,
1637 REFIID riid,
1638 LPVOID*ppvObj) {
1639 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1641 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1643 return Filtergraph_QueryInterface(This, riid, ppvObj);
1646 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) {
1647 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1649 TRACE("(%p/%p)->()\n", This, iface);
1651 return Filtergraph_AddRef(This);
1654 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) {
1655 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1657 TRACE("(%p/%p)->()\n", This, iface);
1659 return Filtergraph_Release(This);
1663 /*** IDispatch methods ***/
1664 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface,
1665 UINT*pctinfo) {
1666 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1668 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1670 return S_OK;
1673 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface,
1674 UINT iTInfo,
1675 LCID lcid,
1676 ITypeInfo**ppTInfo) {
1677 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1679 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1681 return S_OK;
1684 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface,
1685 REFIID riid,
1686 LPOLESTR*rgszNames,
1687 UINT cNames,
1688 LCID lcid,
1689 DISPID*rgDispId) {
1690 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1692 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1694 return S_OK;
1697 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
1698 DISPID dispIdMember,
1699 REFIID riid,
1700 LCID lcid,
1701 WORD wFlags,
1702 DISPPARAMS*pDispParams,
1703 VARIANT*pVarResult,
1704 EXCEPINFO*pExepInfo,
1705 UINT*puArgErr) {
1706 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1708 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);
1710 return S_OK;
1713 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1715 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1717 HRESULT hr;
1718 IPin* pInputPin;
1719 IPin** ppPins;
1720 ULONG nb;
1721 ULONG i;
1722 PIN_INFO PinInfo;
1724 TRACE("%p %p\n", pGraph, pOutputPin);
1725 PinInfo.pFilter = NULL;
1727 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1729 if (SUCCEEDED(hr))
1731 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1732 if (SUCCEEDED(hr))
1733 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1734 IPin_Release(pInputPin);
1737 if (SUCCEEDED(hr))
1739 if (nb == 0)
1741 TRACE("Reached a renderer\n");
1742 /* Count renderers for end of stream notification */
1743 pGraph->nRenderers++;
1745 else
1747 for(i = 0; i < nb; i++)
1749 /* Explore the graph downstream from this pin
1750 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1751 * several input pins are connected to the same output (a MUX for instance). */
1752 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1753 IPin_Release(ppPins[i]);
1756 CoTaskMemFree(ppPins);
1758 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1760 FoundFilter(PinInfo.pFilter, data);
1763 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1764 return hr;
1767 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1769 LONGLONG time = 0;
1770 IReferenceClock *clock = NULL;
1772 IBaseFilter_GetSyncSource(pFilter, &clock);
1773 if (clock)
1775 IReferenceClock_GetTime(clock, &time);
1776 if (time)
1777 /* Add 50 ms */
1778 time += 500000;
1779 if (time < 0)
1780 time = 0;
1781 IReferenceClock_Release(clock);
1784 return IBaseFilter_Run(pFilter, time);
1787 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1789 return IBaseFilter_Pause(pFilter);
1792 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1794 return IBaseFilter_Stop(pFilter);
1797 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1799 FILTER_STATE state;
1800 DWORD time_end = data;
1801 DWORD time_now = GetTickCount();
1802 LONG wait;
1804 if (time_end == INFINITE)
1806 wait = INFINITE;
1808 else if (time_end > time_now)
1810 wait = time_end - time_now;
1812 else
1813 wait = 0;
1815 return IBaseFilter_GetState(pFilter, wait, &state);
1819 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data)
1821 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1822 int i;
1823 IBaseFilter* pfilter;
1824 IEnumPins* pEnum;
1825 HRESULT hr;
1826 IPin* pPin;
1827 DWORD dummy;
1828 PIN_DIRECTION dir;
1829 TRACE("(%p/%p)->()\n", This, iface);
1831 /* Explorer the graph from source filters to renderers, determine renderers
1832 * number and run filters from renderers to source filters */
1833 This->nRenderers = 0;
1834 ResetEvent(This->hEventCompletion);
1836 for(i = 0; i < This->nFilters; i++)
1838 BOOL source = TRUE;
1839 pfilter = This->ppFiltersInGraph[i];
1840 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1841 if (hr != S_OK)
1843 ERR("Enum pins failed %x\n", hr);
1844 continue;
1846 /* Check if it is a source filter */
1847 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1849 IPin_QueryDirection(pPin, &dir);
1850 IPin_Release(pPin);
1851 if (dir == PINDIR_INPUT)
1853 source = FALSE;
1854 break;
1857 if (source)
1859 TRACE("Found a source filter %p\n", pfilter);
1860 IEnumPins_Reset(pEnum);
1861 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1863 /* Explore the graph downstream from this pin */
1864 ExploreGraph(This, pPin, FoundFilter, data);
1865 IPin_Release(pPin);
1867 FoundFilter(pfilter, data);
1869 IEnumPins_Release(pEnum);
1872 return S_FALSE;
1875 /*** IMediaControl methods ***/
1876 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
1877 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1878 TRACE("(%p/%p)->()\n", This, iface);
1880 if (This->state == State_Running) return S_OK;
1882 EnterCriticalSection(&This->cs);
1883 if (This->state == State_Stopped)
1884 This->EcCompleteCount = 0;
1886 if (This->refClock)
1888 IReferenceClock_GetTime(This->refClock, &This->start_time);
1889 This->start_time += 500000;
1891 else This->position = This->start_time = 0;
1893 SendFilterMessage(iface, SendRun, 0);
1894 This->state = State_Running;
1895 LeaveCriticalSection(&This->cs);
1896 return S_FALSE;
1899 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
1900 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1901 TRACE("(%p/%p)->()\n", This, iface);
1903 if (This->state == State_Paused) return S_OK;
1905 EnterCriticalSection(&This->cs);
1906 if (This->state == State_Stopped)
1907 This->EcCompleteCount = 0;
1909 if (This->state == State_Running && This->refClock)
1911 LONGLONG time = This->start_time;
1912 IReferenceClock_GetTime(This->refClock, &time);
1913 This->position += time - This->start_time;
1916 SendFilterMessage(iface, SendPause, 0);
1917 This->state = State_Paused;
1918 LeaveCriticalSection(&This->cs);
1919 return S_FALSE;
1922 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
1923 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1924 TRACE("(%p/%p)->()\n", This, iface);
1926 if (This->state == State_Stopped) return S_OK;
1928 EnterCriticalSection(&This->cs);
1929 if (This->state == State_Running && This->refClock)
1931 LONGLONG time = This->start_time;
1932 IReferenceClock_GetTime(This->refClock, &time);
1933 This->position += time - This->start_time;
1936 if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0);
1937 SendFilterMessage(iface, SendStop, 0);
1938 This->state = State_Stopped;
1939 LeaveCriticalSection(&This->cs);
1940 return S_OK;
1943 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
1944 LONG msTimeout,
1945 OAFilterState *pfs) {
1946 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1947 DWORD end;
1949 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
1951 if (!pfs)
1952 return E_POINTER;
1954 EnterCriticalSection(&This->cs);
1956 *pfs = This->state;
1957 if (msTimeout > 0)
1959 end = GetTickCount() + msTimeout;
1961 else if (msTimeout < 0)
1963 end = INFINITE;
1965 else
1967 end = 0;
1969 if (end)
1970 SendFilterMessage(iface, SendGetState, end);
1972 LeaveCriticalSection(&This->cs);
1974 return S_OK;
1977 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface,
1978 BSTR strFilename) {
1979 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1981 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1983 return S_OK;
1986 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface,
1987 BSTR strFilename,
1988 IDispatch **ppUnk) {
1989 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1991 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1993 return S_OK;
1996 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface,
1997 IDispatch **ppUnk) {
1998 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2000 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2002 return S_OK;
2005 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface,
2006 IDispatch **ppUnk) {
2007 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2009 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2011 return S_OK;
2014 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) {
2015 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2017 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2019 return S_OK;
2023 static const IMediaControlVtbl IMediaControl_VTable =
2025 MediaControl_QueryInterface,
2026 MediaControl_AddRef,
2027 MediaControl_Release,
2028 MediaControl_GetTypeInfoCount,
2029 MediaControl_GetTypeInfo,
2030 MediaControl_GetIDsOfNames,
2031 MediaControl_Invoke,
2032 MediaControl_Run,
2033 MediaControl_Pause,
2034 MediaControl_Stop,
2035 MediaControl_GetState,
2036 MediaControl_RenderFile,
2037 MediaControl_AddSourceFilter,
2038 MediaControl_get_FilterCollection,
2039 MediaControl_get_RegFilterCollection,
2040 MediaControl_StopWhenReady
2044 /*** IUnknown methods ***/
2045 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface,
2046 REFIID riid,
2047 LPVOID*ppvObj) {
2048 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2050 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2052 return Filtergraph_QueryInterface(This, riid, ppvObj);
2055 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) {
2056 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2058 TRACE("(%p/%p)->()\n", This, iface);
2060 return Filtergraph_AddRef(This);
2063 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) {
2064 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2066 TRACE("(%p/%p)->()\n", This, iface);
2068 return Filtergraph_Release(This);
2071 typedef HRESULT WINAPI (*fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2073 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2074 BOOL allnotimpl = TRUE;
2075 int i;
2076 IBaseFilter* pfilter;
2077 IEnumPins* pEnum;
2078 HRESULT hr, hr_return = S_OK;
2079 IPin* pPin;
2080 DWORD dummy;
2081 PIN_DIRECTION dir;
2083 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2084 /* Send a message to all renderers, they are responsible for broadcasting it further */
2086 for(i = 0; i < This->nFilters; i++)
2088 BOOL renderer = TRUE;
2089 pfilter = This->ppFiltersInGraph[i];
2090 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
2091 if (hr != S_OK)
2093 ERR("Enum pins failed %x\n", hr);
2094 continue;
2096 /* Check if it is a source filter */
2097 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2099 IPin_QueryDirection(pPin, &dir);
2100 IPin_Release(pPin);
2101 if (dir != PINDIR_INPUT)
2103 renderer = FALSE;
2104 break;
2107 IEnumPins_Release(pEnum);
2108 if (renderer)
2110 IMediaSeeking *seek = NULL;
2111 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2112 if (!seek)
2113 continue;
2115 hr = FoundSeek(This, seek, arg);
2117 IMediaSeeking_Release(seek);
2118 if (hr_return != E_NOTIMPL)
2119 allnotimpl = FALSE;
2120 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && !FAILED(hr_return)))
2121 hr_return = hr;
2125 if (allnotimpl)
2126 return E_NOTIMPL;
2127 return hr_return;
2130 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2132 HRESULT hr;
2133 DWORD caps = 0;
2135 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2136 if (FAILED(hr))
2137 return hr;
2139 /* Only add common capabilities everything supports */
2140 *(DWORD*)pcaps &= caps;
2142 return hr;
2145 /*** IMediaSeeking methods ***/
2146 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface,
2147 DWORD *pCapabilities) {
2148 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2149 HRESULT hr;
2150 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2152 if (!pCapabilities)
2153 return E_POINTER;
2155 EnterCriticalSection(&This->cs);
2156 *pCapabilities = 0xffffffff;
2158 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2159 LeaveCriticalSection(&This->cs);
2161 return hr;
2164 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface,
2165 DWORD *pCapabilities) {
2166 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2167 DWORD originalcaps;
2168 HRESULT hr;
2169 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2171 if (!pCapabilities)
2172 return E_POINTER;
2174 EnterCriticalSection(&This->cs);
2175 originalcaps = *pCapabilities;
2176 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2177 LeaveCriticalSection(&This->cs);
2179 if (FAILED(hr))
2180 return hr;
2182 if (!*pCapabilities)
2183 return E_FAIL;
2184 if (*pCapabilities != originalcaps)
2185 return S_FALSE;
2186 return S_OK;
2189 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface,
2190 const GUID *pFormat) {
2191 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2193 if (!pFormat)
2194 return E_POINTER;
2196 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2198 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2200 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2201 return S_FALSE;
2204 return S_OK;
2207 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface,
2208 GUID *pFormat) {
2209 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2211 if (!pFormat)
2212 return E_POINTER;
2214 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2215 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2217 return S_OK;
2220 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface,
2221 GUID *pFormat) {
2222 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2224 if (!pFormat)
2225 return E_POINTER;
2227 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2228 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2230 return S_OK;
2233 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface,
2234 const GUID *pFormat) {
2235 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2237 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2238 if (!pFormat)
2239 return E_POINTER;
2241 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2242 return S_FALSE;
2244 return S_OK;
2247 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface,
2248 const GUID *pFormat) {
2249 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2251 if (!pFormat)
2252 return E_POINTER;
2254 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2256 if (This->state != State_Stopped)
2257 return VFW_E_WRONG_STATE;
2259 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2261 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2262 return E_INVALIDARG;
2265 return S_OK;
2268 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2270 HRESULT hr;
2271 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2273 hr = IMediaSeeking_GetDuration(seek, &duration);
2274 if (FAILED(hr))
2275 return hr;
2277 /* FIXME: Minimum or maximum duration? Assuming minimum */
2278 if (duration > 0 && *pdur < duration)
2279 *pdur = duration;
2281 return hr;
2284 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface,
2285 LONGLONG *pDuration) {
2286 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2287 HRESULT hr;
2289 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2291 if (!pDuration)
2292 return E_POINTER;
2294 EnterCriticalSection(&This->cs);
2295 *pDuration = -1;
2296 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2297 LeaveCriticalSection(&This->cs);
2299 TRACE("--->%08x\n", hr);
2300 return hr;
2303 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
2304 LONGLONG *pStop) {
2305 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2306 HRESULT hr = S_OK;
2308 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2310 if (!pStop)
2311 return E_POINTER;
2313 EnterCriticalSection(&This->cs);
2314 if (This->stop_position < 0)
2315 /* Stop position not set, use duration instead */
2316 hr = IMediaSeeking_GetDuration(iface, pStop);
2317 else
2318 *pStop = This->stop_position;
2320 LeaveCriticalSection(&This->cs);
2322 return hr;
2325 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
2326 LONGLONG *pCurrent) {
2327 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2328 LONGLONG time = 0;
2330 if (!pCurrent)
2331 return E_POINTER;
2333 EnterCriticalSection(&This->cs);
2334 if (This->state == State_Running && This->refClock)
2336 IReferenceClock_GetTime(This->refClock, &time);
2337 if (time)
2338 time += This->position - This->start_time;
2339 if (time < This->position)
2340 time = This->position;
2341 *pCurrent = time;
2343 else
2344 *pCurrent = This->position;
2345 LeaveCriticalSection(&This->cs);
2347 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2349 return S_OK;
2352 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
2353 LONGLONG *pTarget,
2354 const GUID *pTargetFormat,
2355 LONGLONG Source,
2356 const GUID *pSourceFormat) {
2357 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2359 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2360 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2362 return S_OK;
2365 struct pos_args {
2366 LONGLONG* current, *stop;
2367 DWORD curflags, stopflags;
2370 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2372 struct pos_args *args = (void*)pargs;
2374 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2377 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
2378 LONGLONG *pCurrent,
2379 DWORD dwCurrentFlags,
2380 LONGLONG *pStop,
2381 DWORD dwStopFlags) {
2382 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2383 HRESULT hr = S_OK;
2384 FILTER_STATE state;
2385 struct pos_args args;
2387 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2389 EnterCriticalSection(&This->cs);
2390 state = This->state;
2391 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2393 if ((dwCurrentFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2395 This->position = *pCurrent;
2397 else if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2398 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2400 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2401 This->stop_position = *pStop;
2402 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2403 FIXME("Stop position not handled yet!\n");
2405 args.current = pCurrent;
2406 args.stop = pStop;
2407 args.curflags = dwCurrentFlags;
2408 args.stopflags = dwStopFlags;
2409 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2411 if (This->refClock && ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning))
2413 /* Update start time, prevents weird jumps */
2414 IReferenceClock_GetTime(This->refClock, &This->start_time);
2416 LeaveCriticalSection(&This->cs);
2418 return hr;
2421 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
2422 LONGLONG *pCurrent,
2423 LONGLONG *pStop) {
2424 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2425 HRESULT hr;
2427 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2428 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2429 if (SUCCEEDED(hr))
2430 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2432 return hr;
2435 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
2436 LONGLONG *pEarliest,
2437 LONGLONG *pLatest) {
2438 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2440 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2442 return S_OK;
2445 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
2446 double dRate) {
2447 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2449 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2451 return S_OK;
2454 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
2455 double *pdRate) {
2456 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2458 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2460 return S_OK;
2463 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
2464 LONGLONG *pllPreroll) {
2465 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2467 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2469 return S_OK;
2473 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2475 MediaSeeking_QueryInterface,
2476 MediaSeeking_AddRef,
2477 MediaSeeking_Release,
2478 MediaSeeking_GetCapabilities,
2479 MediaSeeking_CheckCapabilities,
2480 MediaSeeking_IsFormatSupported,
2481 MediaSeeking_QueryPreferredFormat,
2482 MediaSeeking_GetTimeFormat,
2483 MediaSeeking_IsUsingTimeFormat,
2484 MediaSeeking_SetTimeFormat,
2485 MediaSeeking_GetDuration,
2486 MediaSeeking_GetStopPosition,
2487 MediaSeeking_GetCurrentPosition,
2488 MediaSeeking_ConvertTimeFormat,
2489 MediaSeeking_SetPositions,
2490 MediaSeeking_GetPositions,
2491 MediaSeeking_GetAvailable,
2492 MediaSeeking_SetRate,
2493 MediaSeeking_GetRate,
2494 MediaSeeking_GetPreroll
2497 /*** IUnknown methods ***/
2498 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
2499 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2501 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2503 return Filtergraph_QueryInterface(This, riid, ppvObj);
2506 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
2507 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2509 TRACE("(%p/%p)->()\n", This, iface);
2511 return Filtergraph_AddRef(This);
2514 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
2515 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2517 TRACE("(%p/%p)->()\n", This, iface);
2519 return Filtergraph_Release(This);
2522 /*** IDispatch methods ***/
2523 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2524 FIXME("(%p) stub!\n", iface);
2525 return E_NOTIMPL;
2528 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2529 FIXME("(%p) stub!\n", iface);
2530 return E_NOTIMPL;
2533 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2534 FIXME("(%p) stub!\n", iface);
2535 return E_NOTIMPL;
2538 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2539 FIXME("(%p) stub!\n", iface);
2540 return E_NOTIMPL;
2543 /*** IMediaPosition methods ***/
2544 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
2545 FIXME("(%p)->(%p) stub!\n", iface, plength);
2546 return E_NOTIMPL;
2549 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
2550 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2551 return E_NOTIMPL;
2554 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
2555 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2556 return E_NOTIMPL;
2559 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
2560 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2561 return E_NOTIMPL;
2564 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
2565 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2566 return E_NOTIMPL;
2569 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2570 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2571 return E_NOTIMPL;
2574 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2575 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2576 return E_NOTIMPL;
2579 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
2580 FIXME("(%p)->(%f) stub!\n", iface, dRate);
2581 return E_NOTIMPL;
2584 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
2585 FIXME("(%p)->(%p) stub!\n", iface, pdRate);
2586 return E_NOTIMPL;
2589 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2590 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2591 return E_NOTIMPL;
2594 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2595 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2596 return E_NOTIMPL;
2600 static const IMediaPositionVtbl IMediaPosition_VTable =
2602 MediaPosition_QueryInterface,
2603 MediaPosition_AddRef,
2604 MediaPosition_Release,
2605 MediaPosition_GetTypeInfoCount,
2606 MediaPosition_GetTypeInfo,
2607 MediaPosition_GetIDsOfNames,
2608 MediaPosition_Invoke,
2609 MediaPosition_get_Duration,
2610 MediaPosition_put_CurrentPosition,
2611 MediaPosition_get_CurrentPosition,
2612 MediaPosition_get_StopTime,
2613 MediaPosition_put_StopTime,
2614 MediaPosition_get_PrerollTime,
2615 MediaPosition_put_PrerollTime,
2616 MediaPosition_put_Rate,
2617 MediaPosition_get_Rate,
2618 MediaPosition_CanSeekForward,
2619 MediaPosition_CanSeekBackward
2622 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2624 HRESULT hr = E_NOINTERFACE;
2625 int i;
2626 int entry;
2628 /* Check if the interface type is already registered */
2629 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2630 if (riid == pGraph->ItfCacheEntries[entry].riid)
2632 if (pGraph->ItfCacheEntries[entry].iface)
2634 /* Return the interface if available */
2635 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2636 return S_OK;
2638 break;
2641 if (entry >= MAX_ITF_CACHE_ENTRIES)
2643 FIXME("Not enough space to store interface in the cache\n");
2644 return E_OUTOFMEMORY;
2647 /* Find a filter supporting the requested interface */
2648 for (i = 0; i < pGraph->nFilters; i++)
2650 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2651 if (hr == S_OK)
2653 pGraph->ItfCacheEntries[entry].riid = riid;
2654 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2655 pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
2656 if (entry >= pGraph->nItfCacheEntries)
2657 pGraph->nItfCacheEntries++;
2658 return S_OK;
2660 if (hr != E_NOINTERFACE)
2661 return hr;
2664 return hr;
2667 /*** IUnknown methods ***/
2668 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
2669 REFIID riid,
2670 LPVOID*ppvObj) {
2671 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2673 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2675 return Filtergraph_QueryInterface(This, riid, ppvObj);
2678 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
2679 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2681 TRACE("(%p/%p)->()\n", This, iface);
2683 return Filtergraph_AddRef(This);
2686 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
2687 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2689 TRACE("(%p/%p)->()\n", This, iface);
2691 return Filtergraph_Release(This);
2694 /*** IDispatch methods ***/
2695 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
2696 UINT*pctinfo) {
2697 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2698 IBasicAudio* pBasicAudio;
2699 HRESULT hr;
2701 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2703 EnterCriticalSection(&This->cs);
2705 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2707 if (hr == S_OK)
2708 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2710 LeaveCriticalSection(&This->cs);
2712 return hr;
2715 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2716 UINT iTInfo,
2717 LCID lcid,
2718 ITypeInfo**ppTInfo) {
2719 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2720 IBasicAudio* pBasicAudio;
2721 HRESULT hr;
2723 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2725 EnterCriticalSection(&This->cs);
2727 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2729 if (hr == S_OK)
2730 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2732 LeaveCriticalSection(&This->cs);
2734 return hr;
2737 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2738 REFIID riid,
2739 LPOLESTR*rgszNames,
2740 UINT cNames,
2741 LCID lcid,
2742 DISPID*rgDispId) {
2743 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2744 IBasicAudio* pBasicAudio;
2745 HRESULT hr;
2747 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2749 EnterCriticalSection(&This->cs);
2751 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2753 if (hr == S_OK)
2754 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2756 LeaveCriticalSection(&This->cs);
2758 return hr;
2761 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2762 DISPID dispIdMember,
2763 REFIID riid,
2764 LCID lcid,
2765 WORD wFlags,
2766 DISPPARAMS*pDispParams,
2767 VARIANT*pVarResult,
2768 EXCEPINFO*pExepInfo,
2769 UINT*puArgErr) {
2770 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2771 IBasicAudio* pBasicAudio;
2772 HRESULT hr;
2774 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);
2776 EnterCriticalSection(&This->cs);
2778 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2780 if (hr == S_OK)
2781 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2783 LeaveCriticalSection(&This->cs);
2785 return hr;
2788 /*** IBasicAudio methods ***/
2789 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2790 long lVolume) {
2791 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2792 IBasicAudio* pBasicAudio;
2793 HRESULT hr;
2795 TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2797 EnterCriticalSection(&This->cs);
2799 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2801 if (hr == S_OK)
2802 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2804 LeaveCriticalSection(&This->cs);
2806 return hr;
2809 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2810 long *plVolume) {
2811 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2812 IBasicAudio* pBasicAudio;
2813 HRESULT hr;
2815 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2817 EnterCriticalSection(&This->cs);
2819 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2821 if (hr == S_OK)
2822 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2824 LeaveCriticalSection(&This->cs);
2826 return hr;
2829 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2830 long lBalance) {
2831 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2832 IBasicAudio* pBasicAudio;
2833 HRESULT hr;
2835 TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2837 EnterCriticalSection(&This->cs);
2839 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2841 if (hr == S_OK)
2842 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2844 LeaveCriticalSection(&This->cs);
2846 return hr;
2849 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2850 long *plBalance) {
2851 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2852 IBasicAudio* pBasicAudio;
2853 HRESULT hr;
2855 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2857 EnterCriticalSection(&This->cs);
2859 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2861 if (hr == S_OK)
2862 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2864 LeaveCriticalSection(&This->cs);
2866 return hr;
2869 static const IBasicAudioVtbl IBasicAudio_VTable =
2871 BasicAudio_QueryInterface,
2872 BasicAudio_AddRef,
2873 BasicAudio_Release,
2874 BasicAudio_GetTypeInfoCount,
2875 BasicAudio_GetTypeInfo,
2876 BasicAudio_GetIDsOfNames,
2877 BasicAudio_Invoke,
2878 BasicAudio_put_Volume,
2879 BasicAudio_get_Volume,
2880 BasicAudio_put_Balance,
2881 BasicAudio_get_Balance
2884 /*** IUnknown methods ***/
2885 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface,
2886 REFIID riid,
2887 LPVOID*ppvObj) {
2888 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2890 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2892 return Filtergraph_QueryInterface(This, riid, ppvObj);
2895 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) {
2896 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2898 TRACE("(%p/%p)->()\n", This, iface);
2900 return Filtergraph_AddRef(This);
2903 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) {
2904 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2906 TRACE("(%p/%p)->()\n", This, iface);
2908 return Filtergraph_Release(This);
2911 /*** IDispatch methods ***/
2912 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface,
2913 UINT*pctinfo) {
2914 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2915 IBasicVideo* pBasicVideo;
2916 HRESULT hr;
2918 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2920 EnterCriticalSection(&This->cs);
2922 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2924 if (hr == S_OK)
2925 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2927 LeaveCriticalSection(&This->cs);
2929 return hr;
2932 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface,
2933 UINT iTInfo,
2934 LCID lcid,
2935 ITypeInfo**ppTInfo) {
2936 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2937 IBasicVideo* pBasicVideo;
2938 HRESULT hr;
2940 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2942 EnterCriticalSection(&This->cs);
2944 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2946 if (hr == S_OK)
2947 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2949 LeaveCriticalSection(&This->cs);
2951 return hr;
2954 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface,
2955 REFIID riid,
2956 LPOLESTR*rgszNames,
2957 UINT cNames,
2958 LCID lcid,
2959 DISPID*rgDispId) {
2960 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2961 IBasicVideo* pBasicVideo;
2962 HRESULT hr;
2964 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2966 EnterCriticalSection(&This->cs);
2968 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2970 if (hr == S_OK)
2971 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
2973 LeaveCriticalSection(&This->cs);
2975 return hr;
2978 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface,
2979 DISPID dispIdMember,
2980 REFIID riid,
2981 LCID lcid,
2982 WORD wFlags,
2983 DISPPARAMS*pDispParams,
2984 VARIANT*pVarResult,
2985 EXCEPINFO*pExepInfo,
2986 UINT*puArgErr) {
2987 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2988 IBasicVideo* pBasicVideo;
2989 HRESULT hr;
2991 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);
2993 EnterCriticalSection(&This->cs);
2995 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2997 if (hr == S_OK)
2998 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3000 LeaveCriticalSection(&This->cs);
3002 return hr;
3005 /*** IBasicVideo methods ***/
3006 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface,
3007 REFTIME *pAvgTimePerFrame) {
3008 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3009 IBasicVideo* pBasicVideo;
3010 HRESULT hr;
3012 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3014 EnterCriticalSection(&This->cs);
3016 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3018 if (hr == S_OK)
3019 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3021 LeaveCriticalSection(&This->cs);
3023 return hr;
3026 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface,
3027 long *pBitRate) {
3028 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3029 IBasicVideo* pBasicVideo;
3030 HRESULT hr;
3032 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3034 EnterCriticalSection(&This->cs);
3036 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3038 if (hr == S_OK)
3039 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3041 LeaveCriticalSection(&This->cs);
3043 return hr;
3046 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface,
3047 long *pBitErrorRate) {
3048 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3049 IBasicVideo* pBasicVideo;
3050 HRESULT hr;
3052 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3054 EnterCriticalSection(&This->cs);
3056 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3058 if (hr == S_OK)
3059 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3061 LeaveCriticalSection(&This->cs);
3063 return hr;
3066 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface,
3067 long *pVideoWidth) {
3068 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3069 IBasicVideo* pBasicVideo;
3070 HRESULT hr;
3072 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3074 EnterCriticalSection(&This->cs);
3076 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3078 if (hr == S_OK)
3079 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3081 LeaveCriticalSection(&This->cs);
3083 return hr;
3086 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface,
3087 long *pVideoHeight) {
3088 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3089 IBasicVideo* pBasicVideo;
3090 HRESULT hr;
3092 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3094 EnterCriticalSection(&This->cs);
3096 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3098 if (hr == S_OK)
3099 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3101 LeaveCriticalSection(&This->cs);
3103 return hr;
3106 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface,
3107 long SourceLeft) {
3108 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3109 IBasicVideo* pBasicVideo;
3110 HRESULT hr;
3112 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
3114 EnterCriticalSection(&This->cs);
3116 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3118 if (hr == S_OK)
3119 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3121 LeaveCriticalSection(&This->cs);
3123 return hr;
3126 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface,
3127 long *pSourceLeft) {
3128 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3129 IBasicVideo* pBasicVideo;
3130 HRESULT hr;
3132 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3134 EnterCriticalSection(&This->cs);
3136 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3138 if (hr == S_OK)
3139 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3141 LeaveCriticalSection(&This->cs);
3143 return hr;
3146 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface,
3147 long SourceWidth) {
3148 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3149 IBasicVideo* pBasicVideo;
3150 HRESULT hr;
3152 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
3154 EnterCriticalSection(&This->cs);
3156 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3158 if (hr == S_OK)
3159 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3161 LeaveCriticalSection(&This->cs);
3163 return hr;
3166 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface,
3167 long *pSourceWidth) {
3168 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3169 IBasicVideo* pBasicVideo;
3170 HRESULT hr;
3172 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3174 EnterCriticalSection(&This->cs);
3176 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3178 if (hr == S_OK)
3179 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3181 LeaveCriticalSection(&This->cs);
3183 return hr;
3186 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface,
3187 long SourceTop) {
3188 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3189 IBasicVideo* pBasicVideo;
3190 HRESULT hr;
3192 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
3194 EnterCriticalSection(&This->cs);
3196 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3198 if (hr == S_OK)
3199 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3201 LeaveCriticalSection(&This->cs);
3203 return hr;
3206 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface,
3207 long *pSourceTop) {
3208 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3209 IBasicVideo* pBasicVideo;
3210 HRESULT hr;
3212 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3214 EnterCriticalSection(&This->cs);
3216 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3218 if (hr == S_OK)
3219 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3221 LeaveCriticalSection(&This->cs);
3223 return hr;
3226 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface,
3227 long SourceHeight) {
3228 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3229 IBasicVideo* pBasicVideo;
3230 HRESULT hr;
3232 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
3234 EnterCriticalSection(&This->cs);
3236 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3238 if (hr == S_OK)
3239 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3241 LeaveCriticalSection(&This->cs);
3243 return hr;
3246 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface,
3247 long *pSourceHeight) {
3248 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3249 IBasicVideo* pBasicVideo;
3250 HRESULT hr;
3252 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3254 EnterCriticalSection(&This->cs);
3256 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3258 if (hr == S_OK)
3259 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3261 LeaveCriticalSection(&This->cs);
3263 return hr;
3266 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface,
3267 long DestinationLeft) {
3268 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3269 IBasicVideo* pBasicVideo;
3270 HRESULT hr;
3272 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
3274 EnterCriticalSection(&This->cs);
3276 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3278 if (hr == S_OK)
3279 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3281 LeaveCriticalSection(&This->cs);
3283 return hr;
3286 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface,
3287 long *pDestinationLeft) {
3288 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3289 IBasicVideo* pBasicVideo;
3290 HRESULT hr;
3292 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3294 EnterCriticalSection(&This->cs);
3296 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3298 if (hr == S_OK)
3299 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3301 LeaveCriticalSection(&This->cs);
3303 return hr;
3306 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface,
3307 long DestinationWidth) {
3308 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3309 IBasicVideo* pBasicVideo;
3310 HRESULT hr;
3312 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
3314 EnterCriticalSection(&This->cs);
3316 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3318 if (hr == S_OK)
3319 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3321 LeaveCriticalSection(&This->cs);
3323 return hr;
3326 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface,
3327 long *pDestinationWidth) {
3328 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3329 IBasicVideo* pBasicVideo;
3330 HRESULT hr;
3332 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3334 EnterCriticalSection(&This->cs);
3336 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3338 if (hr == S_OK)
3339 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3341 LeaveCriticalSection(&This->cs);
3343 return hr;
3346 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface,
3347 long DestinationTop) {
3348 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3349 IBasicVideo* pBasicVideo;
3350 HRESULT hr;
3352 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
3354 EnterCriticalSection(&This->cs);
3356 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3358 if (hr == S_OK)
3359 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3361 LeaveCriticalSection(&This->cs);
3363 return hr;
3366 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface,
3367 long *pDestinationTop) {
3368 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3369 IBasicVideo* pBasicVideo;
3370 HRESULT hr;
3372 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3374 EnterCriticalSection(&This->cs);
3376 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3378 if (hr == S_OK)
3379 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3381 LeaveCriticalSection(&This->cs);
3383 return hr;
3386 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface,
3387 long DestinationHeight) {
3388 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3389 IBasicVideo* pBasicVideo;
3390 HRESULT hr;
3392 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
3394 EnterCriticalSection(&This->cs);
3396 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3398 if (hr == S_OK)
3399 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3401 LeaveCriticalSection(&This->cs);
3403 return hr;
3406 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3407 long *pDestinationHeight) {
3408 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3409 IBasicVideo* pBasicVideo;
3410 HRESULT hr;
3412 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3414 EnterCriticalSection(&This->cs);
3416 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3418 if (hr == S_OK)
3419 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3421 LeaveCriticalSection(&This->cs);
3423 return hr;
3426 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface,
3427 long Left,
3428 long Top,
3429 long Width,
3430 long Height) {
3431 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3432 IBasicVideo* pBasicVideo;
3433 HRESULT hr;
3435 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3437 EnterCriticalSection(&This->cs);
3439 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3441 if (hr == S_OK)
3442 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3444 LeaveCriticalSection(&This->cs);
3446 return hr;
3449 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface,
3450 long *pLeft,
3451 long *pTop,
3452 long *pWidth,
3453 long *pHeight) {
3454 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3455 IBasicVideo* pBasicVideo;
3456 HRESULT hr;
3458 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3460 EnterCriticalSection(&This->cs);
3462 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3464 if (hr == S_OK)
3465 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3467 LeaveCriticalSection(&This->cs);
3469 return hr;
3472 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) {
3473 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3474 IBasicVideo* pBasicVideo;
3475 HRESULT hr;
3477 TRACE("(%p/%p)->()\n", This, iface);
3479 EnterCriticalSection(&This->cs);
3481 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3483 if (hr == S_OK)
3484 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3486 LeaveCriticalSection(&This->cs);
3488 return hr;
3491 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface,
3492 long Left,
3493 long Top,
3494 long Width,
3495 long Height) {
3496 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3497 IBasicVideo* pBasicVideo;
3498 HRESULT hr;
3500 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3502 EnterCriticalSection(&This->cs);
3504 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3506 if (hr == S_OK)
3507 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3509 LeaveCriticalSection(&This->cs);
3511 return hr;
3514 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface,
3515 long *pLeft,
3516 long *pTop,
3517 long *pWidth,
3518 long *pHeight) {
3519 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3520 IBasicVideo* pBasicVideo;
3521 HRESULT hr;
3523 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3525 EnterCriticalSection(&This->cs);
3527 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3529 if (hr == S_OK)
3530 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3532 LeaveCriticalSection(&This->cs);
3534 return hr;
3537 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) {
3538 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3539 IBasicVideo* pBasicVideo;
3540 HRESULT hr;
3542 TRACE("(%p/%p)->()\n", This, iface);
3544 EnterCriticalSection(&This->cs);
3546 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3548 if (hr == S_OK)
3549 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3551 LeaveCriticalSection(&This->cs);
3553 return hr;
3556 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface,
3557 long *pWidth,
3558 long *pHeight) {
3559 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3560 IBasicVideo* pBasicVideo;
3561 HRESULT hr;
3563 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3565 EnterCriticalSection(&This->cs);
3567 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3569 if (hr == S_OK)
3570 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3572 LeaveCriticalSection(&This->cs);
3574 return hr;
3577 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface,
3578 long StartIndex,
3579 long Entries,
3580 long *pRetrieved,
3581 long *pPalette) {
3582 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3583 IBasicVideo* pBasicVideo;
3584 HRESULT hr;
3586 TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3588 EnterCriticalSection(&This->cs);
3590 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3592 if (hr == S_OK)
3593 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3595 LeaveCriticalSection(&This->cs);
3597 return hr;
3600 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface,
3601 long *pBufferSize,
3602 long *pDIBImage) {
3603 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3604 IBasicVideo* pBasicVideo;
3605 HRESULT hr;
3607 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3609 EnterCriticalSection(&This->cs);
3611 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3613 if (hr == S_OK)
3614 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3616 LeaveCriticalSection(&This->cs);
3618 return hr;
3621 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) {
3622 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3623 IBasicVideo* pBasicVideo;
3624 HRESULT hr;
3626 TRACE("(%p/%p)->()\n", This, iface);
3628 EnterCriticalSection(&This->cs);
3630 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3632 if (hr == S_OK)
3633 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3635 LeaveCriticalSection(&This->cs);
3637 return hr;
3640 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) {
3641 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3642 IBasicVideo* pBasicVideo;
3643 HRESULT hr;
3645 TRACE("(%p/%p)->()\n", This, iface);
3647 EnterCriticalSection(&This->cs);
3649 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3651 if (hr == S_OK)
3652 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3654 LeaveCriticalSection(&This->cs);
3656 return hr;
3659 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, LONG *plAspectY) {
3660 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3661 IBasicVideo2 *pBasicVideo2;
3662 HRESULT hr;
3664 TRACE("(%p/%p)->()\n", This, iface);
3666 EnterCriticalSection(&This->cs);
3668 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3670 if (hr == S_OK)
3671 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3673 LeaveCriticalSection(&This->cs);
3675 return hr;
3678 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3680 BasicVideo_QueryInterface,
3681 BasicVideo_AddRef,
3682 BasicVideo_Release,
3683 BasicVideo_GetTypeInfoCount,
3684 BasicVideo_GetTypeInfo,
3685 BasicVideo_GetIDsOfNames,
3686 BasicVideo_Invoke,
3687 BasicVideo_get_AvgTimePerFrame,
3688 BasicVideo_get_BitRate,
3689 BasicVideo_get_BitErrorRate,
3690 BasicVideo_get_VideoWidth,
3691 BasicVideo_get_VideoHeight,
3692 BasicVideo_put_SourceLeft,
3693 BasicVideo_get_SourceLeft,
3694 BasicVideo_put_SourceWidth,
3695 BasicVideo_get_SourceWidth,
3696 BasicVideo_put_SourceTop,
3697 BasicVideo_get_SourceTop,
3698 BasicVideo_put_SourceHeight,
3699 BasicVideo_get_SourceHeight,
3700 BasicVideo_put_DestinationLeft,
3701 BasicVideo_get_DestinationLeft,
3702 BasicVideo_put_DestinationWidth,
3703 BasicVideo_get_DestinationWidth,
3704 BasicVideo_put_DestinationTop,
3705 BasicVideo_get_DestinationTop,
3706 BasicVideo_put_DestinationHeight,
3707 BasicVideo_get_DestinationHeight,
3708 BasicVideo_SetSourcePosition,
3709 BasicVideo_GetSourcePosition,
3710 BasicVideo_SetDefaultSourcePosition,
3711 BasicVideo_SetDestinationPosition,
3712 BasicVideo_GetDestinationPosition,
3713 BasicVideo_SetDefaultDestinationPosition,
3714 BasicVideo_GetVideoSize,
3715 BasicVideo_GetVideoPaletteEntries,
3716 BasicVideo_GetCurrentImage,
3717 BasicVideo_IsUsingDefaultSource,
3718 BasicVideo_IsUsingDefaultDestination,
3719 BasicVideo2_GetPreferredAspectRatio
3723 /*** IUnknown methods ***/
3724 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3725 REFIID riid,
3726 LPVOID*ppvObj) {
3727 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3729 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3731 return Filtergraph_QueryInterface(This, riid, ppvObj);
3734 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3735 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3737 TRACE("(%p/%p)->()\n", This, iface);
3739 return Filtergraph_AddRef(This);
3742 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3743 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3745 TRACE("(%p/%p)->()\n", This, iface);
3747 return Filtergraph_Release(This);
3750 /*** IDispatch methods ***/
3751 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3752 UINT*pctinfo) {
3753 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3754 IVideoWindow* pVideoWindow;
3755 HRESULT hr;
3757 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3759 EnterCriticalSection(&This->cs);
3761 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3763 if (hr == S_OK)
3764 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3766 LeaveCriticalSection(&This->cs);
3768 return hr;
3771 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3772 UINT iTInfo,
3773 LCID lcid,
3774 ITypeInfo**ppTInfo) {
3775 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3776 IVideoWindow* pVideoWindow;
3777 HRESULT hr;
3779 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3781 EnterCriticalSection(&This->cs);
3783 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3785 if (hr == S_OK)
3786 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3788 LeaveCriticalSection(&This->cs);
3790 return hr;
3793 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3794 REFIID riid,
3795 LPOLESTR*rgszNames,
3796 UINT cNames,
3797 LCID lcid,
3798 DISPID*rgDispId) {
3799 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3800 IVideoWindow* pVideoWindow;
3801 HRESULT hr;
3803 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3805 EnterCriticalSection(&This->cs);
3807 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3809 if (hr == S_OK)
3810 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3812 LeaveCriticalSection(&This->cs);
3814 return hr;
3817 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3818 DISPID dispIdMember,
3819 REFIID riid,
3820 LCID lcid,
3821 WORD wFlags,
3822 DISPPARAMS*pDispParams,
3823 VARIANT*pVarResult,
3824 EXCEPINFO*pExepInfo,
3825 UINT*puArgErr) {
3826 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3827 IVideoWindow* pVideoWindow;
3828 HRESULT hr;
3830 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);
3832 EnterCriticalSection(&This->cs);
3834 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3836 if (hr == S_OK)
3837 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3839 LeaveCriticalSection(&This->cs);
3841 return hr;
3845 /*** IVideoWindow methods ***/
3846 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3847 BSTR strCaption) {
3848 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3849 IVideoWindow* pVideoWindow;
3850 HRESULT hr;
3852 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3854 EnterCriticalSection(&This->cs);
3856 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3858 if (hr == S_OK)
3859 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3861 LeaveCriticalSection(&This->cs);
3863 return hr;
3866 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3867 BSTR *strCaption) {
3868 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3869 IVideoWindow* pVideoWindow;
3870 HRESULT hr;
3872 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3874 EnterCriticalSection(&This->cs);
3876 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3878 if (hr == S_OK)
3879 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3881 LeaveCriticalSection(&This->cs);
3883 return hr;
3886 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3887 long WindowStyle) {
3888 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3889 IVideoWindow* pVideoWindow;
3890 HRESULT hr;
3892 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3894 EnterCriticalSection(&This->cs);
3896 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3898 if (hr == S_OK)
3899 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3901 LeaveCriticalSection(&This->cs);
3903 return hr;
3906 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3907 long *WindowStyle) {
3908 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3909 IVideoWindow* pVideoWindow;
3910 HRESULT hr;
3912 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3914 EnterCriticalSection(&This->cs);
3916 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3918 if (hr == S_OK)
3919 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3921 LeaveCriticalSection(&This->cs);
3923 return hr;
3926 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3927 long WindowStyleEx) {
3928 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3929 IVideoWindow* pVideoWindow;
3930 HRESULT hr;
3932 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3934 EnterCriticalSection(&This->cs);
3936 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3938 if (hr == S_OK)
3939 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3941 LeaveCriticalSection(&This->cs);
3943 return hr;
3946 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3947 long *WindowStyleEx) {
3948 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3949 IVideoWindow* pVideoWindow;
3950 HRESULT hr;
3952 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3954 EnterCriticalSection(&This->cs);
3956 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3958 if (hr == S_OK)
3959 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
3961 LeaveCriticalSection(&This->cs);
3963 return hr;
3966 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
3967 long AutoShow) {
3968 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3969 IVideoWindow* pVideoWindow;
3970 HRESULT hr;
3972 TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
3974 EnterCriticalSection(&This->cs);
3976 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3978 if (hr == S_OK)
3979 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
3981 LeaveCriticalSection(&This->cs);
3983 return hr;
3986 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
3987 long *AutoShow) {
3988 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3989 IVideoWindow* pVideoWindow;
3990 HRESULT hr;
3992 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
3994 EnterCriticalSection(&This->cs);
3996 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3998 if (hr == S_OK)
3999 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4001 LeaveCriticalSection(&This->cs);
4003 return hr;
4006 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
4007 long WindowState) {
4008 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4009 IVideoWindow* pVideoWindow;
4010 HRESULT hr;
4012 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
4014 EnterCriticalSection(&This->cs);
4016 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4018 if (hr == S_OK)
4019 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4021 LeaveCriticalSection(&This->cs);
4023 return hr;
4026 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
4027 long *WindowState) {
4028 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4029 IVideoWindow* pVideoWindow;
4030 HRESULT hr;
4032 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4034 EnterCriticalSection(&This->cs);
4036 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4038 if (hr == S_OK)
4039 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4041 LeaveCriticalSection(&This->cs);
4043 return hr;
4046 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
4047 long BackgroundPalette) {
4048 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4049 IVideoWindow* pVideoWindow;
4050 HRESULT hr;
4052 TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
4054 EnterCriticalSection(&This->cs);
4056 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4058 if (hr == S_OK)
4059 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4061 LeaveCriticalSection(&This->cs);
4063 return hr;
4066 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4067 long *pBackgroundPalette) {
4068 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4069 IVideoWindow* pVideoWindow;
4070 HRESULT hr;
4072 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4074 EnterCriticalSection(&This->cs);
4076 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4078 if (hr == S_OK)
4079 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4081 LeaveCriticalSection(&This->cs);
4083 return hr;
4086 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
4087 long Visible) {
4088 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4089 IVideoWindow* pVideoWindow;
4090 HRESULT hr;
4092 TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
4094 EnterCriticalSection(&This->cs);
4096 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4098 if (hr == S_OK)
4099 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4101 LeaveCriticalSection(&This->cs);
4103 return hr;
4106 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
4107 long *pVisible) {
4108 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4109 IVideoWindow* pVideoWindow;
4110 HRESULT hr;
4112 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4114 EnterCriticalSection(&This->cs);
4116 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4118 if (hr == S_OK)
4119 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4121 LeaveCriticalSection(&This->cs);
4123 return hr;
4126 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
4127 long Left) {
4128 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4129 IVideoWindow* pVideoWindow;
4130 HRESULT hr;
4132 TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
4134 EnterCriticalSection(&This->cs);
4136 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4138 if (hr == S_OK)
4139 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4141 LeaveCriticalSection(&This->cs);
4143 return hr;
4146 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
4147 long *pLeft) {
4148 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4149 IVideoWindow* pVideoWindow;
4150 HRESULT hr;
4152 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4154 EnterCriticalSection(&This->cs);
4156 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4158 if (hr == S_OK)
4159 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4161 LeaveCriticalSection(&This->cs);
4163 return hr;
4166 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
4167 long Width) {
4168 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4169 IVideoWindow* pVideoWindow;
4170 HRESULT hr;
4172 TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
4174 EnterCriticalSection(&This->cs);
4176 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4178 if (hr == S_OK)
4179 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4181 LeaveCriticalSection(&This->cs);
4183 return hr;
4186 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
4187 long *pWidth) {
4188 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4189 IVideoWindow* pVideoWindow;
4190 HRESULT hr;
4192 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4194 EnterCriticalSection(&This->cs);
4196 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4198 if (hr == S_OK)
4199 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4201 LeaveCriticalSection(&This->cs);
4203 return hr;
4206 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
4207 long Top) {
4208 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4209 IVideoWindow* pVideoWindow;
4210 HRESULT hr;
4212 TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
4214 EnterCriticalSection(&This->cs);
4216 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4218 if (hr == S_OK)
4219 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4221 LeaveCriticalSection(&This->cs);
4223 return hr;
4226 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
4227 long *pTop) {
4228 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4229 IVideoWindow* pVideoWindow;
4230 HRESULT hr;
4232 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4234 EnterCriticalSection(&This->cs);
4236 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4238 if (hr == S_OK)
4239 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4241 LeaveCriticalSection(&This->cs);
4243 return hr;
4246 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
4247 long Height) {
4248 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4249 IVideoWindow* pVideoWindow;
4250 HRESULT hr;
4252 TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
4254 EnterCriticalSection(&This->cs);
4256 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4258 if (hr == S_OK)
4259 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4261 LeaveCriticalSection(&This->cs);
4263 return hr;
4266 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
4267 long *pHeight) {
4268 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4269 IVideoWindow* pVideoWindow;
4270 HRESULT hr;
4272 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4274 EnterCriticalSection(&This->cs);
4276 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4278 if (hr == S_OK)
4279 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4281 LeaveCriticalSection(&This->cs);
4283 return hr;
4286 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
4287 OAHWND Owner) {
4288 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4289 IVideoWindow* pVideoWindow;
4290 HRESULT hr;
4292 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4294 EnterCriticalSection(&This->cs);
4296 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4298 if (hr == S_OK)
4299 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4301 LeaveCriticalSection(&This->cs);
4303 return hr;
4306 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
4307 OAHWND *Owner) {
4308 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4309 IVideoWindow* pVideoWindow;
4310 HRESULT hr;
4312 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4314 EnterCriticalSection(&This->cs);
4316 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4318 if (hr == S_OK)
4319 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4321 LeaveCriticalSection(&This->cs);
4323 return hr;
4326 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
4327 OAHWND Drain) {
4328 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4329 IVideoWindow* pVideoWindow;
4330 HRESULT hr;
4332 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4334 EnterCriticalSection(&This->cs);
4336 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4338 if (hr == S_OK)
4339 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4341 LeaveCriticalSection(&This->cs);
4343 return hr;
4346 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
4347 OAHWND *Drain) {
4348 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4349 IVideoWindow* pVideoWindow;
4350 HRESULT hr;
4352 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4354 EnterCriticalSection(&This->cs);
4356 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4358 if (hr == S_OK)
4359 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4361 LeaveCriticalSection(&This->cs);
4363 return hr;
4366 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
4367 long *Color) {
4368 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4369 IVideoWindow* pVideoWindow;
4370 HRESULT hr;
4372 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4374 EnterCriticalSection(&This->cs);
4376 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4378 if (hr == S_OK)
4379 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4381 LeaveCriticalSection(&This->cs);
4383 return hr;
4386 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
4387 long Color) {
4388 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4389 IVideoWindow* pVideoWindow;
4390 HRESULT hr;
4392 TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
4394 EnterCriticalSection(&This->cs);
4396 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4398 if (hr == S_OK)
4399 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4401 LeaveCriticalSection(&This->cs);
4403 return hr;
4406 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
4407 long *FullScreenMode) {
4408 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4409 IVideoWindow* pVideoWindow;
4410 HRESULT hr;
4412 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4414 EnterCriticalSection(&This->cs);
4416 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4418 if (hr == S_OK)
4419 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4421 LeaveCriticalSection(&This->cs);
4423 return hr;
4426 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
4427 long FullScreenMode) {
4428 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4429 IVideoWindow* pVideoWindow;
4430 HRESULT hr;
4432 TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
4434 EnterCriticalSection(&This->cs);
4436 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4438 if (hr == S_OK)
4439 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4441 LeaveCriticalSection(&This->cs);
4443 return hr;
4446 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
4447 long Focus) {
4448 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4449 IVideoWindow* pVideoWindow;
4450 HRESULT hr;
4452 TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
4454 EnterCriticalSection(&This->cs);
4456 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4458 if (hr == S_OK)
4459 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4461 LeaveCriticalSection(&This->cs);
4463 return hr;
4466 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
4467 OAHWND hwnd,
4468 long uMsg,
4469 LONG_PTR wParam,
4470 LONG_PTR lParam) {
4471 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4472 IVideoWindow* pVideoWindow;
4473 HRESULT hr;
4475 TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
4477 EnterCriticalSection(&This->cs);
4479 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4481 if (hr == S_OK)
4482 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4484 LeaveCriticalSection(&This->cs);
4486 return hr;
4489 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
4490 long Left,
4491 long Top,
4492 long Width,
4493 long Height) {
4494 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4495 IVideoWindow* pVideoWindow;
4496 HRESULT hr;
4498 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
4500 EnterCriticalSection(&This->cs);
4502 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4504 if (hr == S_OK)
4505 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4507 LeaveCriticalSection(&This->cs);
4509 return hr;
4512 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
4513 long *pLeft,
4514 long *pTop,
4515 long *pWidth,
4516 long *pHeight) {
4517 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4518 IVideoWindow* pVideoWindow;
4519 HRESULT hr;
4521 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4523 EnterCriticalSection(&This->cs);
4525 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4527 if (hr == S_OK)
4528 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4530 LeaveCriticalSection(&This->cs);
4532 return hr;
4535 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
4536 long *pWidth,
4537 long *pHeight) {
4538 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4539 IVideoWindow* pVideoWindow;
4540 HRESULT hr;
4542 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4544 EnterCriticalSection(&This->cs);
4546 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4548 if (hr == S_OK)
4549 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4551 LeaveCriticalSection(&This->cs);
4553 return hr;
4556 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
4557 long *pWidth,
4558 long *pHeight) {
4559 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4560 IVideoWindow* pVideoWindow;
4561 HRESULT hr;
4563 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4565 EnterCriticalSection(&This->cs);
4567 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4569 if (hr == S_OK)
4570 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4572 LeaveCriticalSection(&This->cs);
4574 return hr;
4577 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
4578 long *pLeft,
4579 long *pTop,
4580 long *pWidth,
4581 long *pHeight) {
4582 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4583 IVideoWindow* pVideoWindow;
4584 HRESULT hr;
4586 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4588 EnterCriticalSection(&This->cs);
4590 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4592 if (hr == S_OK)
4593 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4595 LeaveCriticalSection(&This->cs);
4597 return hr;
4600 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
4601 long HideCursor) {
4602 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4603 IVideoWindow* pVideoWindow;
4604 HRESULT hr;
4606 TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
4608 EnterCriticalSection(&This->cs);
4610 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4612 if (hr == S_OK)
4613 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4615 LeaveCriticalSection(&This->cs);
4617 return hr;
4620 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
4621 long *CursorHidden) {
4622 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4623 IVideoWindow* pVideoWindow;
4624 HRESULT hr;
4626 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4628 EnterCriticalSection(&This->cs);
4630 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4632 if (hr == S_OK)
4633 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4635 LeaveCriticalSection(&This->cs);
4637 return hr;
4641 static const IVideoWindowVtbl IVideoWindow_VTable =
4643 VideoWindow_QueryInterface,
4644 VideoWindow_AddRef,
4645 VideoWindow_Release,
4646 VideoWindow_GetTypeInfoCount,
4647 VideoWindow_GetTypeInfo,
4648 VideoWindow_GetIDsOfNames,
4649 VideoWindow_Invoke,
4650 VideoWindow_put_Caption,
4651 VideoWindow_get_Caption,
4652 VideoWindow_put_WindowStyle,
4653 VideoWindow_get_WindowStyle,
4654 VideoWindow_put_WindowStyleEx,
4655 VideoWindow_get_WindowStyleEx,
4656 VideoWindow_put_AutoShow,
4657 VideoWindow_get_AutoShow,
4658 VideoWindow_put_WindowState,
4659 VideoWindow_get_WindowState,
4660 VideoWindow_put_BackgroundPalette,
4661 VideoWindow_get_BackgroundPalette,
4662 VideoWindow_put_Visible,
4663 VideoWindow_get_Visible,
4664 VideoWindow_put_Left,
4665 VideoWindow_get_Left,
4666 VideoWindow_put_Width,
4667 VideoWindow_get_Width,
4668 VideoWindow_put_Top,
4669 VideoWindow_get_Top,
4670 VideoWindow_put_Height,
4671 VideoWindow_get_Height,
4672 VideoWindow_put_Owner,
4673 VideoWindow_get_Owner,
4674 VideoWindow_put_MessageDrain,
4675 VideoWindow_get_MessageDrain,
4676 VideoWindow_get_BorderColor,
4677 VideoWindow_put_BorderColor,
4678 VideoWindow_get_FullScreenMode,
4679 VideoWindow_put_FullScreenMode,
4680 VideoWindow_SetWindowForeground,
4681 VideoWindow_NotifyOwnerMessage,
4682 VideoWindow_SetWindowPosition,
4683 VideoWindow_GetWindowPosition,
4684 VideoWindow_GetMinIdealImageSize,
4685 VideoWindow_GetMaxIdealImageSize,
4686 VideoWindow_GetRestorePosition,
4687 VideoWindow_HideCursor,
4688 VideoWindow_IsCursorHidden
4692 /*** IUnknown methods ***/
4693 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
4694 REFIID riid,
4695 LPVOID*ppvObj) {
4696 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4698 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4700 return Filtergraph_QueryInterface(This, riid, ppvObj);
4703 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
4704 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4706 TRACE("(%p/%p)->()\n", This, iface);
4708 return Filtergraph_AddRef(This);
4711 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
4712 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4714 TRACE("(%p/%p)->()\n", This, iface);
4716 return Filtergraph_Release(This);
4719 /*** IDispatch methods ***/
4720 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4721 UINT*pctinfo) {
4722 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4724 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4726 return S_OK;
4729 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4730 UINT iTInfo,
4731 LCID lcid,
4732 ITypeInfo**ppTInfo) {
4733 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4735 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4737 return S_OK;
4740 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4741 REFIID riid,
4742 LPOLESTR*rgszNames,
4743 UINT cNames,
4744 LCID lcid,
4745 DISPID*rgDispId) {
4746 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4748 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4750 return S_OK;
4753 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4754 DISPID dispIdMember,
4755 REFIID riid,
4756 LCID lcid,
4757 WORD wFlags,
4758 DISPPARAMS*pDispParams,
4759 VARIANT*pVarResult,
4760 EXCEPINFO*pExepInfo,
4761 UINT*puArgErr) {
4762 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4764 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);
4766 return S_OK;
4769 /*** IMediaEvent methods ***/
4770 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4771 OAEVENT *hEvent) {
4772 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4774 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4776 *hEvent = (OAEVENT)This->evqueue.msg_event;
4778 return S_OK;
4781 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4782 long *lEventCode,
4783 LONG_PTR *lParam1,
4784 LONG_PTR *lParam2,
4785 long msTimeout) {
4786 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4787 Event evt;
4789 TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4791 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4793 *lEventCode = evt.lEventCode;
4794 *lParam1 = evt.lParam1;
4795 *lParam2 = evt.lParam2;
4796 return S_OK;
4799 *lEventCode = 0;
4800 return E_ABORT;
4803 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4804 long msTimeout,
4805 long *pEvCode) {
4806 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4808 TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4810 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4812 *pEvCode = This->CompletionStatus;
4813 return S_OK;
4816 *pEvCode = 0;
4817 return E_ABORT;
4820 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4821 long lEvCode) {
4822 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4824 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4826 if (lEvCode == EC_COMPLETE)
4827 This->HandleEcComplete = FALSE;
4828 else if (lEvCode == EC_REPAINT)
4829 This->HandleEcRepaint = FALSE;
4830 else if (lEvCode == EC_CLOCK_CHANGED)
4831 This->HandleEcClockChanged = FALSE;
4832 else
4833 return S_FALSE;
4835 return S_OK;
4838 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4839 long lEvCode) {
4840 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4842 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4844 if (lEvCode == EC_COMPLETE)
4845 This->HandleEcComplete = TRUE;
4846 else if (lEvCode == EC_REPAINT)
4847 This->HandleEcRepaint = TRUE;
4848 else if (lEvCode == EC_CLOCK_CHANGED)
4849 This->HandleEcClockChanged = TRUE;
4850 else
4851 return S_FALSE;
4853 return S_OK;
4856 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4857 long lEvCode,
4858 LONG_PTR lParam1,
4859 LONG_PTR lParam2) {
4860 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4862 TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4864 return S_OK;
4867 /*** IMediaEventEx methods ***/
4868 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4869 OAHWND hwnd,
4870 long lMsg,
4871 LONG_PTR lInstanceData) {
4872 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4874 TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4876 This->notif.hWnd = (HWND)hwnd;
4877 This->notif.msg = lMsg;
4878 This->notif.instance = (long) lInstanceData;
4880 return S_OK;
4883 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4884 long lNoNotifyFlags) {
4885 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4887 TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4889 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4890 return E_INVALIDARG;
4892 This->notif.disabled = lNoNotifyFlags;
4894 return S_OK;
4897 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4898 long *lplNoNotifyFlags) {
4899 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4901 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4903 if (!lplNoNotifyFlags)
4904 return E_POINTER;
4906 *lplNoNotifyFlags = This->notif.disabled;
4908 return S_OK;
4912 static const IMediaEventExVtbl IMediaEventEx_VTable =
4914 MediaEvent_QueryInterface,
4915 MediaEvent_AddRef,
4916 MediaEvent_Release,
4917 MediaEvent_GetTypeInfoCount,
4918 MediaEvent_GetTypeInfo,
4919 MediaEvent_GetIDsOfNames,
4920 MediaEvent_Invoke,
4921 MediaEvent_GetEventHandle,
4922 MediaEvent_GetEvent,
4923 MediaEvent_WaitForCompletion,
4924 MediaEvent_CancelDefaultHandling,
4925 MediaEvent_RestoreDefaultHandling,
4926 MediaEvent_FreeEventParams,
4927 MediaEvent_SetNotifyWindow,
4928 MediaEvent_SetNotifyFlags,
4929 MediaEvent_GetNotifyFlags
4933 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4935 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4937 return Filtergraph_QueryInterface(This, riid, ppv);
4940 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4942 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4944 return Filtergraph_AddRef(This);
4947 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4949 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4951 return Filtergraph_Release(This);
4954 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4956 FIXME("(%p): stub\n", pClassID);
4958 return E_NOTIMPL;
4961 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
4963 FIXME("(): stub\n");
4965 return E_NOTIMPL;
4968 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
4970 FIXME("(): stub\n");
4972 return E_NOTIMPL;
4975 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
4977 FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
4979 return E_NOTIMPL;
4982 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
4984 FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
4986 return E_NOTIMPL;
4989 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
4991 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4992 HRESULT hr = S_OK;
4993 int i;
4995 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
4997 EnterCriticalSection(&This->cs);
4999 for (i = 0;i < This->nFilters;i++)
5001 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5002 if (FAILED(hr))
5003 break;
5006 if (FAILED(hr))
5008 for(;i >= 0;i--)
5009 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5011 else
5013 if (This->refClock)
5014 IReferenceClock_Release(This->refClock);
5015 This->refClock = pClock;
5016 if (This->refClock)
5017 IReferenceClock_AddRef(This->refClock);
5019 if (This->HandleEcClockChanged)
5021 IMediaEventSink *pEventSink;
5022 HRESULT eshr;
5024 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5025 if (SUCCEEDED(eshr))
5027 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5028 IMediaEventSink_Release(pEventSink);
5033 LeaveCriticalSection(&This->cs);
5035 return hr;
5038 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5040 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
5042 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5044 if (!ppClock)
5045 return E_POINTER;
5047 EnterCriticalSection(&This->cs);
5049 *ppClock = This->refClock;
5050 if (*ppClock)
5051 IReferenceClock_AddRef(*ppClock);
5053 LeaveCriticalSection(&This->cs);
5055 return S_OK;
5058 static const IMediaFilterVtbl IMediaFilter_VTable =
5060 MediaFilter_QueryInterface,
5061 MediaFilter_AddRef,
5062 MediaFilter_Release,
5063 MediaFilter_GetClassID,
5064 MediaFilter_Stop,
5065 MediaFilter_Pause,
5066 MediaFilter_Run,
5067 MediaFilter_GetState,
5068 MediaFilter_SetSyncSource,
5069 MediaFilter_GetSyncSource
5072 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
5074 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5076 return Filtergraph_QueryInterface(This, riid, ppv);
5079 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5081 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5083 return Filtergraph_AddRef(This);
5086 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5088 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5090 return Filtergraph_Release(This);
5093 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
5095 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5096 Event evt;
5098 TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5100 /* We need thread safety here, let's use the events queue's one */
5101 EnterCriticalSection(&This->evqueue.msg_crst);
5103 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5105 TRACE("Process EC_COMPLETE notification\n");
5106 if (++This->EcCompleteCount == This->nRenderers)
5108 evt.lEventCode = EC_COMPLETE;
5109 evt.lParam1 = S_OK;
5110 evt.lParam2 = 0;
5111 TRACE("Send EC_COMPLETE to app\n");
5112 EventsQueue_PutEvent(&This->evqueue, &evt);
5113 if (!This->notif.disabled && This->notif.hWnd)
5115 TRACE("Send Window message\n");
5116 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5118 This->CompletionStatus = EC_COMPLETE;
5119 SetEvent(This->hEventCompletion);
5122 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5124 /* FIXME: Not handled yet */
5126 else
5128 evt.lEventCode = EventCode;
5129 evt.lParam1 = EventParam1;
5130 evt.lParam2 = EventParam2;
5131 EventsQueue_PutEvent(&This->evqueue, &evt);
5132 if (!This->notif.disabled && This->notif.hWnd)
5133 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5136 LeaveCriticalSection(&This->evqueue.msg_crst);
5137 return S_OK;
5140 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5142 MediaEventSink_QueryInterface,
5143 MediaEventSink_AddRef,
5144 MediaEventSink_Release,
5145 MediaEventSink_Notify
5148 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
5150 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5152 return Filtergraph_QueryInterface(This, riid, ppv);
5155 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5157 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5159 return Filtergraph_AddRef(This);
5162 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5164 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5166 return Filtergraph_Release(This);
5169 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
5170 IPin* pOutputPin,
5171 IPin* pInputPin,
5172 const AM_MEDIA_TYPE* pmtFirstConnection,
5173 IBaseFilter* pUsingFilter,
5174 HANDLE hAbortEvent,
5175 DWORD dwFlags)
5177 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5179 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5181 return E_NOTIMPL;
5184 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
5185 IGraphConfigCallback* pCallback,
5186 PVOID pvContext,
5187 DWORD dwFlags,
5188 HANDLE hAbortEvent)
5190 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5191 HRESULT hr;
5193 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5195 if (hAbortEvent)
5196 FIXME("The parameter hAbortEvent is not handled!\n");
5198 EnterCriticalSection(&This->cs);
5200 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5202 LeaveCriticalSection(&This->cs);
5204 return hr;
5207 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
5208 IBaseFilter* pFilter)
5210 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5212 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5214 return E_NOTIMPL;
5217 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
5218 IEnumFilters** pEnum)
5220 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5222 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5224 return E_NOTIMPL;
5227 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
5228 IBaseFilter* pFilter)
5230 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5232 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5234 return E_NOTIMPL;
5237 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
5238 REFERENCE_TIME* prtStart)
5240 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5242 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5244 return E_NOTIMPL;
5247 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
5248 IPin* pOutputPin,
5249 IPinConnection* pConnection,
5250 HANDLE hEventAbort)
5252 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5254 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5256 return E_NOTIMPL;
5259 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
5260 IBaseFilter* pFilter,
5261 DWORD dwFlags)
5263 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5265 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5267 return E_NOTIMPL;
5270 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
5271 IBaseFilter* pFilter,
5272 DWORD* dwFlags)
5274 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5276 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5278 return E_NOTIMPL;
5281 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
5282 IBaseFilter* pFilter,
5283 DWORD dwFlags)
5285 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5287 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5289 return E_NOTIMPL;
5292 static const IGraphConfigVtbl IGraphConfig_VTable =
5294 GraphConfig_QueryInterface,
5295 GraphConfig_AddRef,
5296 GraphConfig_Release,
5297 GraphConfig_Reconnect,
5298 GraphConfig_Reconfigure,
5299 GraphConfig_AddFilterToCache,
5300 GraphConfig_EnumCacheFilter,
5301 GraphConfig_RemoveFilterFromCache,
5302 GraphConfig_GetStartTime,
5303 GraphConfig_PushThroughData,
5304 GraphConfig_SetFilterFlags,
5305 GraphConfig_GetFilterFlags,
5306 GraphConfig_RemoveFilterEx
5309 static const IUnknownVtbl IInner_VTable =
5311 FilterGraphInner_QueryInterface,
5312 FilterGraphInner_AddRef,
5313 FilterGraphInner_Release
5316 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
5317 REFIID riid,
5318 LPVOID * ppv) {
5319 if (This->bAggregatable)
5320 This->bUnkOuterValid = TRUE;
5322 if (This->pUnkOuter)
5324 if (This->bAggregatable)
5325 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
5327 if (IsEqualIID(riid, &IID_IUnknown))
5329 HRESULT hr;
5331 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5332 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5333 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5334 This->bAggregatable = TRUE;
5335 return hr;
5338 *ppv = NULL;
5339 return E_NOINTERFACE;
5342 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5345 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This) {
5346 if (This->pUnkOuter && This->bUnkOuterValid)
5347 return IUnknown_AddRef(This->pUnkOuter);
5348 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5351 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This) {
5352 if (This->pUnkOuter && This->bUnkOuterValid)
5353 return IUnknown_Release(This->pUnkOuter);
5354 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5357 /* This is the only function that actually creates a FilterGraph class... */
5358 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5360 IFilterGraphImpl *fimpl;
5361 HRESULT hr;
5363 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5365 *ppObj = NULL;
5367 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5368 fimpl->pUnkOuter = pUnkOuter;
5369 fimpl->bUnkOuterValid = FALSE;
5370 fimpl->bAggregatable = FALSE;
5371 fimpl->IInner_vtbl = &IInner_VTable;
5372 fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable;
5373 fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
5374 fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
5375 fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
5376 fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
5377 fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
5378 fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
5379 fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
5380 fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
5381 fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
5382 fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
5383 fimpl->ref = 1;
5384 fimpl->ppFiltersInGraph = NULL;
5385 fimpl->pFilterNames = NULL;
5386 fimpl->nFilters = 0;
5387 fimpl->filterCapacity = 0;
5388 fimpl->nameIndex = 1;
5389 fimpl->refClock = NULL;
5390 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5391 fimpl->HandleEcComplete = TRUE;
5392 fimpl->HandleEcRepaint = TRUE;
5393 fimpl->HandleEcClockChanged = TRUE;
5394 fimpl->notif.hWnd = 0;
5395 fimpl->notif.disabled = FALSE;
5396 fimpl->nRenderers = 0;
5397 fimpl->EcCompleteCount = 0;
5398 fimpl->state = State_Stopped;
5399 EventsQueue_Init(&fimpl->evqueue);
5400 InitializeCriticalSection(&fimpl->cs);
5401 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5402 fimpl->nItfCacheEntries = 0;
5403 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5404 fimpl->start_time = fimpl->position = 0;
5405 fimpl->stop_position = -1;
5407 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
5408 if (FAILED(hr)) {
5409 ERR("Unable to create filter mapper (%x)\n", hr);
5410 return hr;
5412 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
5414 *ppObj = fimpl;
5415 return S_OK;
5418 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5420 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5421 return FilterGraph_create(pUnkOuter, ppObj);