mshtml: Improved VARIANT debug traces in htmlbody.c.
[wine/multimedia.git] / dlls / quartz / filtergraph.c
blob683877f689a6d15c9069a6581bd58b390b7c5d31
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 IFilterGraph2 IFilterGraph2_iface;
153 IMediaControl IMediaControl_iface;
154 IMediaSeeking IMediaSeeking_iface;
155 IBasicAudio IBasicAudio_iface;
156 IBasicVideo2 IBasicVideo2_iface;
157 IVideoWindow IVideoWindow_iface;
158 IMediaEventEx IMediaEventEx_iface;
159 IMediaFilter IMediaFilter_iface;
160 IMediaEventSink IMediaEventSink_iface;
161 IGraphConfig IGraphConfig_iface;
162 IMediaPosition IMediaPosition_iface;
163 IObjectWithSite IObjectWithSite_iface;
164 const IUnknownVtbl * IInner_vtbl;
165 /* IAMGraphStreams */
166 /* IAMStats */
167 /* IFilterChain */
168 /* IFilterMapper2 */
169 /* IGraphVersion */
170 /* IQueueCommand */
171 /* IRegisterServiceProvider */
172 /* IResourceMananger */
173 /* IServiceProvider */
174 /* IVideoFrameStep */
176 LONG ref;
177 IUnknown *punkFilterMapper2;
178 IFilterMapper2 * pFilterMapper2;
179 IBaseFilter ** ppFiltersInGraph;
180 LPWSTR * pFilterNames;
181 int nFilters;
182 int filterCapacity;
183 LONG nameIndex;
184 IReferenceClock *refClock;
185 IBaseFilter *refClockProvider;
186 EventsQueue evqueue;
187 HANDLE hEventCompletion;
188 int CompletionStatus;
189 WndNotify notif;
190 int nRenderers;
191 int EcCompleteCount;
192 int HandleEcComplete;
193 int HandleEcRepaint;
194 int HandleEcClockChanged;
195 OAFilterState state;
196 CRITICAL_SECTION cs;
197 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
198 int nItfCacheEntries;
199 IUnknown * pUnkOuter;
200 BOOL bUnkOuterValid;
201 BOOL bAggregatable;
202 BOOL defaultclock;
203 GUID timeformatseek;
204 REFERENCE_TIME start_time;
205 REFERENCE_TIME pause_time;
206 LONGLONG stop_position;
207 LONG recursioncount;
208 IUnknown *pSite;
209 } IFilterGraphImpl;
211 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
212 REFIID riid, LPVOID * ppv);
213 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This);
214 static ULONG Filtergraph_Release(IFilterGraphImpl *This);
216 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
217 REFIID riid,
218 LPVOID *ppvObj) {
219 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
220 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
222 if (This->bAggregatable)
223 This->bUnkOuterValid = TRUE;
225 if (IsEqualGUID(&IID_IUnknown, riid)) {
226 *ppvObj = &(This->IInner_vtbl);
227 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
228 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
229 IsEqualGUID(&IID_IFilterGraph2, riid) ||
230 IsEqualGUID(&IID_IGraphBuilder, riid)) {
231 *ppvObj = &This->IFilterGraph2_iface;
232 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
233 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
234 *ppvObj = &This->IMediaControl_iface;
235 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
236 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
237 *ppvObj = &This->IMediaSeeking_iface;
238 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
239 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
240 *ppvObj = &This->IBasicAudio_iface;
241 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
242 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
243 IsEqualGUID(&IID_IBasicVideo2, riid)) {
244 *ppvObj = &This->IBasicVideo2_iface;
245 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
246 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
247 *ppvObj = &This->IVideoWindow_iface;
248 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
249 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
250 IsEqualGUID(&IID_IMediaEventEx, riid)) {
251 *ppvObj = &This->IMediaEventEx_iface;
252 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
253 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
254 IsEqualGUID(&IID_IPersist, riid)) {
255 *ppvObj = &This->IMediaFilter_iface;
256 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
257 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
258 *ppvObj = &This->IMediaEventSink_iface;
259 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
260 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
261 *ppvObj = &This->IGraphConfig_iface;
262 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
263 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
264 *ppvObj = &This->IMediaPosition_iface;
265 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
266 } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) {
267 *ppvObj = &This->IObjectWithSite_iface;
268 TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj);
269 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
270 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
271 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
272 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
273 *ppvObj = This->pFilterMapper2;
274 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
275 } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
276 *ppvObj = This->pFilterMapper2;
277 TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
278 } else {
279 *ppvObj = NULL;
280 FIXME("unknown interface %s\n", debugstr_guid(riid));
281 return E_NOINTERFACE;
284 IUnknown_AddRef((IUnknown *)(*ppvObj));
285 return S_OK;
288 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) {
289 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
290 ULONG ref = InterlockedIncrement(&This->ref);
292 TRACE("(%p)->(): new ref = %d\n", This, ref);
294 return ref;
297 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface)
299 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
300 ULONG ref = InterlockedDecrement(&This->ref);
302 TRACE("(%p)->(): new ref = %d\n", This, ref);
304 if (ref == 0) {
305 int i;
307 This->ref = 1; /* guard against reentrancy (aggregation). */
309 IMediaControl_Stop(&This->IMediaControl_iface);
311 while (This->nFilters)
312 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]);
314 if (This->refClock)
315 IReferenceClock_Release(This->refClock);
317 for (i = 0; i < This->nItfCacheEntries; i++)
319 if (This->ItfCacheEntries[i].iface)
320 IUnknown_Release(This->ItfCacheEntries[i].iface);
323 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 interface below.
325 * NOTE: Filtergraph_AddRef isn't suitable, because bUnkOuterValid may be FALSE but punkOuter non-NULL
326 * and already passed as punkOuter to filtermapper in FilterGraph_create - this will happen in case of
327 * CoCreateInstance of filtergraph with non-null pUnkOuter and REFIID other than IID_Unknown that is
328 * cleaning up after error. */
329 if (This->pUnkOuter) IUnknown_AddRef(This->pUnkOuter);
330 else IUnknown_AddRef((IUnknown*)&This->IInner_vtbl);
332 IFilterMapper2_Release(This->pFilterMapper2);
333 IUnknown_Release(This->punkFilterMapper2);
335 if (This->pSite) IUnknown_Release(This->pSite);
337 CloseHandle(This->hEventCompletion);
338 EventsQueue_Destroy(&This->evqueue);
339 This->cs.DebugInfo->Spare[0] = 0;
340 DeleteCriticalSection(&This->cs);
341 CoTaskMemFree(This->ppFiltersInGraph);
342 CoTaskMemFree(This->pFilterNames);
343 CoTaskMemFree(This);
345 return ref;
348 static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface)
350 return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface);
353 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj)
355 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
357 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
359 return Filtergraph_QueryInterface(This, riid, ppvObj);
362 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface)
364 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
366 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
368 return Filtergraph_AddRef(This);
371 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
373 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
375 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
377 return Filtergraph_Release(This);
380 /*** IFilterGraph methods ***/
381 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
382 LPCWSTR pName)
384 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
385 HRESULT hr;
386 int i,j;
387 WCHAR* wszFilterName = NULL;
388 int duplicate_name = FALSE;
390 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
392 if (!pFilter)
393 return E_POINTER;
395 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
397 if (pName)
399 /* Check if name already exists */
400 for(i = 0; i < This->nFilters; i++)
401 if (!strcmpW(This->pFilterNames[i], pName))
403 duplicate_name = TRUE;
404 break;
408 /* If no name given or name already existing, generate one */
409 if (!pName || duplicate_name)
411 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
412 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
414 for (j = 0; j < 10000 ; j++)
416 /* Create name */
417 if (pName)
418 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
419 else
420 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
421 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
423 /* Check if the generated name already exists */
424 for(i = 0; i < This->nFilters; i++)
425 if (!strcmpW(This->pFilterNames[i], wszFilterName))
426 break;
428 /* Compute next index and exit if generated name is suitable */
429 if (This->nameIndex++ == 10000)
430 This->nameIndex = 1;
431 if (i == This->nFilters)
432 break;
434 /* Unable to find a suitable name */
435 if (j == 10000)
437 CoTaskMemFree(wszFilterName);
438 return VFW_E_DUPLICATE_NAME;
441 else
442 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
444 if (This->nFilters + 1 > This->filterCapacity)
446 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
447 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
448 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
449 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
450 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
451 if (This->filterCapacity)
453 CoTaskMemFree(This->ppFiltersInGraph);
454 CoTaskMemFree(This->pFilterNames);
456 This->ppFiltersInGraph = ppNewFilters;
457 This->pFilterNames = pNewNames;
458 This->filterCapacity = newCapacity;
461 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
463 if (SUCCEEDED(hr))
465 IBaseFilter_AddRef(pFilter);
466 This->ppFiltersInGraph[This->nFilters] = pFilter;
467 This->pFilterNames[This->nFilters] = wszFilterName;
468 This->nFilters++;
469 IBaseFilter_SetSyncSource(pFilter, This->refClock);
471 else
472 CoTaskMemFree(wszFilterName);
474 if (SUCCEEDED(hr) && duplicate_name)
475 return VFW_S_DUPLICATE_NAME;
477 return hr;
480 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
482 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
483 int i;
484 HRESULT hr = E_FAIL;
486 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
488 /* FIXME: check graph is stopped */
490 for (i = 0; i < This->nFilters; i++)
492 if (This->ppFiltersInGraph[i] == pFilter)
494 IEnumPins *penumpins = NULL;
495 FILTER_STATE state;
497 if (This->defaultclock && This->refClockProvider == pFilter)
499 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
500 This->defaultclock = 1;
503 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
504 IBaseFilter_GetState(pFilter, 0, &state);
505 if (state == State_Running)
506 IBaseFilter_Pause(pFilter);
507 if (state != State_Stopped)
508 IBaseFilter_Stop(pFilter);
510 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
511 if (SUCCEEDED(hr)) {
512 IPin *ppin;
513 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
515 IPin *victim = NULL;
516 HRESULT h;
517 IPin_ConnectedTo(ppin, &victim);
518 if (victim)
520 h = IPin_Disconnect(victim);
521 TRACE("Disconnect other side: %08x\n", h);
522 if (h == VFW_E_NOT_STOPPED)
524 PIN_INFO pinfo;
525 IPin_QueryPinInfo(victim, &pinfo);
527 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
528 if (state == State_Running)
529 IBaseFilter_Pause(pinfo.pFilter);
530 IBaseFilter_Stop(pinfo.pFilter);
531 IBaseFilter_Release(pinfo.pFilter);
532 h = IPin_Disconnect(victim);
533 TRACE("Disconnect retry: %08x\n", h);
535 IPin_Release(victim);
537 h = IPin_Disconnect(ppin);
538 TRACE("Disconnect 2: %08x\n", h);
540 IPin_Release(ppin);
542 IEnumPins_Release(penumpins);
545 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
546 if (SUCCEEDED(hr))
548 IBaseFilter_SetSyncSource(pFilter, NULL);
549 IBaseFilter_Release(pFilter);
550 CoTaskMemFree(This->pFilterNames[i]);
551 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
552 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
553 This->nFilters--;
554 /* Invalidate interfaces in the cache */
555 for (i = 0; i < This->nItfCacheEntries; i++)
556 if (pFilter == This->ItfCacheEntries[i].filter)
558 IUnknown_Release(This->ItfCacheEntries[i].iface);
559 This->ItfCacheEntries[i].iface = NULL;
560 This->ItfCacheEntries[i].filter = NULL;
562 return S_OK;
564 break;
568 return hr; /* FIXME: check this error code */
571 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum)
573 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
575 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
577 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
580 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName,
581 IBaseFilter **ppFilter)
583 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
584 int i;
586 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
588 if (!ppFilter)
589 return E_POINTER;
591 for (i = 0; i < This->nFilters; i++)
593 if (!strcmpW(pName, This->pFilterNames[i]))
595 *ppFilter = This->ppFiltersInGraph[i];
596 IBaseFilter_AddRef(*ppFilter);
597 return S_OK;
601 *ppFilter = NULL;
602 return VFW_E_NOT_FOUND;
605 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
606 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
608 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
610 #if 1
611 HRESULT hr;
612 PIN_INFO info_out, info_in;
614 hr = IPin_QueryPinInfo(out, &info_out);
615 if (FAILED(hr))
616 return hr;
617 if (info_out.dir != PINDIR_OUTPUT)
619 IBaseFilter_Release(info_out.pFilter);
620 return E_UNEXPECTED;
623 hr = IPin_QueryPinInfo(in, &info_in);
624 if (SUCCEEDED(hr))
625 IBaseFilter_Release(info_in.pFilter);
626 if (FAILED(hr))
627 goto out;
628 if (info_in.dir != PINDIR_INPUT)
630 hr = E_UNEXPECTED;
631 goto out;
634 if (info_out.pFilter == info_in.pFilter)
635 hr = VFW_E_CIRCULAR_GRAPH;
636 else
638 IEnumPins *enumpins;
639 IPin *test;
641 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
642 if (FAILED(hr))
643 goto out;
645 IEnumPins_Reset(enumpins);
646 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
648 PIN_DIRECTION dir = PINDIR_OUTPUT;
649 IPin_QueryDirection(test, &dir);
650 if (dir == PINDIR_INPUT)
652 IPin *victim = NULL;
653 IPin_ConnectedTo(test, &victim);
654 if (victim)
656 hr = CheckCircularConnection(This, victim, in);
657 IPin_Release(victim);
658 if (FAILED(hr))
660 IPin_Release(test);
661 break;
665 IPin_Release(test);
667 IEnumPins_Release(enumpins);
670 out:
671 IBaseFilter_Release(info_out.pFilter);
672 if (FAILED(hr))
673 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
674 return hr;
675 #else
676 /* Debugging filtergraphs not enabled */
677 return S_OK;
678 #endif
682 /* NOTE: despite the implication, it doesn't matter which
683 * way round you put in the input and output pins */
684 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut,
685 const AM_MEDIA_TYPE *pmt)
687 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
688 PIN_DIRECTION dir;
689 HRESULT hr;
691 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
693 /* FIXME: check pins are in graph */
695 if (TRACE_ON(quartz))
697 PIN_INFO PinInfo;
699 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
700 if (FAILED(hr))
701 return hr;
703 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
704 IBaseFilter_Release(PinInfo.pFilter);
706 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
707 if (FAILED(hr))
708 return hr;
710 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
711 IBaseFilter_Release(PinInfo.pFilter);
714 hr = IPin_QueryDirection(ppinIn, &dir);
715 if (SUCCEEDED(hr))
717 if (dir == PINDIR_INPUT)
719 hr = CheckCircularConnection(This, ppinOut, ppinIn);
720 if (SUCCEEDED(hr))
721 hr = IPin_Connect(ppinOut, ppinIn, pmt);
723 else
725 hr = CheckCircularConnection(This, ppinIn, ppinOut);
726 if (SUCCEEDED(hr))
727 hr = IPin_Connect(ppinIn, ppinOut, pmt);
731 return hr;
734 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin)
736 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
737 IPin *pConnectedTo = NULL;
738 HRESULT hr;
739 PIN_DIRECTION pindir;
741 IPin_QueryDirection(ppin, &pindir);
742 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
743 if (FAILED(hr)) {
744 TRACE("Querying connected to failed: %x\n", hr);
745 return hr;
747 IPin_Disconnect(ppin);
748 IPin_Disconnect(pConnectedTo);
749 if (pindir == PINDIR_INPUT)
750 hr = IPin_Connect(pConnectedTo, ppin, NULL);
751 else
752 hr = IPin_Connect(ppin, pConnectedTo, NULL);
753 IPin_Release(pConnectedTo);
754 if (FAILED(hr))
755 WARN("Reconnecting pins failed, pins are not connected now..\n");
756 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
757 return hr;
760 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
762 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
764 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
766 if (!ppin)
767 return E_POINTER;
769 return IPin_Disconnect(ppin);
772 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
774 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
775 IReferenceClock *pClock = NULL;
776 HRESULT hr = S_OK;
777 int i;
779 TRACE("(%p/%p)->() live sources not handled properly!\n", iface, This);
781 EnterCriticalSection(&This->cs);
783 for (i = 0; i < This->nFilters; ++i)
785 DWORD miscflags;
786 IAMFilterMiscFlags *flags = NULL;
787 IUnknown_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags);
788 if (!flags)
789 continue;
790 miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
791 IUnknown_Release(flags);
792 if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
793 IUnknown_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock);
794 if (pClock)
795 break;
798 if (!pClock)
800 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
801 This->refClockProvider = NULL;
803 else
804 This->refClockProvider = This->ppFiltersInGraph[i];
806 if (SUCCEEDED(hr))
808 hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock);
809 This->defaultclock = TRUE;
810 IReferenceClock_Release(pClock);
812 LeaveCriticalSection(&This->cs);
814 return hr;
817 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
819 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
820 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
821 IPropertyBag * pPropBagCat = NULL;
822 HRESULT hr;
824 VariantInit(pvar);
826 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
828 if (SUCCEEDED(hr))
829 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
831 if (SUCCEEDED(hr))
832 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
834 VariantClear(pvar);
836 if (SUCCEEDED(hr))
837 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
839 if (SUCCEEDED(hr))
840 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
842 if (pPropBagCat)
843 IPropertyBag_Release(pPropBagCat);
845 return hr;
848 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
850 HRESULT hr;
851 ULONG nb = 0;
853 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
854 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
855 if (hr == S_OK) {
856 /* Rendered input */
857 } else if (hr == S_FALSE) {
858 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
859 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
860 if (hr != S_OK) {
861 WARN("Error (%x)\n", hr);
863 } else if (hr == E_NOTIMPL) {
864 /* Input connected to all outputs */
865 IEnumPins* penumpins;
866 IPin* ppin;
867 int i = 0;
868 TRACE("E_NOTIMPL\n");
869 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
870 if (FAILED(hr)) {
871 WARN("filter Enumpins failed (%x)\n", hr);
872 return hr;
874 i = 0;
875 /* Count output pins */
876 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
877 PIN_DIRECTION pindir;
878 IPin_QueryDirection(ppin, &pindir);
879 if (pindir == PINDIR_OUTPUT)
880 i++;
881 IPin_Release(ppin);
883 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
884 /* Retrieve output pins */
885 IEnumPins_Reset(penumpins);
886 i = 0;
887 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
888 PIN_DIRECTION pindir;
889 IPin_QueryDirection(ppin, &pindir);
890 if (pindir == PINDIR_OUTPUT)
891 (*pppins)[i++] = ppin;
892 else
893 IPin_Release(ppin);
895 IEnumPins_Release(penumpins);
896 nb = i;
897 if (FAILED(hr)) {
898 WARN("Next failed (%x)\n", hr);
899 return hr;
901 } else if (FAILED(hr)) {
902 WARN("Cannot get internal connection (%x)\n", hr);
903 return hr;
906 *pnb = nb;
907 return S_OK;
910 /*** IGraphBuilder methods ***/
911 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
913 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
914 HRESULT hr;
915 AM_MEDIA_TYPE* mt = NULL;
916 IEnumMediaTypes* penummt = NULL;
917 ULONG nbmt;
918 IEnumPins* penumpins;
919 IEnumMoniker* pEnumMoniker;
920 GUID tab[2];
921 ULONG nb;
922 IMoniker* pMoniker;
923 ULONG pin;
924 PIN_INFO PinInfo;
925 CLSID FilterCLSID;
926 PIN_DIRECTION dir;
928 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
930 if (TRACE_ON(quartz))
932 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
933 if (FAILED(hr))
934 return hr;
936 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
937 IBaseFilter_Release(PinInfo.pFilter);
939 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
940 if (FAILED(hr))
941 return hr;
943 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
944 IBaseFilter_Release(PinInfo.pFilter);
947 EnterCriticalSection(&This->cs);
948 ++This->recursioncount;
949 if (This->recursioncount >= 5)
951 WARN("Recursion count has reached %d\n", This->recursioncount);
952 hr = VFW_E_CANNOT_CONNECT;
953 goto out;
956 hr = IPin_QueryDirection(ppinOut, &dir);
957 if (FAILED(hr))
958 goto out;
960 if (dir == PINDIR_INPUT)
962 IPin *temp;
964 temp = ppinIn;
965 ppinIn = ppinOut;
966 ppinOut = temp;
969 hr = CheckCircularConnection(This, ppinOut, ppinIn);
970 if (FAILED(hr))
971 goto out;
973 /* Try direct connection first */
974 hr = IPin_Connect(ppinOut, ppinIn, NULL);
975 if (SUCCEEDED(hr))
976 goto out;
978 TRACE("Direct connection failed, trying to render using extra filters\n");
980 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
981 if (FAILED(hr))
982 goto out;
984 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
985 IBaseFilter_Release(PinInfo.pFilter);
986 if (FAILED(hr))
987 goto out;
989 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
990 * filter to the minor mediatype of input pin of the renderer */
991 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
992 if (FAILED(hr))
994 WARN("EnumMediaTypes (%x)\n", hr);
995 goto out;
998 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
999 if (FAILED(hr)) {
1000 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1001 goto out;
1004 if (!nbmt)
1006 WARN("No media type found!\n");
1007 hr = VFW_E_INVALIDMEDIATYPE;
1008 goto out;
1010 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1011 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1013 /* Try to find a suitable filter that can connect to the pin to render */
1014 tab[0] = mt->majortype;
1015 tab[1] = mt->subtype;
1016 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1017 if (FAILED(hr)) {
1018 WARN("Unable to enum filters (%x)\n", hr);
1019 goto out;
1022 hr = VFW_E_CANNOT_RENDER;
1023 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1025 VARIANT var;
1026 GUID clsid;
1027 IPin** ppins;
1028 IPin* ppinfilter = NULL;
1029 IBaseFilter* pfilter = NULL;
1030 IAMGraphBuilderCallback *callback = NULL;
1032 hr = GetFilterInfo(pMoniker, &clsid, &var);
1033 IMoniker_Release(pMoniker);
1034 if (FAILED(hr)) {
1035 WARN("Unable to retrieve filter info (%x)\n", hr);
1036 goto error;
1039 if (IsEqualGUID(&clsid, &FilterCLSID)) {
1040 /* Skip filter (same as the one the output pin belongs to) */
1041 goto error;
1044 if (This->pSite)
1046 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1047 if (callback)
1049 HRESULT rc;
1050 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1051 if (FAILED(rc))
1053 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1054 IUnknown_Release(callback);
1055 goto error;
1060 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1061 if (FAILED(hr)) {
1062 WARN("Unable to create filter (%x), trying next one\n", hr);
1063 goto error;
1066 if (callback)
1068 HRESULT rc;
1069 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1070 IUnknown_Release(callback);
1071 if (FAILED(rc))
1073 IBaseFilter_Release(pfilter);
1074 pfilter = NULL;
1075 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1076 goto error;
1080 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1081 if (FAILED(hr)) {
1082 WARN("Unable to add filter (%x)\n", hr);
1083 IBaseFilter_Release(pfilter);
1084 pfilter = NULL;
1085 goto error;
1088 VariantClear(&var);
1090 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1091 if (FAILED(hr)) {
1092 WARN("Enumpins (%x)\n", hr);
1093 goto error;
1096 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1097 IEnumPins_Release(penumpins);
1099 if (FAILED(hr)) {
1100 WARN("Obtaining next pin: (%x)\n", hr);
1101 goto error;
1103 if (pin == 0) {
1104 WARN("Cannot use this filter: no pins\n");
1105 goto error;
1108 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1109 if (FAILED(hr)) {
1110 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1111 goto error;
1113 TRACE("Successfully connected to filter, follow chain...\n");
1115 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
1116 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1118 if (SUCCEEDED(hr)) {
1119 unsigned int i;
1120 if (nb == 0) {
1121 IPin_Disconnect(ppinfilter);
1122 IPin_Disconnect(ppinOut);
1123 goto error;
1125 TRACE("pins to consider: %d\n", nb);
1126 for(i = 0; i < nb; i++)
1128 LPWSTR pinname = NULL;
1130 TRACE("Processing pin %u\n", i);
1132 hr = IPin_QueryId(ppins[i], &pinname);
1133 if (SUCCEEDED(hr))
1135 if (pinname[0] == '~')
1137 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1138 hr = E_FAIL;
1140 else
1141 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1142 CoTaskMemFree(pinname);
1145 if (FAILED(hr)) {
1146 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1148 IPin_Release(ppins[i]);
1149 if (SUCCEEDED(hr)) break;
1151 while (++i < nb) IPin_Release(ppins[i]);
1152 CoTaskMemFree(ppins);
1153 IPin_Release(ppinfilter);
1154 IBaseFilter_Release(pfilter);
1155 if (FAILED(hr))
1157 IPin_Disconnect(ppinfilter);
1158 IPin_Disconnect(ppinOut);
1159 IFilterGraph2_RemoveFilter(iface, pfilter);
1160 continue;
1162 break;
1165 error:
1166 VariantClear(&var);
1167 if (ppinfilter) IPin_Release(ppinfilter);
1168 if (pfilter) {
1169 IFilterGraph2_RemoveFilter(iface, pfilter);
1170 IBaseFilter_Release(pfilter);
1174 out:
1175 if (penummt)
1176 IEnumMediaTypes_Release(penummt);
1177 if (mt)
1178 DeleteMediaType(mt);
1179 --This->recursioncount;
1180 LeaveCriticalSection(&This->cs);
1181 TRACE("--> %08x\n", hr);
1182 return SUCCEEDED(hr) ? S_OK : hr;
1185 static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1187 /* This pin has been connected now, try to call render on all pins that aren't connected */
1188 IPin *to = NULL;
1189 PIN_INFO info;
1190 IEnumPins *enumpins = NULL;
1191 BOOL renderany = FALSE;
1192 BOOL renderall = TRUE;
1194 IPin_QueryPinInfo(ppinOut, &info);
1196 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1197 /* Don't need to hold a reference, IEnumPins does */
1198 IBaseFilter_Release(info.pFilter);
1200 IEnumPins_Reset(enumpins);
1201 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1203 PIN_DIRECTION dir = PINDIR_INPUT;
1205 IPin_QueryDirection(to, &dir);
1207 if (dir == PINDIR_OUTPUT)
1209 IPin *out = NULL;
1211 IPin_ConnectedTo(to, &out);
1212 if (!out)
1214 HRESULT hr;
1215 hr = IFilterGraph2_Render(&This->IFilterGraph2_iface, to);
1216 if (SUCCEEDED(hr))
1217 renderany = TRUE;
1218 else
1219 renderall = FALSE;
1221 else
1222 IPin_Release(out);
1225 IPin_Release(to);
1228 IEnumPins_Release(enumpins);
1230 if (renderall)
1231 return S_OK;
1233 if (renderany)
1234 return VFW_S_PARTIAL_RENDER;
1236 return VFW_E_CANNOT_RENDER;
1239 /* Ogg hates me if I create a direct rendering method
1241 * It can only connect to a pin properly once, so use a recursive method that does
1243 * +----+ --- (PIN 1) (Render is called on this pin)
1244 * | |
1245 * +----+ --- (PIN 2)
1247 * Enumerate possible renderers that EXACTLY match the requested type
1249 * If none is available, try to add intermediate filters that can connect to the input pin
1250 * then call Render on that intermediate pin's output pins
1251 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1252 * and another filter that can connect to the input pin is tried
1253 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1254 * It's recursive, but fun!
1257 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1259 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1260 IEnumMediaTypes* penummt;
1261 AM_MEDIA_TYPE* mt;
1262 ULONG nbmt;
1263 HRESULT hr;
1265 IEnumMoniker* pEnumMoniker;
1266 GUID tab[4];
1267 ULONG nb;
1268 IMoniker* pMoniker;
1269 INT x;
1271 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1273 if (TRACE_ON(quartz))
1275 PIN_INFO PinInfo;
1277 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1278 if (FAILED(hr))
1279 return hr;
1281 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1282 IBaseFilter_Release(PinInfo.pFilter);
1285 /* Try to find out if there is a renderer for the specified subtype already, and use that
1287 EnterCriticalSection(&This->cs);
1288 for (x = 0; x < This->nFilters; ++x)
1290 IEnumPins *enumpins = NULL;
1291 IPin *pin = NULL;
1293 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1295 if (FAILED(hr) || !enumpins)
1296 continue;
1298 IEnumPins_Reset(enumpins);
1299 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1301 IPin *to = NULL;
1302 PIN_DIRECTION dir = PINDIR_OUTPUT;
1304 IPin_QueryDirection(pin, &dir);
1305 if (dir != PINDIR_INPUT)
1307 IPin_Release(pin);
1308 continue;
1310 IPin_ConnectedTo(pin, &to);
1312 if (to == NULL)
1314 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1315 if (SUCCEEDED(hr))
1317 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1318 IPin_Release(pin);
1320 hr = FilterGraph2_RenderRecurse(This, pin);
1321 if (FAILED(hr))
1323 IPin_Disconnect(ppinOut);
1324 IPin_Disconnect(pin);
1325 continue;
1327 IEnumPins_Release(enumpins);
1328 LeaveCriticalSection(&This->cs);
1329 return hr;
1331 WARN("Could not connect!\n");
1333 else
1334 IPin_Release(to);
1336 IPin_Release(pin);
1338 IEnumPins_Release(enumpins);
1341 LeaveCriticalSection(&This->cs);
1343 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1344 if (FAILED(hr)) {
1345 WARN("EnumMediaTypes (%x)\n", hr);
1346 return hr;
1349 IEnumMediaTypes_Reset(penummt);
1351 /* Looks like no existing renderer of the kind exists
1352 * Try adding new ones
1354 tab[0] = tab[1] = GUID_NULL;
1355 while (SUCCEEDED(hr))
1357 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1358 if (FAILED(hr)) {
1359 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1360 break;
1362 if (!nbmt)
1364 hr = VFW_E_CANNOT_RENDER;
1365 break;
1367 else
1369 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1370 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1372 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1373 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1375 DeleteMediaType(mt);
1376 continue;
1379 /* Try to find a suitable renderer with the same media type */
1380 tab[0] = mt->majortype;
1381 tab[1] = mt->subtype;
1382 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1383 if (FAILED(hr))
1385 WARN("Unable to enum filters (%x)\n", hr);
1386 break;
1389 hr = E_FAIL;
1391 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1393 VARIANT var;
1394 GUID clsid;
1395 IPin* ppinfilter;
1396 IBaseFilter* pfilter = NULL;
1397 IEnumPins* penumpins = NULL;
1398 ULONG pin;
1400 hr = GetFilterInfo(pMoniker, &clsid, &var);
1401 IMoniker_Release(pMoniker);
1402 if (FAILED(hr)) {
1403 WARN("Unable to retrieve filter info (%x)\n", hr);
1404 goto error;
1407 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1408 if (FAILED(hr))
1410 WARN("Unable to create filter (%x), trying next one\n", hr);
1411 goto error;
1414 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1415 if (FAILED(hr)) {
1416 WARN("Unable to add filter (%x)\n", hr);
1417 IBaseFilter_Release(pfilter);
1418 pfilter = NULL;
1419 goto error;
1422 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1423 if (FAILED(hr)) {
1424 WARN("Splitter Enumpins (%x)\n", hr);
1425 goto error;
1428 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1430 PIN_DIRECTION dir;
1432 if (pin == 0) {
1433 WARN("No Pin\n");
1434 hr = E_FAIL;
1435 goto error;
1438 hr = IPin_QueryDirection(ppinfilter, &dir);
1439 if (FAILED(hr)) {
1440 IPin_Release(ppinfilter);
1441 WARN("QueryDirection failed (%x)\n", hr);
1442 goto error;
1444 if (dir != PINDIR_INPUT) {
1445 IPin_Release(ppinfilter);
1446 continue; /* Wrong direction */
1449 /* Connect the pin to the "Renderer" */
1450 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1451 IPin_Release(ppinfilter);
1453 if (FAILED(hr)) {
1454 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1455 goto error;
1457 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1459 VariantClear(&var);
1461 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1462 if (FAILED(hr)) {
1463 WARN("Unable to connect recursively (%x)\n", hr);
1464 goto error;
1466 IBaseFilter_Release(pfilter);
1467 break;
1469 if (SUCCEEDED(hr)) {
1470 IEnumPins_Release(penumpins);
1471 break; /* out of IEnumMoniker_Next loop */
1474 /* IEnumPins_Next failed, all other failure case caught by goto error */
1475 WARN("IEnumPins_Next (%x)\n", hr);
1476 /* goto error */
1478 error:
1479 VariantClear(&var);
1480 if (penumpins)
1481 IEnumPins_Release(penumpins);
1482 if (pfilter) {
1483 IFilterGraph2_RemoveFilter(iface, pfilter);
1484 IBaseFilter_Release(pfilter);
1486 if (SUCCEEDED(hr)) DebugBreak();
1489 IEnumMoniker_Release(pEnumMoniker);
1490 if (nbmt)
1491 DeleteMediaType(mt);
1492 if (SUCCEEDED(hr))
1493 break;
1494 hr = S_OK;
1497 IEnumMediaTypes_Release(penummt);
1498 return hr;
1501 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1502 LPCWSTR lpcwstrPlayList)
1504 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1505 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1506 IBaseFilter* preader = NULL;
1507 IPin* ppinreader = NULL;
1508 IEnumPins* penumpins = NULL;
1509 HRESULT hr;
1510 BOOL partial = FALSE;
1511 HRESULT any = FALSE;
1513 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1515 if (lpcwstrPlayList != NULL)
1516 return E_INVALIDARG;
1518 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1519 if (FAILED(hr))
1520 return hr;
1522 if (SUCCEEDED(hr))
1523 hr = IBaseFilter_EnumPins(preader, &penumpins);
1524 if (SUCCEEDED(hr))
1526 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1528 PIN_DIRECTION dir;
1530 IPin_QueryDirection(ppinreader, &dir);
1531 if (dir == PINDIR_OUTPUT)
1533 INT i;
1535 hr = IFilterGraph2_Render(iface, ppinreader);
1536 TRACE("Render %08x\n", hr);
1538 for (i = 0; i < This->nFilters; ++i)
1539 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1541 if (SUCCEEDED(hr))
1542 any = TRUE;
1543 if (hr != S_OK)
1544 partial = TRUE;
1546 IPin_Release(ppinreader);
1548 IEnumPins_Release(penumpins);
1550 if (!any)
1551 hr = VFW_E_CANNOT_RENDER;
1552 else if (partial)
1553 hr = VFW_S_PARTIAL_RENDER;
1554 else
1555 hr = S_OK;
1557 IBaseFilter_Release(preader);
1559 TRACE("--> %08x\n", hr);
1560 return hr;
1563 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1564 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1566 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1567 HRESULT hr = S_OK;
1568 HKEY extkey;
1569 LONG lRet;
1571 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
1572 hr = HRESULT_FROM_WIN32(lRet);
1574 if (SUCCEEDED(hr))
1576 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
1577 WCHAR *ext = PathFindExtensionW(pszFileName);
1578 WCHAR clsid_key[39];
1579 GUID clsid;
1580 DWORD size = sizeof(clsid_key);
1581 HKEY pathkey;
1583 if (!ext)
1585 CloseHandle(extkey);
1586 return E_FAIL;
1589 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
1590 hr = HRESULT_FROM_WIN32(lRet);
1591 CloseHandle(extkey);
1592 if (FAILED(hr))
1593 return hr;
1595 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
1596 hr = HRESULT_FROM_WIN32(lRet);
1597 CloseHandle(pathkey);
1598 if (FAILED(hr))
1599 return hr;
1601 CLSIDFromString(clsid_key, &clsid);
1603 TRACE("CLSID: %s\n", debugstr_guid(&clsid));
1604 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1605 if (SUCCEEDED(hr))
1607 IFileSourceFilter *source = NULL;
1608 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1609 if (SUCCEEDED(hr))
1610 IFileSourceFilter_Release(source);
1611 else
1612 IBaseFilter_Release(*filter);
1615 if (FAILED(hr))
1616 *filter = NULL;
1617 return hr;
1620 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1621 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1623 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1624 HRESULT hr;
1625 IBaseFilter* preader;
1626 IFileSourceFilter* pfile = NULL;
1627 AM_MEDIA_TYPE mt;
1628 WCHAR* filename;
1630 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1632 /* Try from file name first, then fall back to default asynchronous reader */
1633 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1635 if (FAILED(hr))
1636 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1637 if (FAILED(hr)) {
1638 WARN("Unable to create file source filter (%x)\n", hr);
1639 return hr;
1642 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1643 if (FAILED(hr)) {
1644 WARN("Unable add filter (%x)\n", hr);
1645 IBaseFilter_Release(preader);
1646 return hr;
1649 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1650 if (FAILED(hr)) {
1651 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1652 goto error;
1655 /* Load the file in the file source filter */
1656 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1657 if (FAILED(hr)) {
1658 WARN("Load (%x)\n", hr);
1659 goto error;
1662 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1663 if (FAILED(hr)) {
1664 WARN("GetCurFile (%x)\n", hr);
1665 goto error;
1668 TRACE("File %s\n", debugstr_w(filename));
1669 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1670 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1672 if (ppFilter)
1673 *ppFilter = preader;
1674 IFileSourceFilter_Release(pfile);
1676 return S_OK;
1678 error:
1679 if (pfile)
1680 IFileSourceFilter_Release(pfile);
1681 IFilterGraph2_RemoveFilter(iface, preader);
1682 IBaseFilter_Release(preader);
1684 return hr;
1687 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1689 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1691 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1693 return S_OK;
1696 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1698 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1700 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1702 return S_OK;
1705 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1707 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1709 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1711 return S_OK;
1714 /*** IFilterGraph2 methods ***/
1715 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1716 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1718 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1720 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1722 return S_OK;
1725 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1726 const AM_MEDIA_TYPE *pmt)
1728 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1730 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1732 return S_OK;
1735 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1736 DWORD *pvContext)
1738 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1740 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1742 return S_OK;
1746 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1748 FilterGraph2_QueryInterface,
1749 FilterGraph2_AddRef,
1750 FilterGraph2_Release,
1751 FilterGraph2_AddFilter,
1752 FilterGraph2_RemoveFilter,
1753 FilterGraph2_EnumFilters,
1754 FilterGraph2_FindFilterByName,
1755 FilterGraph2_ConnectDirect,
1756 FilterGraph2_Reconnect,
1757 FilterGraph2_Disconnect,
1758 FilterGraph2_SetDefaultSyncSource,
1759 FilterGraph2_Connect,
1760 FilterGraph2_Render,
1761 FilterGraph2_RenderFile,
1762 FilterGraph2_AddSourceFilter,
1763 FilterGraph2_SetLogFile,
1764 FilterGraph2_Abort,
1765 FilterGraph2_ShouldOperationContinue,
1766 FilterGraph2_AddSourceFilterForMoniker,
1767 FilterGraph2_ReconnectEx,
1768 FilterGraph2_RenderEx
1771 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
1773 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
1776 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
1778 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1780 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1782 return Filtergraph_QueryInterface(This, riid, ppvObj);
1785 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
1787 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1789 TRACE("(%p/%p)->()\n", This, iface);
1791 return Filtergraph_AddRef(This);
1794 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
1796 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1798 TRACE("(%p/%p)->()\n", This, iface);
1800 return Filtergraph_Release(This);
1804 /*** IDispatch methods ***/
1805 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
1807 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1809 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1811 return S_OK;
1814 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
1815 ITypeInfo **ppTInfo)
1817 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1819 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1821 return S_OK;
1824 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
1825 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1827 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1829 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1831 return S_OK;
1834 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
1835 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
1836 UINT *puArgErr)
1838 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1840 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);
1842 return S_OK;
1845 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1847 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1849 HRESULT hr;
1850 IPin* pInputPin;
1851 IPin** ppPins;
1852 ULONG nb;
1853 ULONG i;
1854 PIN_INFO PinInfo;
1856 TRACE("%p %p\n", pGraph, pOutputPin);
1857 PinInfo.pFilter = NULL;
1859 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1861 if (SUCCEEDED(hr))
1863 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1864 if (SUCCEEDED(hr))
1865 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1866 IPin_Release(pInputPin);
1869 if (SUCCEEDED(hr))
1871 if (nb == 0)
1873 TRACE("Reached a renderer\n");
1874 /* Count renderers for end of stream notification */
1875 pGraph->nRenderers++;
1877 else
1879 for(i = 0; i < nb; i++)
1881 /* Explore the graph downstream from this pin
1882 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1883 * several input pins are connected to the same output (a MUX for instance). */
1884 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1885 IPin_Release(ppPins[i]);
1888 CoTaskMemFree(ppPins);
1890 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1892 FoundFilter(PinInfo.pFilter, data);
1895 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1896 return hr;
1899 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1901 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
1902 return IBaseFilter_Run(pFilter, time);
1905 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1907 return IBaseFilter_Pause(pFilter);
1910 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1912 return IBaseFilter_Stop(pFilter);
1915 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1917 FILTER_STATE state;
1918 DWORD time_end = data;
1919 DWORD time_now = GetTickCount();
1920 LONG wait;
1922 if (time_end == INFINITE)
1924 wait = INFINITE;
1926 else if (time_end > time_now)
1928 wait = time_end - time_now;
1930 else
1931 wait = 0;
1933 return IBaseFilter_GetState(pFilter, wait, &state);
1937 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
1939 int i;
1940 IBaseFilter* pfilter;
1941 IEnumPins* pEnum;
1942 HRESULT hr;
1943 IPin* pPin;
1944 DWORD dummy;
1945 PIN_DIRECTION dir;
1947 TRACE("(%p)->()\n", This);
1949 /* Explorer the graph from source filters to renderers, determine renderers
1950 * number and run filters from renderers to source filters */
1951 This->nRenderers = 0;
1952 ResetEvent(This->hEventCompletion);
1954 for(i = 0; i < This->nFilters; i++)
1956 BOOL source = TRUE;
1957 pfilter = This->ppFiltersInGraph[i];
1958 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1959 if (hr != S_OK)
1961 WARN("Enum pins failed %x\n", hr);
1962 continue;
1964 /* Check if it is a source filter */
1965 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1967 IPin_QueryDirection(pPin, &dir);
1968 IPin_Release(pPin);
1969 if (dir == PINDIR_INPUT)
1971 source = FALSE;
1972 break;
1975 if (source)
1977 TRACE("Found a source filter %p\n", pfilter);
1978 IEnumPins_Reset(pEnum);
1979 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1981 /* Explore the graph downstream from this pin */
1982 ExploreGraph(This, pPin, FoundFilter, data);
1983 IPin_Release(pPin);
1985 FoundFilter(pfilter, data);
1987 IEnumPins_Release(pEnum);
1990 return S_FALSE;
1993 /*** IMediaControl methods ***/
1994 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
1996 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1998 TRACE("(%p/%p)->()\n", This, iface);
2000 EnterCriticalSection(&This->cs);
2001 if (This->state == State_Running)
2002 goto out;
2003 This->EcCompleteCount = 0;
2005 if (This->defaultclock && !This->refClock)
2006 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)This);
2008 if (This->refClock)
2010 REFERENCE_TIME now;
2011 IReferenceClock_GetTime(This->refClock, &now);
2012 if (This->state == State_Stopped)
2013 This->start_time = now + 500000;
2014 else if (This->pause_time >= 0)
2015 This->start_time += now - This->pause_time;
2016 else
2017 This->start_time = now;
2019 else This->start_time = 0;
2021 SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time);
2022 This->state = State_Running;
2023 out:
2024 LeaveCriticalSection(&This->cs);
2025 return S_FALSE;
2028 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2030 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2032 TRACE("(%p/%p)->()\n", This, iface);
2034 EnterCriticalSection(&This->cs);
2035 if (This->state == State_Paused)
2036 goto out;
2038 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2039 IReferenceClock_GetTime(This->refClock, &This->pause_time);
2040 else
2041 This->pause_time = -1;
2043 SendFilterMessage(This, SendPause, 0);
2044 This->state = State_Paused;
2045 out:
2046 LeaveCriticalSection(&This->cs);
2047 return S_FALSE;
2050 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2052 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2054 TRACE("(%p/%p)->()\n", This, iface);
2056 if (This->state == State_Stopped) return S_OK;
2058 EnterCriticalSection(&This->cs);
2059 if (This->state == State_Running) SendFilterMessage(This, SendPause, 0);
2060 SendFilterMessage(This, SendStop, 0);
2061 This->state = State_Stopped;
2062 LeaveCriticalSection(&This->cs);
2063 return S_OK;
2066 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout,
2067 OAFilterState *pfs)
2069 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2070 DWORD end;
2072 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
2074 if (!pfs)
2075 return E_POINTER;
2077 EnterCriticalSection(&This->cs);
2079 *pfs = This->state;
2080 if (msTimeout > 0)
2082 end = GetTickCount() + msTimeout;
2084 else if (msTimeout < 0)
2086 end = INFINITE;
2088 else
2090 end = 0;
2092 if (end)
2093 SendFilterMessage(This, SendGetState, end);
2095 LeaveCriticalSection(&This->cs);
2097 return S_OK;
2100 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2102 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2104 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
2106 return S_OK;
2109 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2110 IDispatch **ppUnk)
2112 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2114 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2116 return S_OK;
2119 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2121 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2123 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2125 return S_OK;
2128 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2130 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2132 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2134 return S_OK;
2137 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2139 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2141 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2143 return S_OK;
2147 static const IMediaControlVtbl IMediaControl_VTable =
2149 MediaControl_QueryInterface,
2150 MediaControl_AddRef,
2151 MediaControl_Release,
2152 MediaControl_GetTypeInfoCount,
2153 MediaControl_GetTypeInfo,
2154 MediaControl_GetIDsOfNames,
2155 MediaControl_Invoke,
2156 MediaControl_Run,
2157 MediaControl_Pause,
2158 MediaControl_Stop,
2159 MediaControl_GetState,
2160 MediaControl_RenderFile,
2161 MediaControl_AddSourceFilter,
2162 MediaControl_get_FilterCollection,
2163 MediaControl_get_RegFilterCollection,
2164 MediaControl_StopWhenReady
2167 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2169 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2172 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2174 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2176 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2178 return Filtergraph_QueryInterface(This, riid, ppvObj);
2181 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2183 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2185 TRACE("(%p/%p)->()\n", This, iface);
2187 return Filtergraph_AddRef(This);
2190 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2192 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2194 TRACE("(%p/%p)->()\n", This, iface);
2196 return Filtergraph_Release(This);
2199 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2201 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2202 BOOL allnotimpl = TRUE;
2203 int i;
2204 HRESULT hr, hr_return = S_OK;
2206 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2207 /* Send a message to all renderers, they are responsible for broadcasting it further */
2209 for(i = 0; i < This->nFilters; i++)
2211 IMediaSeeking *seek = NULL;
2212 IBaseFilter* pfilter = This->ppFiltersInGraph[i];
2213 IAMFilterMiscFlags *flags = NULL;
2214 ULONG filterflags;
2215 IUnknown_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags);
2216 if (!flags)
2217 continue;
2218 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2219 IUnknown_Release(flags);
2220 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2221 continue;
2223 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2224 if (!seek)
2225 continue;
2226 hr = FoundSeek(This, seek, arg);
2227 IMediaSeeking_Release(seek);
2228 if (hr_return != E_NOTIMPL)
2229 allnotimpl = FALSE;
2230 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2231 hr_return = hr;
2234 if (allnotimpl)
2235 return E_NOTIMPL;
2236 return hr_return;
2239 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2241 HRESULT hr;
2242 DWORD caps = 0;
2244 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2245 if (FAILED(hr))
2246 return hr;
2248 /* Only add common capabilities everything supports */
2249 *(DWORD*)pcaps &= caps;
2251 return hr;
2254 /*** IMediaSeeking methods ***/
2255 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2257 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2258 HRESULT hr;
2260 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2262 if (!pCapabilities)
2263 return E_POINTER;
2265 EnterCriticalSection(&This->cs);
2266 *pCapabilities = 0xffffffff;
2268 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2269 LeaveCriticalSection(&This->cs);
2271 return hr;
2274 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2276 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2277 DWORD originalcaps;
2278 HRESULT hr;
2280 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2282 if (!pCapabilities)
2283 return E_POINTER;
2285 EnterCriticalSection(&This->cs);
2286 originalcaps = *pCapabilities;
2287 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2288 LeaveCriticalSection(&This->cs);
2290 if (FAILED(hr))
2291 return hr;
2293 if (!*pCapabilities)
2294 return E_FAIL;
2295 if (*pCapabilities != originalcaps)
2296 return S_FALSE;
2297 return S_OK;
2300 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2302 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2304 if (!pFormat)
2305 return E_POINTER;
2307 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2309 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2311 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2312 return S_FALSE;
2315 return S_OK;
2318 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2320 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2322 if (!pFormat)
2323 return E_POINTER;
2325 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2326 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2328 return S_OK;
2331 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2333 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2335 if (!pFormat)
2336 return E_POINTER;
2338 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2339 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2341 return S_OK;
2344 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2346 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2348 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2349 if (!pFormat)
2350 return E_POINTER;
2352 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2353 return S_FALSE;
2355 return S_OK;
2358 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2360 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2362 if (!pFormat)
2363 return E_POINTER;
2365 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2367 if (This->state != State_Stopped)
2368 return VFW_E_WRONG_STATE;
2370 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2372 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2373 return E_INVALIDARG;
2376 return S_OK;
2379 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2381 HRESULT hr;
2382 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2384 hr = IMediaSeeking_GetDuration(seek, &duration);
2385 if (FAILED(hr))
2386 return hr;
2388 if (*pdur < duration)
2389 *pdur = duration;
2390 return hr;
2393 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2395 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2396 HRESULT hr;
2398 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2400 if (!pDuration)
2401 return E_POINTER;
2403 EnterCriticalSection(&This->cs);
2404 *pDuration = 0;
2405 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2406 LeaveCriticalSection(&This->cs);
2408 TRACE("--->%08x\n", hr);
2409 return hr;
2412 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2414 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2415 HRESULT hr = S_OK;
2417 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2419 if (!pStop)
2420 return E_POINTER;
2422 EnterCriticalSection(&This->cs);
2423 if (This->stop_position < 0)
2424 /* Stop position not set, use duration instead */
2425 hr = IMediaSeeking_GetDuration(iface, pStop);
2426 else
2427 *pStop = This->stop_position;
2428 LeaveCriticalSection(&This->cs);
2430 return hr;
2433 static HRESULT WINAPI FoundCurrentPosition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pposition)
2435 HRESULT hr;
2436 LONGLONG pos = 0, *ppos = (LONGLONG*)pposition;
2438 hr = IMediaSeeking_GetCurrentPosition(seek, &pos);
2439 if (FAILED(hr))
2440 return hr;
2442 if (*ppos < 0 || pos < *ppos)
2443 *ppos = pos;
2444 return hr;
2447 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2449 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2450 HRESULT hr;
2452 if (!pCurrent)
2453 return E_POINTER;
2455 EnterCriticalSection(&This->cs);
2456 *pCurrent = -1;
2457 hr = all_renderers_seek(This, FoundCurrentPosition, (DWORD_PTR)pCurrent);
2458 if (hr == E_NOTIMPL) {
2459 LONGLONG time = 0;
2460 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2462 IReferenceClock_GetTime(This->refClock, &time);
2463 if (time)
2464 time -= This->start_time;
2466 if (This->pause_time > 0)
2467 time += This->pause_time;
2468 *pCurrent = time;
2469 hr = S_OK;
2471 LeaveCriticalSection(&This->cs);
2473 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2475 return hr;
2478 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2479 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2481 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2483 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2484 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2486 return S_OK;
2489 struct pos_args {
2490 LONGLONG* current, *stop;
2491 DWORD curflags, stopflags;
2494 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2496 struct pos_args *args = (void*)pargs;
2498 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2501 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2502 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2504 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2505 HRESULT hr = S_OK;
2506 FILTER_STATE state;
2507 struct pos_args args;
2509 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2511 EnterCriticalSection(&This->cs);
2512 state = This->state;
2513 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2515 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2516 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2517 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2519 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2520 This->stop_position = *pStop;
2521 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2522 FIXME("Stop position not handled yet!\n");
2524 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2525 IMediaControl_Pause(&This->IMediaControl_iface);
2526 args.current = pCurrent;
2527 args.stop = pStop;
2528 args.curflags = dwCurrentFlags;
2529 args.stopflags = dwStopFlags;
2530 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2532 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2533 This->pause_time = This->start_time = -1;
2534 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2535 IMediaControl_Run(&This->IMediaControl_iface);
2536 LeaveCriticalSection(&This->cs);
2538 return hr;
2541 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2542 LONGLONG *pStop)
2544 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2545 HRESULT hr;
2547 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2548 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2549 if (SUCCEEDED(hr))
2550 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2552 return hr;
2555 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2556 LONGLONG *pLatest)
2558 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2560 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2562 return S_OK;
2565 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2567 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2569 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2571 return S_OK;
2574 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2576 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2578 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2580 return S_OK;
2583 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2585 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2587 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2589 return S_OK;
2593 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2595 MediaSeeking_QueryInterface,
2596 MediaSeeking_AddRef,
2597 MediaSeeking_Release,
2598 MediaSeeking_GetCapabilities,
2599 MediaSeeking_CheckCapabilities,
2600 MediaSeeking_IsFormatSupported,
2601 MediaSeeking_QueryPreferredFormat,
2602 MediaSeeking_GetTimeFormat,
2603 MediaSeeking_IsUsingTimeFormat,
2604 MediaSeeking_SetTimeFormat,
2605 MediaSeeking_GetDuration,
2606 MediaSeeking_GetStopPosition,
2607 MediaSeeking_GetCurrentPosition,
2608 MediaSeeking_ConvertTimeFormat,
2609 MediaSeeking_SetPositions,
2610 MediaSeeking_GetPositions,
2611 MediaSeeking_GetAvailable,
2612 MediaSeeking_SetRate,
2613 MediaSeeking_GetRate,
2614 MediaSeeking_GetPreroll
2617 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2619 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2622 /*** IUnknown methods ***/
2623 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2625 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2627 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2628 return Filtergraph_QueryInterface(This, riid, ppvObj);
2631 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2633 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2635 TRACE("(%p/%p)->()\n", This, iface);
2636 return Filtergraph_AddRef(This);
2639 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2641 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2643 TRACE("(%p/%p)->()\n", This, iface);
2644 return Filtergraph_Release(This);
2647 /*** IDispatch methods ***/
2648 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2649 FIXME("(%p) stub!\n", iface);
2650 return E_NOTIMPL;
2653 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2654 FIXME("(%p) stub!\n", iface);
2655 return E_NOTIMPL;
2658 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2659 FIXME("(%p) stub!\n", iface);
2660 return E_NOTIMPL;
2663 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2664 FIXME("(%p) stub!\n", iface);
2665 return E_NOTIMPL;
2668 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2670 GUID time_format;
2671 HRESULT hr;
2673 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2674 if (FAILED(hr))
2675 return hr;
2676 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2678 FIXME("Unsupported time format.\n");
2679 return E_NOTIMPL;
2682 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2683 return S_OK;
2686 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2688 GUID time_format;
2689 HRESULT hr;
2691 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2692 if (FAILED(hr))
2693 return hr;
2694 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2696 FIXME("Unsupported time format.\n");
2697 return E_NOTIMPL;
2700 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2701 return S_OK;
2704 /*** IMediaPosition methods ***/
2705 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2707 LONGLONG duration;
2708 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2709 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2710 if (FAILED(hr))
2711 return hr;
2712 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2715 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2717 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2718 LONGLONG reftime;
2719 HRESULT hr;
2721 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2722 if (FAILED(hr))
2723 return hr;
2724 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2725 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2728 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2730 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2731 LONGLONG pos;
2732 HRESULT hr;
2734 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2735 if (FAILED(hr))
2736 return hr;
2737 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2740 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2742 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2743 LONGLONG pos;
2744 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2745 if (FAILED(hr))
2746 return hr;
2747 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2750 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2752 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2753 LONGLONG reftime;
2754 HRESULT hr;
2756 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2757 if (FAILED(hr))
2758 return hr;
2759 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2760 &reftime, AM_SEEKING_AbsolutePositioning);
2763 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2764 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2765 return E_NOTIMPL;
2768 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2769 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2770 return E_NOTIMPL;
2773 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2775 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2776 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2779 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2781 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2782 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2785 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){
2791 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2792 return E_NOTIMPL;
2796 static const IMediaPositionVtbl IMediaPosition_VTable =
2798 MediaPosition_QueryInterface,
2799 MediaPosition_AddRef,
2800 MediaPosition_Release,
2801 MediaPosition_GetTypeInfoCount,
2802 MediaPosition_GetTypeInfo,
2803 MediaPosition_GetIDsOfNames,
2804 MediaPosition_Invoke,
2805 MediaPosition_get_Duration,
2806 MediaPosition_put_CurrentPosition,
2807 MediaPosition_get_CurrentPosition,
2808 MediaPosition_get_StopTime,
2809 MediaPosition_put_StopTime,
2810 MediaPosition_get_PrerollTime,
2811 MediaPosition_put_PrerollTime,
2812 MediaPosition_put_Rate,
2813 MediaPosition_get_Rate,
2814 MediaPosition_CanSeekForward,
2815 MediaPosition_CanSeekBackward
2818 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2820 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2823 /*** IUnknown methods ***/
2824 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2826 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2828 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2829 return Filtergraph_QueryInterface(This, riid, ppvObj);
2832 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2834 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2836 TRACE("(%p/%p)->()\n", This, iface);
2837 return Filtergraph_AddRef(This);
2840 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2842 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2844 TRACE("(%p/%p)->()\n", This, iface);
2845 return Filtergraph_Release(This);
2848 /*** IObjectWithSite methods ***/
2850 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2852 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2854 TRACE("(%p/%p)->()\n", This, iface);
2855 if (This->pSite) IUnknown_Release(This->pSite);
2856 This->pSite = pUnkSite;
2857 IUnknown_AddRef(This->pSite);
2858 return S_OK;
2861 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2863 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2865 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2867 *ppvSite = NULL;
2868 if (!This->pSite)
2869 return E_FAIL;
2870 else
2871 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2874 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2876 ObjectWithSite_QueryInterface,
2877 ObjectWithSite_AddRef,
2878 ObjectWithSite_Release,
2879 ObjectWithSite_SetSite,
2880 ObjectWithSite_GetSite,
2883 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2885 HRESULT hr = E_NOINTERFACE;
2886 int i;
2887 int entry;
2889 /* Check if the interface type is already registered */
2890 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2891 if (riid == pGraph->ItfCacheEntries[entry].riid)
2893 if (pGraph->ItfCacheEntries[entry].iface)
2895 /* Return the interface if available */
2896 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2897 return S_OK;
2899 break;
2902 if (entry >= MAX_ITF_CACHE_ENTRIES)
2904 FIXME("Not enough space to store interface in the cache\n");
2905 return E_OUTOFMEMORY;
2908 /* Find a filter supporting the requested interface */
2909 for (i = 0; i < pGraph->nFilters; i++)
2911 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2912 if (hr == S_OK)
2914 pGraph->ItfCacheEntries[entry].riid = riid;
2915 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2916 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
2917 if (entry >= pGraph->nItfCacheEntries)
2918 pGraph->nItfCacheEntries++;
2919 return S_OK;
2921 if (hr != E_NOINTERFACE)
2922 return hr;
2925 return hr;
2928 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
2930 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
2933 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
2935 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2937 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2939 return Filtergraph_QueryInterface(This, riid, ppvObj);
2942 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
2944 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2946 TRACE("(%p/%p)->()\n", This, iface);
2948 return Filtergraph_AddRef(This);
2951 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
2953 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2955 TRACE("(%p/%p)->()\n", This, iface);
2957 return Filtergraph_Release(This);
2960 /*** IDispatch methods ***/
2961 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
2963 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2964 IBasicAudio* pBasicAudio;
2965 HRESULT hr;
2967 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2969 EnterCriticalSection(&This->cs);
2971 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2973 if (hr == S_OK)
2974 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2976 LeaveCriticalSection(&This->cs);
2978 return hr;
2981 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
2982 ITypeInfo **ppTInfo)
2984 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2985 IBasicAudio* pBasicAudio;
2986 HRESULT hr;
2988 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2990 EnterCriticalSection(&This->cs);
2992 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2994 if (hr == S_OK)
2995 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2997 LeaveCriticalSection(&This->cs);
2999 return hr;
3002 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
3003 UINT cNames, LCID lcid, DISPID *rgDispId)
3005 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3006 IBasicAudio* pBasicAudio;
3007 HRESULT hr;
3009 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3011 EnterCriticalSection(&This->cs);
3013 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3015 if (hr == S_OK)
3016 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3018 LeaveCriticalSection(&This->cs);
3020 return hr;
3023 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3024 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3025 UINT *puArgErr)
3027 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3028 IBasicAudio* pBasicAudio;
3029 HRESULT hr;
3031 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);
3033 EnterCriticalSection(&This->cs);
3035 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3037 if (hr == S_OK)
3038 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3040 LeaveCriticalSection(&This->cs);
3042 return hr;
3045 /*** IBasicAudio methods ***/
3046 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3048 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3049 IBasicAudio* pBasicAudio;
3050 HRESULT hr;
3052 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3054 EnterCriticalSection(&This->cs);
3056 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3058 if (hr == S_OK)
3059 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3061 LeaveCriticalSection(&This->cs);
3063 return hr;
3066 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3068 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3069 IBasicAudio* pBasicAudio;
3070 HRESULT hr;
3072 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3074 EnterCriticalSection(&This->cs);
3076 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3078 if (hr == S_OK)
3079 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3081 LeaveCriticalSection(&This->cs);
3083 return hr;
3086 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3088 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3089 IBasicAudio* pBasicAudio;
3090 HRESULT hr;
3092 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3094 EnterCriticalSection(&This->cs);
3096 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3098 if (hr == S_OK)
3099 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3101 LeaveCriticalSection(&This->cs);
3103 return hr;
3106 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3108 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3109 IBasicAudio* pBasicAudio;
3110 HRESULT hr;
3112 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3114 EnterCriticalSection(&This->cs);
3116 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3118 if (hr == S_OK)
3119 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3121 LeaveCriticalSection(&This->cs);
3123 return hr;
3126 static const IBasicAudioVtbl IBasicAudio_VTable =
3128 BasicAudio_QueryInterface,
3129 BasicAudio_AddRef,
3130 BasicAudio_Release,
3131 BasicAudio_GetTypeInfoCount,
3132 BasicAudio_GetTypeInfo,
3133 BasicAudio_GetIDsOfNames,
3134 BasicAudio_Invoke,
3135 BasicAudio_put_Volume,
3136 BasicAudio_get_Volume,
3137 BasicAudio_put_Balance,
3138 BasicAudio_get_Balance
3141 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3143 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3146 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3148 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3150 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3152 return Filtergraph_QueryInterface(This, riid, ppvObj);
3155 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3157 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3159 TRACE("(%p/%p)->()\n", This, iface);
3161 return Filtergraph_AddRef(This);
3164 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3166 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3168 TRACE("(%p/%p)->()\n", This, iface);
3170 return Filtergraph_Release(This);
3173 /*** IDispatch methods ***/
3174 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3176 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3177 IBasicVideo *pBasicVideo;
3178 HRESULT hr;
3180 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3182 EnterCriticalSection(&This->cs);
3184 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3186 if (hr == S_OK)
3187 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3189 LeaveCriticalSection(&This->cs);
3191 return hr;
3194 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3195 ITypeInfo **ppTInfo)
3197 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3198 IBasicVideo *pBasicVideo;
3199 HRESULT hr;
3201 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3203 EnterCriticalSection(&This->cs);
3205 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3207 if (hr == S_OK)
3208 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3210 LeaveCriticalSection(&This->cs);
3212 return hr;
3215 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3216 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3218 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3219 IBasicVideo *pBasicVideo;
3220 HRESULT hr;
3222 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3224 EnterCriticalSection(&This->cs);
3226 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3228 if (hr == S_OK)
3229 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3231 LeaveCriticalSection(&This->cs);
3233 return hr;
3236 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3237 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3238 UINT *puArgErr)
3240 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3241 IBasicVideo *pBasicVideo;
3242 HRESULT hr;
3244 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);
3246 EnterCriticalSection(&This->cs);
3248 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3250 if (hr == S_OK)
3251 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3253 LeaveCriticalSection(&This->cs);
3255 return hr;
3258 /*** IBasicVideo methods ***/
3259 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3261 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3262 IBasicVideo *pBasicVideo;
3263 HRESULT hr;
3265 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3267 EnterCriticalSection(&This->cs);
3269 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3271 if (hr == S_OK)
3272 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3274 LeaveCriticalSection(&This->cs);
3276 return hr;
3279 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3281 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3282 IBasicVideo *pBasicVideo;
3283 HRESULT hr;
3285 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3287 EnterCriticalSection(&This->cs);
3289 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3291 if (hr == S_OK)
3292 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3294 LeaveCriticalSection(&This->cs);
3296 return hr;
3299 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3301 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3302 IBasicVideo *pBasicVideo;
3303 HRESULT hr;
3305 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3307 EnterCriticalSection(&This->cs);
3309 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3311 if (hr == S_OK)
3312 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3314 LeaveCriticalSection(&This->cs);
3316 return hr;
3319 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3321 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3322 IBasicVideo *pBasicVideo;
3323 HRESULT hr;
3325 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3327 EnterCriticalSection(&This->cs);
3329 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3331 if (hr == S_OK)
3332 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3334 LeaveCriticalSection(&This->cs);
3336 return hr;
3339 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3341 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3342 IBasicVideo *pBasicVideo;
3343 HRESULT hr;
3345 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3347 EnterCriticalSection(&This->cs);
3349 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3351 if (hr == S_OK)
3352 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3354 LeaveCriticalSection(&This->cs);
3356 return hr;
3359 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3361 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3362 IBasicVideo *pBasicVideo;
3363 HRESULT hr;
3365 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3367 EnterCriticalSection(&This->cs);
3369 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3371 if (hr == S_OK)
3372 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3374 LeaveCriticalSection(&This->cs);
3376 return hr;
3379 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3381 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3382 IBasicVideo *pBasicVideo;
3383 HRESULT hr;
3385 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3387 EnterCriticalSection(&This->cs);
3389 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3391 if (hr == S_OK)
3392 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3394 LeaveCriticalSection(&This->cs);
3396 return hr;
3399 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3401 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3402 IBasicVideo *pBasicVideo;
3403 HRESULT hr;
3405 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3407 EnterCriticalSection(&This->cs);
3409 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3411 if (hr == S_OK)
3412 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3414 LeaveCriticalSection(&This->cs);
3416 return hr;
3419 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3421 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3422 IBasicVideo *pBasicVideo;
3423 HRESULT hr;
3425 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3427 EnterCriticalSection(&This->cs);
3429 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3431 if (hr == S_OK)
3432 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3434 LeaveCriticalSection(&This->cs);
3436 return hr;
3439 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3441 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3442 IBasicVideo *pBasicVideo;
3443 HRESULT hr;
3445 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3447 EnterCriticalSection(&This->cs);
3449 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3451 if (hr == S_OK)
3452 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3454 LeaveCriticalSection(&This->cs);
3456 return hr;
3459 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3461 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3462 IBasicVideo *pBasicVideo;
3463 HRESULT hr;
3465 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3467 EnterCriticalSection(&This->cs);
3469 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3471 if (hr == S_OK)
3472 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3474 LeaveCriticalSection(&This->cs);
3476 return hr;
3479 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3481 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3482 IBasicVideo *pBasicVideo;
3483 HRESULT hr;
3485 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3487 EnterCriticalSection(&This->cs);
3489 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3491 if (hr == S_OK)
3492 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3494 LeaveCriticalSection(&This->cs);
3496 return hr;
3499 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3501 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3502 IBasicVideo *pBasicVideo;
3503 HRESULT hr;
3505 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3507 EnterCriticalSection(&This->cs);
3509 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3511 if (hr == S_OK)
3512 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3514 LeaveCriticalSection(&This->cs);
3516 return hr;
3519 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3521 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3522 IBasicVideo *pBasicVideo;
3523 HRESULT hr;
3525 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3527 EnterCriticalSection(&This->cs);
3529 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3531 if (hr == S_OK)
3532 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3534 LeaveCriticalSection(&This->cs);
3536 return hr;
3539 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3541 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3542 IBasicVideo *pBasicVideo;
3543 HRESULT hr;
3545 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3547 EnterCriticalSection(&This->cs);
3549 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3551 if (hr == S_OK)
3552 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3554 LeaveCriticalSection(&This->cs);
3556 return hr;
3559 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3561 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3562 IBasicVideo *pBasicVideo;
3563 HRESULT hr;
3565 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3567 EnterCriticalSection(&This->cs);
3569 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3571 if (hr == S_OK)
3572 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3574 LeaveCriticalSection(&This->cs);
3576 return hr;
3579 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3581 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3582 IBasicVideo *pBasicVideo;
3583 HRESULT hr;
3585 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3587 EnterCriticalSection(&This->cs);
3589 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3591 if (hr == S_OK)
3592 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3594 LeaveCriticalSection(&This->cs);
3596 return hr;
3599 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3601 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3602 IBasicVideo *pBasicVideo;
3603 HRESULT hr;
3605 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3607 EnterCriticalSection(&This->cs);
3609 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3611 if (hr == S_OK)
3612 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3614 LeaveCriticalSection(&This->cs);
3616 return hr;
3619 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3621 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3622 IBasicVideo *pBasicVideo;
3623 HRESULT hr;
3625 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3627 EnterCriticalSection(&This->cs);
3629 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3631 if (hr == S_OK)
3632 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3634 LeaveCriticalSection(&This->cs);
3636 return hr;
3639 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3641 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3642 IBasicVideo *pBasicVideo;
3643 HRESULT hr;
3645 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3647 EnterCriticalSection(&This->cs);
3649 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3651 if (hr == S_OK)
3652 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3654 LeaveCriticalSection(&This->cs);
3656 return hr;
3659 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3660 LONG *pDestinationHeight)
3662 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3663 IBasicVideo *pBasicVideo;
3664 HRESULT hr;
3666 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3668 EnterCriticalSection(&This->cs);
3670 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3672 if (hr == S_OK)
3673 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3675 LeaveCriticalSection(&This->cs);
3677 return hr;
3680 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3681 LONG Width, LONG Height)
3683 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3684 IBasicVideo *pBasicVideo;
3685 HRESULT hr;
3687 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3689 EnterCriticalSection(&This->cs);
3691 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3693 if (hr == S_OK)
3694 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3696 LeaveCriticalSection(&This->cs);
3698 return hr;
3701 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3702 LONG *pWidth, LONG *pHeight)
3704 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3705 IBasicVideo *pBasicVideo;
3706 HRESULT hr;
3708 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3710 EnterCriticalSection(&This->cs);
3712 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3714 if (hr == S_OK)
3715 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3717 LeaveCriticalSection(&This->cs);
3719 return hr;
3722 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3724 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3725 IBasicVideo *pBasicVideo;
3726 HRESULT hr;
3728 TRACE("(%p/%p)->()\n", This, iface);
3730 EnterCriticalSection(&This->cs);
3732 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3734 if (hr == S_OK)
3735 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3737 LeaveCriticalSection(&This->cs);
3739 return hr;
3742 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3743 LONG Width, LONG Height)
3745 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3746 IBasicVideo *pBasicVideo;
3747 HRESULT hr;
3749 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3751 EnterCriticalSection(&This->cs);
3753 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3755 if (hr == S_OK)
3756 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3758 LeaveCriticalSection(&This->cs);
3760 return hr;
3763 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3764 LONG *pTop, LONG *pWidth, LONG *pHeight)
3766 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3767 IBasicVideo *pBasicVideo;
3768 HRESULT hr;
3770 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3772 EnterCriticalSection(&This->cs);
3774 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3776 if (hr == S_OK)
3777 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3779 LeaveCriticalSection(&This->cs);
3781 return hr;
3784 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3786 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3787 IBasicVideo *pBasicVideo;
3788 HRESULT hr;
3790 TRACE("(%p/%p)->()\n", This, iface);
3792 EnterCriticalSection(&This->cs);
3794 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3796 if (hr == S_OK)
3797 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3799 LeaveCriticalSection(&This->cs);
3801 return hr;
3804 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3806 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3807 IBasicVideo *pBasicVideo;
3808 HRESULT hr;
3810 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3812 EnterCriticalSection(&This->cs);
3814 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3816 if (hr == S_OK)
3817 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3819 LeaveCriticalSection(&This->cs);
3821 return hr;
3824 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3825 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3827 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3828 IBasicVideo *pBasicVideo;
3829 HRESULT hr;
3831 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3833 EnterCriticalSection(&This->cs);
3835 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3837 if (hr == S_OK)
3838 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3840 LeaveCriticalSection(&This->cs);
3842 return hr;
3845 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3846 LONG *pDIBImage)
3848 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3849 IBasicVideo *pBasicVideo;
3850 HRESULT hr;
3852 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3854 EnterCriticalSection(&This->cs);
3856 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3858 if (hr == S_OK)
3859 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3861 LeaveCriticalSection(&This->cs);
3863 return hr;
3866 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3868 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3869 IBasicVideo *pBasicVideo;
3870 HRESULT hr;
3872 TRACE("(%p/%p)->()\n", This, iface);
3874 EnterCriticalSection(&This->cs);
3876 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3878 if (hr == S_OK)
3879 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3881 LeaveCriticalSection(&This->cs);
3883 return hr;
3886 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
3888 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3889 IBasicVideo *pBasicVideo;
3890 HRESULT hr;
3892 TRACE("(%p/%p)->()\n", This, iface);
3894 EnterCriticalSection(&This->cs);
3896 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3898 if (hr == S_OK)
3899 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3901 LeaveCriticalSection(&This->cs);
3903 return hr;
3906 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
3907 LONG *plAspectY)
3909 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3910 IBasicVideo2 *pBasicVideo2;
3911 HRESULT hr;
3913 TRACE("(%p/%p)->()\n", This, iface);
3915 EnterCriticalSection(&This->cs);
3917 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3919 if (hr == S_OK)
3920 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3922 LeaveCriticalSection(&This->cs);
3924 return hr;
3927 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3929 BasicVideo_QueryInterface,
3930 BasicVideo_AddRef,
3931 BasicVideo_Release,
3932 BasicVideo_GetTypeInfoCount,
3933 BasicVideo_GetTypeInfo,
3934 BasicVideo_GetIDsOfNames,
3935 BasicVideo_Invoke,
3936 BasicVideo_get_AvgTimePerFrame,
3937 BasicVideo_get_BitRate,
3938 BasicVideo_get_BitErrorRate,
3939 BasicVideo_get_VideoWidth,
3940 BasicVideo_get_VideoHeight,
3941 BasicVideo_put_SourceLeft,
3942 BasicVideo_get_SourceLeft,
3943 BasicVideo_put_SourceWidth,
3944 BasicVideo_get_SourceWidth,
3945 BasicVideo_put_SourceTop,
3946 BasicVideo_get_SourceTop,
3947 BasicVideo_put_SourceHeight,
3948 BasicVideo_get_SourceHeight,
3949 BasicVideo_put_DestinationLeft,
3950 BasicVideo_get_DestinationLeft,
3951 BasicVideo_put_DestinationWidth,
3952 BasicVideo_get_DestinationWidth,
3953 BasicVideo_put_DestinationTop,
3954 BasicVideo_get_DestinationTop,
3955 BasicVideo_put_DestinationHeight,
3956 BasicVideo_get_DestinationHeight,
3957 BasicVideo_SetSourcePosition,
3958 BasicVideo_GetSourcePosition,
3959 BasicVideo_SetDefaultSourcePosition,
3960 BasicVideo_SetDestinationPosition,
3961 BasicVideo_GetDestinationPosition,
3962 BasicVideo_SetDefaultDestinationPosition,
3963 BasicVideo_GetVideoSize,
3964 BasicVideo_GetVideoPaletteEntries,
3965 BasicVideo_GetCurrentImage,
3966 BasicVideo_IsUsingDefaultSource,
3967 BasicVideo_IsUsingDefaultDestination,
3968 BasicVideo2_GetPreferredAspectRatio
3971 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
3973 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
3976 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
3978 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3980 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3982 return Filtergraph_QueryInterface(This, riid, ppvObj);
3985 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
3987 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3989 TRACE("(%p/%p)->()\n", This, iface);
3991 return Filtergraph_AddRef(This);
3994 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
3996 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3998 TRACE("(%p/%p)->()\n", This, iface);
4000 return Filtergraph_Release(This);
4003 /*** IDispatch methods ***/
4004 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4006 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4007 IVideoWindow *pVideoWindow;
4008 HRESULT hr;
4010 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4012 EnterCriticalSection(&This->cs);
4014 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4016 if (hr == S_OK)
4017 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4019 LeaveCriticalSection(&This->cs);
4021 return hr;
4024 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4025 ITypeInfo **ppTInfo)
4027 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4028 IVideoWindow *pVideoWindow;
4029 HRESULT hr;
4031 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4033 EnterCriticalSection(&This->cs);
4035 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4037 if (hr == S_OK)
4038 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4040 LeaveCriticalSection(&This->cs);
4042 return hr;
4045 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4046 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4048 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4049 IVideoWindow *pVideoWindow;
4050 HRESULT hr;
4052 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4054 EnterCriticalSection(&This->cs);
4056 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4058 if (hr == S_OK)
4059 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4061 LeaveCriticalSection(&This->cs);
4063 return hr;
4066 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4067 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4068 UINT*puArgErr)
4070 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4071 IVideoWindow *pVideoWindow;
4072 HRESULT hr;
4074 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);
4076 EnterCriticalSection(&This->cs);
4078 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4080 if (hr == S_OK)
4081 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4083 LeaveCriticalSection(&This->cs);
4085 return hr;
4089 /*** IVideoWindow methods ***/
4090 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4092 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4093 IVideoWindow *pVideoWindow;
4094 HRESULT hr;
4096 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4098 EnterCriticalSection(&This->cs);
4100 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4102 if (hr == S_OK)
4103 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4105 LeaveCriticalSection(&This->cs);
4107 return hr;
4110 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4112 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4113 IVideoWindow *pVideoWindow;
4114 HRESULT hr;
4116 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4118 EnterCriticalSection(&This->cs);
4120 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4122 if (hr == S_OK)
4123 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4125 LeaveCriticalSection(&This->cs);
4127 return hr;
4130 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4132 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4133 IVideoWindow *pVideoWindow;
4134 HRESULT hr;
4136 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4138 EnterCriticalSection(&This->cs);
4140 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4142 if (hr == S_OK)
4143 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4145 LeaveCriticalSection(&This->cs);
4147 return hr;
4150 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4152 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4153 IVideoWindow *pVideoWindow;
4154 HRESULT hr;
4156 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4158 EnterCriticalSection(&This->cs);
4160 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4162 if (hr == S_OK)
4163 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4165 LeaveCriticalSection(&This->cs);
4167 return hr;
4170 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4172 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4173 IVideoWindow *pVideoWindow;
4174 HRESULT hr;
4176 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4178 EnterCriticalSection(&This->cs);
4180 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4182 if (hr == S_OK)
4183 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4185 LeaveCriticalSection(&This->cs);
4187 return hr;
4190 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4192 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4193 IVideoWindow *pVideoWindow;
4194 HRESULT hr;
4196 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4198 EnterCriticalSection(&This->cs);
4200 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4202 if (hr == S_OK)
4203 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4205 LeaveCriticalSection(&This->cs);
4207 return hr;
4210 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4212 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4213 IVideoWindow *pVideoWindow;
4214 HRESULT hr;
4216 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4218 EnterCriticalSection(&This->cs);
4220 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4222 if (hr == S_OK)
4223 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4225 LeaveCriticalSection(&This->cs);
4227 return hr;
4230 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4232 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4233 IVideoWindow *pVideoWindow;
4234 HRESULT hr;
4236 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4238 EnterCriticalSection(&This->cs);
4240 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4242 if (hr == S_OK)
4243 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4245 LeaveCriticalSection(&This->cs);
4247 return hr;
4250 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4252 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4253 IVideoWindow *pVideoWindow;
4254 HRESULT hr;
4256 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4258 EnterCriticalSection(&This->cs);
4260 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4262 if (hr == S_OK)
4263 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4265 LeaveCriticalSection(&This->cs);
4267 return hr;
4270 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4272 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4273 IVideoWindow *pVideoWindow;
4274 HRESULT hr;
4276 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4278 EnterCriticalSection(&This->cs);
4280 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4282 if (hr == S_OK)
4283 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4285 LeaveCriticalSection(&This->cs);
4287 return hr;
4290 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4292 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4293 IVideoWindow *pVideoWindow;
4294 HRESULT hr;
4296 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4298 EnterCriticalSection(&This->cs);
4300 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4302 if (hr == S_OK)
4303 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4305 LeaveCriticalSection(&This->cs);
4307 return hr;
4310 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4311 LONG *pBackgroundPalette)
4313 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4314 IVideoWindow *pVideoWindow;
4315 HRESULT hr;
4317 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4319 EnterCriticalSection(&This->cs);
4321 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4323 if (hr == S_OK)
4324 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4326 LeaveCriticalSection(&This->cs);
4328 return hr;
4331 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4333 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4334 IVideoWindow *pVideoWindow;
4335 HRESULT hr;
4337 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4339 EnterCriticalSection(&This->cs);
4341 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4343 if (hr == S_OK)
4344 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4346 LeaveCriticalSection(&This->cs);
4348 return hr;
4351 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4353 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4354 IVideoWindow *pVideoWindow;
4355 HRESULT hr;
4357 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4359 EnterCriticalSection(&This->cs);
4361 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4363 if (hr == S_OK)
4364 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4366 LeaveCriticalSection(&This->cs);
4368 return hr;
4371 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4373 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4374 IVideoWindow *pVideoWindow;
4375 HRESULT hr;
4377 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4379 EnterCriticalSection(&This->cs);
4381 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4383 if (hr == S_OK)
4384 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4386 LeaveCriticalSection(&This->cs);
4388 return hr;
4391 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4393 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4394 IVideoWindow *pVideoWindow;
4395 HRESULT hr;
4397 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4399 EnterCriticalSection(&This->cs);
4401 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4403 if (hr == S_OK)
4404 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4406 LeaveCriticalSection(&This->cs);
4408 return hr;
4411 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4413 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4414 IVideoWindow *pVideoWindow;
4415 HRESULT hr;
4417 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4419 EnterCriticalSection(&This->cs);
4421 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4423 if (hr == S_OK)
4424 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4426 LeaveCriticalSection(&This->cs);
4428 return hr;
4431 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4433 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4434 IVideoWindow *pVideoWindow;
4435 HRESULT hr;
4437 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4439 EnterCriticalSection(&This->cs);
4441 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4443 if (hr == S_OK)
4444 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4446 LeaveCriticalSection(&This->cs);
4448 return hr;
4451 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4453 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4454 IVideoWindow *pVideoWindow;
4455 HRESULT hr;
4457 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4459 EnterCriticalSection(&This->cs);
4461 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4463 if (hr == S_OK)
4464 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4466 LeaveCriticalSection(&This->cs);
4468 return hr;
4471 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4473 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4474 IVideoWindow *pVideoWindow;
4475 HRESULT hr;
4477 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4479 EnterCriticalSection(&This->cs);
4481 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4483 if (hr == S_OK)
4484 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4486 LeaveCriticalSection(&This->cs);
4488 return hr;
4491 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4493 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4494 IVideoWindow *pVideoWindow;
4495 HRESULT hr;
4497 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4499 EnterCriticalSection(&This->cs);
4501 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4503 if (hr == S_OK)
4504 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4506 LeaveCriticalSection(&This->cs);
4508 return hr;
4511 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4513 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4514 IVideoWindow *pVideoWindow;
4515 HRESULT hr;
4517 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4519 EnterCriticalSection(&This->cs);
4521 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4523 if (hr == S_OK)
4524 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4526 LeaveCriticalSection(&This->cs);
4528 return hr;
4531 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4533 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4534 IVideoWindow *pVideoWindow;
4535 HRESULT hr;
4537 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4539 EnterCriticalSection(&This->cs);
4541 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4543 if (hr == S_OK)
4544 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4546 LeaveCriticalSection(&This->cs);
4548 return hr;
4551 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4553 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4554 IVideoWindow *pVideoWindow;
4555 HRESULT hr;
4557 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4559 EnterCriticalSection(&This->cs);
4561 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4563 if (hr == S_OK)
4564 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4566 LeaveCriticalSection(&This->cs);
4568 return hr;
4571 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4573 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4574 IVideoWindow *pVideoWindow;
4575 HRESULT hr;
4577 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4579 EnterCriticalSection(&This->cs);
4581 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4583 if (hr == S_OK)
4584 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4586 LeaveCriticalSection(&This->cs);
4588 return hr;
4591 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4593 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4594 IVideoWindow *pVideoWindow;
4595 HRESULT hr;
4597 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4599 EnterCriticalSection(&This->cs);
4601 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4603 if (hr == S_OK)
4604 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4606 LeaveCriticalSection(&This->cs);
4608 return hr;
4611 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4613 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4614 IVideoWindow *pVideoWindow;
4615 HRESULT hr;
4617 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4619 EnterCriticalSection(&This->cs);
4621 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4623 if (hr == S_OK)
4624 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4626 LeaveCriticalSection(&This->cs);
4628 return hr;
4631 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4633 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4634 IVideoWindow *pVideoWindow;
4635 HRESULT hr;
4637 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4639 EnterCriticalSection(&This->cs);
4641 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4643 if (hr == S_OK)
4644 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4646 LeaveCriticalSection(&This->cs);
4648 return hr;
4651 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4653 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4654 IVideoWindow *pVideoWindow;
4655 HRESULT hr;
4657 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4659 EnterCriticalSection(&This->cs);
4661 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4663 if (hr == S_OK)
4664 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4666 LeaveCriticalSection(&This->cs);
4668 return hr;
4671 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4673 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4674 IVideoWindow *pVideoWindow;
4675 HRESULT hr;
4677 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4679 EnterCriticalSection(&This->cs);
4681 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4683 if (hr == S_OK)
4684 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4686 LeaveCriticalSection(&This->cs);
4688 return hr;
4691 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4693 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4694 IVideoWindow *pVideoWindow;
4695 HRESULT hr;
4697 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4699 EnterCriticalSection(&This->cs);
4701 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4703 if (hr == S_OK)
4704 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4706 LeaveCriticalSection(&This->cs);
4708 return hr;
4711 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4712 LONG_PTR wParam, LONG_PTR lParam)
4714 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4715 IVideoWindow *pVideoWindow;
4716 HRESULT hr;
4718 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4720 EnterCriticalSection(&This->cs);
4722 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4724 if (hr == S_OK)
4725 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4727 LeaveCriticalSection(&This->cs);
4729 return hr;
4732 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4733 LONG Width, LONG Height)
4735 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4736 IVideoWindow *pVideoWindow;
4737 HRESULT hr;
4739 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4741 EnterCriticalSection(&This->cs);
4743 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4745 if (hr == S_OK)
4746 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4748 LeaveCriticalSection(&This->cs);
4750 return hr;
4753 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4754 LONG *pWidth, LONG *pHeight)
4756 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4757 IVideoWindow *pVideoWindow;
4758 HRESULT hr;
4760 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4762 EnterCriticalSection(&This->cs);
4764 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4766 if (hr == S_OK)
4767 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4769 LeaveCriticalSection(&This->cs);
4771 return hr;
4774 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4775 LONG *pHeight)
4777 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4778 IVideoWindow *pVideoWindow;
4779 HRESULT hr;
4781 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4783 EnterCriticalSection(&This->cs);
4785 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4787 if (hr == S_OK)
4788 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4790 LeaveCriticalSection(&This->cs);
4792 return hr;
4795 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4796 LONG *pHeight)
4798 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4799 IVideoWindow *pVideoWindow;
4800 HRESULT hr;
4802 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4804 EnterCriticalSection(&This->cs);
4806 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4808 if (hr == S_OK)
4809 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4811 LeaveCriticalSection(&This->cs);
4813 return hr;
4816 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4817 LONG *pWidth, LONG *pHeight)
4819 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4820 IVideoWindow *pVideoWindow;
4821 HRESULT hr;
4823 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4825 EnterCriticalSection(&This->cs);
4827 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4829 if (hr == S_OK)
4830 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4832 LeaveCriticalSection(&This->cs);
4834 return hr;
4837 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4839 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4840 IVideoWindow *pVideoWindow;
4841 HRESULT hr;
4843 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4845 EnterCriticalSection(&This->cs);
4847 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4849 if (hr == S_OK)
4850 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4852 LeaveCriticalSection(&This->cs);
4854 return hr;
4857 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4859 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4860 IVideoWindow *pVideoWindow;
4861 HRESULT hr;
4863 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4865 EnterCriticalSection(&This->cs);
4867 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4869 if (hr == S_OK)
4870 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4872 LeaveCriticalSection(&This->cs);
4874 return hr;
4878 static const IVideoWindowVtbl IVideoWindow_VTable =
4880 VideoWindow_QueryInterface,
4881 VideoWindow_AddRef,
4882 VideoWindow_Release,
4883 VideoWindow_GetTypeInfoCount,
4884 VideoWindow_GetTypeInfo,
4885 VideoWindow_GetIDsOfNames,
4886 VideoWindow_Invoke,
4887 VideoWindow_put_Caption,
4888 VideoWindow_get_Caption,
4889 VideoWindow_put_WindowStyle,
4890 VideoWindow_get_WindowStyle,
4891 VideoWindow_put_WindowStyleEx,
4892 VideoWindow_get_WindowStyleEx,
4893 VideoWindow_put_AutoShow,
4894 VideoWindow_get_AutoShow,
4895 VideoWindow_put_WindowState,
4896 VideoWindow_get_WindowState,
4897 VideoWindow_put_BackgroundPalette,
4898 VideoWindow_get_BackgroundPalette,
4899 VideoWindow_put_Visible,
4900 VideoWindow_get_Visible,
4901 VideoWindow_put_Left,
4902 VideoWindow_get_Left,
4903 VideoWindow_put_Width,
4904 VideoWindow_get_Width,
4905 VideoWindow_put_Top,
4906 VideoWindow_get_Top,
4907 VideoWindow_put_Height,
4908 VideoWindow_get_Height,
4909 VideoWindow_put_Owner,
4910 VideoWindow_get_Owner,
4911 VideoWindow_put_MessageDrain,
4912 VideoWindow_get_MessageDrain,
4913 VideoWindow_get_BorderColor,
4914 VideoWindow_put_BorderColor,
4915 VideoWindow_get_FullScreenMode,
4916 VideoWindow_put_FullScreenMode,
4917 VideoWindow_SetWindowForeground,
4918 VideoWindow_NotifyOwnerMessage,
4919 VideoWindow_SetWindowPosition,
4920 VideoWindow_GetWindowPosition,
4921 VideoWindow_GetMinIdealImageSize,
4922 VideoWindow_GetMaxIdealImageSize,
4923 VideoWindow_GetRestorePosition,
4924 VideoWindow_HideCursor,
4925 VideoWindow_IsCursorHidden
4928 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
4930 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
4933 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
4935 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4937 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4939 return Filtergraph_QueryInterface(This, riid, ppvObj);
4942 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
4944 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4946 TRACE("(%p/%p)->()\n", This, iface);
4948 return Filtergraph_AddRef(This);
4951 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
4953 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4955 TRACE("(%p/%p)->()\n", This, iface);
4957 return Filtergraph_Release(This);
4960 /*** IDispatch methods ***/
4961 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
4963 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4965 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4967 return S_OK;
4970 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
4971 ITypeInfo **ppTInfo)
4973 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4975 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4977 return S_OK;
4980 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
4981 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4983 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4985 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4987 return S_OK;
4990 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
4991 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4992 UINT *puArgErr)
4994 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4996 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);
4998 return S_OK;
5001 /*** IMediaEvent methods ***/
5002 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5004 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5006 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5008 *hEvent = (OAEVENT)This->evqueue.msg_event;
5010 return S_OK;
5013 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5014 LONG_PTR *lParam2, LONG msTimeout)
5016 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5017 Event evt;
5019 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5021 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5023 *lEventCode = evt.lEventCode;
5024 *lParam1 = evt.lParam1;
5025 *lParam2 = evt.lParam2;
5026 return S_OK;
5029 *lEventCode = 0;
5030 return E_ABORT;
5033 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5034 LONG *pEvCode)
5036 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5038 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5040 if (This->state != State_Running)
5041 return VFW_E_WRONG_STATE;
5043 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5045 *pEvCode = This->CompletionStatus;
5046 return S_OK;
5049 *pEvCode = 0;
5050 return E_ABORT;
5053 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5055 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5057 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5059 if (lEvCode == EC_COMPLETE)
5060 This->HandleEcComplete = FALSE;
5061 else if (lEvCode == EC_REPAINT)
5062 This->HandleEcRepaint = FALSE;
5063 else if (lEvCode == EC_CLOCK_CHANGED)
5064 This->HandleEcClockChanged = FALSE;
5065 else
5066 return S_FALSE;
5068 return S_OK;
5071 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5073 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5075 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5077 if (lEvCode == EC_COMPLETE)
5078 This->HandleEcComplete = TRUE;
5079 else if (lEvCode == EC_REPAINT)
5080 This->HandleEcRepaint = TRUE;
5081 else if (lEvCode == EC_CLOCK_CHANGED)
5082 This->HandleEcClockChanged = TRUE;
5083 else
5084 return S_FALSE;
5086 return S_OK;
5089 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5090 LONG_PTR lParam1, LONG_PTR lParam2)
5092 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5094 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5096 return S_OK;
5099 /*** IMediaEventEx methods ***/
5100 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5101 LONG_PTR lInstanceData)
5103 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5105 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5107 This->notif.hWnd = (HWND)hwnd;
5108 This->notif.msg = lMsg;
5109 This->notif.instance = lInstanceData;
5111 return S_OK;
5114 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5116 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5118 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5120 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5121 return E_INVALIDARG;
5123 This->notif.disabled = lNoNotifyFlags;
5125 return S_OK;
5128 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5130 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5132 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5134 if (!lplNoNotifyFlags)
5135 return E_POINTER;
5137 *lplNoNotifyFlags = This->notif.disabled;
5139 return S_OK;
5143 static const IMediaEventExVtbl IMediaEventEx_VTable =
5145 MediaEvent_QueryInterface,
5146 MediaEvent_AddRef,
5147 MediaEvent_Release,
5148 MediaEvent_GetTypeInfoCount,
5149 MediaEvent_GetTypeInfo,
5150 MediaEvent_GetIDsOfNames,
5151 MediaEvent_Invoke,
5152 MediaEvent_GetEventHandle,
5153 MediaEvent_GetEvent,
5154 MediaEvent_WaitForCompletion,
5155 MediaEvent_CancelDefaultHandling,
5156 MediaEvent_RestoreDefaultHandling,
5157 MediaEvent_FreeEventParams,
5158 MediaEvent_SetNotifyWindow,
5159 MediaEvent_SetNotifyFlags,
5160 MediaEvent_GetNotifyFlags
5164 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5166 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5169 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5171 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5173 return Filtergraph_QueryInterface(This, riid, ppv);
5176 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5178 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5180 return Filtergraph_AddRef(This);
5183 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5185 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5187 return Filtergraph_Release(This);
5190 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5192 FIXME("(%p): stub\n", pClassID);
5194 return E_NOTIMPL;
5197 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5199 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5201 return MediaControl_Stop(&This->IMediaControl_iface);
5204 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5206 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5208 return MediaControl_Pause(&This->IMediaControl_iface);
5211 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5213 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5215 if (tStart)
5216 FIXME("Run called with non-null tStart: %x%08x\n",
5217 (int)(tStart>>32), (int)tStart);
5219 return MediaControl_Run(&This->IMediaControl_iface);
5222 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
5223 FILTER_STATE *pState)
5225 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5227 return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
5230 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5232 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5233 HRESULT hr = S_OK;
5234 int i;
5236 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5238 EnterCriticalSection(&This->cs);
5240 for (i = 0;i < This->nFilters;i++)
5242 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5243 if (FAILED(hr))
5244 break;
5247 if (FAILED(hr))
5249 for(;i >= 0;i--)
5250 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5252 else
5254 if (This->refClock)
5255 IReferenceClock_Release(This->refClock);
5256 This->refClock = pClock;
5257 if (This->refClock)
5258 IReferenceClock_AddRef(This->refClock);
5259 This->defaultclock = FALSE;
5261 if (This->HandleEcClockChanged)
5263 IMediaEventSink *pEventSink;
5264 HRESULT eshr;
5266 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5267 if (SUCCEEDED(eshr))
5269 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5270 IMediaEventSink_Release(pEventSink);
5275 LeaveCriticalSection(&This->cs);
5277 return hr;
5280 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5282 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5284 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5286 if (!ppClock)
5287 return E_POINTER;
5289 EnterCriticalSection(&This->cs);
5291 *ppClock = This->refClock;
5292 if (*ppClock)
5293 IReferenceClock_AddRef(*ppClock);
5295 LeaveCriticalSection(&This->cs);
5297 return S_OK;
5300 static const IMediaFilterVtbl IMediaFilter_VTable =
5302 MediaFilter_QueryInterface,
5303 MediaFilter_AddRef,
5304 MediaFilter_Release,
5305 MediaFilter_GetClassID,
5306 MediaFilter_Stop,
5307 MediaFilter_Pause,
5308 MediaFilter_Run,
5309 MediaFilter_GetState,
5310 MediaFilter_SetSyncSource,
5311 MediaFilter_GetSyncSource
5314 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5316 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5319 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5321 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5323 return Filtergraph_QueryInterface(This, riid, ppv);
5326 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5328 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5330 return Filtergraph_AddRef(This);
5333 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5335 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5337 return Filtergraph_Release(This);
5340 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5341 LONG_PTR EventParam1, LONG_PTR EventParam2)
5343 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5344 Event evt;
5346 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5348 /* We need thread safety here, let's use the events queue's one */
5349 EnterCriticalSection(&This->evqueue.msg_crst);
5351 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5353 TRACE("Process EC_COMPLETE notification\n");
5354 if (++This->EcCompleteCount == This->nRenderers)
5356 evt.lEventCode = EC_COMPLETE;
5357 evt.lParam1 = S_OK;
5358 evt.lParam2 = 0;
5359 TRACE("Send EC_COMPLETE to app\n");
5360 EventsQueue_PutEvent(&This->evqueue, &evt);
5361 if (!This->notif.disabled && This->notif.hWnd)
5363 TRACE("Send Window message\n");
5364 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5366 This->CompletionStatus = EC_COMPLETE;
5367 SetEvent(This->hEventCompletion);
5370 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5372 /* FIXME: Not handled yet */
5374 else
5376 evt.lEventCode = EventCode;
5377 evt.lParam1 = EventParam1;
5378 evt.lParam2 = EventParam2;
5379 EventsQueue_PutEvent(&This->evqueue, &evt);
5380 if (!This->notif.disabled && This->notif.hWnd)
5381 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5384 LeaveCriticalSection(&This->evqueue.msg_crst);
5385 return S_OK;
5388 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5390 MediaEventSink_QueryInterface,
5391 MediaEventSink_AddRef,
5392 MediaEventSink_Release,
5393 MediaEventSink_Notify
5396 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5398 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5401 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5403 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5405 return Filtergraph_QueryInterface(This, riid, ppv);
5408 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5410 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5412 return Filtergraph_AddRef(This);
5415 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5417 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5419 return Filtergraph_Release(This);
5422 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5423 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5424 DWORD dwFlags)
5426 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5428 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5430 return E_NOTIMPL;
5433 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5434 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5436 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5437 HRESULT hr;
5439 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5441 if (hAbortEvent)
5442 FIXME("The parameter hAbortEvent is not handled!\n");
5444 EnterCriticalSection(&This->cs);
5446 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5448 LeaveCriticalSection(&This->cs);
5450 return hr;
5453 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5455 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5457 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5459 return E_NOTIMPL;
5462 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5464 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5466 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5468 return E_NOTIMPL;
5471 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5473 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5475 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5477 return E_NOTIMPL;
5480 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5482 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5484 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5486 return E_NOTIMPL;
5489 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5490 IPinConnection *pConnection, HANDLE hEventAbort)
5492 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5494 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5496 return E_NOTIMPL;
5499 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5500 DWORD dwFlags)
5502 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5504 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5506 return E_NOTIMPL;
5509 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5510 DWORD *dwFlags)
5512 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5514 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5516 return E_NOTIMPL;
5519 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5520 DWORD dwFlags)
5522 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5524 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5526 return E_NOTIMPL;
5529 static const IGraphConfigVtbl IGraphConfig_VTable =
5531 GraphConfig_QueryInterface,
5532 GraphConfig_AddRef,
5533 GraphConfig_Release,
5534 GraphConfig_Reconnect,
5535 GraphConfig_Reconfigure,
5536 GraphConfig_AddFilterToCache,
5537 GraphConfig_EnumCacheFilter,
5538 GraphConfig_RemoveFilterFromCache,
5539 GraphConfig_GetStartTime,
5540 GraphConfig_PushThroughData,
5541 GraphConfig_SetFilterFlags,
5542 GraphConfig_GetFilterFlags,
5543 GraphConfig_RemoveFilterEx
5546 static const IUnknownVtbl IInner_VTable =
5548 FilterGraphInner_QueryInterface,
5549 FilterGraphInner_AddRef,
5550 FilterGraphInner_Release
5553 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
5554 REFIID riid,
5555 LPVOID * ppv) {
5556 if (This->bAggregatable)
5557 This->bUnkOuterValid = TRUE;
5559 if (This->pUnkOuter)
5561 if (This->bAggregatable)
5562 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
5564 if (IsEqualIID(riid, &IID_IUnknown))
5566 HRESULT hr;
5568 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5569 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5570 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5571 This->bAggregatable = TRUE;
5572 return hr;
5575 *ppv = NULL;
5576 return E_NOINTERFACE;
5579 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5582 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) {
5583 if (This->pUnkOuter && This->bUnkOuterValid)
5584 return IUnknown_AddRef(This->pUnkOuter);
5585 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5588 static ULONG Filtergraph_Release(IFilterGraphImpl *This) {
5589 if (This->pUnkOuter && This->bUnkOuterValid)
5590 return IUnknown_Release(This->pUnkOuter);
5591 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5594 /* This is the only function that actually creates a FilterGraph class... */
5595 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5597 IFilterGraphImpl *fimpl;
5598 HRESULT hr;
5600 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5602 *ppObj = NULL;
5604 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5605 fimpl->pUnkOuter = pUnkOuter;
5606 fimpl->bUnkOuterValid = FALSE;
5607 fimpl->bAggregatable = FALSE;
5608 fimpl->defaultclock = TRUE;
5609 fimpl->IInner_vtbl = &IInner_VTable;
5610 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5611 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5612 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5613 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5614 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5615 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5616 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5617 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5618 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5619 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5620 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5621 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5622 fimpl->ref = 1;
5623 fimpl->ppFiltersInGraph = NULL;
5624 fimpl->pFilterNames = NULL;
5625 fimpl->nFilters = 0;
5626 fimpl->filterCapacity = 0;
5627 fimpl->nameIndex = 1;
5628 fimpl->refClock = NULL;
5629 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5630 fimpl->HandleEcComplete = TRUE;
5631 fimpl->HandleEcRepaint = TRUE;
5632 fimpl->HandleEcClockChanged = TRUE;
5633 fimpl->notif.hWnd = 0;
5634 fimpl->notif.disabled = FALSE;
5635 fimpl->nRenderers = 0;
5636 fimpl->EcCompleteCount = 0;
5637 fimpl->refClockProvider = NULL;
5638 fimpl->state = State_Stopped;
5639 fimpl->pSite = NULL;
5640 EventsQueue_Init(&fimpl->evqueue);
5641 InitializeCriticalSection(&fimpl->cs);
5642 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5643 fimpl->nItfCacheEntries = 0;
5644 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5645 fimpl->start_time = fimpl->pause_time = 0;
5646 fimpl->stop_position = -1;
5647 fimpl->punkFilterMapper2 = NULL;
5648 fimpl->recursioncount = 0;
5650 /* create Filtermapper aggregated. */
5651 hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER,
5652 &IID_IUnknown, (LPVOID*)&fimpl->punkFilterMapper2);
5654 if (SUCCEEDED(hr)) {
5655 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
5658 if (SUCCEEDED(hr)) {
5659 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5660 if (pUnkOuter) IUnknown_Release(pUnkOuter);
5661 else IUnknown_Release((IUnknown*)&fimpl->IInner_vtbl);
5664 if (FAILED(hr)) {
5665 ERR("Unable to create filter mapper (%x)\n", hr);
5666 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5667 CloseHandle(fimpl->hEventCompletion);
5668 EventsQueue_Destroy(&fimpl->evqueue);
5669 fimpl->cs.DebugInfo->Spare[0] = 0;
5670 DeleteCriticalSection(&fimpl->cs);
5671 CoTaskMemFree(fimpl);
5672 return hr;
5675 *ppObj = fimpl;
5676 return S_OK;
5679 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5681 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5682 return FilterGraph_create(pUnkOuter, ppObj);