msvcp: Sync istream<>::peek implementations.
[wine.git] / dlls / quartz / filtergraph.c
blobc31de59bf7f307d836323760acbfba0164a1090f
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)->()\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)->()\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 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename);
2096 return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL);
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)
2643 FIXME("(%p) stub!\n", iface);
2644 return E_NOTIMPL;
2647 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2649 FIXME("(%p) stub!\n", iface);
2650 return E_NOTIMPL;
2653 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
2655 FIXME("(%p) stub!\n", iface);
2656 return E_NOTIMPL;
2659 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2661 FIXME("(%p) stub!\n", iface);
2662 return E_NOTIMPL;
2665 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2667 GUID time_format;
2668 HRESULT hr;
2670 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2671 if (FAILED(hr))
2672 return hr;
2673 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2675 FIXME("Unsupported time format.\n");
2676 return E_NOTIMPL;
2679 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2680 return S_OK;
2683 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2685 GUID time_format;
2686 HRESULT hr;
2688 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2689 if (FAILED(hr))
2690 return hr;
2691 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2693 FIXME("Unsupported time format.\n");
2694 return E_NOTIMPL;
2697 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2698 return S_OK;
2701 /*** IMediaPosition methods ***/
2702 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2704 LONGLONG duration;
2705 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2706 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2707 if (FAILED(hr))
2708 return hr;
2709 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2712 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2714 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2715 LONGLONG reftime;
2716 HRESULT hr;
2718 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2719 if (FAILED(hr))
2720 return hr;
2721 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2722 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2725 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2727 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2728 LONGLONG pos;
2729 HRESULT hr;
2731 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2732 if (FAILED(hr))
2733 return hr;
2734 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2737 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2739 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2740 LONGLONG pos;
2741 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2742 if (FAILED(hr))
2743 return hr;
2744 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2747 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2749 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2750 LONGLONG reftime;
2751 HRESULT hr;
2753 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2754 if (FAILED(hr))
2755 return hr;
2756 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2757 &reftime, AM_SEEKING_AbsolutePositioning);
2760 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime)
2762 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2763 return E_NOTIMPL;
2766 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime)
2768 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2769 return E_NOTIMPL;
2772 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2774 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2775 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2778 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2780 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2781 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2784 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward)
2786 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2787 return E_NOTIMPL;
2790 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward)
2792 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2793 return E_NOTIMPL;
2797 static const IMediaPositionVtbl IMediaPosition_VTable =
2799 MediaPosition_QueryInterface,
2800 MediaPosition_AddRef,
2801 MediaPosition_Release,
2802 MediaPosition_GetTypeInfoCount,
2803 MediaPosition_GetTypeInfo,
2804 MediaPosition_GetIDsOfNames,
2805 MediaPosition_Invoke,
2806 MediaPosition_get_Duration,
2807 MediaPosition_put_CurrentPosition,
2808 MediaPosition_get_CurrentPosition,
2809 MediaPosition_get_StopTime,
2810 MediaPosition_put_StopTime,
2811 MediaPosition_get_PrerollTime,
2812 MediaPosition_put_PrerollTime,
2813 MediaPosition_put_Rate,
2814 MediaPosition_get_Rate,
2815 MediaPosition_CanSeekForward,
2816 MediaPosition_CanSeekBackward
2819 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2821 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2824 /*** IUnknown methods ***/
2825 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2827 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2829 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2831 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2834 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2836 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2838 TRACE("(%p/%p)->()\n", This, iface);
2840 return IUnknown_AddRef(This->outer_unk);
2843 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2845 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2847 TRACE("(%p/%p)->()\n", This, iface);
2849 return IUnknown_Release(This->outer_unk);
2852 /*** IObjectWithSite methods ***/
2854 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2856 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2858 TRACE("(%p/%p)->()\n", This, iface);
2859 if (This->pSite) IUnknown_Release(This->pSite);
2860 This->pSite = pUnkSite;
2861 IUnknown_AddRef(This->pSite);
2862 return S_OK;
2865 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2867 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2869 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2871 *ppvSite = NULL;
2872 if (!This->pSite)
2873 return E_FAIL;
2874 else
2875 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2878 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2880 ObjectWithSite_QueryInterface,
2881 ObjectWithSite_AddRef,
2882 ObjectWithSite_Release,
2883 ObjectWithSite_SetSite,
2884 ObjectWithSite_GetSite,
2887 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2889 HRESULT hr = E_NOINTERFACE;
2890 int i;
2891 int entry;
2893 /* Check if the interface type is already registered */
2894 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2895 if (riid == pGraph->ItfCacheEntries[entry].riid)
2897 if (pGraph->ItfCacheEntries[entry].iface)
2899 /* Return the interface if available */
2900 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2901 return S_OK;
2903 break;
2906 if (entry >= MAX_ITF_CACHE_ENTRIES)
2908 FIXME("Not enough space to store interface in the cache\n");
2909 return E_OUTOFMEMORY;
2912 /* Find a filter supporting the requested interface */
2913 for (i = 0; i < pGraph->nFilters; i++)
2915 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2916 if (hr == S_OK)
2918 pGraph->ItfCacheEntries[entry].riid = riid;
2919 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2920 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
2921 if (entry >= pGraph->nItfCacheEntries)
2922 pGraph->nItfCacheEntries++;
2923 return S_OK;
2925 if (hr != E_NOINTERFACE)
2926 return hr;
2929 return hr;
2932 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
2934 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
2937 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
2939 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2941 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2943 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2946 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
2948 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2950 TRACE("(%p/%p)->()\n", This, iface);
2952 return IUnknown_AddRef(This->outer_unk);
2955 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
2957 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2959 TRACE("(%p/%p)->()\n", This, iface);
2961 return IUnknown_Release(This->outer_unk);
2964 /*** IDispatch methods ***/
2965 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
2967 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2968 IBasicAudio* pBasicAudio;
2969 HRESULT hr;
2971 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2973 EnterCriticalSection(&This->cs);
2975 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2977 if (hr == S_OK)
2978 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2980 LeaveCriticalSection(&This->cs);
2982 return hr;
2985 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
2986 ITypeInfo **ppTInfo)
2988 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2989 IBasicAudio* pBasicAudio;
2990 HRESULT hr;
2992 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2994 EnterCriticalSection(&This->cs);
2996 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2998 if (hr == S_OK)
2999 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
3001 LeaveCriticalSection(&This->cs);
3003 return hr;
3006 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
3007 UINT cNames, LCID lcid, DISPID *rgDispId)
3009 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3010 IBasicAudio* pBasicAudio;
3011 HRESULT hr;
3013 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3015 EnterCriticalSection(&This->cs);
3017 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3019 if (hr == S_OK)
3020 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3022 LeaveCriticalSection(&This->cs);
3024 return hr;
3027 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3028 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3029 UINT *puArgErr)
3031 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3032 IBasicAudio* pBasicAudio;
3033 HRESULT hr;
3035 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);
3037 EnterCriticalSection(&This->cs);
3039 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3041 if (hr == S_OK)
3042 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3044 LeaveCriticalSection(&This->cs);
3046 return hr;
3049 /*** IBasicAudio methods ***/
3050 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3052 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3053 IBasicAudio* pBasicAudio;
3054 HRESULT hr;
3056 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3058 EnterCriticalSection(&This->cs);
3060 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3062 if (hr == S_OK)
3063 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3065 LeaveCriticalSection(&This->cs);
3067 return hr;
3070 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3072 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3073 IBasicAudio* pBasicAudio;
3074 HRESULT hr;
3076 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3078 EnterCriticalSection(&This->cs);
3080 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3082 if (hr == S_OK)
3083 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3085 LeaveCriticalSection(&This->cs);
3087 return hr;
3090 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3092 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3093 IBasicAudio* pBasicAudio;
3094 HRESULT hr;
3096 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3098 EnterCriticalSection(&This->cs);
3100 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3102 if (hr == S_OK)
3103 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3105 LeaveCriticalSection(&This->cs);
3107 return hr;
3110 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3112 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3113 IBasicAudio* pBasicAudio;
3114 HRESULT hr;
3116 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3118 EnterCriticalSection(&This->cs);
3120 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3122 if (hr == S_OK)
3123 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3125 LeaveCriticalSection(&This->cs);
3127 return hr;
3130 static const IBasicAudioVtbl IBasicAudio_VTable =
3132 BasicAudio_QueryInterface,
3133 BasicAudio_AddRef,
3134 BasicAudio_Release,
3135 BasicAudio_GetTypeInfoCount,
3136 BasicAudio_GetTypeInfo,
3137 BasicAudio_GetIDsOfNames,
3138 BasicAudio_Invoke,
3139 BasicAudio_put_Volume,
3140 BasicAudio_get_Volume,
3141 BasicAudio_put_Balance,
3142 BasicAudio_get_Balance
3145 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3147 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3150 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3152 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3154 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3156 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3159 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3161 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3163 TRACE("(%p/%p)->()\n", This, iface);
3165 return IUnknown_AddRef(This->outer_unk);
3168 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3170 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3172 TRACE("(%p/%p)->()\n", This, iface);
3174 return IUnknown_Release(This->outer_unk);
3177 /*** IDispatch methods ***/
3178 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3180 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3181 IBasicVideo *pBasicVideo;
3182 HRESULT hr;
3184 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3186 EnterCriticalSection(&This->cs);
3188 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3190 if (hr == S_OK)
3191 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3193 LeaveCriticalSection(&This->cs);
3195 return hr;
3198 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3199 ITypeInfo **ppTInfo)
3201 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3202 IBasicVideo *pBasicVideo;
3203 HRESULT hr;
3205 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3207 EnterCriticalSection(&This->cs);
3209 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3211 if (hr == S_OK)
3212 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3214 LeaveCriticalSection(&This->cs);
3216 return hr;
3219 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3220 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3222 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3223 IBasicVideo *pBasicVideo;
3224 HRESULT hr;
3226 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3228 EnterCriticalSection(&This->cs);
3230 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3232 if (hr == S_OK)
3233 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3235 LeaveCriticalSection(&This->cs);
3237 return hr;
3240 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3241 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3242 UINT *puArgErr)
3244 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3245 IBasicVideo *pBasicVideo;
3246 HRESULT hr;
3248 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);
3250 EnterCriticalSection(&This->cs);
3252 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3254 if (hr == S_OK)
3255 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3257 LeaveCriticalSection(&This->cs);
3259 return hr;
3262 /*** IBasicVideo methods ***/
3263 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3265 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3266 IBasicVideo *pBasicVideo;
3267 HRESULT hr;
3269 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3271 EnterCriticalSection(&This->cs);
3273 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3275 if (hr == S_OK)
3276 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3278 LeaveCriticalSection(&This->cs);
3280 return hr;
3283 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3285 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3286 IBasicVideo *pBasicVideo;
3287 HRESULT hr;
3289 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3291 EnterCriticalSection(&This->cs);
3293 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3295 if (hr == S_OK)
3296 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3298 LeaveCriticalSection(&This->cs);
3300 return hr;
3303 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3305 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3306 IBasicVideo *pBasicVideo;
3307 HRESULT hr;
3309 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3311 EnterCriticalSection(&This->cs);
3313 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3315 if (hr == S_OK)
3316 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3318 LeaveCriticalSection(&This->cs);
3320 return hr;
3323 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3325 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3326 IBasicVideo *pBasicVideo;
3327 HRESULT hr;
3329 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3331 EnterCriticalSection(&This->cs);
3333 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3335 if (hr == S_OK)
3336 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3338 LeaveCriticalSection(&This->cs);
3340 return hr;
3343 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3345 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3346 IBasicVideo *pBasicVideo;
3347 HRESULT hr;
3349 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3351 EnterCriticalSection(&This->cs);
3353 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3355 if (hr == S_OK)
3356 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3358 LeaveCriticalSection(&This->cs);
3360 return hr;
3363 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3365 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3366 IBasicVideo *pBasicVideo;
3367 HRESULT hr;
3369 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3371 EnterCriticalSection(&This->cs);
3373 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3375 if (hr == S_OK)
3376 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3378 LeaveCriticalSection(&This->cs);
3380 return hr;
3383 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3385 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3386 IBasicVideo *pBasicVideo;
3387 HRESULT hr;
3389 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3391 EnterCriticalSection(&This->cs);
3393 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3395 if (hr == S_OK)
3396 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3398 LeaveCriticalSection(&This->cs);
3400 return hr;
3403 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3405 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3406 IBasicVideo *pBasicVideo;
3407 HRESULT hr;
3409 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3411 EnterCriticalSection(&This->cs);
3413 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3415 if (hr == S_OK)
3416 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3418 LeaveCriticalSection(&This->cs);
3420 return hr;
3423 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3425 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3426 IBasicVideo *pBasicVideo;
3427 HRESULT hr;
3429 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3431 EnterCriticalSection(&This->cs);
3433 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3435 if (hr == S_OK)
3436 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3438 LeaveCriticalSection(&This->cs);
3440 return hr;
3443 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3445 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3446 IBasicVideo *pBasicVideo;
3447 HRESULT hr;
3449 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3451 EnterCriticalSection(&This->cs);
3453 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3455 if (hr == S_OK)
3456 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3458 LeaveCriticalSection(&This->cs);
3460 return hr;
3463 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3465 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3466 IBasicVideo *pBasicVideo;
3467 HRESULT hr;
3469 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3471 EnterCriticalSection(&This->cs);
3473 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3475 if (hr == S_OK)
3476 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3478 LeaveCriticalSection(&This->cs);
3480 return hr;
3483 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3485 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3486 IBasicVideo *pBasicVideo;
3487 HRESULT hr;
3489 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3491 EnterCriticalSection(&This->cs);
3493 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3495 if (hr == S_OK)
3496 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3498 LeaveCriticalSection(&This->cs);
3500 return hr;
3503 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3505 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3506 IBasicVideo *pBasicVideo;
3507 HRESULT hr;
3509 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3511 EnterCriticalSection(&This->cs);
3513 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3515 if (hr == S_OK)
3516 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3518 LeaveCriticalSection(&This->cs);
3520 return hr;
3523 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3525 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3526 IBasicVideo *pBasicVideo;
3527 HRESULT hr;
3529 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3531 EnterCriticalSection(&This->cs);
3533 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3535 if (hr == S_OK)
3536 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3538 LeaveCriticalSection(&This->cs);
3540 return hr;
3543 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3545 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3546 IBasicVideo *pBasicVideo;
3547 HRESULT hr;
3549 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3551 EnterCriticalSection(&This->cs);
3553 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3555 if (hr == S_OK)
3556 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3558 LeaveCriticalSection(&This->cs);
3560 return hr;
3563 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3565 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3566 IBasicVideo *pBasicVideo;
3567 HRESULT hr;
3569 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3571 EnterCriticalSection(&This->cs);
3573 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3575 if (hr == S_OK)
3576 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3578 LeaveCriticalSection(&This->cs);
3580 return hr;
3583 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3585 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3586 IBasicVideo *pBasicVideo;
3587 HRESULT hr;
3589 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3591 EnterCriticalSection(&This->cs);
3593 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3595 if (hr == S_OK)
3596 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3598 LeaveCriticalSection(&This->cs);
3600 return hr;
3603 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3605 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3606 IBasicVideo *pBasicVideo;
3607 HRESULT hr;
3609 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3611 EnterCriticalSection(&This->cs);
3613 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3615 if (hr == S_OK)
3616 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3618 LeaveCriticalSection(&This->cs);
3620 return hr;
3623 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3625 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3626 IBasicVideo *pBasicVideo;
3627 HRESULT hr;
3629 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3631 EnterCriticalSection(&This->cs);
3633 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3635 if (hr == S_OK)
3636 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3638 LeaveCriticalSection(&This->cs);
3640 return hr;
3643 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3645 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3646 IBasicVideo *pBasicVideo;
3647 HRESULT hr;
3649 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3651 EnterCriticalSection(&This->cs);
3653 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3655 if (hr == S_OK)
3656 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3658 LeaveCriticalSection(&This->cs);
3660 return hr;
3663 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3664 LONG *pDestinationHeight)
3666 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3667 IBasicVideo *pBasicVideo;
3668 HRESULT hr;
3670 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3672 EnterCriticalSection(&This->cs);
3674 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3676 if (hr == S_OK)
3677 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3679 LeaveCriticalSection(&This->cs);
3681 return hr;
3684 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3685 LONG Width, LONG Height)
3687 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3688 IBasicVideo *pBasicVideo;
3689 HRESULT hr;
3691 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3693 EnterCriticalSection(&This->cs);
3695 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3697 if (hr == S_OK)
3698 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3700 LeaveCriticalSection(&This->cs);
3702 return hr;
3705 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3706 LONG *pWidth, LONG *pHeight)
3708 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3709 IBasicVideo *pBasicVideo;
3710 HRESULT hr;
3712 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3714 EnterCriticalSection(&This->cs);
3716 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3718 if (hr == S_OK)
3719 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3721 LeaveCriticalSection(&This->cs);
3723 return hr;
3726 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3728 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3729 IBasicVideo *pBasicVideo;
3730 HRESULT hr;
3732 TRACE("(%p/%p)->()\n", This, iface);
3734 EnterCriticalSection(&This->cs);
3736 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3738 if (hr == S_OK)
3739 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3741 LeaveCriticalSection(&This->cs);
3743 return hr;
3746 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3747 LONG Width, LONG Height)
3749 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3750 IBasicVideo *pBasicVideo;
3751 HRESULT hr;
3753 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3755 EnterCriticalSection(&This->cs);
3757 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3759 if (hr == S_OK)
3760 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3762 LeaveCriticalSection(&This->cs);
3764 return hr;
3767 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3768 LONG *pTop, LONG *pWidth, LONG *pHeight)
3770 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3771 IBasicVideo *pBasicVideo;
3772 HRESULT hr;
3774 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3776 EnterCriticalSection(&This->cs);
3778 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3780 if (hr == S_OK)
3781 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3783 LeaveCriticalSection(&This->cs);
3785 return hr;
3788 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3790 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3791 IBasicVideo *pBasicVideo;
3792 HRESULT hr;
3794 TRACE("(%p/%p)->()\n", This, iface);
3796 EnterCriticalSection(&This->cs);
3798 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3800 if (hr == S_OK)
3801 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3803 LeaveCriticalSection(&This->cs);
3805 return hr;
3808 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3810 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3811 IBasicVideo *pBasicVideo;
3812 HRESULT hr;
3814 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3816 EnterCriticalSection(&This->cs);
3818 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3820 if (hr == S_OK)
3821 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3823 LeaveCriticalSection(&This->cs);
3825 return hr;
3828 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3829 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3831 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3832 IBasicVideo *pBasicVideo;
3833 HRESULT hr;
3835 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3837 EnterCriticalSection(&This->cs);
3839 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3841 if (hr == S_OK)
3842 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3844 LeaveCriticalSection(&This->cs);
3846 return hr;
3849 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3850 LONG *pDIBImage)
3852 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3853 IBasicVideo *pBasicVideo;
3854 HRESULT hr;
3856 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3858 EnterCriticalSection(&This->cs);
3860 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3862 if (hr == S_OK)
3863 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3865 LeaveCriticalSection(&This->cs);
3867 return hr;
3870 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3872 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3873 IBasicVideo *pBasicVideo;
3874 HRESULT hr;
3876 TRACE("(%p/%p)->()\n", This, iface);
3878 EnterCriticalSection(&This->cs);
3880 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3882 if (hr == S_OK)
3883 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3885 LeaveCriticalSection(&This->cs);
3887 return hr;
3890 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
3892 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3893 IBasicVideo *pBasicVideo;
3894 HRESULT hr;
3896 TRACE("(%p/%p)->()\n", This, iface);
3898 EnterCriticalSection(&This->cs);
3900 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3902 if (hr == S_OK)
3903 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3905 LeaveCriticalSection(&This->cs);
3907 return hr;
3910 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
3911 LONG *plAspectY)
3913 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3914 IBasicVideo2 *pBasicVideo2;
3915 HRESULT hr;
3917 TRACE("(%p/%p)->()\n", This, iface);
3919 EnterCriticalSection(&This->cs);
3921 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3923 if (hr == S_OK)
3924 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3926 LeaveCriticalSection(&This->cs);
3928 return hr;
3931 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3933 BasicVideo_QueryInterface,
3934 BasicVideo_AddRef,
3935 BasicVideo_Release,
3936 BasicVideo_GetTypeInfoCount,
3937 BasicVideo_GetTypeInfo,
3938 BasicVideo_GetIDsOfNames,
3939 BasicVideo_Invoke,
3940 BasicVideo_get_AvgTimePerFrame,
3941 BasicVideo_get_BitRate,
3942 BasicVideo_get_BitErrorRate,
3943 BasicVideo_get_VideoWidth,
3944 BasicVideo_get_VideoHeight,
3945 BasicVideo_put_SourceLeft,
3946 BasicVideo_get_SourceLeft,
3947 BasicVideo_put_SourceWidth,
3948 BasicVideo_get_SourceWidth,
3949 BasicVideo_put_SourceTop,
3950 BasicVideo_get_SourceTop,
3951 BasicVideo_put_SourceHeight,
3952 BasicVideo_get_SourceHeight,
3953 BasicVideo_put_DestinationLeft,
3954 BasicVideo_get_DestinationLeft,
3955 BasicVideo_put_DestinationWidth,
3956 BasicVideo_get_DestinationWidth,
3957 BasicVideo_put_DestinationTop,
3958 BasicVideo_get_DestinationTop,
3959 BasicVideo_put_DestinationHeight,
3960 BasicVideo_get_DestinationHeight,
3961 BasicVideo_SetSourcePosition,
3962 BasicVideo_GetSourcePosition,
3963 BasicVideo_SetDefaultSourcePosition,
3964 BasicVideo_SetDestinationPosition,
3965 BasicVideo_GetDestinationPosition,
3966 BasicVideo_SetDefaultDestinationPosition,
3967 BasicVideo_GetVideoSize,
3968 BasicVideo_GetVideoPaletteEntries,
3969 BasicVideo_GetCurrentImage,
3970 BasicVideo_IsUsingDefaultSource,
3971 BasicVideo_IsUsingDefaultDestination,
3972 BasicVideo2_GetPreferredAspectRatio
3975 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
3977 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
3980 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
3982 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3984 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3986 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3989 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
3991 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3993 TRACE("(%p/%p)->()\n", This, iface);
3995 return IUnknown_AddRef(This->outer_unk);
3998 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
4000 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4002 TRACE("(%p/%p)->()\n", This, iface);
4004 return IUnknown_Release(This->outer_unk);
4007 /*** IDispatch methods ***/
4008 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4010 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4011 IVideoWindow *pVideoWindow;
4012 HRESULT hr;
4014 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4016 EnterCriticalSection(&This->cs);
4018 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4020 if (hr == S_OK)
4021 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4023 LeaveCriticalSection(&This->cs);
4025 return hr;
4028 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4029 ITypeInfo **ppTInfo)
4031 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4032 IVideoWindow *pVideoWindow;
4033 HRESULT hr;
4035 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4037 EnterCriticalSection(&This->cs);
4039 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4041 if (hr == S_OK)
4042 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4044 LeaveCriticalSection(&This->cs);
4046 return hr;
4049 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4050 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4052 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4053 IVideoWindow *pVideoWindow;
4054 HRESULT hr;
4056 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4058 EnterCriticalSection(&This->cs);
4060 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4062 if (hr == S_OK)
4063 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4065 LeaveCriticalSection(&This->cs);
4067 return hr;
4070 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4071 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4072 UINT*puArgErr)
4074 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4075 IVideoWindow *pVideoWindow;
4076 HRESULT hr;
4078 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);
4080 EnterCriticalSection(&This->cs);
4082 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4084 if (hr == S_OK)
4085 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4087 LeaveCriticalSection(&This->cs);
4089 return hr;
4093 /*** IVideoWindow methods ***/
4094 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4096 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4097 IVideoWindow *pVideoWindow;
4098 HRESULT hr;
4100 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4102 EnterCriticalSection(&This->cs);
4104 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4106 if (hr == S_OK)
4107 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4109 LeaveCriticalSection(&This->cs);
4111 return hr;
4114 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4116 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4117 IVideoWindow *pVideoWindow;
4118 HRESULT hr;
4120 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4122 EnterCriticalSection(&This->cs);
4124 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4126 if (hr == S_OK)
4127 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4129 LeaveCriticalSection(&This->cs);
4131 return hr;
4134 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4136 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4137 IVideoWindow *pVideoWindow;
4138 HRESULT hr;
4140 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4142 EnterCriticalSection(&This->cs);
4144 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4146 if (hr == S_OK)
4147 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4149 LeaveCriticalSection(&This->cs);
4151 return hr;
4154 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4156 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4157 IVideoWindow *pVideoWindow;
4158 HRESULT hr;
4160 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4162 EnterCriticalSection(&This->cs);
4164 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4166 if (hr == S_OK)
4167 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4169 LeaveCriticalSection(&This->cs);
4171 return hr;
4174 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4176 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4177 IVideoWindow *pVideoWindow;
4178 HRESULT hr;
4180 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4182 EnterCriticalSection(&This->cs);
4184 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4186 if (hr == S_OK)
4187 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4189 LeaveCriticalSection(&This->cs);
4191 return hr;
4194 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4196 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4197 IVideoWindow *pVideoWindow;
4198 HRESULT hr;
4200 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4202 EnterCriticalSection(&This->cs);
4204 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4206 if (hr == S_OK)
4207 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4209 LeaveCriticalSection(&This->cs);
4211 return hr;
4214 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4216 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4217 IVideoWindow *pVideoWindow;
4218 HRESULT hr;
4220 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4222 EnterCriticalSection(&This->cs);
4224 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4226 if (hr == S_OK)
4227 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4229 LeaveCriticalSection(&This->cs);
4231 return hr;
4234 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4236 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4237 IVideoWindow *pVideoWindow;
4238 HRESULT hr;
4240 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4242 EnterCriticalSection(&This->cs);
4244 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4246 if (hr == S_OK)
4247 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4249 LeaveCriticalSection(&This->cs);
4251 return hr;
4254 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4256 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4257 IVideoWindow *pVideoWindow;
4258 HRESULT hr;
4260 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4262 EnterCriticalSection(&This->cs);
4264 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4266 if (hr == S_OK)
4267 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4269 LeaveCriticalSection(&This->cs);
4271 return hr;
4274 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4276 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4277 IVideoWindow *pVideoWindow;
4278 HRESULT hr;
4280 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4282 EnterCriticalSection(&This->cs);
4284 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4286 if (hr == S_OK)
4287 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4289 LeaveCriticalSection(&This->cs);
4291 return hr;
4294 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4296 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4297 IVideoWindow *pVideoWindow;
4298 HRESULT hr;
4300 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4302 EnterCriticalSection(&This->cs);
4304 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4306 if (hr == S_OK)
4307 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4309 LeaveCriticalSection(&This->cs);
4311 return hr;
4314 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4315 LONG *pBackgroundPalette)
4317 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4318 IVideoWindow *pVideoWindow;
4319 HRESULT hr;
4321 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4323 EnterCriticalSection(&This->cs);
4325 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4327 if (hr == S_OK)
4328 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4330 LeaveCriticalSection(&This->cs);
4332 return hr;
4335 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4337 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4338 IVideoWindow *pVideoWindow;
4339 HRESULT hr;
4341 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4343 EnterCriticalSection(&This->cs);
4345 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4347 if (hr == S_OK)
4348 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4350 LeaveCriticalSection(&This->cs);
4352 return hr;
4355 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4357 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4358 IVideoWindow *pVideoWindow;
4359 HRESULT hr;
4361 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4363 EnterCriticalSection(&This->cs);
4365 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4367 if (hr == S_OK)
4368 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4370 LeaveCriticalSection(&This->cs);
4372 return hr;
4375 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4377 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4378 IVideoWindow *pVideoWindow;
4379 HRESULT hr;
4381 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4383 EnterCriticalSection(&This->cs);
4385 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4387 if (hr == S_OK)
4388 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4390 LeaveCriticalSection(&This->cs);
4392 return hr;
4395 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4397 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4398 IVideoWindow *pVideoWindow;
4399 HRESULT hr;
4401 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4403 EnterCriticalSection(&This->cs);
4405 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4407 if (hr == S_OK)
4408 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4410 LeaveCriticalSection(&This->cs);
4412 return hr;
4415 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4417 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4418 IVideoWindow *pVideoWindow;
4419 HRESULT hr;
4421 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4423 EnterCriticalSection(&This->cs);
4425 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4427 if (hr == S_OK)
4428 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4430 LeaveCriticalSection(&This->cs);
4432 return hr;
4435 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4437 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4438 IVideoWindow *pVideoWindow;
4439 HRESULT hr;
4441 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4443 EnterCriticalSection(&This->cs);
4445 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4447 if (hr == S_OK)
4448 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4450 LeaveCriticalSection(&This->cs);
4452 return hr;
4455 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4457 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4458 IVideoWindow *pVideoWindow;
4459 HRESULT hr;
4461 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4463 EnterCriticalSection(&This->cs);
4465 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4467 if (hr == S_OK)
4468 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4470 LeaveCriticalSection(&This->cs);
4472 return hr;
4475 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4477 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4478 IVideoWindow *pVideoWindow;
4479 HRESULT hr;
4481 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4483 EnterCriticalSection(&This->cs);
4485 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4487 if (hr == S_OK)
4488 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4490 LeaveCriticalSection(&This->cs);
4492 return hr;
4495 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4497 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4498 IVideoWindow *pVideoWindow;
4499 HRESULT hr;
4501 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4503 EnterCriticalSection(&This->cs);
4505 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4507 if (hr == S_OK)
4508 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4510 LeaveCriticalSection(&This->cs);
4512 return hr;
4515 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4517 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4518 IVideoWindow *pVideoWindow;
4519 HRESULT hr;
4521 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4523 EnterCriticalSection(&This->cs);
4525 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4527 if (hr == S_OK)
4528 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4530 LeaveCriticalSection(&This->cs);
4532 return hr;
4535 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4537 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4538 IVideoWindow *pVideoWindow;
4539 HRESULT hr;
4541 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4543 EnterCriticalSection(&This->cs);
4545 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4547 if (hr == S_OK)
4548 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4550 LeaveCriticalSection(&This->cs);
4552 return hr;
4555 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4557 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4558 IVideoWindow *pVideoWindow;
4559 HRESULT hr;
4561 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4563 EnterCriticalSection(&This->cs);
4565 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4567 if (hr == S_OK)
4568 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4570 LeaveCriticalSection(&This->cs);
4572 return hr;
4575 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4577 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4578 IVideoWindow *pVideoWindow;
4579 HRESULT hr;
4581 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4583 EnterCriticalSection(&This->cs);
4585 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4587 if (hr == S_OK)
4588 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4590 LeaveCriticalSection(&This->cs);
4592 return hr;
4595 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4597 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4598 IVideoWindow *pVideoWindow;
4599 HRESULT hr;
4601 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4603 EnterCriticalSection(&This->cs);
4605 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4607 if (hr == S_OK)
4608 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4610 LeaveCriticalSection(&This->cs);
4612 return hr;
4615 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4617 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4618 IVideoWindow *pVideoWindow;
4619 HRESULT hr;
4621 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4623 EnterCriticalSection(&This->cs);
4625 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4627 if (hr == S_OK)
4628 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4630 LeaveCriticalSection(&This->cs);
4632 return hr;
4635 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4637 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4638 IVideoWindow *pVideoWindow;
4639 HRESULT hr;
4641 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4643 EnterCriticalSection(&This->cs);
4645 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4647 if (hr == S_OK)
4648 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4650 LeaveCriticalSection(&This->cs);
4652 return hr;
4655 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4657 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4658 IVideoWindow *pVideoWindow;
4659 HRESULT hr;
4661 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4663 EnterCriticalSection(&This->cs);
4665 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4667 if (hr == S_OK)
4668 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4670 LeaveCriticalSection(&This->cs);
4672 return hr;
4675 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4677 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4678 IVideoWindow *pVideoWindow;
4679 HRESULT hr;
4681 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4683 EnterCriticalSection(&This->cs);
4685 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4687 if (hr == S_OK)
4688 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4690 LeaveCriticalSection(&This->cs);
4692 return hr;
4695 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4697 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4698 IVideoWindow *pVideoWindow;
4699 HRESULT hr;
4701 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4703 EnterCriticalSection(&This->cs);
4705 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4707 if (hr == S_OK)
4708 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4710 LeaveCriticalSection(&This->cs);
4712 return hr;
4715 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4716 LONG_PTR wParam, LONG_PTR lParam)
4718 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4719 IVideoWindow *pVideoWindow;
4720 HRESULT hr;
4722 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4724 EnterCriticalSection(&This->cs);
4726 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4728 if (hr == S_OK)
4729 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4731 LeaveCriticalSection(&This->cs);
4733 return hr;
4736 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4737 LONG Width, LONG Height)
4739 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4740 IVideoWindow *pVideoWindow;
4741 HRESULT hr;
4743 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4745 EnterCriticalSection(&This->cs);
4747 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4749 if (hr == S_OK)
4750 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4752 LeaveCriticalSection(&This->cs);
4754 return hr;
4757 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4758 LONG *pWidth, LONG *pHeight)
4760 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4761 IVideoWindow *pVideoWindow;
4762 HRESULT hr;
4764 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4766 EnterCriticalSection(&This->cs);
4768 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4770 if (hr == S_OK)
4771 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4773 LeaveCriticalSection(&This->cs);
4775 return hr;
4778 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4779 LONG *pHeight)
4781 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4782 IVideoWindow *pVideoWindow;
4783 HRESULT hr;
4785 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4787 EnterCriticalSection(&This->cs);
4789 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4791 if (hr == S_OK)
4792 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4794 LeaveCriticalSection(&This->cs);
4796 return hr;
4799 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4800 LONG *pHeight)
4802 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4803 IVideoWindow *pVideoWindow;
4804 HRESULT hr;
4806 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4808 EnterCriticalSection(&This->cs);
4810 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4812 if (hr == S_OK)
4813 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4815 LeaveCriticalSection(&This->cs);
4817 return hr;
4820 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4821 LONG *pWidth, LONG *pHeight)
4823 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4824 IVideoWindow *pVideoWindow;
4825 HRESULT hr;
4827 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4829 EnterCriticalSection(&This->cs);
4831 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4833 if (hr == S_OK)
4834 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4836 LeaveCriticalSection(&This->cs);
4838 return hr;
4841 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4843 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4844 IVideoWindow *pVideoWindow;
4845 HRESULT hr;
4847 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4849 EnterCriticalSection(&This->cs);
4851 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4853 if (hr == S_OK)
4854 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4856 LeaveCriticalSection(&This->cs);
4858 return hr;
4861 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4863 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4864 IVideoWindow *pVideoWindow;
4865 HRESULT hr;
4867 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4869 EnterCriticalSection(&This->cs);
4871 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4873 if (hr == S_OK)
4874 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4876 LeaveCriticalSection(&This->cs);
4878 return hr;
4882 static const IVideoWindowVtbl IVideoWindow_VTable =
4884 VideoWindow_QueryInterface,
4885 VideoWindow_AddRef,
4886 VideoWindow_Release,
4887 VideoWindow_GetTypeInfoCount,
4888 VideoWindow_GetTypeInfo,
4889 VideoWindow_GetIDsOfNames,
4890 VideoWindow_Invoke,
4891 VideoWindow_put_Caption,
4892 VideoWindow_get_Caption,
4893 VideoWindow_put_WindowStyle,
4894 VideoWindow_get_WindowStyle,
4895 VideoWindow_put_WindowStyleEx,
4896 VideoWindow_get_WindowStyleEx,
4897 VideoWindow_put_AutoShow,
4898 VideoWindow_get_AutoShow,
4899 VideoWindow_put_WindowState,
4900 VideoWindow_get_WindowState,
4901 VideoWindow_put_BackgroundPalette,
4902 VideoWindow_get_BackgroundPalette,
4903 VideoWindow_put_Visible,
4904 VideoWindow_get_Visible,
4905 VideoWindow_put_Left,
4906 VideoWindow_get_Left,
4907 VideoWindow_put_Width,
4908 VideoWindow_get_Width,
4909 VideoWindow_put_Top,
4910 VideoWindow_get_Top,
4911 VideoWindow_put_Height,
4912 VideoWindow_get_Height,
4913 VideoWindow_put_Owner,
4914 VideoWindow_get_Owner,
4915 VideoWindow_put_MessageDrain,
4916 VideoWindow_get_MessageDrain,
4917 VideoWindow_get_BorderColor,
4918 VideoWindow_put_BorderColor,
4919 VideoWindow_get_FullScreenMode,
4920 VideoWindow_put_FullScreenMode,
4921 VideoWindow_SetWindowForeground,
4922 VideoWindow_NotifyOwnerMessage,
4923 VideoWindow_SetWindowPosition,
4924 VideoWindow_GetWindowPosition,
4925 VideoWindow_GetMinIdealImageSize,
4926 VideoWindow_GetMaxIdealImageSize,
4927 VideoWindow_GetRestorePosition,
4928 VideoWindow_HideCursor,
4929 VideoWindow_IsCursorHidden
4932 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
4934 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
4937 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
4939 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4941 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4943 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4946 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
4948 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4950 TRACE("(%p/%p)->()\n", This, iface);
4952 return IUnknown_AddRef(This->outer_unk);
4955 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
4957 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4959 TRACE("(%p/%p)->()\n", This, iface);
4961 return IUnknown_Release(This->outer_unk);
4964 /*** IDispatch methods ***/
4965 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
4967 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4969 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4971 return S_OK;
4974 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
4975 ITypeInfo **ppTInfo)
4977 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4979 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4981 return S_OK;
4984 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
4985 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4987 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4989 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4991 return S_OK;
4994 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
4995 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4996 UINT *puArgErr)
4998 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5000 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);
5002 return S_OK;
5005 /*** IMediaEvent methods ***/
5006 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5008 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5010 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5012 *hEvent = (OAEVENT)This->evqueue.msg_event;
5014 return S_OK;
5017 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5018 LONG_PTR *lParam2, LONG msTimeout)
5020 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5021 Event evt;
5023 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5025 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5027 *lEventCode = evt.lEventCode;
5028 *lParam1 = evt.lParam1;
5029 *lParam2 = evt.lParam2;
5030 return S_OK;
5033 *lEventCode = 0;
5034 return E_ABORT;
5037 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5038 LONG *pEvCode)
5040 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5042 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5044 if (This->state != State_Running)
5045 return VFW_E_WRONG_STATE;
5047 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5049 *pEvCode = This->CompletionStatus;
5050 return S_OK;
5053 *pEvCode = 0;
5054 return E_ABORT;
5057 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5059 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5061 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5063 if (lEvCode == EC_COMPLETE)
5064 This->HandleEcComplete = FALSE;
5065 else if (lEvCode == EC_REPAINT)
5066 This->HandleEcRepaint = FALSE;
5067 else if (lEvCode == EC_CLOCK_CHANGED)
5068 This->HandleEcClockChanged = FALSE;
5069 else
5070 return S_FALSE;
5072 return S_OK;
5075 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5077 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5079 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5081 if (lEvCode == EC_COMPLETE)
5082 This->HandleEcComplete = TRUE;
5083 else if (lEvCode == EC_REPAINT)
5084 This->HandleEcRepaint = TRUE;
5085 else if (lEvCode == EC_CLOCK_CHANGED)
5086 This->HandleEcClockChanged = TRUE;
5087 else
5088 return S_FALSE;
5090 return S_OK;
5093 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5094 LONG_PTR lParam1, LONG_PTR lParam2)
5096 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5098 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5100 return S_OK;
5103 /*** IMediaEventEx methods ***/
5104 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5105 LONG_PTR lInstanceData)
5107 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5109 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5111 This->notif.hWnd = (HWND)hwnd;
5112 This->notif.msg = lMsg;
5113 This->notif.instance = lInstanceData;
5115 return S_OK;
5118 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5120 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5122 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5124 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5125 return E_INVALIDARG;
5127 This->notif.disabled = lNoNotifyFlags;
5129 return S_OK;
5132 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5134 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5136 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5138 if (!lplNoNotifyFlags)
5139 return E_POINTER;
5141 *lplNoNotifyFlags = This->notif.disabled;
5143 return S_OK;
5147 static const IMediaEventExVtbl IMediaEventEx_VTable =
5149 MediaEvent_QueryInterface,
5150 MediaEvent_AddRef,
5151 MediaEvent_Release,
5152 MediaEvent_GetTypeInfoCount,
5153 MediaEvent_GetTypeInfo,
5154 MediaEvent_GetIDsOfNames,
5155 MediaEvent_Invoke,
5156 MediaEvent_GetEventHandle,
5157 MediaEvent_GetEvent,
5158 MediaEvent_WaitForCompletion,
5159 MediaEvent_CancelDefaultHandling,
5160 MediaEvent_RestoreDefaultHandling,
5161 MediaEvent_FreeEventParams,
5162 MediaEvent_SetNotifyWindow,
5163 MediaEvent_SetNotifyFlags,
5164 MediaEvent_GetNotifyFlags
5168 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5170 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5173 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5175 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5177 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5180 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5182 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5184 return IUnknown_AddRef(This->outer_unk);
5187 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5189 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5191 return IUnknown_Release(This->outer_unk);
5194 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5196 FIXME("(%p): stub\n", pClassID);
5198 return E_NOTIMPL;
5201 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5203 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5205 return MediaControl_Stop(&This->IMediaControl_iface);
5208 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5210 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5212 return MediaControl_Pause(&This->IMediaControl_iface);
5215 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5217 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5219 if (tStart)
5220 FIXME("Run called with non-null tStart: %x%08x\n",
5221 (int)(tStart>>32), (int)tStart);
5223 return MediaControl_Run(&This->IMediaControl_iface);
5226 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
5227 FILTER_STATE *pState)
5229 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5231 return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
5234 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5236 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5237 HRESULT hr = S_OK;
5238 int i;
5240 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5242 EnterCriticalSection(&This->cs);
5244 for (i = 0;i < This->nFilters;i++)
5246 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5247 if (FAILED(hr))
5248 break;
5251 if (FAILED(hr))
5253 for(;i >= 0;i--)
5254 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5256 else
5258 if (This->refClock)
5259 IReferenceClock_Release(This->refClock);
5260 This->refClock = pClock;
5261 if (This->refClock)
5262 IReferenceClock_AddRef(This->refClock);
5263 This->defaultclock = FALSE;
5265 if (This->HandleEcClockChanged)
5267 IMediaEventSink *pEventSink;
5268 HRESULT eshr;
5270 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5271 if (SUCCEEDED(eshr))
5273 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5274 IMediaEventSink_Release(pEventSink);
5279 LeaveCriticalSection(&This->cs);
5281 return hr;
5284 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5286 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5288 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5290 if (!ppClock)
5291 return E_POINTER;
5293 EnterCriticalSection(&This->cs);
5295 *ppClock = This->refClock;
5296 if (*ppClock)
5297 IReferenceClock_AddRef(*ppClock);
5299 LeaveCriticalSection(&This->cs);
5301 return S_OK;
5304 static const IMediaFilterVtbl IMediaFilter_VTable =
5306 MediaFilter_QueryInterface,
5307 MediaFilter_AddRef,
5308 MediaFilter_Release,
5309 MediaFilter_GetClassID,
5310 MediaFilter_Stop,
5311 MediaFilter_Pause,
5312 MediaFilter_Run,
5313 MediaFilter_GetState,
5314 MediaFilter_SetSyncSource,
5315 MediaFilter_GetSyncSource
5318 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5320 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5323 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5325 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5327 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5330 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5332 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5334 return IUnknown_AddRef(This->outer_unk);
5337 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5339 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5341 return IUnknown_Release(This->outer_unk);
5344 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5345 LONG_PTR EventParam1, LONG_PTR EventParam2)
5347 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5348 Event evt;
5350 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5352 /* We need thread safety here, let's use the events queue's one */
5353 EnterCriticalSection(&This->evqueue.msg_crst);
5355 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5357 TRACE("Process EC_COMPLETE notification\n");
5358 if (++This->EcCompleteCount == This->nRenderers)
5360 evt.lEventCode = EC_COMPLETE;
5361 evt.lParam1 = S_OK;
5362 evt.lParam2 = 0;
5363 TRACE("Send EC_COMPLETE to app\n");
5364 EventsQueue_PutEvent(&This->evqueue, &evt);
5365 if (!This->notif.disabled && This->notif.hWnd)
5367 TRACE("Send Window message\n");
5368 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5370 This->CompletionStatus = EC_COMPLETE;
5371 SetEvent(This->hEventCompletion);
5374 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5376 /* FIXME: Not handled yet */
5378 else
5380 evt.lEventCode = EventCode;
5381 evt.lParam1 = EventParam1;
5382 evt.lParam2 = EventParam2;
5383 EventsQueue_PutEvent(&This->evqueue, &evt);
5384 if (!This->notif.disabled && This->notif.hWnd)
5385 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5388 LeaveCriticalSection(&This->evqueue.msg_crst);
5389 return S_OK;
5392 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5394 MediaEventSink_QueryInterface,
5395 MediaEventSink_AddRef,
5396 MediaEventSink_Release,
5397 MediaEventSink_Notify
5400 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5402 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5405 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5407 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5409 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5412 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5414 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5416 return IUnknown_AddRef(This->outer_unk);
5419 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5421 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5423 return IUnknown_Release(This->outer_unk);
5426 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5427 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5428 DWORD dwFlags)
5430 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5432 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5434 return E_NOTIMPL;
5437 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5438 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5440 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5441 HRESULT hr;
5443 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5445 if (hAbortEvent)
5446 FIXME("The parameter hAbortEvent is not handled!\n");
5448 EnterCriticalSection(&This->cs);
5450 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5452 LeaveCriticalSection(&This->cs);
5454 return hr;
5457 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5459 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5461 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5463 return E_NOTIMPL;
5466 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5468 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5470 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5472 return E_NOTIMPL;
5475 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5477 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5479 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5481 return E_NOTIMPL;
5484 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5486 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5488 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5490 return E_NOTIMPL;
5493 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5494 IPinConnection *pConnection, HANDLE hEventAbort)
5496 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5498 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5500 return E_NOTIMPL;
5503 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5504 DWORD dwFlags)
5506 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5508 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5510 return E_NOTIMPL;
5513 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5514 DWORD *dwFlags)
5516 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5518 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5520 return E_NOTIMPL;
5523 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5524 DWORD dwFlags)
5526 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5528 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5530 return E_NOTIMPL;
5533 static const IGraphConfigVtbl IGraphConfig_VTable =
5535 GraphConfig_QueryInterface,
5536 GraphConfig_AddRef,
5537 GraphConfig_Release,
5538 GraphConfig_Reconnect,
5539 GraphConfig_Reconfigure,
5540 GraphConfig_AddFilterToCache,
5541 GraphConfig_EnumCacheFilter,
5542 GraphConfig_RemoveFilterFromCache,
5543 GraphConfig_GetStartTime,
5544 GraphConfig_PushThroughData,
5545 GraphConfig_SetFilterFlags,
5546 GraphConfig_GetFilterFlags,
5547 GraphConfig_RemoveFilterEx
5550 static const IUnknownVtbl IInner_VTable =
5552 FilterGraphInner_QueryInterface,
5553 FilterGraphInner_AddRef,
5554 FilterGraphInner_Release
5557 /* This is the only function that actually creates a FilterGraph class... */
5558 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5560 IFilterGraphImpl *fimpl;
5561 HRESULT hr;
5563 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5565 *ppObj = NULL;
5567 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5568 fimpl->defaultclock = TRUE;
5569 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5570 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5571 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5572 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5573 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5574 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5575 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5576 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5577 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5578 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5579 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5580 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5581 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5582 fimpl->ref = 1;
5583 fimpl->ppFiltersInGraph = NULL;
5584 fimpl->pFilterNames = NULL;
5585 fimpl->nFilters = 0;
5586 fimpl->filterCapacity = 0;
5587 fimpl->nameIndex = 1;
5588 fimpl->refClock = NULL;
5589 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5590 fimpl->HandleEcComplete = TRUE;
5591 fimpl->HandleEcRepaint = TRUE;
5592 fimpl->HandleEcClockChanged = TRUE;
5593 fimpl->notif.hWnd = 0;
5594 fimpl->notif.disabled = FALSE;
5595 fimpl->nRenderers = 0;
5596 fimpl->EcCompleteCount = 0;
5597 fimpl->refClockProvider = NULL;
5598 fimpl->state = State_Stopped;
5599 fimpl->pSite = NULL;
5600 EventsQueue_Init(&fimpl->evqueue);
5601 InitializeCriticalSection(&fimpl->cs);
5602 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5603 fimpl->nItfCacheEntries = 0;
5604 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5605 fimpl->start_time = fimpl->pause_time = 0;
5606 fimpl->stop_position = -1;
5607 fimpl->punkFilterMapper2 = NULL;
5608 fimpl->recursioncount = 0;
5610 if (pUnkOuter)
5611 fimpl->outer_unk = pUnkOuter;
5612 else
5613 fimpl->outer_unk = &fimpl->IUnknown_inner;
5615 /* create Filtermapper aggregated. */
5616 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5617 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5619 if (SUCCEEDED(hr))
5620 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2,
5621 (void**)&fimpl->pFilterMapper2);
5623 if (SUCCEEDED(hr))
5624 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5625 IUnknown_Release(fimpl->outer_unk);
5627 if (FAILED(hr)) {
5628 ERR("Unable to create filter mapper (%x)\n", hr);
5629 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5630 CloseHandle(fimpl->hEventCompletion);
5631 EventsQueue_Destroy(&fimpl->evqueue);
5632 fimpl->cs.DebugInfo->Spare[0] = 0;
5633 DeleteCriticalSection(&fimpl->cs);
5634 CoTaskMemFree(fimpl);
5635 return hr;
5638 *ppObj = &fimpl->IUnknown_inner;
5639 return S_OK;
5642 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5644 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5645 return FilterGraph_create(pUnkOuter, ppObj);