Release 1.5.13.
[wine.git] / dlls / quartz / filtergraph.c
blob239cf0bbd24e397f8120d67ad943d922dcf2fbb9
1 /* DirectShow FilterGraph object (QUARTZ.DLL)
3 * Copyright 2002 Lionel Ulmer
4 * Copyright 2004 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdarg.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "shlwapi.h"
31 #include "dshow.h"
32 #include "wine/debug.h"
33 #include "quartz_private.h"
34 #include "ole2.h"
35 #include "olectl.h"
36 #include "strmif.h"
37 #include "vfwmsgs.h"
38 #include "evcode.h"
39 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
44 typedef struct {
45 HWND hWnd; /* Target window */
46 UINT msg; /* User window message */
47 LONG_PTR instance; /* User data */
48 int disabled; /* Disabled messages posting */
49 } WndNotify;
51 typedef struct {
52 LONG lEventCode; /* Event code */
53 LONG_PTR lParam1; /* Param1 */
54 LONG_PTR lParam2; /* Param2 */
55 } Event;
57 /* messages ring implementation for queuing events (taken from winmm) */
58 #define EVENTS_RING_BUFFER_INCREMENT 64
59 typedef struct {
60 Event* messages;
61 int ring_buffer_size;
62 int msg_tosave;
63 int msg_toget;
64 CRITICAL_SECTION msg_crst;
65 HANDLE msg_event; /* Signaled for no empty queue */
66 } EventsQueue;
68 static int EventsQueue_Init(EventsQueue* omr)
70 omr->msg_toget = 0;
71 omr->msg_tosave = 0;
72 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
73 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
74 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
75 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
77 InitializeCriticalSection(&omr->msg_crst);
78 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
79 return TRUE;
82 static int EventsQueue_Destroy(EventsQueue* omr)
84 CloseHandle(omr->msg_event);
85 CoTaskMemFree(omr->messages);
86 omr->msg_crst.DebugInfo->Spare[0] = 0;
87 DeleteCriticalSection(&omr->msg_crst);
88 return TRUE;
91 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
93 EnterCriticalSection(&omr->msg_crst);
94 if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))
96 int old_ring_buffer_size = omr->ring_buffer_size;
97 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
98 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
99 omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event));
100 /* Now we need to rearrange the ring buffer so that the new
101 buffers just allocated are in between omr->msg_tosave and
102 omr->msg_toget.
104 if (omr->msg_tosave < omr->msg_toget)
106 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
107 &(omr->messages[omr->msg_toget]),
108 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
110 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
113 omr->messages[omr->msg_tosave] = *evt;
114 SetEvent(omr->msg_event);
115 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
116 LeaveCriticalSection(&omr->msg_crst);
117 return TRUE;
120 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
122 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
123 return FALSE;
125 EnterCriticalSection(&omr->msg_crst);
127 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
129 LeaveCriticalSection(&omr->msg_crst);
130 return FALSE;
133 *evt = omr->messages[omr->msg_toget];
134 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
136 /* Mark the buffer as empty if needed */
137 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
138 ResetEvent(omr->msg_event);
140 LeaveCriticalSection(&omr->msg_crst);
141 return TRUE;
144 #define MAX_ITF_CACHE_ENTRIES 3
145 typedef struct _ITF_CACHE_ENTRY {
146 const IID* riid;
147 IBaseFilter* filter;
148 IUnknown* iface;
149 } ITF_CACHE_ENTRY;
151 typedef struct _IFilterGraphImpl {
152 IUnknown IUnknown_inner;
153 IFilterGraph2 IFilterGraph2_iface;
154 IMediaControl IMediaControl_iface;
155 IMediaSeeking IMediaSeeking_iface;
156 IBasicAudio IBasicAudio_iface;
157 IBasicVideo2 IBasicVideo2_iface;
158 IVideoWindow IVideoWindow_iface;
159 IMediaEventEx IMediaEventEx_iface;
160 IMediaFilter IMediaFilter_iface;
161 IMediaEventSink IMediaEventSink_iface;
162 IGraphConfig IGraphConfig_iface;
163 IMediaPosition IMediaPosition_iface;
164 IObjectWithSite IObjectWithSite_iface;
165 /* IAMGraphStreams */
166 /* IAMStats */
167 /* IFilterChain */
168 /* IFilterMapper2 */
169 /* IGraphVersion */
170 /* IQueueCommand */
171 /* IRegisterServiceProvider */
172 /* IResourceMananger */
173 /* IServiceProvider */
174 /* IVideoFrameStep */
176 IUnknown *outer_unk;
177 LONG ref;
178 IUnknown *punkFilterMapper2;
179 IFilterMapper2 * pFilterMapper2;
180 IBaseFilter ** ppFiltersInGraph;
181 LPWSTR * pFilterNames;
182 int nFilters;
183 int filterCapacity;
184 LONG nameIndex;
185 IReferenceClock *refClock;
186 IBaseFilter *refClockProvider;
187 EventsQueue evqueue;
188 HANDLE hEventCompletion;
189 int CompletionStatus;
190 WndNotify notif;
191 int nRenderers;
192 int EcCompleteCount;
193 int HandleEcComplete;
194 int HandleEcRepaint;
195 int HandleEcClockChanged;
196 OAFilterState state;
197 CRITICAL_SECTION cs;
198 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
199 int nItfCacheEntries;
200 BOOL defaultclock;
201 GUID timeformatseek;
202 REFERENCE_TIME start_time;
203 REFERENCE_TIME pause_time;
204 LONGLONG stop_position;
205 LONG recursioncount;
206 IUnknown *pSite;
207 } IFilterGraphImpl;
209 static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface)
211 return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner);
214 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObj)
216 IFilterGraphImpl *This = impl_from_IUnknown(iface);
217 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
219 if (IsEqualGUID(&IID_IUnknown, riid)) {
220 *ppvObj = &This->IUnknown_inner;
221 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
222 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
223 IsEqualGUID(&IID_IFilterGraph2, riid) ||
224 IsEqualGUID(&IID_IGraphBuilder, riid)) {
225 *ppvObj = &This->IFilterGraph2_iface;
226 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
227 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
228 *ppvObj = &This->IMediaControl_iface;
229 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
230 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
231 *ppvObj = &This->IMediaSeeking_iface;
232 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
233 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
234 *ppvObj = &This->IBasicAudio_iface;
235 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
236 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
237 IsEqualGUID(&IID_IBasicVideo2, riid)) {
238 *ppvObj = &This->IBasicVideo2_iface;
239 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
240 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
241 *ppvObj = &This->IVideoWindow_iface;
242 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
243 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
244 IsEqualGUID(&IID_IMediaEventEx, riid)) {
245 *ppvObj = &This->IMediaEventEx_iface;
246 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
247 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
248 IsEqualGUID(&IID_IPersist, riid)) {
249 *ppvObj = &This->IMediaFilter_iface;
250 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
251 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
252 *ppvObj = &This->IMediaEventSink_iface;
253 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
254 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
255 *ppvObj = &This->IGraphConfig_iface;
256 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
257 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
258 *ppvObj = &This->IMediaPosition_iface;
259 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
260 } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) {
261 *ppvObj = &This->IObjectWithSite_iface;
262 TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj);
263 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
264 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
265 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
266 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
267 *ppvObj = This->pFilterMapper2;
268 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
269 } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
270 *ppvObj = This->pFilterMapper2;
271 TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
272 } else {
273 *ppvObj = NULL;
274 FIXME("unknown interface %s\n", debugstr_guid(riid));
275 return E_NOINTERFACE;
278 IUnknown_AddRef((IUnknown *)*ppvObj);
279 return S_OK;
282 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown *iface)
284 IFilterGraphImpl *This = impl_from_IUnknown(iface);
285 ULONG ref = InterlockedIncrement(&This->ref);
287 TRACE("(%p)->(): new ref = %d\n", This, ref);
289 return ref;
292 static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
294 IFilterGraphImpl *This = impl_from_IUnknown(iface);
295 ULONG ref = InterlockedDecrement(&This->ref);
297 TRACE("(%p)->(): new ref = %d\n", This, ref);
299 if (ref == 0) {
300 int i;
302 This->ref = 1; /* guard against reentrancy (aggregation). */
304 IMediaControl_Stop(&This->IMediaControl_iface);
306 while (This->nFilters)
307 IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, This->ppFiltersInGraph[0]);
309 if (This->refClock)
310 IReferenceClock_Release(This->refClock);
312 for (i = 0; i < This->nItfCacheEntries; i++)
314 if (This->ItfCacheEntries[i].iface)
315 IUnknown_Release(This->ItfCacheEntries[i].iface);
318 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 */
319 IUnknown_AddRef(This->outer_unk);
320 IFilterMapper2_Release(This->pFilterMapper2);
321 IUnknown_Release(This->punkFilterMapper2);
323 if (This->pSite) IUnknown_Release(This->pSite);
325 CloseHandle(This->hEventCompletion);
326 EventsQueue_Destroy(&This->evqueue);
327 This->cs.DebugInfo->Spare[0] = 0;
328 DeleteCriticalSection(&This->cs);
329 CoTaskMemFree(This->ppFiltersInGraph);
330 CoTaskMemFree(This->pFilterNames);
331 CoTaskMemFree(This);
333 return ref;
336 static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface)
338 return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface);
341 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj)
343 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
345 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
347 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
350 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface)
352 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
354 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
356 return IUnknown_AddRef(This->outer_unk);
359 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
361 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
363 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
365 return IUnknown_Release(This->outer_unk);
368 /*** IFilterGraph methods ***/
369 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
370 LPCWSTR pName)
372 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
373 HRESULT hr;
374 int i,j;
375 WCHAR* wszFilterName = NULL;
376 int duplicate_name = FALSE;
378 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
380 if (!pFilter)
381 return E_POINTER;
383 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
385 if (pName)
387 /* Check if name already exists */
388 for(i = 0; i < This->nFilters; i++)
389 if (!strcmpW(This->pFilterNames[i], pName))
391 duplicate_name = TRUE;
392 break;
396 /* If no name given or name already existing, generate one */
397 if (!pName || duplicate_name)
399 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
400 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
402 for (j = 0; j < 10000 ; j++)
404 /* Create name */
405 if (pName)
406 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
407 else
408 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
409 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
411 /* Check if the generated name already exists */
412 for(i = 0; i < This->nFilters; i++)
413 if (!strcmpW(This->pFilterNames[i], wszFilterName))
414 break;
416 /* Compute next index and exit if generated name is suitable */
417 if (This->nameIndex++ == 10000)
418 This->nameIndex = 1;
419 if (i == This->nFilters)
420 break;
422 /* Unable to find a suitable name */
423 if (j == 10000)
425 CoTaskMemFree(wszFilterName);
426 return VFW_E_DUPLICATE_NAME;
429 else
430 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
432 if (This->nFilters + 1 > This->filterCapacity)
434 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
435 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
436 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
437 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
438 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
439 if (This->filterCapacity)
441 CoTaskMemFree(This->ppFiltersInGraph);
442 CoTaskMemFree(This->pFilterNames);
444 This->ppFiltersInGraph = ppNewFilters;
445 This->pFilterNames = pNewNames;
446 This->filterCapacity = newCapacity;
449 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
451 if (SUCCEEDED(hr))
453 IBaseFilter_AddRef(pFilter);
454 This->ppFiltersInGraph[This->nFilters] = pFilter;
455 This->pFilterNames[This->nFilters] = wszFilterName;
456 This->nFilters++;
457 IBaseFilter_SetSyncSource(pFilter, This->refClock);
459 else
460 CoTaskMemFree(wszFilterName);
462 if (SUCCEEDED(hr) && duplicate_name)
463 return VFW_S_DUPLICATE_NAME;
465 return hr;
468 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
470 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
471 int i;
472 HRESULT hr = E_FAIL;
474 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
476 /* FIXME: check graph is stopped */
478 for (i = 0; i < This->nFilters; i++)
480 if (This->ppFiltersInGraph[i] == pFilter)
482 IEnumPins *penumpins = NULL;
483 FILTER_STATE state;
485 if (This->defaultclock && This->refClockProvider == pFilter)
487 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
488 This->defaultclock = 1;
491 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
492 IBaseFilter_GetState(pFilter, 0, &state);
493 if (state == State_Running)
494 IBaseFilter_Pause(pFilter);
495 if (state != State_Stopped)
496 IBaseFilter_Stop(pFilter);
498 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
499 if (SUCCEEDED(hr)) {
500 IPin *ppin;
501 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
503 IPin *victim = NULL;
504 HRESULT h;
505 IPin_ConnectedTo(ppin, &victim);
506 if (victim)
508 h = IPin_Disconnect(victim);
509 TRACE("Disconnect other side: %08x\n", h);
510 if (h == VFW_E_NOT_STOPPED)
512 PIN_INFO pinfo;
513 IPin_QueryPinInfo(victim, &pinfo);
515 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
516 if (state == State_Running)
517 IBaseFilter_Pause(pinfo.pFilter);
518 IBaseFilter_Stop(pinfo.pFilter);
519 IBaseFilter_Release(pinfo.pFilter);
520 h = IPin_Disconnect(victim);
521 TRACE("Disconnect retry: %08x\n", h);
523 IPin_Release(victim);
525 h = IPin_Disconnect(ppin);
526 TRACE("Disconnect 2: %08x\n", h);
528 IPin_Release(ppin);
530 IEnumPins_Release(penumpins);
533 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
534 if (SUCCEEDED(hr))
536 IBaseFilter_SetSyncSource(pFilter, NULL);
537 IBaseFilter_Release(pFilter);
538 CoTaskMemFree(This->pFilterNames[i]);
539 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
540 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
541 This->nFilters--;
542 /* Invalidate interfaces in the cache */
543 for (i = 0; i < This->nItfCacheEntries; i++)
544 if (pFilter == This->ItfCacheEntries[i].filter)
546 IUnknown_Release(This->ItfCacheEntries[i].iface);
547 This->ItfCacheEntries[i].iface = NULL;
548 This->ItfCacheEntries[i].filter = NULL;
550 return S_OK;
552 break;
556 return hr; /* FIXME: check this error code */
559 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum)
561 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
563 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
565 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
568 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName,
569 IBaseFilter **ppFilter)
571 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
572 int i;
574 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
576 if (!ppFilter)
577 return E_POINTER;
579 for (i = 0; i < This->nFilters; i++)
581 if (!strcmpW(pName, This->pFilterNames[i]))
583 *ppFilter = This->ppFiltersInGraph[i];
584 IBaseFilter_AddRef(*ppFilter);
585 return S_OK;
589 *ppFilter = NULL;
590 return VFW_E_NOT_FOUND;
593 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
594 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
596 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
598 #if 1
599 HRESULT hr;
600 PIN_INFO info_out, info_in;
602 hr = IPin_QueryPinInfo(out, &info_out);
603 if (FAILED(hr))
604 return hr;
605 if (info_out.dir != PINDIR_OUTPUT)
607 IBaseFilter_Release(info_out.pFilter);
608 return E_UNEXPECTED;
611 hr = IPin_QueryPinInfo(in, &info_in);
612 if (SUCCEEDED(hr))
613 IBaseFilter_Release(info_in.pFilter);
614 if (FAILED(hr))
615 goto out;
616 if (info_in.dir != PINDIR_INPUT)
618 hr = E_UNEXPECTED;
619 goto out;
622 if (info_out.pFilter == info_in.pFilter)
623 hr = VFW_E_CIRCULAR_GRAPH;
624 else
626 IEnumPins *enumpins;
627 IPin *test;
629 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
630 if (FAILED(hr))
631 goto out;
633 IEnumPins_Reset(enumpins);
634 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
636 PIN_DIRECTION dir = PINDIR_OUTPUT;
637 IPin_QueryDirection(test, &dir);
638 if (dir == PINDIR_INPUT)
640 IPin *victim = NULL;
641 IPin_ConnectedTo(test, &victim);
642 if (victim)
644 hr = CheckCircularConnection(This, victim, in);
645 IPin_Release(victim);
646 if (FAILED(hr))
648 IPin_Release(test);
649 break;
653 IPin_Release(test);
655 IEnumPins_Release(enumpins);
658 out:
659 IBaseFilter_Release(info_out.pFilter);
660 if (FAILED(hr))
661 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
662 return hr;
663 #else
664 /* Debugging filtergraphs not enabled */
665 return S_OK;
666 #endif
670 /* NOTE: despite the implication, it doesn't matter which
671 * way round you put in the input and output pins */
672 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut,
673 const AM_MEDIA_TYPE *pmt)
675 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
676 PIN_DIRECTION dir;
677 HRESULT hr;
679 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
681 /* FIXME: check pins are in graph */
683 if (TRACE_ON(quartz))
685 PIN_INFO PinInfo;
687 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
688 if (FAILED(hr))
689 return hr;
691 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
692 IBaseFilter_Release(PinInfo.pFilter);
694 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
695 if (FAILED(hr))
696 return hr;
698 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
699 IBaseFilter_Release(PinInfo.pFilter);
702 hr = IPin_QueryDirection(ppinIn, &dir);
703 if (SUCCEEDED(hr))
705 if (dir == PINDIR_INPUT)
707 hr = CheckCircularConnection(This, ppinOut, ppinIn);
708 if (SUCCEEDED(hr))
709 hr = IPin_Connect(ppinOut, ppinIn, pmt);
711 else
713 hr = CheckCircularConnection(This, ppinIn, ppinOut);
714 if (SUCCEEDED(hr))
715 hr = IPin_Connect(ppinIn, ppinOut, pmt);
719 return hr;
722 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin)
724 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
725 IPin *pConnectedTo = NULL;
726 HRESULT hr;
727 PIN_DIRECTION pindir;
729 IPin_QueryDirection(ppin, &pindir);
730 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
731 if (FAILED(hr)) {
732 TRACE("Querying connected to failed: %x\n", hr);
733 return hr;
735 IPin_Disconnect(ppin);
736 IPin_Disconnect(pConnectedTo);
737 if (pindir == PINDIR_INPUT)
738 hr = IPin_Connect(pConnectedTo, ppin, NULL);
739 else
740 hr = IPin_Connect(ppin, pConnectedTo, NULL);
741 IPin_Release(pConnectedTo);
742 if (FAILED(hr))
743 WARN("Reconnecting pins failed, pins are not connected now..\n");
744 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
745 return hr;
748 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
750 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
752 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
754 if (!ppin)
755 return E_POINTER;
757 return IPin_Disconnect(ppin);
760 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
762 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
763 IReferenceClock *pClock = NULL;
764 HRESULT hr = S_OK;
765 int i;
767 TRACE("(%p/%p)->() live sources not handled properly!\n", iface, This);
769 EnterCriticalSection(&This->cs);
771 for (i = 0; i < This->nFilters; ++i)
773 DWORD miscflags;
774 IAMFilterMiscFlags *flags = NULL;
775 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags);
776 if (!flags)
777 continue;
778 miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
779 IAMFilterMiscFlags_Release(flags);
780 if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
781 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock);
782 if (pClock)
783 break;
786 if (!pClock)
788 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
789 This->refClockProvider = NULL;
791 else
792 This->refClockProvider = This->ppFiltersInGraph[i];
794 if (SUCCEEDED(hr))
796 hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock);
797 This->defaultclock = TRUE;
798 IReferenceClock_Release(pClock);
800 LeaveCriticalSection(&This->cs);
802 return hr;
805 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
807 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
808 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
809 IPropertyBag * pPropBagCat = NULL;
810 HRESULT hr;
812 VariantInit(pvar);
814 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
816 if (SUCCEEDED(hr))
817 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
819 if (SUCCEEDED(hr))
820 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
822 VariantClear(pvar);
824 if (SUCCEEDED(hr))
825 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
827 if (SUCCEEDED(hr))
828 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
830 if (pPropBagCat)
831 IPropertyBag_Release(pPropBagCat);
833 return hr;
836 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
838 HRESULT hr;
839 ULONG nb = 0;
841 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
842 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
843 if (hr == S_OK) {
844 /* Rendered input */
845 } else if (hr == S_FALSE) {
846 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
847 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
848 if (hr != S_OK) {
849 WARN("Error (%x)\n", hr);
851 } else if (hr == E_NOTIMPL) {
852 /* Input connected to all outputs */
853 IEnumPins* penumpins;
854 IPin* ppin;
855 int i = 0;
856 TRACE("E_NOTIMPL\n");
857 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
858 if (FAILED(hr)) {
859 WARN("filter Enumpins failed (%x)\n", hr);
860 return hr;
862 i = 0;
863 /* Count output pins */
864 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
865 PIN_DIRECTION pindir;
866 IPin_QueryDirection(ppin, &pindir);
867 if (pindir == PINDIR_OUTPUT)
868 i++;
869 IPin_Release(ppin);
871 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
872 /* Retrieve output pins */
873 IEnumPins_Reset(penumpins);
874 i = 0;
875 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
876 PIN_DIRECTION pindir;
877 IPin_QueryDirection(ppin, &pindir);
878 if (pindir == PINDIR_OUTPUT)
879 (*pppins)[i++] = ppin;
880 else
881 IPin_Release(ppin);
883 IEnumPins_Release(penumpins);
884 nb = i;
885 if (FAILED(hr)) {
886 WARN("Next failed (%x)\n", hr);
887 return hr;
889 } else if (FAILED(hr)) {
890 WARN("Cannot get internal connection (%x)\n", hr);
891 return hr;
894 *pnb = nb;
895 return S_OK;
898 /*** IGraphBuilder methods ***/
899 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
901 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
902 HRESULT hr;
903 AM_MEDIA_TYPE* mt = NULL;
904 IEnumMediaTypes* penummt = NULL;
905 ULONG nbmt;
906 IEnumPins* penumpins;
907 IEnumMoniker* pEnumMoniker;
908 GUID tab[2];
909 ULONG nb = 0;
910 IMoniker* pMoniker;
911 ULONG pin;
912 PIN_INFO PinInfo;
913 CLSID FilterCLSID;
914 PIN_DIRECTION dir;
915 unsigned int i = 0;
917 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
919 if (TRACE_ON(quartz))
921 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
922 if (FAILED(hr))
923 return hr;
925 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
926 IBaseFilter_Release(PinInfo.pFilter);
928 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
929 if (FAILED(hr))
930 return hr;
932 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
933 IBaseFilter_Release(PinInfo.pFilter);
936 EnterCriticalSection(&This->cs);
937 ++This->recursioncount;
938 if (This->recursioncount >= 5)
940 WARN("Recursion count has reached %d\n", This->recursioncount);
941 hr = VFW_E_CANNOT_CONNECT;
942 goto out;
945 hr = IPin_QueryDirection(ppinOut, &dir);
946 if (FAILED(hr))
947 goto out;
949 if (dir == PINDIR_INPUT)
951 IPin *temp;
953 temp = ppinIn;
954 ppinIn = ppinOut;
955 ppinOut = temp;
958 hr = CheckCircularConnection(This, ppinOut, ppinIn);
959 if (FAILED(hr))
960 goto out;
962 /* Try direct connection first */
963 hr = IPin_Connect(ppinOut, ppinIn, NULL);
964 if (SUCCEEDED(hr))
965 goto out;
967 TRACE("Direct connection failed, trying to render using extra filters\n");
969 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
970 if (FAILED(hr))
971 goto out;
973 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
974 IBaseFilter_Release(PinInfo.pFilter);
975 if (FAILED(hr))
976 goto out;
978 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
979 * filter to the minor mediatype of input pin of the renderer */
980 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
981 if (FAILED(hr))
983 WARN("EnumMediaTypes (%x)\n", hr);
984 goto out;
987 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
988 if (FAILED(hr)) {
989 WARN("IEnumMediaTypes_Next (%x)\n", hr);
990 goto out;
993 if (!nbmt)
995 WARN("No media type found!\n");
996 hr = VFW_E_INVALIDMEDIATYPE;
997 goto out;
999 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1000 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1002 /* Try to find a suitable filter that can connect to the pin to render */
1003 tab[0] = mt->majortype;
1004 tab[1] = mt->subtype;
1005 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1006 if (FAILED(hr)) {
1007 WARN("Unable to enum filters (%x)\n", hr);
1008 goto out;
1011 hr = VFW_E_CANNOT_RENDER;
1012 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1014 VARIANT var;
1015 GUID clsid;
1016 IPin** ppins = NULL;
1017 IPin* ppinfilter = NULL;
1018 IBaseFilter* pfilter = NULL;
1019 IAMGraphBuilderCallback *callback = NULL;
1021 hr = GetFilterInfo(pMoniker, &clsid, &var);
1022 IMoniker_Release(pMoniker);
1023 if (FAILED(hr)) {
1024 WARN("Unable to retrieve filter info (%x)\n", hr);
1025 goto error;
1028 if (IsEqualGUID(&clsid, &FilterCLSID)) {
1029 /* Skip filter (same as the one the output pin belongs to) */
1030 goto error;
1033 if (This->pSite)
1035 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1036 if (callback)
1038 HRESULT rc;
1039 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1040 if (FAILED(rc))
1042 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1043 IAMGraphBuilderCallback_Release(callback);
1044 goto error;
1049 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1050 if (FAILED(hr)) {
1051 WARN("Unable to create filter (%x), trying next one\n", hr);
1052 goto error;
1055 if (callback)
1057 HRESULT rc;
1058 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1059 IAMGraphBuilderCallback_Release(callback);
1060 if (FAILED(rc))
1062 IBaseFilter_Release(pfilter);
1063 pfilter = NULL;
1064 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1065 goto error;
1069 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1070 if (FAILED(hr)) {
1071 WARN("Unable to add filter (%x)\n", hr);
1072 IBaseFilter_Release(pfilter);
1073 pfilter = NULL;
1074 goto error;
1077 VariantClear(&var);
1079 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1080 if (FAILED(hr)) {
1081 WARN("Enumpins (%x)\n", hr);
1082 goto error;
1085 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1086 IEnumPins_Release(penumpins);
1088 if (FAILED(hr)) {
1089 WARN("Obtaining next pin: (%x)\n", hr);
1090 goto error;
1092 if (pin == 0) {
1093 WARN("Cannot use this filter: no pins\n");
1094 goto error;
1097 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1098 if (FAILED(hr)) {
1099 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1100 goto error;
1102 TRACE("Successfully connected to filter, follow chain...\n");
1104 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
1105 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1107 if (SUCCEEDED(hr)) {
1108 if (nb == 0) {
1109 IPin_Disconnect(ppinfilter);
1110 IPin_Disconnect(ppinOut);
1111 goto error;
1113 TRACE("pins to consider: %d\n", nb);
1114 for(i = 0; i < nb; i++)
1116 LPWSTR pinname = NULL;
1118 TRACE("Processing pin %u\n", i);
1120 hr = IPin_QueryId(ppins[i], &pinname);
1121 if (SUCCEEDED(hr))
1123 if (pinname[0] == '~')
1125 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1126 hr = E_FAIL;
1128 else
1129 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1130 CoTaskMemFree(pinname);
1133 if (FAILED(hr)) {
1134 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1136 IPin_Release(ppins[i]);
1137 if (SUCCEEDED(hr)) break;
1139 while (++i < nb) IPin_Release(ppins[i]);
1140 CoTaskMemFree(ppins);
1141 IPin_Release(ppinfilter);
1142 IBaseFilter_Release(pfilter);
1143 if (FAILED(hr))
1145 IPin_Disconnect(ppinfilter);
1146 IPin_Disconnect(ppinOut);
1147 IFilterGraph2_RemoveFilter(iface, pfilter);
1148 continue;
1150 break;
1153 error:
1154 VariantClear(&var);
1155 if (ppinfilter) IPin_Release(ppinfilter);
1156 if (pfilter) {
1157 IFilterGraph2_RemoveFilter(iface, pfilter);
1158 IBaseFilter_Release(pfilter);
1160 while (++i < nb) IPin_Release(ppins[i]);
1161 CoTaskMemFree(ppins);
1164 out:
1165 if (penummt)
1166 IEnumMediaTypes_Release(penummt);
1167 if (mt)
1168 DeleteMediaType(mt);
1169 --This->recursioncount;
1170 LeaveCriticalSection(&This->cs);
1171 TRACE("--> %08x\n", hr);
1172 return SUCCEEDED(hr) ? S_OK : hr;
1175 static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1177 /* This pin has been connected now, try to call render on all pins that aren't connected */
1178 IPin *to = NULL;
1179 PIN_INFO info;
1180 IEnumPins *enumpins = NULL;
1181 BOOL renderany = FALSE;
1182 BOOL renderall = TRUE;
1184 IPin_QueryPinInfo(ppinOut, &info);
1186 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1187 /* Don't need to hold a reference, IEnumPins does */
1188 IBaseFilter_Release(info.pFilter);
1190 IEnumPins_Reset(enumpins);
1191 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1193 PIN_DIRECTION dir = PINDIR_INPUT;
1195 IPin_QueryDirection(to, &dir);
1197 if (dir == PINDIR_OUTPUT)
1199 IPin *out = NULL;
1201 IPin_ConnectedTo(to, &out);
1202 if (!out)
1204 HRESULT hr;
1205 hr = IFilterGraph2_Render(&This->IFilterGraph2_iface, to);
1206 if (SUCCEEDED(hr))
1207 renderany = TRUE;
1208 else
1209 renderall = FALSE;
1211 else
1212 IPin_Release(out);
1215 IPin_Release(to);
1218 IEnumPins_Release(enumpins);
1220 if (renderall)
1221 return S_OK;
1223 if (renderany)
1224 return VFW_S_PARTIAL_RENDER;
1226 return VFW_E_CANNOT_RENDER;
1229 /* Ogg hates me if I create a direct rendering method
1231 * It can only connect to a pin properly once, so use a recursive method that does
1233 * +----+ --- (PIN 1) (Render is called on this pin)
1234 * | |
1235 * +----+ --- (PIN 2)
1237 * Enumerate possible renderers that EXACTLY match the requested type
1239 * If none is available, try to add intermediate filters that can connect to the input pin
1240 * then call Render on that intermediate pin's output pins
1241 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1242 * and another filter that can connect to the input pin is tried
1243 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1244 * It's recursive, but fun!
1247 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1249 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1250 IEnumMediaTypes* penummt;
1251 AM_MEDIA_TYPE* mt;
1252 ULONG nbmt;
1253 HRESULT hr;
1255 IEnumMoniker* pEnumMoniker;
1256 GUID tab[4];
1257 ULONG nb;
1258 IMoniker* pMoniker;
1259 INT x;
1261 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1263 if (TRACE_ON(quartz))
1265 PIN_INFO PinInfo;
1267 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1268 if (FAILED(hr))
1269 return hr;
1271 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1272 IBaseFilter_Release(PinInfo.pFilter);
1275 /* Try to find out if there is a renderer for the specified subtype already, and use that
1277 EnterCriticalSection(&This->cs);
1278 for (x = 0; x < This->nFilters; ++x)
1280 IEnumPins *enumpins = NULL;
1281 IPin *pin = NULL;
1283 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1285 if (FAILED(hr) || !enumpins)
1286 continue;
1288 IEnumPins_Reset(enumpins);
1289 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1291 IPin *to = NULL;
1292 PIN_DIRECTION dir = PINDIR_OUTPUT;
1294 IPin_QueryDirection(pin, &dir);
1295 if (dir != PINDIR_INPUT)
1297 IPin_Release(pin);
1298 continue;
1300 IPin_ConnectedTo(pin, &to);
1302 if (to == NULL)
1304 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1305 if (SUCCEEDED(hr))
1307 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1308 IPin_Release(pin);
1310 hr = FilterGraph2_RenderRecurse(This, pin);
1311 if (FAILED(hr))
1313 IPin_Disconnect(ppinOut);
1314 IPin_Disconnect(pin);
1315 continue;
1317 IEnumPins_Release(enumpins);
1318 LeaveCriticalSection(&This->cs);
1319 return hr;
1321 WARN("Could not connect!\n");
1323 else
1324 IPin_Release(to);
1326 IPin_Release(pin);
1328 IEnumPins_Release(enumpins);
1331 LeaveCriticalSection(&This->cs);
1333 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1334 if (FAILED(hr)) {
1335 WARN("EnumMediaTypes (%x)\n", hr);
1336 return hr;
1339 IEnumMediaTypes_Reset(penummt);
1341 /* Looks like no existing renderer of the kind exists
1342 * Try adding new ones
1344 tab[0] = tab[1] = GUID_NULL;
1345 while (SUCCEEDED(hr))
1347 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1348 if (FAILED(hr)) {
1349 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1350 break;
1352 if (!nbmt)
1354 hr = VFW_E_CANNOT_RENDER;
1355 break;
1357 else
1359 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1360 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1362 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1363 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1365 DeleteMediaType(mt);
1366 continue;
1369 /* Try to find a suitable renderer with the same media type */
1370 tab[0] = mt->majortype;
1371 tab[1] = mt->subtype;
1372 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1373 if (FAILED(hr))
1375 WARN("Unable to enum filters (%x)\n", hr);
1376 break;
1379 hr = E_FAIL;
1381 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1383 VARIANT var;
1384 GUID clsid;
1385 IPin* ppinfilter;
1386 IBaseFilter* pfilter = NULL;
1387 IEnumPins* penumpins = NULL;
1388 ULONG pin;
1390 hr = GetFilterInfo(pMoniker, &clsid, &var);
1391 IMoniker_Release(pMoniker);
1392 if (FAILED(hr)) {
1393 WARN("Unable to retrieve filter info (%x)\n", hr);
1394 goto error;
1397 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1398 if (FAILED(hr))
1400 WARN("Unable to create filter (%x), trying next one\n", hr);
1401 goto error;
1404 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1405 if (FAILED(hr)) {
1406 WARN("Unable to add filter (%x)\n", hr);
1407 IBaseFilter_Release(pfilter);
1408 pfilter = NULL;
1409 goto error;
1412 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1413 if (FAILED(hr)) {
1414 WARN("Splitter Enumpins (%x)\n", hr);
1415 goto error;
1418 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1420 PIN_DIRECTION dir;
1422 if (pin == 0) {
1423 WARN("No Pin\n");
1424 hr = E_FAIL;
1425 goto error;
1428 hr = IPin_QueryDirection(ppinfilter, &dir);
1429 if (FAILED(hr)) {
1430 IPin_Release(ppinfilter);
1431 WARN("QueryDirection failed (%x)\n", hr);
1432 goto error;
1434 if (dir != PINDIR_INPUT) {
1435 IPin_Release(ppinfilter);
1436 continue; /* Wrong direction */
1439 /* Connect the pin to the "Renderer" */
1440 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1441 IPin_Release(ppinfilter);
1443 if (FAILED(hr)) {
1444 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1445 goto error;
1447 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1449 VariantClear(&var);
1451 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1452 if (FAILED(hr)) {
1453 WARN("Unable to connect recursively (%x)\n", hr);
1454 goto error;
1456 IBaseFilter_Release(pfilter);
1457 break;
1459 if (SUCCEEDED(hr)) {
1460 IEnumPins_Release(penumpins);
1461 break; /* out of IEnumMoniker_Next loop */
1464 /* IEnumPins_Next failed, all other failure case caught by goto error */
1465 WARN("IEnumPins_Next (%x)\n", hr);
1466 /* goto error */
1468 error:
1469 VariantClear(&var);
1470 if (penumpins)
1471 IEnumPins_Release(penumpins);
1472 if (pfilter) {
1473 IFilterGraph2_RemoveFilter(iface, pfilter);
1474 IBaseFilter_Release(pfilter);
1476 if (SUCCEEDED(hr)) DebugBreak();
1479 IEnumMoniker_Release(pEnumMoniker);
1480 if (nbmt)
1481 DeleteMediaType(mt);
1482 if (SUCCEEDED(hr))
1483 break;
1484 hr = S_OK;
1487 IEnumMediaTypes_Release(penummt);
1488 return hr;
1491 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1492 LPCWSTR lpcwstrPlayList)
1494 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1495 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1496 IBaseFilter* preader = NULL;
1497 IPin* ppinreader = NULL;
1498 IEnumPins* penumpins = NULL;
1499 HRESULT hr;
1500 BOOL partial = FALSE;
1501 HRESULT any = FALSE;
1503 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1505 if (lpcwstrPlayList != NULL)
1506 return E_INVALIDARG;
1508 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1509 if (FAILED(hr))
1510 return hr;
1512 if (SUCCEEDED(hr))
1513 hr = IBaseFilter_EnumPins(preader, &penumpins);
1514 if (SUCCEEDED(hr))
1516 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1518 PIN_DIRECTION dir;
1520 IPin_QueryDirection(ppinreader, &dir);
1521 if (dir == PINDIR_OUTPUT)
1523 INT i;
1525 hr = IFilterGraph2_Render(iface, ppinreader);
1526 TRACE("Render %08x\n", hr);
1528 for (i = 0; i < This->nFilters; ++i)
1529 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1531 if (SUCCEEDED(hr))
1532 any = TRUE;
1533 if (hr != S_OK)
1534 partial = TRUE;
1536 IPin_Release(ppinreader);
1538 IEnumPins_Release(penumpins);
1540 if (!any)
1541 hr = VFW_E_CANNOT_RENDER;
1542 else if (partial)
1543 hr = VFW_S_PARTIAL_RENDER;
1544 else
1545 hr = S_OK;
1547 IBaseFilter_Release(preader);
1549 TRACE("--> %08x\n", hr);
1550 return hr;
1553 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1554 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1556 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1557 HRESULT hr = S_OK;
1558 HKEY extkey;
1559 LONG lRet;
1561 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
1562 hr = HRESULT_FROM_WIN32(lRet);
1564 if (SUCCEEDED(hr))
1566 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
1567 WCHAR *ext = PathFindExtensionW(pszFileName);
1568 WCHAR clsid_key[39];
1569 GUID clsid;
1570 DWORD size = sizeof(clsid_key);
1571 HKEY pathkey;
1573 if (!ext)
1575 CloseHandle(extkey);
1576 return E_FAIL;
1579 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
1580 hr = HRESULT_FROM_WIN32(lRet);
1581 CloseHandle(extkey);
1582 if (FAILED(hr))
1583 return hr;
1585 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
1586 hr = HRESULT_FROM_WIN32(lRet);
1587 CloseHandle(pathkey);
1588 if (FAILED(hr))
1589 return hr;
1591 CLSIDFromString(clsid_key, &clsid);
1593 TRACE("CLSID: %s\n", debugstr_guid(&clsid));
1594 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1595 if (SUCCEEDED(hr))
1597 IFileSourceFilter *source = NULL;
1598 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1599 if (SUCCEEDED(hr))
1600 IFileSourceFilter_Release(source);
1601 else
1602 IBaseFilter_Release(*filter);
1605 if (FAILED(hr))
1606 *filter = NULL;
1607 return hr;
1610 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1611 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1613 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1614 HRESULT hr;
1615 IBaseFilter* preader;
1616 IFileSourceFilter* pfile = NULL;
1617 AM_MEDIA_TYPE mt;
1618 WCHAR* filename;
1620 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1622 /* Try from file name first, then fall back to default asynchronous reader */
1623 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1625 if (FAILED(hr))
1626 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1627 if (FAILED(hr)) {
1628 WARN("Unable to create file source filter (%x)\n", hr);
1629 return hr;
1632 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1633 if (FAILED(hr)) {
1634 WARN("Unable add filter (%x)\n", hr);
1635 IBaseFilter_Release(preader);
1636 return hr;
1639 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1640 if (FAILED(hr)) {
1641 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1642 goto error;
1645 /* Load the file in the file source filter */
1646 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1647 if (FAILED(hr)) {
1648 WARN("Load (%x)\n", hr);
1649 goto error;
1652 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1653 if (FAILED(hr)) {
1654 WARN("GetCurFile (%x)\n", hr);
1655 goto error;
1658 TRACE("File %s\n", debugstr_w(filename));
1659 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1660 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1662 if (ppFilter)
1663 *ppFilter = preader;
1664 IFileSourceFilter_Release(pfile);
1666 return S_OK;
1668 error:
1669 if (pfile)
1670 IFileSourceFilter_Release(pfile);
1671 IFilterGraph2_RemoveFilter(iface, preader);
1672 IBaseFilter_Release(preader);
1674 return hr;
1677 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1679 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1681 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1683 return S_OK;
1686 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1688 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1690 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1692 return S_OK;
1695 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1697 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1699 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1701 return S_OK;
1704 /*** IFilterGraph2 methods ***/
1705 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1706 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1708 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1710 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1712 return S_OK;
1715 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1716 const AM_MEDIA_TYPE *pmt)
1718 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1720 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1722 return S_OK;
1725 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1726 DWORD *pvContext)
1728 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1730 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1732 return S_OK;
1736 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1738 FilterGraph2_QueryInterface,
1739 FilterGraph2_AddRef,
1740 FilterGraph2_Release,
1741 FilterGraph2_AddFilter,
1742 FilterGraph2_RemoveFilter,
1743 FilterGraph2_EnumFilters,
1744 FilterGraph2_FindFilterByName,
1745 FilterGraph2_ConnectDirect,
1746 FilterGraph2_Reconnect,
1747 FilterGraph2_Disconnect,
1748 FilterGraph2_SetDefaultSyncSource,
1749 FilterGraph2_Connect,
1750 FilterGraph2_Render,
1751 FilterGraph2_RenderFile,
1752 FilterGraph2_AddSourceFilter,
1753 FilterGraph2_SetLogFile,
1754 FilterGraph2_Abort,
1755 FilterGraph2_ShouldOperationContinue,
1756 FilterGraph2_AddSourceFilterForMoniker,
1757 FilterGraph2_ReconnectEx,
1758 FilterGraph2_RenderEx
1761 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
1763 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
1766 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
1768 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1770 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1772 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1775 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
1777 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1779 TRACE("(%p/%p)->()\n", This, iface);
1781 return IUnknown_AddRef(This->outer_unk);
1784 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
1786 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1788 TRACE("(%p/%p)->()\n", This, iface);
1790 return IUnknown_Release(This->outer_unk);
1794 /*** IDispatch methods ***/
1795 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
1797 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1799 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1801 return S_OK;
1804 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
1805 ITypeInfo **ppTInfo)
1807 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1809 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1811 return S_OK;
1814 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
1815 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1817 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1819 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1821 return S_OK;
1824 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
1825 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
1826 UINT *puArgErr)
1828 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1830 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);
1832 return S_OK;
1835 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1837 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1839 HRESULT hr;
1840 IPin* pInputPin;
1841 IPin** ppPins;
1842 ULONG nb;
1843 ULONG i;
1844 PIN_INFO PinInfo;
1846 TRACE("%p %p\n", pGraph, pOutputPin);
1847 PinInfo.pFilter = NULL;
1849 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1851 if (SUCCEEDED(hr))
1853 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1854 if (SUCCEEDED(hr))
1855 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1856 IPin_Release(pInputPin);
1859 if (SUCCEEDED(hr))
1861 if (nb == 0)
1863 TRACE("Reached a renderer\n");
1864 /* Count renderers for end of stream notification */
1865 pGraph->nRenderers++;
1867 else
1869 for(i = 0; i < nb; i++)
1871 /* Explore the graph downstream from this pin
1872 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1873 * several input pins are connected to the same output (a MUX for instance). */
1874 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1875 IPin_Release(ppPins[i]);
1878 CoTaskMemFree(ppPins);
1880 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1882 FoundFilter(PinInfo.pFilter, data);
1885 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1886 return hr;
1889 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1891 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
1892 return IBaseFilter_Run(pFilter, time);
1895 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1897 return IBaseFilter_Pause(pFilter);
1900 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1902 return IBaseFilter_Stop(pFilter);
1905 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1907 FILTER_STATE state;
1908 DWORD time_end = data;
1909 DWORD time_now = GetTickCount();
1910 LONG wait;
1912 if (time_end == INFINITE)
1914 wait = INFINITE;
1916 else if (time_end > time_now)
1918 wait = time_end - time_now;
1920 else
1921 wait = 0;
1923 return IBaseFilter_GetState(pFilter, wait, &state);
1927 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
1929 int i;
1930 IBaseFilter* pfilter;
1931 IEnumPins* pEnum;
1932 HRESULT hr;
1933 IPin* pPin;
1934 DWORD dummy;
1935 PIN_DIRECTION dir;
1937 TRACE("(%p)->()\n", This);
1939 /* Explorer the graph from source filters to renderers, determine renderers
1940 * number and run filters from renderers to source filters */
1941 This->nRenderers = 0;
1942 ResetEvent(This->hEventCompletion);
1944 for(i = 0; i < This->nFilters; i++)
1946 BOOL source = TRUE;
1947 pfilter = This->ppFiltersInGraph[i];
1948 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1949 if (hr != S_OK)
1951 WARN("Enum pins failed %x\n", hr);
1952 continue;
1954 /* Check if it is a source filter */
1955 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1957 IPin_QueryDirection(pPin, &dir);
1958 IPin_Release(pPin);
1959 if (dir == PINDIR_INPUT)
1961 source = FALSE;
1962 break;
1965 if (source)
1967 TRACE("Found a source filter %p\n", pfilter);
1968 IEnumPins_Reset(pEnum);
1969 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1971 /* Explore the graph downstream from this pin */
1972 ExploreGraph(This, pPin, FoundFilter, data);
1973 IPin_Release(pPin);
1975 FoundFilter(pfilter, data);
1977 IEnumPins_Release(pEnum);
1980 return S_FALSE;
1983 /*** IMediaControl methods ***/
1984 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
1986 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1988 TRACE("(%p/%p)->()\n", This, iface);
1990 EnterCriticalSection(&This->cs);
1991 if (This->state == State_Running)
1992 goto out;
1993 This->EcCompleteCount = 0;
1995 if (This->defaultclock && !This->refClock)
1996 IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
1998 if (This->refClock)
2000 REFERENCE_TIME now;
2001 IReferenceClock_GetTime(This->refClock, &now);
2002 if (This->state == State_Stopped)
2003 This->start_time = now + 500000;
2004 else if (This->pause_time >= 0)
2005 This->start_time += now - This->pause_time;
2006 else
2007 This->start_time = now;
2009 else This->start_time = 0;
2011 SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time);
2012 This->state = State_Running;
2013 out:
2014 LeaveCriticalSection(&This->cs);
2015 return S_FALSE;
2018 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2020 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2022 TRACE("(%p/%p)->()\n", This, iface);
2024 EnterCriticalSection(&This->cs);
2025 if (This->state == State_Paused)
2026 goto out;
2028 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2029 IReferenceClock_GetTime(This->refClock, &This->pause_time);
2030 else
2031 This->pause_time = -1;
2033 SendFilterMessage(This, SendPause, 0);
2034 This->state = State_Paused;
2035 out:
2036 LeaveCriticalSection(&This->cs);
2037 return S_FALSE;
2040 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2042 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2044 TRACE("(%p/%p)->()\n", This, iface);
2046 if (This->state == State_Stopped) return S_OK;
2048 EnterCriticalSection(&This->cs);
2049 if (This->state == State_Running) SendFilterMessage(This, SendPause, 0);
2050 SendFilterMessage(This, SendStop, 0);
2051 This->state = State_Stopped;
2052 LeaveCriticalSection(&This->cs);
2053 return S_OK;
2056 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout,
2057 OAFilterState *pfs)
2059 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2060 DWORD end;
2062 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
2064 if (!pfs)
2065 return E_POINTER;
2067 EnterCriticalSection(&This->cs);
2069 *pfs = This->state;
2070 if (msTimeout > 0)
2072 end = GetTickCount() + msTimeout;
2074 else if (msTimeout < 0)
2076 end = INFINITE;
2078 else
2080 end = 0;
2082 if (end)
2083 SendFilterMessage(This, SendGetState, end);
2085 LeaveCriticalSection(&This->cs);
2087 return S_OK;
2090 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2092 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2094 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
2096 return S_OK;
2099 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2100 IDispatch **ppUnk)
2102 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2104 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2106 return S_OK;
2109 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2111 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2113 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2115 return S_OK;
2118 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2120 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2122 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2124 return S_OK;
2127 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2129 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2131 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2133 return S_OK;
2137 static const IMediaControlVtbl IMediaControl_VTable =
2139 MediaControl_QueryInterface,
2140 MediaControl_AddRef,
2141 MediaControl_Release,
2142 MediaControl_GetTypeInfoCount,
2143 MediaControl_GetTypeInfo,
2144 MediaControl_GetIDsOfNames,
2145 MediaControl_Invoke,
2146 MediaControl_Run,
2147 MediaControl_Pause,
2148 MediaControl_Stop,
2149 MediaControl_GetState,
2150 MediaControl_RenderFile,
2151 MediaControl_AddSourceFilter,
2152 MediaControl_get_FilterCollection,
2153 MediaControl_get_RegFilterCollection,
2154 MediaControl_StopWhenReady
2157 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2159 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2162 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2164 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2166 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2168 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2171 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2173 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2175 TRACE("(%p/%p)->()\n", This, iface);
2177 return IUnknown_AddRef(This->outer_unk);
2180 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2182 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2184 TRACE("(%p/%p)->()\n", This, iface);
2186 return IUnknown_Release(This->outer_unk);
2189 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2191 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2192 BOOL allnotimpl = TRUE;
2193 int i;
2194 HRESULT hr, hr_return = S_OK;
2196 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2197 /* Send a message to all renderers, they are responsible for broadcasting it further */
2199 for(i = 0; i < This->nFilters; i++)
2201 IMediaSeeking *seek = NULL;
2202 IBaseFilter* pfilter = This->ppFiltersInGraph[i];
2203 IAMFilterMiscFlags *flags = NULL;
2204 ULONG filterflags;
2205 IBaseFilter_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags);
2206 if (!flags)
2207 continue;
2208 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2209 IAMFilterMiscFlags_Release(flags);
2210 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2211 continue;
2213 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2214 if (!seek)
2215 continue;
2216 hr = FoundSeek(This, seek, arg);
2217 IMediaSeeking_Release(seek);
2218 if (hr_return != E_NOTIMPL)
2219 allnotimpl = FALSE;
2220 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2221 hr_return = hr;
2224 if (allnotimpl)
2225 return E_NOTIMPL;
2226 return hr_return;
2229 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2231 HRESULT hr;
2232 DWORD caps = 0;
2234 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2235 if (FAILED(hr))
2236 return hr;
2238 /* Only add common capabilities everything supports */
2239 *(DWORD*)pcaps &= caps;
2241 return hr;
2244 /*** IMediaSeeking methods ***/
2245 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2247 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2248 HRESULT hr;
2250 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2252 if (!pCapabilities)
2253 return E_POINTER;
2255 EnterCriticalSection(&This->cs);
2256 *pCapabilities = 0xffffffff;
2258 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2259 LeaveCriticalSection(&This->cs);
2261 return hr;
2264 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2266 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2267 DWORD originalcaps;
2268 HRESULT hr;
2270 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2272 if (!pCapabilities)
2273 return E_POINTER;
2275 EnterCriticalSection(&This->cs);
2276 originalcaps = *pCapabilities;
2277 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2278 LeaveCriticalSection(&This->cs);
2280 if (FAILED(hr))
2281 return hr;
2283 if (!*pCapabilities)
2284 return E_FAIL;
2285 if (*pCapabilities != originalcaps)
2286 return S_FALSE;
2287 return S_OK;
2290 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2292 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2294 if (!pFormat)
2295 return E_POINTER;
2297 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2299 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2301 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2302 return S_FALSE;
2305 return S_OK;
2308 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2310 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2312 if (!pFormat)
2313 return E_POINTER;
2315 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2316 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2318 return S_OK;
2321 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2323 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2325 if (!pFormat)
2326 return E_POINTER;
2328 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2329 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2331 return S_OK;
2334 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2336 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2338 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2339 if (!pFormat)
2340 return E_POINTER;
2342 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2343 return S_FALSE;
2345 return S_OK;
2348 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2350 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2352 if (!pFormat)
2353 return E_POINTER;
2355 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2357 if (This->state != State_Stopped)
2358 return VFW_E_WRONG_STATE;
2360 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2362 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2363 return E_INVALIDARG;
2366 return S_OK;
2369 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2371 HRESULT hr;
2372 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2374 hr = IMediaSeeking_GetDuration(seek, &duration);
2375 if (FAILED(hr))
2376 return hr;
2378 if (*pdur < duration)
2379 *pdur = duration;
2380 return hr;
2383 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2385 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2386 HRESULT hr;
2388 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2390 if (!pDuration)
2391 return E_POINTER;
2393 EnterCriticalSection(&This->cs);
2394 *pDuration = 0;
2395 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2396 LeaveCriticalSection(&This->cs);
2398 TRACE("--->%08x\n", hr);
2399 return hr;
2402 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2404 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2405 HRESULT hr = S_OK;
2407 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2409 if (!pStop)
2410 return E_POINTER;
2412 EnterCriticalSection(&This->cs);
2413 if (This->stop_position < 0)
2414 /* Stop position not set, use duration instead */
2415 hr = IMediaSeeking_GetDuration(iface, pStop);
2416 else
2417 *pStop = This->stop_position;
2418 LeaveCriticalSection(&This->cs);
2420 return hr;
2423 static HRESULT WINAPI FoundCurrentPosition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pposition)
2425 HRESULT hr;
2426 LONGLONG pos = 0, *ppos = (LONGLONG*)pposition;
2428 hr = IMediaSeeking_GetCurrentPosition(seek, &pos);
2429 if (FAILED(hr))
2430 return hr;
2432 if (*ppos < 0 || pos < *ppos)
2433 *ppos = pos;
2434 return hr;
2437 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2439 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2440 HRESULT hr;
2442 if (!pCurrent)
2443 return E_POINTER;
2445 EnterCriticalSection(&This->cs);
2446 *pCurrent = -1;
2447 hr = all_renderers_seek(This, FoundCurrentPosition, (DWORD_PTR)pCurrent);
2448 if (hr == E_NOTIMPL) {
2449 LONGLONG time = 0;
2450 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2452 IReferenceClock_GetTime(This->refClock, &time);
2453 if (time)
2454 time -= This->start_time;
2456 if (This->pause_time > 0)
2457 time += This->pause_time;
2458 *pCurrent = time;
2459 hr = S_OK;
2461 LeaveCriticalSection(&This->cs);
2463 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2465 return hr;
2468 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2469 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2471 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2473 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2474 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2476 return S_OK;
2479 struct pos_args {
2480 LONGLONG* current, *stop;
2481 DWORD curflags, stopflags;
2484 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2486 struct pos_args *args = (void*)pargs;
2488 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2491 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2492 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2494 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2495 HRESULT hr = S_OK;
2496 FILTER_STATE state;
2497 struct pos_args args;
2499 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2501 EnterCriticalSection(&This->cs);
2502 state = This->state;
2503 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2505 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2506 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2507 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2509 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2510 This->stop_position = *pStop;
2511 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2512 FIXME("Stop position not handled yet!\n");
2514 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2515 IMediaControl_Pause(&This->IMediaControl_iface);
2516 args.current = pCurrent;
2517 args.stop = pStop;
2518 args.curflags = dwCurrentFlags;
2519 args.stopflags = dwStopFlags;
2520 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2522 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2523 This->pause_time = This->start_time = -1;
2524 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2525 IMediaControl_Run(&This->IMediaControl_iface);
2526 LeaveCriticalSection(&This->cs);
2528 return hr;
2531 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2532 LONGLONG *pStop)
2534 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2535 HRESULT hr;
2537 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2538 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2539 if (SUCCEEDED(hr))
2540 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2542 return hr;
2545 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2546 LONGLONG *pLatest)
2548 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2550 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2552 return S_OK;
2555 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2557 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2559 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2561 return S_OK;
2564 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2566 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2568 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2570 return S_OK;
2573 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2575 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2577 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2579 return S_OK;
2583 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2585 MediaSeeking_QueryInterface,
2586 MediaSeeking_AddRef,
2587 MediaSeeking_Release,
2588 MediaSeeking_GetCapabilities,
2589 MediaSeeking_CheckCapabilities,
2590 MediaSeeking_IsFormatSupported,
2591 MediaSeeking_QueryPreferredFormat,
2592 MediaSeeking_GetTimeFormat,
2593 MediaSeeking_IsUsingTimeFormat,
2594 MediaSeeking_SetTimeFormat,
2595 MediaSeeking_GetDuration,
2596 MediaSeeking_GetStopPosition,
2597 MediaSeeking_GetCurrentPosition,
2598 MediaSeeking_ConvertTimeFormat,
2599 MediaSeeking_SetPositions,
2600 MediaSeeking_GetPositions,
2601 MediaSeeking_GetAvailable,
2602 MediaSeeking_SetRate,
2603 MediaSeeking_GetRate,
2604 MediaSeeking_GetPreroll
2607 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2609 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2612 /*** IUnknown methods ***/
2613 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2615 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2617 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2619 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2622 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2624 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2626 TRACE("(%p/%p)->()\n", This, iface);
2628 return IUnknown_AddRef(This->outer_unk);
2631 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2633 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2635 TRACE("(%p/%p)->()\n", This, iface);
2637 return IUnknown_Release(This->outer_unk);
2640 /*** IDispatch methods ***/
2641 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2642 FIXME("(%p) stub!\n", iface);
2643 return E_NOTIMPL;
2646 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2647 FIXME("(%p) stub!\n", iface);
2648 return E_NOTIMPL;
2651 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2652 FIXME("(%p) stub!\n", iface);
2653 return E_NOTIMPL;
2656 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2657 FIXME("(%p) stub!\n", iface);
2658 return E_NOTIMPL;
2661 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2663 GUID time_format;
2664 HRESULT hr;
2666 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2667 if (FAILED(hr))
2668 return hr;
2669 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2671 FIXME("Unsupported time format.\n");
2672 return E_NOTIMPL;
2675 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2676 return S_OK;
2679 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2681 GUID time_format;
2682 HRESULT hr;
2684 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2685 if (FAILED(hr))
2686 return hr;
2687 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2689 FIXME("Unsupported time format.\n");
2690 return E_NOTIMPL;
2693 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2694 return S_OK;
2697 /*** IMediaPosition methods ***/
2698 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2700 LONGLONG duration;
2701 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2702 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2703 if (FAILED(hr))
2704 return hr;
2705 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2708 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2710 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2711 LONGLONG reftime;
2712 HRESULT hr;
2714 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2715 if (FAILED(hr))
2716 return hr;
2717 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2718 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2721 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2723 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2724 LONGLONG pos;
2725 HRESULT hr;
2727 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2728 if (FAILED(hr))
2729 return hr;
2730 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2733 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2735 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2736 LONGLONG pos;
2737 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2738 if (FAILED(hr))
2739 return hr;
2740 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2743 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2745 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2746 LONGLONG reftime;
2747 HRESULT hr;
2749 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2750 if (FAILED(hr))
2751 return hr;
2752 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2753 &reftime, AM_SEEKING_AbsolutePositioning);
2756 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2757 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2758 return E_NOTIMPL;
2761 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2762 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2763 return E_NOTIMPL;
2766 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2768 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2769 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2772 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2774 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2775 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2778 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2779 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2780 return E_NOTIMPL;
2783 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2784 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2785 return E_NOTIMPL;
2789 static const IMediaPositionVtbl IMediaPosition_VTable =
2791 MediaPosition_QueryInterface,
2792 MediaPosition_AddRef,
2793 MediaPosition_Release,
2794 MediaPosition_GetTypeInfoCount,
2795 MediaPosition_GetTypeInfo,
2796 MediaPosition_GetIDsOfNames,
2797 MediaPosition_Invoke,
2798 MediaPosition_get_Duration,
2799 MediaPosition_put_CurrentPosition,
2800 MediaPosition_get_CurrentPosition,
2801 MediaPosition_get_StopTime,
2802 MediaPosition_put_StopTime,
2803 MediaPosition_get_PrerollTime,
2804 MediaPosition_put_PrerollTime,
2805 MediaPosition_put_Rate,
2806 MediaPosition_get_Rate,
2807 MediaPosition_CanSeekForward,
2808 MediaPosition_CanSeekBackward
2811 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2813 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2816 /*** IUnknown methods ***/
2817 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2819 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2821 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2823 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2826 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2828 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2830 TRACE("(%p/%p)->()\n", This, iface);
2832 return IUnknown_AddRef(This->outer_unk);
2835 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2837 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2839 TRACE("(%p/%p)->()\n", This, iface);
2841 return IUnknown_Release(This->outer_unk);
2844 /*** IObjectWithSite methods ***/
2846 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2848 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2850 TRACE("(%p/%p)->()\n", This, iface);
2851 if (This->pSite) IUnknown_Release(This->pSite);
2852 This->pSite = pUnkSite;
2853 IUnknown_AddRef(This->pSite);
2854 return S_OK;
2857 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2859 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2861 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2863 *ppvSite = NULL;
2864 if (!This->pSite)
2865 return E_FAIL;
2866 else
2867 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2870 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2872 ObjectWithSite_QueryInterface,
2873 ObjectWithSite_AddRef,
2874 ObjectWithSite_Release,
2875 ObjectWithSite_SetSite,
2876 ObjectWithSite_GetSite,
2879 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2881 HRESULT hr = E_NOINTERFACE;
2882 int i;
2883 int entry;
2885 /* Check if the interface type is already registered */
2886 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2887 if (riid == pGraph->ItfCacheEntries[entry].riid)
2889 if (pGraph->ItfCacheEntries[entry].iface)
2891 /* Return the interface if available */
2892 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2893 return S_OK;
2895 break;
2898 if (entry >= MAX_ITF_CACHE_ENTRIES)
2900 FIXME("Not enough space to store interface in the cache\n");
2901 return E_OUTOFMEMORY;
2904 /* Find a filter supporting the requested interface */
2905 for (i = 0; i < pGraph->nFilters; i++)
2907 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2908 if (hr == S_OK)
2910 pGraph->ItfCacheEntries[entry].riid = riid;
2911 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2912 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
2913 if (entry >= pGraph->nItfCacheEntries)
2914 pGraph->nItfCacheEntries++;
2915 return S_OK;
2917 if (hr != E_NOINTERFACE)
2918 return hr;
2921 return hr;
2924 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
2926 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
2929 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
2931 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2933 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2935 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2938 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
2940 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2942 TRACE("(%p/%p)->()\n", This, iface);
2944 return IUnknown_AddRef(This->outer_unk);
2947 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
2949 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2951 TRACE("(%p/%p)->()\n", This, iface);
2953 return IUnknown_Release(This->outer_unk);
2956 /*** IDispatch methods ***/
2957 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
2959 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2960 IBasicAudio* pBasicAudio;
2961 HRESULT hr;
2963 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2965 EnterCriticalSection(&This->cs);
2967 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2969 if (hr == S_OK)
2970 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2972 LeaveCriticalSection(&This->cs);
2974 return hr;
2977 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
2978 ITypeInfo **ppTInfo)
2980 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2981 IBasicAudio* pBasicAudio;
2982 HRESULT hr;
2984 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2986 EnterCriticalSection(&This->cs);
2988 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2990 if (hr == S_OK)
2991 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2993 LeaveCriticalSection(&This->cs);
2995 return hr;
2998 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
2999 UINT cNames, LCID lcid, DISPID *rgDispId)
3001 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3002 IBasicAudio* pBasicAudio;
3003 HRESULT hr;
3005 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3007 EnterCriticalSection(&This->cs);
3009 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3011 if (hr == S_OK)
3012 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3014 LeaveCriticalSection(&This->cs);
3016 return hr;
3019 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3020 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3021 UINT *puArgErr)
3023 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3024 IBasicAudio* pBasicAudio;
3025 HRESULT hr;
3027 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);
3029 EnterCriticalSection(&This->cs);
3031 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3033 if (hr == S_OK)
3034 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3036 LeaveCriticalSection(&This->cs);
3038 return hr;
3041 /*** IBasicAudio methods ***/
3042 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3044 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3045 IBasicAudio* pBasicAudio;
3046 HRESULT hr;
3048 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3050 EnterCriticalSection(&This->cs);
3052 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3054 if (hr == S_OK)
3055 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3057 LeaveCriticalSection(&This->cs);
3059 return hr;
3062 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3064 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3065 IBasicAudio* pBasicAudio;
3066 HRESULT hr;
3068 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3070 EnterCriticalSection(&This->cs);
3072 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3074 if (hr == S_OK)
3075 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3077 LeaveCriticalSection(&This->cs);
3079 return hr;
3082 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3084 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3085 IBasicAudio* pBasicAudio;
3086 HRESULT hr;
3088 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3090 EnterCriticalSection(&This->cs);
3092 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3094 if (hr == S_OK)
3095 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3097 LeaveCriticalSection(&This->cs);
3099 return hr;
3102 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3104 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3105 IBasicAudio* pBasicAudio;
3106 HRESULT hr;
3108 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3110 EnterCriticalSection(&This->cs);
3112 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3114 if (hr == S_OK)
3115 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3117 LeaveCriticalSection(&This->cs);
3119 return hr;
3122 static const IBasicAudioVtbl IBasicAudio_VTable =
3124 BasicAudio_QueryInterface,
3125 BasicAudio_AddRef,
3126 BasicAudio_Release,
3127 BasicAudio_GetTypeInfoCount,
3128 BasicAudio_GetTypeInfo,
3129 BasicAudio_GetIDsOfNames,
3130 BasicAudio_Invoke,
3131 BasicAudio_put_Volume,
3132 BasicAudio_get_Volume,
3133 BasicAudio_put_Balance,
3134 BasicAudio_get_Balance
3137 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3139 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3142 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3144 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3146 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3148 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3151 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3153 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3155 TRACE("(%p/%p)->()\n", This, iface);
3157 return IUnknown_AddRef(This->outer_unk);
3160 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3162 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3164 TRACE("(%p/%p)->()\n", This, iface);
3166 return IUnknown_Release(This->outer_unk);
3169 /*** IDispatch methods ***/
3170 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3172 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3173 IBasicVideo *pBasicVideo;
3174 HRESULT hr;
3176 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3178 EnterCriticalSection(&This->cs);
3180 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3182 if (hr == S_OK)
3183 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3185 LeaveCriticalSection(&This->cs);
3187 return hr;
3190 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3191 ITypeInfo **ppTInfo)
3193 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3194 IBasicVideo *pBasicVideo;
3195 HRESULT hr;
3197 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3199 EnterCriticalSection(&This->cs);
3201 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3203 if (hr == S_OK)
3204 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3206 LeaveCriticalSection(&This->cs);
3208 return hr;
3211 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3212 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3214 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3215 IBasicVideo *pBasicVideo;
3216 HRESULT hr;
3218 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3220 EnterCriticalSection(&This->cs);
3222 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3224 if (hr == S_OK)
3225 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3227 LeaveCriticalSection(&This->cs);
3229 return hr;
3232 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3233 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3234 UINT *puArgErr)
3236 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3237 IBasicVideo *pBasicVideo;
3238 HRESULT hr;
3240 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);
3242 EnterCriticalSection(&This->cs);
3244 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3246 if (hr == S_OK)
3247 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3249 LeaveCriticalSection(&This->cs);
3251 return hr;
3254 /*** IBasicVideo methods ***/
3255 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3257 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3258 IBasicVideo *pBasicVideo;
3259 HRESULT hr;
3261 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3263 EnterCriticalSection(&This->cs);
3265 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3267 if (hr == S_OK)
3268 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3270 LeaveCriticalSection(&This->cs);
3272 return hr;
3275 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3277 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3278 IBasicVideo *pBasicVideo;
3279 HRESULT hr;
3281 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3283 EnterCriticalSection(&This->cs);
3285 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3287 if (hr == S_OK)
3288 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3290 LeaveCriticalSection(&This->cs);
3292 return hr;
3295 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3297 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3298 IBasicVideo *pBasicVideo;
3299 HRESULT hr;
3301 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3303 EnterCriticalSection(&This->cs);
3305 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3307 if (hr == S_OK)
3308 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3310 LeaveCriticalSection(&This->cs);
3312 return hr;
3315 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3317 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3318 IBasicVideo *pBasicVideo;
3319 HRESULT hr;
3321 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3323 EnterCriticalSection(&This->cs);
3325 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3327 if (hr == S_OK)
3328 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3330 LeaveCriticalSection(&This->cs);
3332 return hr;
3335 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3337 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3338 IBasicVideo *pBasicVideo;
3339 HRESULT hr;
3341 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3343 EnterCriticalSection(&This->cs);
3345 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3347 if (hr == S_OK)
3348 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3350 LeaveCriticalSection(&This->cs);
3352 return hr;
3355 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3357 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3358 IBasicVideo *pBasicVideo;
3359 HRESULT hr;
3361 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3363 EnterCriticalSection(&This->cs);
3365 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3367 if (hr == S_OK)
3368 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3370 LeaveCriticalSection(&This->cs);
3372 return hr;
3375 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3377 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3378 IBasicVideo *pBasicVideo;
3379 HRESULT hr;
3381 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3383 EnterCriticalSection(&This->cs);
3385 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3387 if (hr == S_OK)
3388 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3390 LeaveCriticalSection(&This->cs);
3392 return hr;
3395 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3397 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3398 IBasicVideo *pBasicVideo;
3399 HRESULT hr;
3401 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3403 EnterCriticalSection(&This->cs);
3405 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3407 if (hr == S_OK)
3408 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3410 LeaveCriticalSection(&This->cs);
3412 return hr;
3415 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3417 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3418 IBasicVideo *pBasicVideo;
3419 HRESULT hr;
3421 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3423 EnterCriticalSection(&This->cs);
3425 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3427 if (hr == S_OK)
3428 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3430 LeaveCriticalSection(&This->cs);
3432 return hr;
3435 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3437 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3438 IBasicVideo *pBasicVideo;
3439 HRESULT hr;
3441 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3443 EnterCriticalSection(&This->cs);
3445 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3447 if (hr == S_OK)
3448 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3450 LeaveCriticalSection(&This->cs);
3452 return hr;
3455 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3457 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3458 IBasicVideo *pBasicVideo;
3459 HRESULT hr;
3461 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3463 EnterCriticalSection(&This->cs);
3465 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3467 if (hr == S_OK)
3468 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3470 LeaveCriticalSection(&This->cs);
3472 return hr;
3475 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3477 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3478 IBasicVideo *pBasicVideo;
3479 HRESULT hr;
3481 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3483 EnterCriticalSection(&This->cs);
3485 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3487 if (hr == S_OK)
3488 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3490 LeaveCriticalSection(&This->cs);
3492 return hr;
3495 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3497 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3498 IBasicVideo *pBasicVideo;
3499 HRESULT hr;
3501 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3503 EnterCriticalSection(&This->cs);
3505 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3507 if (hr == S_OK)
3508 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3510 LeaveCriticalSection(&This->cs);
3512 return hr;
3515 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3517 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3518 IBasicVideo *pBasicVideo;
3519 HRESULT hr;
3521 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3523 EnterCriticalSection(&This->cs);
3525 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3527 if (hr == S_OK)
3528 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3530 LeaveCriticalSection(&This->cs);
3532 return hr;
3535 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3537 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3538 IBasicVideo *pBasicVideo;
3539 HRESULT hr;
3541 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3543 EnterCriticalSection(&This->cs);
3545 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3547 if (hr == S_OK)
3548 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3550 LeaveCriticalSection(&This->cs);
3552 return hr;
3555 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3557 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3558 IBasicVideo *pBasicVideo;
3559 HRESULT hr;
3561 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3563 EnterCriticalSection(&This->cs);
3565 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3567 if (hr == S_OK)
3568 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3570 LeaveCriticalSection(&This->cs);
3572 return hr;
3575 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3577 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3578 IBasicVideo *pBasicVideo;
3579 HRESULT hr;
3581 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3583 EnterCriticalSection(&This->cs);
3585 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3587 if (hr == S_OK)
3588 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3590 LeaveCriticalSection(&This->cs);
3592 return hr;
3595 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3597 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3598 IBasicVideo *pBasicVideo;
3599 HRESULT hr;
3601 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3603 EnterCriticalSection(&This->cs);
3605 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3607 if (hr == S_OK)
3608 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3610 LeaveCriticalSection(&This->cs);
3612 return hr;
3615 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3617 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3618 IBasicVideo *pBasicVideo;
3619 HRESULT hr;
3621 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3623 EnterCriticalSection(&This->cs);
3625 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3627 if (hr == S_OK)
3628 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3630 LeaveCriticalSection(&This->cs);
3632 return hr;
3635 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3637 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3638 IBasicVideo *pBasicVideo;
3639 HRESULT hr;
3641 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3643 EnterCriticalSection(&This->cs);
3645 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3647 if (hr == S_OK)
3648 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3650 LeaveCriticalSection(&This->cs);
3652 return hr;
3655 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3656 LONG *pDestinationHeight)
3658 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3659 IBasicVideo *pBasicVideo;
3660 HRESULT hr;
3662 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3664 EnterCriticalSection(&This->cs);
3666 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3668 if (hr == S_OK)
3669 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3671 LeaveCriticalSection(&This->cs);
3673 return hr;
3676 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3677 LONG Width, LONG Height)
3679 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3680 IBasicVideo *pBasicVideo;
3681 HRESULT hr;
3683 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3685 EnterCriticalSection(&This->cs);
3687 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3689 if (hr == S_OK)
3690 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3692 LeaveCriticalSection(&This->cs);
3694 return hr;
3697 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3698 LONG *pWidth, LONG *pHeight)
3700 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3701 IBasicVideo *pBasicVideo;
3702 HRESULT hr;
3704 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3706 EnterCriticalSection(&This->cs);
3708 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3710 if (hr == S_OK)
3711 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3713 LeaveCriticalSection(&This->cs);
3715 return hr;
3718 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3720 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3721 IBasicVideo *pBasicVideo;
3722 HRESULT hr;
3724 TRACE("(%p/%p)->()\n", This, iface);
3726 EnterCriticalSection(&This->cs);
3728 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3730 if (hr == S_OK)
3731 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3733 LeaveCriticalSection(&This->cs);
3735 return hr;
3738 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3739 LONG Width, LONG Height)
3741 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3742 IBasicVideo *pBasicVideo;
3743 HRESULT hr;
3745 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3747 EnterCriticalSection(&This->cs);
3749 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3751 if (hr == S_OK)
3752 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3754 LeaveCriticalSection(&This->cs);
3756 return hr;
3759 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3760 LONG *pTop, LONG *pWidth, LONG *pHeight)
3762 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3763 IBasicVideo *pBasicVideo;
3764 HRESULT hr;
3766 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3768 EnterCriticalSection(&This->cs);
3770 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3772 if (hr == S_OK)
3773 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3775 LeaveCriticalSection(&This->cs);
3777 return hr;
3780 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3782 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3783 IBasicVideo *pBasicVideo;
3784 HRESULT hr;
3786 TRACE("(%p/%p)->()\n", This, iface);
3788 EnterCriticalSection(&This->cs);
3790 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3792 if (hr == S_OK)
3793 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3795 LeaveCriticalSection(&This->cs);
3797 return hr;
3800 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3802 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3803 IBasicVideo *pBasicVideo;
3804 HRESULT hr;
3806 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3808 EnterCriticalSection(&This->cs);
3810 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3812 if (hr == S_OK)
3813 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3815 LeaveCriticalSection(&This->cs);
3817 return hr;
3820 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3821 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3823 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3824 IBasicVideo *pBasicVideo;
3825 HRESULT hr;
3827 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3829 EnterCriticalSection(&This->cs);
3831 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3833 if (hr == S_OK)
3834 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3836 LeaveCriticalSection(&This->cs);
3838 return hr;
3841 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3842 LONG *pDIBImage)
3844 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3845 IBasicVideo *pBasicVideo;
3846 HRESULT hr;
3848 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3850 EnterCriticalSection(&This->cs);
3852 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3854 if (hr == S_OK)
3855 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3857 LeaveCriticalSection(&This->cs);
3859 return hr;
3862 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3864 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3865 IBasicVideo *pBasicVideo;
3866 HRESULT hr;
3868 TRACE("(%p/%p)->()\n", This, iface);
3870 EnterCriticalSection(&This->cs);
3872 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3874 if (hr == S_OK)
3875 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3877 LeaveCriticalSection(&This->cs);
3879 return hr;
3882 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
3884 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3885 IBasicVideo *pBasicVideo;
3886 HRESULT hr;
3888 TRACE("(%p/%p)->()\n", This, iface);
3890 EnterCriticalSection(&This->cs);
3892 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3894 if (hr == S_OK)
3895 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3897 LeaveCriticalSection(&This->cs);
3899 return hr;
3902 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
3903 LONG *plAspectY)
3905 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3906 IBasicVideo2 *pBasicVideo2;
3907 HRESULT hr;
3909 TRACE("(%p/%p)->()\n", This, iface);
3911 EnterCriticalSection(&This->cs);
3913 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3915 if (hr == S_OK)
3916 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3918 LeaveCriticalSection(&This->cs);
3920 return hr;
3923 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3925 BasicVideo_QueryInterface,
3926 BasicVideo_AddRef,
3927 BasicVideo_Release,
3928 BasicVideo_GetTypeInfoCount,
3929 BasicVideo_GetTypeInfo,
3930 BasicVideo_GetIDsOfNames,
3931 BasicVideo_Invoke,
3932 BasicVideo_get_AvgTimePerFrame,
3933 BasicVideo_get_BitRate,
3934 BasicVideo_get_BitErrorRate,
3935 BasicVideo_get_VideoWidth,
3936 BasicVideo_get_VideoHeight,
3937 BasicVideo_put_SourceLeft,
3938 BasicVideo_get_SourceLeft,
3939 BasicVideo_put_SourceWidth,
3940 BasicVideo_get_SourceWidth,
3941 BasicVideo_put_SourceTop,
3942 BasicVideo_get_SourceTop,
3943 BasicVideo_put_SourceHeight,
3944 BasicVideo_get_SourceHeight,
3945 BasicVideo_put_DestinationLeft,
3946 BasicVideo_get_DestinationLeft,
3947 BasicVideo_put_DestinationWidth,
3948 BasicVideo_get_DestinationWidth,
3949 BasicVideo_put_DestinationTop,
3950 BasicVideo_get_DestinationTop,
3951 BasicVideo_put_DestinationHeight,
3952 BasicVideo_get_DestinationHeight,
3953 BasicVideo_SetSourcePosition,
3954 BasicVideo_GetSourcePosition,
3955 BasicVideo_SetDefaultSourcePosition,
3956 BasicVideo_SetDestinationPosition,
3957 BasicVideo_GetDestinationPosition,
3958 BasicVideo_SetDefaultDestinationPosition,
3959 BasicVideo_GetVideoSize,
3960 BasicVideo_GetVideoPaletteEntries,
3961 BasicVideo_GetCurrentImage,
3962 BasicVideo_IsUsingDefaultSource,
3963 BasicVideo_IsUsingDefaultDestination,
3964 BasicVideo2_GetPreferredAspectRatio
3967 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
3969 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
3972 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
3974 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3976 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3978 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3981 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
3983 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3985 TRACE("(%p/%p)->()\n", This, iface);
3987 return IUnknown_AddRef(This->outer_unk);
3990 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
3992 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3994 TRACE("(%p/%p)->()\n", This, iface);
3996 return IUnknown_Release(This->outer_unk);
3999 /*** IDispatch methods ***/
4000 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4002 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4003 IVideoWindow *pVideoWindow;
4004 HRESULT hr;
4006 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4008 EnterCriticalSection(&This->cs);
4010 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4012 if (hr == S_OK)
4013 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4015 LeaveCriticalSection(&This->cs);
4017 return hr;
4020 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4021 ITypeInfo **ppTInfo)
4023 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4024 IVideoWindow *pVideoWindow;
4025 HRESULT hr;
4027 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4029 EnterCriticalSection(&This->cs);
4031 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4033 if (hr == S_OK)
4034 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4036 LeaveCriticalSection(&This->cs);
4038 return hr;
4041 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4042 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4044 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4045 IVideoWindow *pVideoWindow;
4046 HRESULT hr;
4048 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4050 EnterCriticalSection(&This->cs);
4052 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4054 if (hr == S_OK)
4055 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4057 LeaveCriticalSection(&This->cs);
4059 return hr;
4062 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4063 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4064 UINT*puArgErr)
4066 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4067 IVideoWindow *pVideoWindow;
4068 HRESULT hr;
4070 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);
4072 EnterCriticalSection(&This->cs);
4074 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4076 if (hr == S_OK)
4077 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4079 LeaveCriticalSection(&This->cs);
4081 return hr;
4085 /*** IVideoWindow methods ***/
4086 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4088 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4089 IVideoWindow *pVideoWindow;
4090 HRESULT hr;
4092 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4094 EnterCriticalSection(&This->cs);
4096 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4098 if (hr == S_OK)
4099 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4101 LeaveCriticalSection(&This->cs);
4103 return hr;
4106 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4108 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4109 IVideoWindow *pVideoWindow;
4110 HRESULT hr;
4112 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4114 EnterCriticalSection(&This->cs);
4116 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4118 if (hr == S_OK)
4119 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4121 LeaveCriticalSection(&This->cs);
4123 return hr;
4126 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4128 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4129 IVideoWindow *pVideoWindow;
4130 HRESULT hr;
4132 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4134 EnterCriticalSection(&This->cs);
4136 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4138 if (hr == S_OK)
4139 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4141 LeaveCriticalSection(&This->cs);
4143 return hr;
4146 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4148 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4149 IVideoWindow *pVideoWindow;
4150 HRESULT hr;
4152 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4154 EnterCriticalSection(&This->cs);
4156 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4158 if (hr == S_OK)
4159 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4161 LeaveCriticalSection(&This->cs);
4163 return hr;
4166 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4168 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4169 IVideoWindow *pVideoWindow;
4170 HRESULT hr;
4172 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4174 EnterCriticalSection(&This->cs);
4176 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4178 if (hr == S_OK)
4179 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4181 LeaveCriticalSection(&This->cs);
4183 return hr;
4186 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4188 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4189 IVideoWindow *pVideoWindow;
4190 HRESULT hr;
4192 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4194 EnterCriticalSection(&This->cs);
4196 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4198 if (hr == S_OK)
4199 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4201 LeaveCriticalSection(&This->cs);
4203 return hr;
4206 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4208 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4209 IVideoWindow *pVideoWindow;
4210 HRESULT hr;
4212 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4214 EnterCriticalSection(&This->cs);
4216 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4218 if (hr == S_OK)
4219 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4221 LeaveCriticalSection(&This->cs);
4223 return hr;
4226 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4228 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4229 IVideoWindow *pVideoWindow;
4230 HRESULT hr;
4232 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4234 EnterCriticalSection(&This->cs);
4236 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4238 if (hr == S_OK)
4239 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4241 LeaveCriticalSection(&This->cs);
4243 return hr;
4246 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4248 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4249 IVideoWindow *pVideoWindow;
4250 HRESULT hr;
4252 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4254 EnterCriticalSection(&This->cs);
4256 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4258 if (hr == S_OK)
4259 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4261 LeaveCriticalSection(&This->cs);
4263 return hr;
4266 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4268 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4269 IVideoWindow *pVideoWindow;
4270 HRESULT hr;
4272 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4274 EnterCriticalSection(&This->cs);
4276 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4278 if (hr == S_OK)
4279 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4281 LeaveCriticalSection(&This->cs);
4283 return hr;
4286 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4288 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4289 IVideoWindow *pVideoWindow;
4290 HRESULT hr;
4292 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4294 EnterCriticalSection(&This->cs);
4296 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4298 if (hr == S_OK)
4299 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4301 LeaveCriticalSection(&This->cs);
4303 return hr;
4306 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4307 LONG *pBackgroundPalette)
4309 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4310 IVideoWindow *pVideoWindow;
4311 HRESULT hr;
4313 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4315 EnterCriticalSection(&This->cs);
4317 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4319 if (hr == S_OK)
4320 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4322 LeaveCriticalSection(&This->cs);
4324 return hr;
4327 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4329 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4330 IVideoWindow *pVideoWindow;
4331 HRESULT hr;
4333 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4335 EnterCriticalSection(&This->cs);
4337 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4339 if (hr == S_OK)
4340 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4342 LeaveCriticalSection(&This->cs);
4344 return hr;
4347 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4349 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4350 IVideoWindow *pVideoWindow;
4351 HRESULT hr;
4353 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4355 EnterCriticalSection(&This->cs);
4357 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4359 if (hr == S_OK)
4360 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4362 LeaveCriticalSection(&This->cs);
4364 return hr;
4367 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4369 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4370 IVideoWindow *pVideoWindow;
4371 HRESULT hr;
4373 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4375 EnterCriticalSection(&This->cs);
4377 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4379 if (hr == S_OK)
4380 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4382 LeaveCriticalSection(&This->cs);
4384 return hr;
4387 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4389 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4390 IVideoWindow *pVideoWindow;
4391 HRESULT hr;
4393 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4395 EnterCriticalSection(&This->cs);
4397 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4399 if (hr == S_OK)
4400 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4402 LeaveCriticalSection(&This->cs);
4404 return hr;
4407 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4409 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4410 IVideoWindow *pVideoWindow;
4411 HRESULT hr;
4413 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4415 EnterCriticalSection(&This->cs);
4417 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4419 if (hr == S_OK)
4420 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4422 LeaveCriticalSection(&This->cs);
4424 return hr;
4427 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4429 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4430 IVideoWindow *pVideoWindow;
4431 HRESULT hr;
4433 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4435 EnterCriticalSection(&This->cs);
4437 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4439 if (hr == S_OK)
4440 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4442 LeaveCriticalSection(&This->cs);
4444 return hr;
4447 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4449 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4450 IVideoWindow *pVideoWindow;
4451 HRESULT hr;
4453 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4455 EnterCriticalSection(&This->cs);
4457 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4459 if (hr == S_OK)
4460 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4462 LeaveCriticalSection(&This->cs);
4464 return hr;
4467 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4469 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4470 IVideoWindow *pVideoWindow;
4471 HRESULT hr;
4473 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4475 EnterCriticalSection(&This->cs);
4477 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4479 if (hr == S_OK)
4480 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4482 LeaveCriticalSection(&This->cs);
4484 return hr;
4487 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4489 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4490 IVideoWindow *pVideoWindow;
4491 HRESULT hr;
4493 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4495 EnterCriticalSection(&This->cs);
4497 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4499 if (hr == S_OK)
4500 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4502 LeaveCriticalSection(&This->cs);
4504 return hr;
4507 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4509 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4510 IVideoWindow *pVideoWindow;
4511 HRESULT hr;
4513 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4515 EnterCriticalSection(&This->cs);
4517 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4519 if (hr == S_OK)
4520 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4522 LeaveCriticalSection(&This->cs);
4524 return hr;
4527 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4529 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4530 IVideoWindow *pVideoWindow;
4531 HRESULT hr;
4533 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4535 EnterCriticalSection(&This->cs);
4537 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4539 if (hr == S_OK)
4540 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4542 LeaveCriticalSection(&This->cs);
4544 return hr;
4547 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4549 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4550 IVideoWindow *pVideoWindow;
4551 HRESULT hr;
4553 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4555 EnterCriticalSection(&This->cs);
4557 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4559 if (hr == S_OK)
4560 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4562 LeaveCriticalSection(&This->cs);
4564 return hr;
4567 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4569 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4570 IVideoWindow *pVideoWindow;
4571 HRESULT hr;
4573 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4575 EnterCriticalSection(&This->cs);
4577 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4579 if (hr == S_OK)
4580 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4582 LeaveCriticalSection(&This->cs);
4584 return hr;
4587 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4589 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4590 IVideoWindow *pVideoWindow;
4591 HRESULT hr;
4593 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4595 EnterCriticalSection(&This->cs);
4597 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4599 if (hr == S_OK)
4600 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4602 LeaveCriticalSection(&This->cs);
4604 return hr;
4607 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4609 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4610 IVideoWindow *pVideoWindow;
4611 HRESULT hr;
4613 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4615 EnterCriticalSection(&This->cs);
4617 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4619 if (hr == S_OK)
4620 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4622 LeaveCriticalSection(&This->cs);
4624 return hr;
4627 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4629 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4630 IVideoWindow *pVideoWindow;
4631 HRESULT hr;
4633 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4635 EnterCriticalSection(&This->cs);
4637 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4639 if (hr == S_OK)
4640 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4642 LeaveCriticalSection(&This->cs);
4644 return hr;
4647 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4649 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4650 IVideoWindow *pVideoWindow;
4651 HRESULT hr;
4653 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4655 EnterCriticalSection(&This->cs);
4657 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4659 if (hr == S_OK)
4660 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4662 LeaveCriticalSection(&This->cs);
4664 return hr;
4667 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4669 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4670 IVideoWindow *pVideoWindow;
4671 HRESULT hr;
4673 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4675 EnterCriticalSection(&This->cs);
4677 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4679 if (hr == S_OK)
4680 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4682 LeaveCriticalSection(&This->cs);
4684 return hr;
4687 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4689 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4690 IVideoWindow *pVideoWindow;
4691 HRESULT hr;
4693 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4695 EnterCriticalSection(&This->cs);
4697 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4699 if (hr == S_OK)
4700 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4702 LeaveCriticalSection(&This->cs);
4704 return hr;
4707 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4708 LONG_PTR wParam, LONG_PTR lParam)
4710 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4711 IVideoWindow *pVideoWindow;
4712 HRESULT hr;
4714 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4716 EnterCriticalSection(&This->cs);
4718 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4720 if (hr == S_OK)
4721 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4723 LeaveCriticalSection(&This->cs);
4725 return hr;
4728 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4729 LONG Width, LONG Height)
4731 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4732 IVideoWindow *pVideoWindow;
4733 HRESULT hr;
4735 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4737 EnterCriticalSection(&This->cs);
4739 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4741 if (hr == S_OK)
4742 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4744 LeaveCriticalSection(&This->cs);
4746 return hr;
4749 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4750 LONG *pWidth, LONG *pHeight)
4752 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4753 IVideoWindow *pVideoWindow;
4754 HRESULT hr;
4756 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4758 EnterCriticalSection(&This->cs);
4760 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4762 if (hr == S_OK)
4763 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4765 LeaveCriticalSection(&This->cs);
4767 return hr;
4770 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4771 LONG *pHeight)
4773 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4774 IVideoWindow *pVideoWindow;
4775 HRESULT hr;
4777 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4779 EnterCriticalSection(&This->cs);
4781 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4783 if (hr == S_OK)
4784 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4786 LeaveCriticalSection(&This->cs);
4788 return hr;
4791 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4792 LONG *pHeight)
4794 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4795 IVideoWindow *pVideoWindow;
4796 HRESULT hr;
4798 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4800 EnterCriticalSection(&This->cs);
4802 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4804 if (hr == S_OK)
4805 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4807 LeaveCriticalSection(&This->cs);
4809 return hr;
4812 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4813 LONG *pWidth, LONG *pHeight)
4815 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4816 IVideoWindow *pVideoWindow;
4817 HRESULT hr;
4819 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4821 EnterCriticalSection(&This->cs);
4823 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4825 if (hr == S_OK)
4826 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4828 LeaveCriticalSection(&This->cs);
4830 return hr;
4833 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4835 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4836 IVideoWindow *pVideoWindow;
4837 HRESULT hr;
4839 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4841 EnterCriticalSection(&This->cs);
4843 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4845 if (hr == S_OK)
4846 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4848 LeaveCriticalSection(&This->cs);
4850 return hr;
4853 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4855 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4856 IVideoWindow *pVideoWindow;
4857 HRESULT hr;
4859 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4861 EnterCriticalSection(&This->cs);
4863 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4865 if (hr == S_OK)
4866 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4868 LeaveCriticalSection(&This->cs);
4870 return hr;
4874 static const IVideoWindowVtbl IVideoWindow_VTable =
4876 VideoWindow_QueryInterface,
4877 VideoWindow_AddRef,
4878 VideoWindow_Release,
4879 VideoWindow_GetTypeInfoCount,
4880 VideoWindow_GetTypeInfo,
4881 VideoWindow_GetIDsOfNames,
4882 VideoWindow_Invoke,
4883 VideoWindow_put_Caption,
4884 VideoWindow_get_Caption,
4885 VideoWindow_put_WindowStyle,
4886 VideoWindow_get_WindowStyle,
4887 VideoWindow_put_WindowStyleEx,
4888 VideoWindow_get_WindowStyleEx,
4889 VideoWindow_put_AutoShow,
4890 VideoWindow_get_AutoShow,
4891 VideoWindow_put_WindowState,
4892 VideoWindow_get_WindowState,
4893 VideoWindow_put_BackgroundPalette,
4894 VideoWindow_get_BackgroundPalette,
4895 VideoWindow_put_Visible,
4896 VideoWindow_get_Visible,
4897 VideoWindow_put_Left,
4898 VideoWindow_get_Left,
4899 VideoWindow_put_Width,
4900 VideoWindow_get_Width,
4901 VideoWindow_put_Top,
4902 VideoWindow_get_Top,
4903 VideoWindow_put_Height,
4904 VideoWindow_get_Height,
4905 VideoWindow_put_Owner,
4906 VideoWindow_get_Owner,
4907 VideoWindow_put_MessageDrain,
4908 VideoWindow_get_MessageDrain,
4909 VideoWindow_get_BorderColor,
4910 VideoWindow_put_BorderColor,
4911 VideoWindow_get_FullScreenMode,
4912 VideoWindow_put_FullScreenMode,
4913 VideoWindow_SetWindowForeground,
4914 VideoWindow_NotifyOwnerMessage,
4915 VideoWindow_SetWindowPosition,
4916 VideoWindow_GetWindowPosition,
4917 VideoWindow_GetMinIdealImageSize,
4918 VideoWindow_GetMaxIdealImageSize,
4919 VideoWindow_GetRestorePosition,
4920 VideoWindow_HideCursor,
4921 VideoWindow_IsCursorHidden
4924 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
4926 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
4929 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
4931 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4933 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4935 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4938 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
4940 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4942 TRACE("(%p/%p)->()\n", This, iface);
4944 return IUnknown_AddRef(This->outer_unk);
4947 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
4949 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4951 TRACE("(%p/%p)->()\n", This, iface);
4953 return IUnknown_Release(This->outer_unk);
4956 /*** IDispatch methods ***/
4957 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
4959 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4961 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4963 return S_OK;
4966 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
4967 ITypeInfo **ppTInfo)
4969 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4971 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4973 return S_OK;
4976 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
4977 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4979 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4981 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4983 return S_OK;
4986 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
4987 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4988 UINT *puArgErr)
4990 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4992 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);
4994 return S_OK;
4997 /*** IMediaEvent methods ***/
4998 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5000 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5002 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5004 *hEvent = (OAEVENT)This->evqueue.msg_event;
5006 return S_OK;
5009 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5010 LONG_PTR *lParam2, LONG msTimeout)
5012 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5013 Event evt;
5015 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5017 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5019 *lEventCode = evt.lEventCode;
5020 *lParam1 = evt.lParam1;
5021 *lParam2 = evt.lParam2;
5022 return S_OK;
5025 *lEventCode = 0;
5026 return E_ABORT;
5029 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5030 LONG *pEvCode)
5032 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5034 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5036 if (This->state != State_Running)
5037 return VFW_E_WRONG_STATE;
5039 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5041 *pEvCode = This->CompletionStatus;
5042 return S_OK;
5045 *pEvCode = 0;
5046 return E_ABORT;
5049 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5051 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5053 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5055 if (lEvCode == EC_COMPLETE)
5056 This->HandleEcComplete = FALSE;
5057 else if (lEvCode == EC_REPAINT)
5058 This->HandleEcRepaint = FALSE;
5059 else if (lEvCode == EC_CLOCK_CHANGED)
5060 This->HandleEcClockChanged = FALSE;
5061 else
5062 return S_FALSE;
5064 return S_OK;
5067 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5069 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5071 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5073 if (lEvCode == EC_COMPLETE)
5074 This->HandleEcComplete = TRUE;
5075 else if (lEvCode == EC_REPAINT)
5076 This->HandleEcRepaint = TRUE;
5077 else if (lEvCode == EC_CLOCK_CHANGED)
5078 This->HandleEcClockChanged = TRUE;
5079 else
5080 return S_FALSE;
5082 return S_OK;
5085 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5086 LONG_PTR lParam1, LONG_PTR lParam2)
5088 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5090 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5092 return S_OK;
5095 /*** IMediaEventEx methods ***/
5096 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5097 LONG_PTR lInstanceData)
5099 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5101 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5103 This->notif.hWnd = (HWND)hwnd;
5104 This->notif.msg = lMsg;
5105 This->notif.instance = lInstanceData;
5107 return S_OK;
5110 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5112 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5114 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5116 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5117 return E_INVALIDARG;
5119 This->notif.disabled = lNoNotifyFlags;
5121 return S_OK;
5124 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5126 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5128 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5130 if (!lplNoNotifyFlags)
5131 return E_POINTER;
5133 *lplNoNotifyFlags = This->notif.disabled;
5135 return S_OK;
5139 static const IMediaEventExVtbl IMediaEventEx_VTable =
5141 MediaEvent_QueryInterface,
5142 MediaEvent_AddRef,
5143 MediaEvent_Release,
5144 MediaEvent_GetTypeInfoCount,
5145 MediaEvent_GetTypeInfo,
5146 MediaEvent_GetIDsOfNames,
5147 MediaEvent_Invoke,
5148 MediaEvent_GetEventHandle,
5149 MediaEvent_GetEvent,
5150 MediaEvent_WaitForCompletion,
5151 MediaEvent_CancelDefaultHandling,
5152 MediaEvent_RestoreDefaultHandling,
5153 MediaEvent_FreeEventParams,
5154 MediaEvent_SetNotifyWindow,
5155 MediaEvent_SetNotifyFlags,
5156 MediaEvent_GetNotifyFlags
5160 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5162 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5165 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5167 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5169 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5172 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5174 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5176 return IUnknown_AddRef(This->outer_unk);
5179 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5181 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5183 return IUnknown_Release(This->outer_unk);
5186 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5188 FIXME("(%p): stub\n", pClassID);
5190 return E_NOTIMPL;
5193 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5195 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5197 return MediaControl_Stop(&This->IMediaControl_iface);
5200 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5202 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5204 return MediaControl_Pause(&This->IMediaControl_iface);
5207 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5209 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5211 if (tStart)
5212 FIXME("Run called with non-null tStart: %x%08x\n",
5213 (int)(tStart>>32), (int)tStart);
5215 return MediaControl_Run(&This->IMediaControl_iface);
5218 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
5219 FILTER_STATE *pState)
5221 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5223 return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
5226 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5228 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5229 HRESULT hr = S_OK;
5230 int i;
5232 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5234 EnterCriticalSection(&This->cs);
5236 for (i = 0;i < This->nFilters;i++)
5238 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5239 if (FAILED(hr))
5240 break;
5243 if (FAILED(hr))
5245 for(;i >= 0;i--)
5246 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5248 else
5250 if (This->refClock)
5251 IReferenceClock_Release(This->refClock);
5252 This->refClock = pClock;
5253 if (This->refClock)
5254 IReferenceClock_AddRef(This->refClock);
5255 This->defaultclock = FALSE;
5257 if (This->HandleEcClockChanged)
5259 IMediaEventSink *pEventSink;
5260 HRESULT eshr;
5262 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5263 if (SUCCEEDED(eshr))
5265 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5266 IMediaEventSink_Release(pEventSink);
5271 LeaveCriticalSection(&This->cs);
5273 return hr;
5276 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5278 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5280 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5282 if (!ppClock)
5283 return E_POINTER;
5285 EnterCriticalSection(&This->cs);
5287 *ppClock = This->refClock;
5288 if (*ppClock)
5289 IReferenceClock_AddRef(*ppClock);
5291 LeaveCriticalSection(&This->cs);
5293 return S_OK;
5296 static const IMediaFilterVtbl IMediaFilter_VTable =
5298 MediaFilter_QueryInterface,
5299 MediaFilter_AddRef,
5300 MediaFilter_Release,
5301 MediaFilter_GetClassID,
5302 MediaFilter_Stop,
5303 MediaFilter_Pause,
5304 MediaFilter_Run,
5305 MediaFilter_GetState,
5306 MediaFilter_SetSyncSource,
5307 MediaFilter_GetSyncSource
5310 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5312 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5315 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5317 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5319 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5322 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5324 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5326 return IUnknown_AddRef(This->outer_unk);
5329 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5331 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5333 return IUnknown_Release(This->outer_unk);
5336 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5337 LONG_PTR EventParam1, LONG_PTR EventParam2)
5339 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5340 Event evt;
5342 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5344 /* We need thread safety here, let's use the events queue's one */
5345 EnterCriticalSection(&This->evqueue.msg_crst);
5347 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5349 TRACE("Process EC_COMPLETE notification\n");
5350 if (++This->EcCompleteCount == This->nRenderers)
5352 evt.lEventCode = EC_COMPLETE;
5353 evt.lParam1 = S_OK;
5354 evt.lParam2 = 0;
5355 TRACE("Send EC_COMPLETE to app\n");
5356 EventsQueue_PutEvent(&This->evqueue, &evt);
5357 if (!This->notif.disabled && This->notif.hWnd)
5359 TRACE("Send Window message\n");
5360 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5362 This->CompletionStatus = EC_COMPLETE;
5363 SetEvent(This->hEventCompletion);
5366 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5368 /* FIXME: Not handled yet */
5370 else
5372 evt.lEventCode = EventCode;
5373 evt.lParam1 = EventParam1;
5374 evt.lParam2 = EventParam2;
5375 EventsQueue_PutEvent(&This->evqueue, &evt);
5376 if (!This->notif.disabled && This->notif.hWnd)
5377 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5380 LeaveCriticalSection(&This->evqueue.msg_crst);
5381 return S_OK;
5384 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5386 MediaEventSink_QueryInterface,
5387 MediaEventSink_AddRef,
5388 MediaEventSink_Release,
5389 MediaEventSink_Notify
5392 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5394 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5397 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5399 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5401 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5404 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5406 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5408 return IUnknown_AddRef(This->outer_unk);
5411 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5413 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5415 return IUnknown_Release(This->outer_unk);
5418 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5419 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5420 DWORD dwFlags)
5422 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5424 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5426 return E_NOTIMPL;
5429 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5430 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5432 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5433 HRESULT hr;
5435 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5437 if (hAbortEvent)
5438 FIXME("The parameter hAbortEvent is not handled!\n");
5440 EnterCriticalSection(&This->cs);
5442 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5444 LeaveCriticalSection(&This->cs);
5446 return hr;
5449 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5451 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5453 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5455 return E_NOTIMPL;
5458 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5460 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5462 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5464 return E_NOTIMPL;
5467 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5469 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5471 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5473 return E_NOTIMPL;
5476 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5478 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5480 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5482 return E_NOTIMPL;
5485 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5486 IPinConnection *pConnection, HANDLE hEventAbort)
5488 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5490 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5492 return E_NOTIMPL;
5495 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5496 DWORD dwFlags)
5498 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5500 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5502 return E_NOTIMPL;
5505 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5506 DWORD *dwFlags)
5508 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5510 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5512 return E_NOTIMPL;
5515 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5516 DWORD dwFlags)
5518 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5520 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5522 return E_NOTIMPL;
5525 static const IGraphConfigVtbl IGraphConfig_VTable =
5527 GraphConfig_QueryInterface,
5528 GraphConfig_AddRef,
5529 GraphConfig_Release,
5530 GraphConfig_Reconnect,
5531 GraphConfig_Reconfigure,
5532 GraphConfig_AddFilterToCache,
5533 GraphConfig_EnumCacheFilter,
5534 GraphConfig_RemoveFilterFromCache,
5535 GraphConfig_GetStartTime,
5536 GraphConfig_PushThroughData,
5537 GraphConfig_SetFilterFlags,
5538 GraphConfig_GetFilterFlags,
5539 GraphConfig_RemoveFilterEx
5542 static const IUnknownVtbl IInner_VTable =
5544 FilterGraphInner_QueryInterface,
5545 FilterGraphInner_AddRef,
5546 FilterGraphInner_Release
5549 /* This is the only function that actually creates a FilterGraph class... */
5550 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5552 IFilterGraphImpl *fimpl;
5553 HRESULT hr;
5555 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5557 *ppObj = NULL;
5559 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5560 fimpl->defaultclock = TRUE;
5561 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5562 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5563 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5564 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5565 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5566 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5567 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5568 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5569 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5570 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5571 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5572 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5573 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5574 fimpl->ref = 1;
5575 fimpl->ppFiltersInGraph = NULL;
5576 fimpl->pFilterNames = NULL;
5577 fimpl->nFilters = 0;
5578 fimpl->filterCapacity = 0;
5579 fimpl->nameIndex = 1;
5580 fimpl->refClock = NULL;
5581 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5582 fimpl->HandleEcComplete = TRUE;
5583 fimpl->HandleEcRepaint = TRUE;
5584 fimpl->HandleEcClockChanged = TRUE;
5585 fimpl->notif.hWnd = 0;
5586 fimpl->notif.disabled = FALSE;
5587 fimpl->nRenderers = 0;
5588 fimpl->EcCompleteCount = 0;
5589 fimpl->refClockProvider = NULL;
5590 fimpl->state = State_Stopped;
5591 fimpl->pSite = NULL;
5592 EventsQueue_Init(&fimpl->evqueue);
5593 InitializeCriticalSection(&fimpl->cs);
5594 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5595 fimpl->nItfCacheEntries = 0;
5596 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5597 fimpl->start_time = fimpl->pause_time = 0;
5598 fimpl->stop_position = -1;
5599 fimpl->punkFilterMapper2 = NULL;
5600 fimpl->recursioncount = 0;
5602 if (pUnkOuter)
5603 fimpl->outer_unk = pUnkOuter;
5604 else
5605 fimpl->outer_unk = &fimpl->IUnknown_inner;
5607 /* create Filtermapper aggregated. */
5608 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5609 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5611 if (SUCCEEDED(hr))
5612 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2,
5613 (void**)&fimpl->pFilterMapper2);
5615 if (SUCCEEDED(hr))
5616 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5617 IUnknown_Release(fimpl->outer_unk);
5619 if (FAILED(hr)) {
5620 ERR("Unable to create filter mapper (%x)\n", hr);
5621 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5622 CloseHandle(fimpl->hEventCompletion);
5623 EventsQueue_Destroy(&fimpl->evqueue);
5624 fimpl->cs.DebugInfo->Spare[0] = 0;
5625 DeleteCriticalSection(&fimpl->cs);
5626 CoTaskMemFree(fimpl);
5627 return hr;
5630 *ppObj = &fimpl->IUnknown_inner;
5631 return S_OK;
5634 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5636 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5637 return FilterGraph_create(pUnkOuter, ppObj);