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
32 #include "wine/debug.h"
33 #include "quartz_private.h"
39 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 HWND hWnd; /* Target window */
46 UINT msg; /* User window message */
47 LONG_PTR instance; /* User data */
48 int disabled; /* Disabled messages posting */
52 LONG lEventCode; /* Event code */
53 LONG_PTR lParam1; /* Param1 */
54 LONG_PTR lParam2; /* Param2 */
57 /* messages ring implementation for queuing events (taken from winmm) */
58 #define EVENTS_RING_BUFFER_INCREMENT 64
64 CRITICAL_SECTION msg_crst;
65 HANDLE msg_event; /* Signaled for no empty queue */
68 static int EventsQueue_Init(EventsQueue* omr)
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");
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);
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
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);
120 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
122 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
125 EnterCriticalSection(&omr->msg_crst);
127 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
129 LeaveCriticalSection(&omr->msg_crst);
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);
144 #define MAX_ITF_CACHE_ENTRIES 3
145 typedef struct _ITF_CACHE_ENTRY {
151 typedef struct _IFilterGraphImpl {
152 IUnknown IUnknown_inner;
153 IFilterGraph2 IFilterGraph2_iface;
154 IMediaControl IMediaControl_iface;
155 IMediaSeeking IMediaSeeking_iface;
156 IBasicAudio IBasicAudio_iface;
157 IBasicVideo2 IBasicVideo2_iface;
158 IVideoWindow IVideoWindow_iface;
159 IMediaEventEx IMediaEventEx_iface;
160 IMediaFilter IMediaFilter_iface;
161 IMediaEventSink IMediaEventSink_iface;
162 IGraphConfig IGraphConfig_iface;
163 IMediaPosition IMediaPosition_iface;
164 IObjectWithSite IObjectWithSite_iface;
165 /* IAMGraphStreams */
171 /* IRegisterServiceProvider */
172 /* IResourceMananger */
173 /* IServiceProvider */
174 /* IVideoFrameStep */
178 IUnknown *punkFilterMapper2;
179 IFilterMapper2 * pFilterMapper2;
180 IBaseFilter ** ppFiltersInGraph;
181 LPWSTR * pFilterNames;
185 IReferenceClock *refClock;
186 IBaseFilter *refClockProvider;
188 HANDLE hEventCompletion;
189 int CompletionStatus;
193 int HandleEcComplete;
195 int HandleEcClockChanged;
198 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
199 int nItfCacheEntries;
202 REFERENCE_TIME start_time;
203 REFERENCE_TIME pause_time;
204 LONGLONG stop_position;
209 static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface)
211 return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner);
214 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObj)
216 IFilterGraphImpl *This = impl_from_IUnknown(iface);
217 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
219 if (IsEqualGUID(&IID_IUnknown, riid)) {
220 *ppvObj = &This->IUnknown_inner;
221 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
222 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
223 IsEqualGUID(&IID_IFilterGraph2, riid) ||
224 IsEqualGUID(&IID_IGraphBuilder, riid)) {
225 *ppvObj = &This->IFilterGraph2_iface;
226 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
227 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
228 *ppvObj = &This->IMediaControl_iface;
229 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
230 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
231 *ppvObj = &This->IMediaSeeking_iface;
232 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
233 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
234 *ppvObj = &This->IBasicAudio_iface;
235 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
236 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
237 IsEqualGUID(&IID_IBasicVideo2, riid)) {
238 *ppvObj = &This->IBasicVideo2_iface;
239 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
240 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
241 *ppvObj = &This->IVideoWindow_iface;
242 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
243 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
244 IsEqualGUID(&IID_IMediaEventEx, riid)) {
245 *ppvObj = &This->IMediaEventEx_iface;
246 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
247 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
248 IsEqualGUID(&IID_IPersist, riid)) {
249 *ppvObj = &This->IMediaFilter_iface;
250 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
251 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
252 *ppvObj = &This->IMediaEventSink_iface;
253 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
254 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
255 *ppvObj = &This->IGraphConfig_iface;
256 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
257 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
258 *ppvObj = &This->IMediaPosition_iface;
259 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
260 } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) {
261 *ppvObj = &This->IObjectWithSite_iface;
262 TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj);
263 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
264 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
265 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
266 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
267 *ppvObj = This->pFilterMapper2;
268 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
269 } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
270 *ppvObj = This->pFilterMapper2;
271 TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
274 FIXME("unknown interface %s\n", debugstr_guid(riid));
275 return E_NOINTERFACE;
278 IUnknown_AddRef((IUnknown *)*ppvObj);
282 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown *iface)
284 IFilterGraphImpl *This = impl_from_IUnknown(iface);
285 ULONG ref = InterlockedIncrement(&This->ref);
287 TRACE("(%p)->(): new ref = %d\n", This, ref);
292 static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
294 IFilterGraphImpl *This = impl_from_IUnknown(iface);
295 ULONG ref = InterlockedDecrement(&This->ref);
297 TRACE("(%p)->(): new ref = %d\n", This, ref);
302 This->ref = 1; /* guard against reentrancy (aggregation). */
304 IMediaControl_Stop(&This->IMediaControl_iface);
306 while (This->nFilters)
307 IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, This->ppFiltersInGraph[0]);
310 IReferenceClock_Release(This->refClock);
312 for (i = 0; i < This->nItfCacheEntries; i++)
314 if (This->ItfCacheEntries[i].iface)
315 IUnknown_Release(This->ItfCacheEntries[i].iface);
318 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 */
319 IUnknown_AddRef(This->outer_unk);
320 IFilterMapper2_Release(This->pFilterMapper2);
321 IUnknown_Release(This->punkFilterMapper2);
323 if (This->pSite) IUnknown_Release(This->pSite);
325 CloseHandle(This->hEventCompletion);
326 EventsQueue_Destroy(&This->evqueue);
327 This->cs.DebugInfo->Spare[0] = 0;
328 DeleteCriticalSection(&This->cs);
329 CoTaskMemFree(This->ppFiltersInGraph);
330 CoTaskMemFree(This->pFilterNames);
336 static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface)
338 return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface);
341 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj)
343 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
345 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
347 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
350 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface)
352 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
354 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
356 return IUnknown_AddRef(This->outer_unk);
359 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
361 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
363 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
365 return IUnknown_Release(This->outer_unk);
368 /*** IFilterGraph methods ***/
369 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
372 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
375 WCHAR* wszFilterName = NULL;
376 int duplicate_name = FALSE;
378 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
383 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
387 /* Check if name already exists */
388 for(i = 0; i < This->nFilters; i++)
389 if (!strcmpW(This->pFilterNames[i], pName))
391 duplicate_name = TRUE;
396 /* If no name given or name already existing, generate one */
397 if (!pName || duplicate_name)
399 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
400 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
402 for (j = 0; j < 10000 ; j++)
406 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
408 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
409 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
411 /* Check if the generated name already exists */
412 for(i = 0; i < This->nFilters; i++)
413 if (!strcmpW(This->pFilterNames[i], wszFilterName))
416 /* Compute next index and exit if generated name is suitable */
417 if (This->nameIndex++ == 10000)
419 if (i == This->nFilters)
422 /* Unable to find a suitable name */
425 CoTaskMemFree(wszFilterName);
426 return VFW_E_DUPLICATE_NAME;
430 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
432 if (This->nFilters + 1 > This->filterCapacity)
434 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
435 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
436 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
437 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
438 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
439 if (This->filterCapacity)
441 CoTaskMemFree(This->ppFiltersInGraph);
442 CoTaskMemFree(This->pFilterNames);
444 This->ppFiltersInGraph = ppNewFilters;
445 This->pFilterNames = pNewNames;
446 This->filterCapacity = newCapacity;
449 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
453 IBaseFilter_AddRef(pFilter);
454 This->ppFiltersInGraph[This->nFilters] = pFilter;
455 This->pFilterNames[This->nFilters] = wszFilterName;
457 IBaseFilter_SetSyncSource(pFilter, This->refClock);
460 CoTaskMemFree(wszFilterName);
462 if (SUCCEEDED(hr) && duplicate_name)
463 return VFW_S_DUPLICATE_NAME;
468 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
470 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
474 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
476 /* FIXME: check graph is stopped */
478 for (i = 0; i < This->nFilters; i++)
480 if (This->ppFiltersInGraph[i] == pFilter)
482 IEnumPins *penumpins = NULL;
485 if (This->defaultclock && This->refClockProvider == pFilter)
487 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
488 This->defaultclock = 1;
491 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
492 IBaseFilter_GetState(pFilter, 0, &state);
493 if (state == State_Running)
494 IBaseFilter_Pause(pFilter);
495 if (state != State_Stopped)
496 IBaseFilter_Stop(pFilter);
498 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
501 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
505 IPin_ConnectedTo(ppin, &victim);
508 h = IPin_Disconnect(victim);
509 TRACE("Disconnect other side: %08x\n", h);
510 if (h == VFW_E_NOT_STOPPED)
513 IPin_QueryPinInfo(victim, &pinfo);
515 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
516 if (state == State_Running)
517 IBaseFilter_Pause(pinfo.pFilter);
518 IBaseFilter_Stop(pinfo.pFilter);
519 IBaseFilter_Release(pinfo.pFilter);
520 h = IPin_Disconnect(victim);
521 TRACE("Disconnect retry: %08x\n", h);
523 IPin_Release(victim);
525 h = IPin_Disconnect(ppin);
526 TRACE("Disconnect 2: %08x\n", h);
530 IEnumPins_Release(penumpins);
533 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
536 IBaseFilter_SetSyncSource(pFilter, NULL);
537 IBaseFilter_Release(pFilter);
538 CoTaskMemFree(This->pFilterNames[i]);
539 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
540 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
542 /* Invalidate interfaces in the cache */
543 for (i = 0; i < This->nItfCacheEntries; i++)
544 if (pFilter == This->ItfCacheEntries[i].filter)
546 IUnknown_Release(This->ItfCacheEntries[i].iface);
547 This->ItfCacheEntries[i].iface = NULL;
548 This->ItfCacheEntries[i].filter = NULL;
556 return hr; /* FIXME: check this error code */
559 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum)
561 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
563 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
565 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
568 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName,
569 IBaseFilter **ppFilter)
571 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
574 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
579 for (i = 0; i < This->nFilters; i++)
581 if (!strcmpW(pName, This->pFilterNames[i]))
583 *ppFilter = This->ppFiltersInGraph[i];
584 IBaseFilter_AddRef(*ppFilter);
590 return VFW_E_NOT_FOUND;
593 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
594 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
596 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
600 PIN_INFO info_out, info_in;
602 hr = IPin_QueryPinInfo(out, &info_out);
605 if (info_out.dir != PINDIR_OUTPUT)
607 IBaseFilter_Release(info_out.pFilter);
611 hr = IPin_QueryPinInfo(in, &info_in);
613 IBaseFilter_Release(info_in.pFilter);
616 if (info_in.dir != PINDIR_INPUT)
622 if (info_out.pFilter == info_in.pFilter)
623 hr = VFW_E_CIRCULAR_GRAPH;
629 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
633 IEnumPins_Reset(enumpins);
634 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
636 PIN_DIRECTION dir = PINDIR_OUTPUT;
637 IPin_QueryDirection(test, &dir);
638 if (dir == PINDIR_INPUT)
641 IPin_ConnectedTo(test, &victim);
644 hr = CheckCircularConnection(This, victim, in);
645 IPin_Release(victim);
655 IEnumPins_Release(enumpins);
659 IBaseFilter_Release(info_out.pFilter);
661 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
664 /* Debugging filtergraphs not enabled */
670 /* NOTE: despite the implication, it doesn't matter which
671 * way round you put in the input and output pins */
672 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut,
673 const AM_MEDIA_TYPE *pmt)
675 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
679 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
681 /* FIXME: check pins are in graph */
683 if (TRACE_ON(quartz))
687 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
691 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
692 IBaseFilter_Release(PinInfo.pFilter);
694 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
698 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
699 IBaseFilter_Release(PinInfo.pFilter);
702 hr = IPin_QueryDirection(ppinIn, &dir);
705 if (dir == PINDIR_INPUT)
707 hr = CheckCircularConnection(This, ppinOut, ppinIn);
709 hr = IPin_Connect(ppinOut, ppinIn, pmt);
713 hr = CheckCircularConnection(This, ppinIn, ppinOut);
715 hr = IPin_Connect(ppinIn, ppinOut, pmt);
722 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin)
724 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
725 IPin *pConnectedTo = NULL;
727 PIN_DIRECTION pindir;
729 IPin_QueryDirection(ppin, &pindir);
730 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
732 TRACE("Querying connected to failed: %x\n", hr);
735 IPin_Disconnect(ppin);
736 IPin_Disconnect(pConnectedTo);
737 if (pindir == PINDIR_INPUT)
738 hr = IPin_Connect(pConnectedTo, ppin, NULL);
740 hr = IPin_Connect(ppin, pConnectedTo, NULL);
741 IPin_Release(pConnectedTo);
743 WARN("Reconnecting pins failed, pins are not connected now..\n");
744 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
748 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
750 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
752 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
757 return IPin_Disconnect(ppin);
760 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
762 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
763 IReferenceClock *pClock = NULL;
767 TRACE("(%p/%p)->() live sources not handled properly!\n", iface, This);
769 EnterCriticalSection(&This->cs);
771 for (i = 0; i < This->nFilters; ++i)
774 IAMFilterMiscFlags *flags = NULL;
775 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags);
778 miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
779 IAMFilterMiscFlags_Release(flags);
780 if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
781 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock);
788 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
789 This->refClockProvider = NULL;
792 This->refClockProvider = This->ppFiltersInGraph[i];
796 hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock);
797 This->defaultclock = TRUE;
798 IReferenceClock_Release(pClock);
800 LeaveCriticalSection(&This->cs);
805 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
807 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
808 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
809 IPropertyBag * pPropBagCat = NULL;
814 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
817 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
820 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
825 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
828 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
831 IPropertyBag_Release(pPropBagCat);
836 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
841 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
842 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
845 } else if (hr == S_FALSE) {
846 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
847 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
849 WARN("Error (%x)\n", hr);
851 } else if (hr == E_NOTIMPL) {
852 /* Input connected to all outputs */
853 IEnumPins* penumpins;
856 TRACE("E_NOTIMPL\n");
857 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
859 WARN("filter Enumpins failed (%x)\n", hr);
863 /* Count output pins */
864 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
865 PIN_DIRECTION pindir;
866 IPin_QueryDirection(ppin, &pindir);
867 if (pindir == PINDIR_OUTPUT)
871 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
872 /* Retrieve output pins */
873 IEnumPins_Reset(penumpins);
875 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
876 PIN_DIRECTION pindir;
877 IPin_QueryDirection(ppin, &pindir);
878 if (pindir == PINDIR_OUTPUT)
879 (*pppins)[i++] = ppin;
883 IEnumPins_Release(penumpins);
886 WARN("Next failed (%x)\n", hr);
889 } else if (FAILED(hr)) {
890 WARN("Cannot get internal connection (%x)\n", hr);
898 /*** IGraphBuilder methods ***/
899 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
901 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
903 AM_MEDIA_TYPE* mt = NULL;
904 IEnumMediaTypes* penummt = NULL;
906 IEnumPins* penumpins;
907 IEnumMoniker* pEnumMoniker;
917 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
919 if (TRACE_ON(quartz))
921 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
925 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
926 IBaseFilter_Release(PinInfo.pFilter);
928 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
932 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
933 IBaseFilter_Release(PinInfo.pFilter);
936 EnterCriticalSection(&This->cs);
937 ++This->recursioncount;
938 if (This->recursioncount >= 5)
940 WARN("Recursion count has reached %d\n", This->recursioncount);
941 hr = VFW_E_CANNOT_CONNECT;
945 hr = IPin_QueryDirection(ppinOut, &dir);
949 if (dir == PINDIR_INPUT)
958 hr = CheckCircularConnection(This, ppinOut, ppinIn);
962 /* Try direct connection first */
963 hr = IPin_Connect(ppinOut, ppinIn, NULL);
967 TRACE("Direct connection failed, trying to render using extra filters\n");
969 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
973 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
974 IBaseFilter_Release(PinInfo.pFilter);
978 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
979 * filter to the minor mediatype of input pin of the renderer */
980 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
983 WARN("EnumMediaTypes (%x)\n", hr);
987 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
989 WARN("IEnumMediaTypes_Next (%x)\n", hr);
995 WARN("No media type found!\n");
996 hr = VFW_E_INVALIDMEDIATYPE;
999 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1000 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1002 /* Try to find a suitable filter that can connect to the pin to render */
1003 tab[0] = mt->majortype;
1004 tab[1] = mt->subtype;
1005 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1007 WARN("Unable to enum filters (%x)\n", hr);
1011 hr = VFW_E_CANNOT_RENDER;
1012 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1016 IPin** ppins = NULL;
1017 IPin* ppinfilter = NULL;
1018 IBaseFilter* pfilter = NULL;
1019 IAMGraphBuilderCallback *callback = NULL;
1021 hr = GetFilterInfo(pMoniker, &clsid, &var);
1022 IMoniker_Release(pMoniker);
1024 WARN("Unable to retrieve filter info (%x)\n", hr);
1028 if (IsEqualGUID(&clsid, &FilterCLSID)) {
1029 /* Skip filter (same as the one the output pin belongs to) */
1035 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1039 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1042 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1043 IAMGraphBuilderCallback_Release(callback);
1049 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1051 WARN("Unable to create filter (%x), trying next one\n", hr);
1058 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1059 IAMGraphBuilderCallback_Release(callback);
1062 IBaseFilter_Release(pfilter);
1064 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1069 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1071 WARN("Unable to add filter (%x)\n", hr);
1072 IBaseFilter_Release(pfilter);
1079 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1081 WARN("Enumpins (%x)\n", hr);
1085 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1086 IEnumPins_Release(penumpins);
1089 WARN("Obtaining next pin: (%x)\n", hr);
1093 WARN("Cannot use this filter: no pins\n");
1097 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1099 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1102 TRACE("Successfully connected to filter, follow chain...\n");
1104 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
1105 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1107 if (SUCCEEDED(hr)) {
1109 IPin_Disconnect(ppinfilter);
1110 IPin_Disconnect(ppinOut);
1113 TRACE("pins to consider: %d\n", nb);
1114 for(i = 0; i < nb; i++)
1116 LPWSTR pinname = NULL;
1118 TRACE("Processing pin %u\n", i);
1120 hr = IPin_QueryId(ppins[i], &pinname);
1123 if (pinname[0] == '~')
1125 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1129 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1130 CoTaskMemFree(pinname);
1134 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1136 IPin_Release(ppins[i]);
1137 if (SUCCEEDED(hr)) break;
1139 while (++i < nb) IPin_Release(ppins[i]);
1140 CoTaskMemFree(ppins);
1141 IPin_Release(ppinfilter);
1142 IBaseFilter_Release(pfilter);
1145 IPin_Disconnect(ppinfilter);
1146 IPin_Disconnect(ppinOut);
1147 IFilterGraph2_RemoveFilter(iface, pfilter);
1155 if (ppinfilter) IPin_Release(ppinfilter);
1157 IFilterGraph2_RemoveFilter(iface, pfilter);
1158 IBaseFilter_Release(pfilter);
1160 while (++i < nb) IPin_Release(ppins[i]);
1161 CoTaskMemFree(ppins);
1166 IEnumMediaTypes_Release(penummt);
1168 DeleteMediaType(mt);
1169 --This->recursioncount;
1170 LeaveCriticalSection(&This->cs);
1171 TRACE("--> %08x\n", hr);
1172 return SUCCEEDED(hr) ? S_OK : hr;
1175 static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1177 /* This pin has been connected now, try to call render on all pins that aren't connected */
1180 IEnumPins *enumpins = NULL;
1181 BOOL renderany = FALSE;
1182 BOOL renderall = TRUE;
1184 IPin_QueryPinInfo(ppinOut, &info);
1186 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1187 /* Don't need to hold a reference, IEnumPins does */
1188 IBaseFilter_Release(info.pFilter);
1190 IEnumPins_Reset(enumpins);
1191 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1193 PIN_DIRECTION dir = PINDIR_INPUT;
1195 IPin_QueryDirection(to, &dir);
1197 if (dir == PINDIR_OUTPUT)
1201 IPin_ConnectedTo(to, &out);
1205 hr = IFilterGraph2_Render(&This->IFilterGraph2_iface, to);
1218 IEnumPins_Release(enumpins);
1224 return VFW_S_PARTIAL_RENDER;
1226 return VFW_E_CANNOT_RENDER;
1229 /* Ogg hates me if I create a direct rendering method
1231 * It can only connect to a pin properly once, so use a recursive method that does
1233 * +----+ --- (PIN 1) (Render is called on this pin)
1235 * +----+ --- (PIN 2)
1237 * Enumerate possible renderers that EXACTLY match the requested type
1239 * If none is available, try to add intermediate filters that can connect to the input pin
1240 * then call Render on that intermediate pin's output pins
1241 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1242 * and another filter that can connect to the input pin is tried
1243 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1244 * It's recursive, but fun!
1247 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1249 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1250 IEnumMediaTypes* penummt;
1255 IEnumMoniker* pEnumMoniker;
1261 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1263 if (TRACE_ON(quartz))
1267 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1271 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1272 IBaseFilter_Release(PinInfo.pFilter);
1275 /* Try to find out if there is a renderer for the specified subtype already, and use that
1277 EnterCriticalSection(&This->cs);
1278 for (x = 0; x < This->nFilters; ++x)
1280 IEnumPins *enumpins = NULL;
1283 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1285 if (FAILED(hr) || !enumpins)
1288 IEnumPins_Reset(enumpins);
1289 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1292 PIN_DIRECTION dir = PINDIR_OUTPUT;
1294 IPin_QueryDirection(pin, &dir);
1295 if (dir != PINDIR_INPUT)
1300 IPin_ConnectedTo(pin, &to);
1304 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1307 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1310 hr = FilterGraph2_RenderRecurse(This, pin);
1313 IPin_Disconnect(ppinOut);
1314 IPin_Disconnect(pin);
1317 IEnumPins_Release(enumpins);
1318 LeaveCriticalSection(&This->cs);
1321 WARN("Could not connect!\n");
1328 IEnumPins_Release(enumpins);
1331 LeaveCriticalSection(&This->cs);
1333 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1335 WARN("EnumMediaTypes (%x)\n", hr);
1339 IEnumMediaTypes_Reset(penummt);
1341 /* Looks like no existing renderer of the kind exists
1342 * Try adding new ones
1344 tab[0] = tab[1] = GUID_NULL;
1345 while (SUCCEEDED(hr))
1347 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1349 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1354 hr = VFW_E_CANNOT_RENDER;
1359 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1360 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1362 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1363 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1365 DeleteMediaType(mt);
1369 /* Try to find a suitable renderer with the same media type */
1370 tab[0] = mt->majortype;
1371 tab[1] = mt->subtype;
1372 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1375 WARN("Unable to enum filters (%x)\n", hr);
1381 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1386 IBaseFilter* pfilter = NULL;
1387 IEnumPins* penumpins = NULL;
1390 hr = GetFilterInfo(pMoniker, &clsid, &var);
1391 IMoniker_Release(pMoniker);
1393 WARN("Unable to retrieve filter info (%x)\n", hr);
1397 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1400 WARN("Unable to create filter (%x), trying next one\n", hr);
1404 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1406 WARN("Unable to add filter (%x)\n", hr);
1407 IBaseFilter_Release(pfilter);
1412 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1414 WARN("Splitter Enumpins (%x)\n", hr);
1418 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1428 hr = IPin_QueryDirection(ppinfilter, &dir);
1430 IPin_Release(ppinfilter);
1431 WARN("QueryDirection failed (%x)\n", hr);
1434 if (dir != PINDIR_INPUT) {
1435 IPin_Release(ppinfilter);
1436 continue; /* Wrong direction */
1439 /* Connect the pin to the "Renderer" */
1440 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1441 IPin_Release(ppinfilter);
1444 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1447 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1451 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1453 WARN("Unable to connect recursively (%x)\n", hr);
1456 IBaseFilter_Release(pfilter);
1459 if (SUCCEEDED(hr)) {
1460 IEnumPins_Release(penumpins);
1461 break; /* out of IEnumMoniker_Next loop */
1464 /* IEnumPins_Next failed, all other failure case caught by goto error */
1465 WARN("IEnumPins_Next (%x)\n", hr);
1471 IEnumPins_Release(penumpins);
1473 IFilterGraph2_RemoveFilter(iface, pfilter);
1474 IBaseFilter_Release(pfilter);
1476 if (SUCCEEDED(hr)) DebugBreak();
1479 IEnumMoniker_Release(pEnumMoniker);
1481 DeleteMediaType(mt);
1487 IEnumMediaTypes_Release(penummt);
1491 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1492 LPCWSTR lpcwstrPlayList)
1494 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1495 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1496 IBaseFilter* preader = NULL;
1497 IPin* ppinreader = NULL;
1498 IEnumPins* penumpins = NULL;
1500 BOOL partial = FALSE;
1501 HRESULT any = FALSE;
1503 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1505 if (lpcwstrPlayList != NULL)
1506 return E_INVALIDARG;
1508 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1513 hr = IBaseFilter_EnumPins(preader, &penumpins);
1516 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1520 IPin_QueryDirection(ppinreader, &dir);
1521 if (dir == PINDIR_OUTPUT)
1525 hr = IFilterGraph2_Render(iface, ppinreader);
1526 TRACE("Render %08x\n", hr);
1528 for (i = 0; i < This->nFilters; ++i)
1529 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1536 IPin_Release(ppinreader);
1538 IEnumPins_Release(penumpins);
1541 hr = VFW_E_CANNOT_RENDER;
1543 hr = VFW_S_PARTIAL_RENDER;
1547 IBaseFilter_Release(preader);
1549 TRACE("--> %08x\n", hr);
1553 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1554 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1556 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1561 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
1562 hr = HRESULT_FROM_WIN32(lRet);
1566 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
1567 WCHAR *ext = PathFindExtensionW(pszFileName);
1568 WCHAR clsid_key[39];
1570 DWORD size = sizeof(clsid_key);
1575 CloseHandle(extkey);
1579 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
1580 hr = HRESULT_FROM_WIN32(lRet);
1581 CloseHandle(extkey);
1585 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
1586 hr = HRESULT_FROM_WIN32(lRet);
1587 CloseHandle(pathkey);
1591 CLSIDFromString(clsid_key, &clsid);
1593 TRACE("CLSID: %s\n", debugstr_guid(&clsid));
1594 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1597 IFileSourceFilter *source = NULL;
1598 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1600 IFileSourceFilter_Release(source);
1602 IBaseFilter_Release(*filter);
1610 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1611 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1613 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1615 IBaseFilter* preader;
1616 IFileSourceFilter* pfile = NULL;
1620 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1622 /* Try from file name first, then fall back to default asynchronous reader */
1623 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1626 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1628 WARN("Unable to create file source filter (%x)\n", hr);
1632 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1634 WARN("Unable add filter (%x)\n", hr);
1635 IBaseFilter_Release(preader);
1639 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1641 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1645 /* Load the file in the file source filter */
1646 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1648 WARN("Load (%x)\n", hr);
1652 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1654 WARN("GetCurFile (%x)\n", hr);
1658 TRACE("File %s\n", debugstr_w(filename));
1659 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1660 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1663 *ppFilter = preader;
1664 IFileSourceFilter_Release(pfile);
1670 IFileSourceFilter_Release(pfile);
1671 IFilterGraph2_RemoveFilter(iface, preader);
1672 IBaseFilter_Release(preader);
1677 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1679 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1681 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1686 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1688 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1690 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1695 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1697 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1699 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1704 /*** IFilterGraph2 methods ***/
1705 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1706 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1708 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1710 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1715 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1716 const AM_MEDIA_TYPE *pmt)
1718 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1720 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1725 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1728 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1730 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1736 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1738 FilterGraph2_QueryInterface,
1739 FilterGraph2_AddRef,
1740 FilterGraph2_Release,
1741 FilterGraph2_AddFilter,
1742 FilterGraph2_RemoveFilter,
1743 FilterGraph2_EnumFilters,
1744 FilterGraph2_FindFilterByName,
1745 FilterGraph2_ConnectDirect,
1746 FilterGraph2_Reconnect,
1747 FilterGraph2_Disconnect,
1748 FilterGraph2_SetDefaultSyncSource,
1749 FilterGraph2_Connect,
1750 FilterGraph2_Render,
1751 FilterGraph2_RenderFile,
1752 FilterGraph2_AddSourceFilter,
1753 FilterGraph2_SetLogFile,
1755 FilterGraph2_ShouldOperationContinue,
1756 FilterGraph2_AddSourceFilterForMoniker,
1757 FilterGraph2_ReconnectEx,
1758 FilterGraph2_RenderEx
1761 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
1763 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
1766 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
1768 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1770 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1772 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1775 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
1777 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1779 TRACE("(%p/%p)->()\n", This, iface);
1781 return IUnknown_AddRef(This->outer_unk);
1784 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
1786 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1788 TRACE("(%p/%p)->()\n", This, iface);
1790 return IUnknown_Release(This->outer_unk);
1794 /*** IDispatch methods ***/
1795 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
1797 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1799 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1804 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
1805 ITypeInfo **ppTInfo)
1807 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1809 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1814 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
1815 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1817 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1819 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1824 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
1825 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
1828 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1830 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1835 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1837 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1846 TRACE("%p %p\n", pGraph, pOutputPin);
1847 PinInfo.pFilter = NULL;
1849 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1853 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1855 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1856 IPin_Release(pInputPin);
1863 TRACE("Reached a renderer\n");
1864 /* Count renderers for end of stream notification */
1865 pGraph->nRenderers++;
1869 for(i = 0; i < nb; i++)
1871 /* Explore the graph downstream from this pin
1872 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1873 * several input pins are connected to the same output (a MUX for instance). */
1874 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1875 IPin_Release(ppPins[i]);
1878 CoTaskMemFree(ppPins);
1880 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1882 FoundFilter(PinInfo.pFilter, data);
1885 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1889 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1891 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
1892 return IBaseFilter_Run(pFilter, time);
1895 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1897 return IBaseFilter_Pause(pFilter);
1900 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1902 return IBaseFilter_Stop(pFilter);
1905 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1908 DWORD time_end = data;
1909 DWORD time_now = GetTickCount();
1912 if (time_end == INFINITE)
1916 else if (time_end > time_now)
1918 wait = time_end - time_now;
1923 return IBaseFilter_GetState(pFilter, wait, &state);
1927 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
1930 IBaseFilter* pfilter;
1937 TRACE("(%p)->()\n", This);
1939 /* Explorer the graph from source filters to renderers, determine renderers
1940 * number and run filters from renderers to source filters */
1941 This->nRenderers = 0;
1942 ResetEvent(This->hEventCompletion);
1944 for(i = 0; i < This->nFilters; i++)
1947 pfilter = This->ppFiltersInGraph[i];
1948 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1951 WARN("Enum pins failed %x\n", hr);
1954 /* Check if it is a source filter */
1955 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1957 IPin_QueryDirection(pPin, &dir);
1959 if (dir == PINDIR_INPUT)
1967 TRACE("Found a source filter %p\n", pfilter);
1968 IEnumPins_Reset(pEnum);
1969 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1971 /* Explore the graph downstream from this pin */
1972 ExploreGraph(This, pPin, FoundFilter, data);
1975 FoundFilter(pfilter, data);
1977 IEnumPins_Release(pEnum);
1983 /*** IMediaControl methods ***/
1984 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
1986 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1988 TRACE("(%p/%p)->()\n", This, iface);
1990 EnterCriticalSection(&This->cs);
1991 if (This->state == State_Running)
1993 This->EcCompleteCount = 0;
1995 if (This->defaultclock && !This->refClock)
1996 IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
2001 IReferenceClock_GetTime(This->refClock, &now);
2002 if (This->state == State_Stopped)
2003 This->start_time = now + 500000;
2004 else if (This->pause_time >= 0)
2005 This->start_time += now - This->pause_time;
2007 This->start_time = now;
2009 else This->start_time = 0;
2011 SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time);
2012 This->state = State_Running;
2014 LeaveCriticalSection(&This->cs);
2018 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2020 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2022 TRACE("(%p/%p)->()\n", This, iface);
2024 EnterCriticalSection(&This->cs);
2025 if (This->state == State_Paused)
2028 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2029 IReferenceClock_GetTime(This->refClock, &This->pause_time);
2031 This->pause_time = -1;
2033 SendFilterMessage(This, SendPause, 0);
2034 This->state = State_Paused;
2036 LeaveCriticalSection(&This->cs);
2040 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2042 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2044 TRACE("(%p/%p)->()\n", This, iface);
2046 if (This->state == State_Stopped) return S_OK;
2048 EnterCriticalSection(&This->cs);
2049 if (This->state == State_Running) SendFilterMessage(This, SendPause, 0);
2050 SendFilterMessage(This, SendStop, 0);
2051 This->state = State_Stopped;
2052 LeaveCriticalSection(&This->cs);
2056 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout,
2059 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2062 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
2067 EnterCriticalSection(&This->cs);
2072 end = GetTickCount() + msTimeout;
2074 else if (msTimeout < 0)
2083 SendFilterMessage(This, SendGetState, end);
2085 LeaveCriticalSection(&This->cs);
2090 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2092 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2094 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename);
2096 return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL);
2099 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2102 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2104 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2109 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2111 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2113 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2118 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2120 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2122 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2127 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2129 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2131 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2137 static const IMediaControlVtbl IMediaControl_VTable =
2139 MediaControl_QueryInterface,
2140 MediaControl_AddRef,
2141 MediaControl_Release,
2142 MediaControl_GetTypeInfoCount,
2143 MediaControl_GetTypeInfo,
2144 MediaControl_GetIDsOfNames,
2145 MediaControl_Invoke,
2149 MediaControl_GetState,
2150 MediaControl_RenderFile,
2151 MediaControl_AddSourceFilter,
2152 MediaControl_get_FilterCollection,
2153 MediaControl_get_RegFilterCollection,
2154 MediaControl_StopWhenReady
2157 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2159 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2162 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2164 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2166 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2168 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2171 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2173 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2175 TRACE("(%p/%p)->()\n", This, iface);
2177 return IUnknown_AddRef(This->outer_unk);
2180 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2182 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2184 TRACE("(%p/%p)->()\n", This, iface);
2186 return IUnknown_Release(This->outer_unk);
2189 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2191 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2192 BOOL allnotimpl = TRUE;
2194 HRESULT hr, hr_return = S_OK;
2196 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2197 /* Send a message to all renderers, they are responsible for broadcasting it further */
2199 for(i = 0; i < This->nFilters; i++)
2201 IMediaSeeking *seek = NULL;
2202 IBaseFilter* pfilter = This->ppFiltersInGraph[i];
2203 IAMFilterMiscFlags *flags = NULL;
2205 IBaseFilter_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags);
2208 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2209 IAMFilterMiscFlags_Release(flags);
2210 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2213 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2216 hr = FoundSeek(This, seek, arg);
2217 IMediaSeeking_Release(seek);
2218 if (hr_return != E_NOTIMPL)
2220 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2229 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2234 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2238 /* Only add common capabilities everything supports */
2239 *(DWORD*)pcaps &= caps;
2244 /*** IMediaSeeking methods ***/
2245 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2247 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2250 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2255 EnterCriticalSection(&This->cs);
2256 *pCapabilities = 0xffffffff;
2258 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2259 LeaveCriticalSection(&This->cs);
2264 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2266 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2270 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2275 EnterCriticalSection(&This->cs);
2276 originalcaps = *pCapabilities;
2277 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2278 LeaveCriticalSection(&This->cs);
2283 if (!*pCapabilities)
2285 if (*pCapabilities != originalcaps)
2290 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2292 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2297 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2299 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2301 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2308 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2310 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2315 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2316 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2321 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2323 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2328 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2329 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2334 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2336 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2338 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2342 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2348 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2350 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2355 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2357 if (This->state != State_Stopped)
2358 return VFW_E_WRONG_STATE;
2360 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2362 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2363 return E_INVALIDARG;
2369 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2372 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2374 hr = IMediaSeeking_GetDuration(seek, &duration);
2378 if (*pdur < duration)
2383 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2385 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2388 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2393 EnterCriticalSection(&This->cs);
2395 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2396 LeaveCriticalSection(&This->cs);
2398 TRACE("--->%08x\n", hr);
2402 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2404 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2407 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2412 EnterCriticalSection(&This->cs);
2413 if (This->stop_position < 0)
2414 /* Stop position not set, use duration instead */
2415 hr = IMediaSeeking_GetDuration(iface, pStop);
2417 *pStop = This->stop_position;
2418 LeaveCriticalSection(&This->cs);
2423 static HRESULT WINAPI FoundCurrentPosition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pposition)
2426 LONGLONG pos = 0, *ppos = (LONGLONG*)pposition;
2428 hr = IMediaSeeking_GetCurrentPosition(seek, &pos);
2432 if (*ppos < 0 || pos < *ppos)
2437 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2439 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2445 EnterCriticalSection(&This->cs);
2447 hr = all_renderers_seek(This, FoundCurrentPosition, (DWORD_PTR)pCurrent);
2448 if (hr == E_NOTIMPL) {
2450 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2452 IReferenceClock_GetTime(This->refClock, &time);
2454 time -= This->start_time;
2456 if (This->pause_time > 0)
2457 time += This->pause_time;
2461 LeaveCriticalSection(&This->cs);
2463 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2468 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2469 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2471 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2473 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2474 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2480 LONGLONG* current, *stop;
2481 DWORD curflags, stopflags;
2484 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2486 struct pos_args *args = (void*)pargs;
2488 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2491 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2492 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2494 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2497 struct pos_args args;
2499 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2501 EnterCriticalSection(&This->cs);
2502 state = This->state;
2503 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2505 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2506 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2507 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2509 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2510 This->stop_position = *pStop;
2511 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2512 FIXME("Stop position not handled yet!\n");
2514 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2515 IMediaControl_Pause(&This->IMediaControl_iface);
2516 args.current = pCurrent;
2518 args.curflags = dwCurrentFlags;
2519 args.stopflags = dwStopFlags;
2520 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2522 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2523 This->pause_time = This->start_time = -1;
2524 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2525 IMediaControl_Run(&This->IMediaControl_iface);
2526 LeaveCriticalSection(&This->cs);
2531 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2534 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2537 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2538 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2540 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2545 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2548 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2550 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2555 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2557 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2559 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2564 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2566 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2568 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2573 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2575 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2577 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2583 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2585 MediaSeeking_QueryInterface,
2586 MediaSeeking_AddRef,
2587 MediaSeeking_Release,
2588 MediaSeeking_GetCapabilities,
2589 MediaSeeking_CheckCapabilities,
2590 MediaSeeking_IsFormatSupported,
2591 MediaSeeking_QueryPreferredFormat,
2592 MediaSeeking_GetTimeFormat,
2593 MediaSeeking_IsUsingTimeFormat,
2594 MediaSeeking_SetTimeFormat,
2595 MediaSeeking_GetDuration,
2596 MediaSeeking_GetStopPosition,
2597 MediaSeeking_GetCurrentPosition,
2598 MediaSeeking_ConvertTimeFormat,
2599 MediaSeeking_SetPositions,
2600 MediaSeeking_GetPositions,
2601 MediaSeeking_GetAvailable,
2602 MediaSeeking_SetRate,
2603 MediaSeeking_GetRate,
2604 MediaSeeking_GetPreroll
2607 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2609 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2612 /*** IUnknown methods ***/
2613 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2615 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2617 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2619 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2622 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2624 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2626 TRACE("(%p/%p)->()\n", This, iface);
2628 return IUnknown_AddRef(This->outer_unk);
2631 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2633 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2635 TRACE("(%p/%p)->()\n", This, iface);
2637 return IUnknown_Release(This->outer_unk);
2640 /*** IDispatch methods ***/
2641 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2642 FIXME("(%p) stub!\n", iface);
2646 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2647 FIXME("(%p) stub!\n", iface);
2651 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2652 FIXME("(%p) stub!\n", iface);
2656 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2657 FIXME("(%p) stub!\n", iface);
2661 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2666 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2669 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2671 FIXME("Unsupported time format.\n");
2675 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2679 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2684 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2687 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2689 FIXME("Unsupported time format.\n");
2693 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2697 /*** IMediaPosition methods ***/
2698 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2701 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2702 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2705 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2708 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2710 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2714 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2717 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2718 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2721 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2723 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2727 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2730 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2733 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2735 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2737 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2740 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2743 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2745 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2749 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2752 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2753 &reftime, AM_SEEKING_AbsolutePositioning);
2756 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2757 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2761 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2762 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2766 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2768 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2769 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2772 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2774 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2775 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2778 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2779 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2783 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2784 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2789 static const IMediaPositionVtbl IMediaPosition_VTable =
2791 MediaPosition_QueryInterface,
2792 MediaPosition_AddRef,
2793 MediaPosition_Release,
2794 MediaPosition_GetTypeInfoCount,
2795 MediaPosition_GetTypeInfo,
2796 MediaPosition_GetIDsOfNames,
2797 MediaPosition_Invoke,
2798 MediaPosition_get_Duration,
2799 MediaPosition_put_CurrentPosition,
2800 MediaPosition_get_CurrentPosition,
2801 MediaPosition_get_StopTime,
2802 MediaPosition_put_StopTime,
2803 MediaPosition_get_PrerollTime,
2804 MediaPosition_put_PrerollTime,
2805 MediaPosition_put_Rate,
2806 MediaPosition_get_Rate,
2807 MediaPosition_CanSeekForward,
2808 MediaPosition_CanSeekBackward
2811 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2813 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2816 /*** IUnknown methods ***/
2817 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2819 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2821 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2823 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2826 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2828 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2830 TRACE("(%p/%p)->()\n", This, iface);
2832 return IUnknown_AddRef(This->outer_unk);
2835 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2837 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2839 TRACE("(%p/%p)->()\n", This, iface);
2841 return IUnknown_Release(This->outer_unk);
2844 /*** IObjectWithSite methods ***/
2846 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2848 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2850 TRACE("(%p/%p)->()\n", This, iface);
2851 if (This->pSite) IUnknown_Release(This->pSite);
2852 This->pSite = pUnkSite;
2853 IUnknown_AddRef(This->pSite);
2857 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2859 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2861 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2867 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2870 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2872 ObjectWithSite_QueryInterface,
2873 ObjectWithSite_AddRef,
2874 ObjectWithSite_Release,
2875 ObjectWithSite_SetSite,
2876 ObjectWithSite_GetSite,
2879 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2881 HRESULT hr = E_NOINTERFACE;
2885 /* Check if the interface type is already registered */
2886 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2887 if (riid == pGraph->ItfCacheEntries[entry].riid)
2889 if (pGraph->ItfCacheEntries[entry].iface)
2891 /* Return the interface if available */
2892 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2898 if (entry >= MAX_ITF_CACHE_ENTRIES)
2900 FIXME("Not enough space to store interface in the cache\n");
2901 return E_OUTOFMEMORY;
2904 /* Find a filter supporting the requested interface */
2905 for (i = 0; i < pGraph->nFilters; i++)
2907 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2910 pGraph->ItfCacheEntries[entry].riid = riid;
2911 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2912 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
2913 if (entry >= pGraph->nItfCacheEntries)
2914 pGraph->nItfCacheEntries++;
2917 if (hr != E_NOINTERFACE)
2924 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
2926 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
2929 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
2931 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2933 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2935 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2938 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
2940 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2942 TRACE("(%p/%p)->()\n", This, iface);
2944 return IUnknown_AddRef(This->outer_unk);
2947 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
2949 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2951 TRACE("(%p/%p)->()\n", This, iface);
2953 return IUnknown_Release(This->outer_unk);
2956 /*** IDispatch methods ***/
2957 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
2959 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2960 IBasicAudio* pBasicAudio;
2963 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2965 EnterCriticalSection(&This->cs);
2967 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2970 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2972 LeaveCriticalSection(&This->cs);
2977 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
2978 ITypeInfo **ppTInfo)
2980 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2981 IBasicAudio* pBasicAudio;
2984 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2986 EnterCriticalSection(&This->cs);
2988 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2991 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2993 LeaveCriticalSection(&This->cs);
2998 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
2999 UINT cNames, LCID lcid, DISPID *rgDispId)
3001 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3002 IBasicAudio* pBasicAudio;
3005 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3007 EnterCriticalSection(&This->cs);
3009 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3012 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3014 LeaveCriticalSection(&This->cs);
3019 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3020 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3023 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3024 IBasicAudio* pBasicAudio;
3027 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3029 EnterCriticalSection(&This->cs);
3031 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3034 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3036 LeaveCriticalSection(&This->cs);
3041 /*** IBasicAudio methods ***/
3042 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3044 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3045 IBasicAudio* pBasicAudio;
3048 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3050 EnterCriticalSection(&This->cs);
3052 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3055 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3057 LeaveCriticalSection(&This->cs);
3062 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3064 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3065 IBasicAudio* pBasicAudio;
3068 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3070 EnterCriticalSection(&This->cs);
3072 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3075 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3077 LeaveCriticalSection(&This->cs);
3082 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3084 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3085 IBasicAudio* pBasicAudio;
3088 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3090 EnterCriticalSection(&This->cs);
3092 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3095 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3097 LeaveCriticalSection(&This->cs);
3102 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3104 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3105 IBasicAudio* pBasicAudio;
3108 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3110 EnterCriticalSection(&This->cs);
3112 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3115 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3117 LeaveCriticalSection(&This->cs);
3122 static const IBasicAudioVtbl IBasicAudio_VTable =
3124 BasicAudio_QueryInterface,
3127 BasicAudio_GetTypeInfoCount,
3128 BasicAudio_GetTypeInfo,
3129 BasicAudio_GetIDsOfNames,
3131 BasicAudio_put_Volume,
3132 BasicAudio_get_Volume,
3133 BasicAudio_put_Balance,
3134 BasicAudio_get_Balance
3137 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3139 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3142 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3144 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3146 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3148 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3151 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3153 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3155 TRACE("(%p/%p)->()\n", This, iface);
3157 return IUnknown_AddRef(This->outer_unk);
3160 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3162 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3164 TRACE("(%p/%p)->()\n", This, iface);
3166 return IUnknown_Release(This->outer_unk);
3169 /*** IDispatch methods ***/
3170 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3172 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3173 IBasicVideo *pBasicVideo;
3176 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3178 EnterCriticalSection(&This->cs);
3180 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3183 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3185 LeaveCriticalSection(&This->cs);
3190 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3191 ITypeInfo **ppTInfo)
3193 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3194 IBasicVideo *pBasicVideo;
3197 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3199 EnterCriticalSection(&This->cs);
3201 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3204 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3206 LeaveCriticalSection(&This->cs);
3211 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3212 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3214 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3215 IBasicVideo *pBasicVideo;
3218 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3220 EnterCriticalSection(&This->cs);
3222 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3225 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3227 LeaveCriticalSection(&This->cs);
3232 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3233 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3236 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3237 IBasicVideo *pBasicVideo;
3240 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3242 EnterCriticalSection(&This->cs);
3244 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3247 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3249 LeaveCriticalSection(&This->cs);
3254 /*** IBasicVideo methods ***/
3255 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3257 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3258 IBasicVideo *pBasicVideo;
3261 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3263 EnterCriticalSection(&This->cs);
3265 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3268 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3270 LeaveCriticalSection(&This->cs);
3275 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3277 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3278 IBasicVideo *pBasicVideo;
3281 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3283 EnterCriticalSection(&This->cs);
3285 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3288 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3290 LeaveCriticalSection(&This->cs);
3295 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3297 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3298 IBasicVideo *pBasicVideo;
3301 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3303 EnterCriticalSection(&This->cs);
3305 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3308 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3310 LeaveCriticalSection(&This->cs);
3315 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3317 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3318 IBasicVideo *pBasicVideo;
3321 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3323 EnterCriticalSection(&This->cs);
3325 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3328 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3330 LeaveCriticalSection(&This->cs);
3335 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3337 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3338 IBasicVideo *pBasicVideo;
3341 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3343 EnterCriticalSection(&This->cs);
3345 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3348 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3350 LeaveCriticalSection(&This->cs);
3355 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3357 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3358 IBasicVideo *pBasicVideo;
3361 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3363 EnterCriticalSection(&This->cs);
3365 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3368 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3370 LeaveCriticalSection(&This->cs);
3375 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3377 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3378 IBasicVideo *pBasicVideo;
3381 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3383 EnterCriticalSection(&This->cs);
3385 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3388 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3390 LeaveCriticalSection(&This->cs);
3395 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3397 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3398 IBasicVideo *pBasicVideo;
3401 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3403 EnterCriticalSection(&This->cs);
3405 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3408 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3410 LeaveCriticalSection(&This->cs);
3415 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3417 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3418 IBasicVideo *pBasicVideo;
3421 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3423 EnterCriticalSection(&This->cs);
3425 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3428 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3430 LeaveCriticalSection(&This->cs);
3435 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3437 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3438 IBasicVideo *pBasicVideo;
3441 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3443 EnterCriticalSection(&This->cs);
3445 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3448 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3450 LeaveCriticalSection(&This->cs);
3455 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3457 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3458 IBasicVideo *pBasicVideo;
3461 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3463 EnterCriticalSection(&This->cs);
3465 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3468 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3470 LeaveCriticalSection(&This->cs);
3475 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3477 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3478 IBasicVideo *pBasicVideo;
3481 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3483 EnterCriticalSection(&This->cs);
3485 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3488 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3490 LeaveCriticalSection(&This->cs);
3495 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3497 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3498 IBasicVideo *pBasicVideo;
3501 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3503 EnterCriticalSection(&This->cs);
3505 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3508 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3510 LeaveCriticalSection(&This->cs);
3515 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3517 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3518 IBasicVideo *pBasicVideo;
3521 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3523 EnterCriticalSection(&This->cs);
3525 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3528 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3530 LeaveCriticalSection(&This->cs);
3535 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3537 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3538 IBasicVideo *pBasicVideo;
3541 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3543 EnterCriticalSection(&This->cs);
3545 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3548 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3550 LeaveCriticalSection(&This->cs);
3555 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3557 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3558 IBasicVideo *pBasicVideo;
3561 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3563 EnterCriticalSection(&This->cs);
3565 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3568 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3570 LeaveCriticalSection(&This->cs);
3575 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3577 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3578 IBasicVideo *pBasicVideo;
3581 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3583 EnterCriticalSection(&This->cs);
3585 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3588 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3590 LeaveCriticalSection(&This->cs);
3595 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3597 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3598 IBasicVideo *pBasicVideo;
3601 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3603 EnterCriticalSection(&This->cs);
3605 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3608 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3610 LeaveCriticalSection(&This->cs);
3615 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3617 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3618 IBasicVideo *pBasicVideo;
3621 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3623 EnterCriticalSection(&This->cs);
3625 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3628 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3630 LeaveCriticalSection(&This->cs);
3635 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3637 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3638 IBasicVideo *pBasicVideo;
3641 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3643 EnterCriticalSection(&This->cs);
3645 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3648 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3650 LeaveCriticalSection(&This->cs);
3655 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3656 LONG *pDestinationHeight)
3658 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3659 IBasicVideo *pBasicVideo;
3662 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3664 EnterCriticalSection(&This->cs);
3666 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3669 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3671 LeaveCriticalSection(&This->cs);
3676 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3677 LONG Width, LONG Height)
3679 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3680 IBasicVideo *pBasicVideo;
3683 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3685 EnterCriticalSection(&This->cs);
3687 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3690 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3692 LeaveCriticalSection(&This->cs);
3697 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3698 LONG *pWidth, LONG *pHeight)
3700 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3701 IBasicVideo *pBasicVideo;
3704 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3706 EnterCriticalSection(&This->cs);
3708 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3711 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3713 LeaveCriticalSection(&This->cs);
3718 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3720 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3721 IBasicVideo *pBasicVideo;
3724 TRACE("(%p/%p)->()\n", This, iface);
3726 EnterCriticalSection(&This->cs);
3728 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3731 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3733 LeaveCriticalSection(&This->cs);
3738 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3739 LONG Width, LONG Height)
3741 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3742 IBasicVideo *pBasicVideo;
3745 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3747 EnterCriticalSection(&This->cs);
3749 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3752 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3754 LeaveCriticalSection(&This->cs);
3759 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3760 LONG *pTop, LONG *pWidth, LONG *pHeight)
3762 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3763 IBasicVideo *pBasicVideo;
3766 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3768 EnterCriticalSection(&This->cs);
3770 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3773 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3775 LeaveCriticalSection(&This->cs);
3780 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3782 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3783 IBasicVideo *pBasicVideo;
3786 TRACE("(%p/%p)->()\n", This, iface);
3788 EnterCriticalSection(&This->cs);
3790 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3793 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3795 LeaveCriticalSection(&This->cs);
3800 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3802 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3803 IBasicVideo *pBasicVideo;
3806 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3808 EnterCriticalSection(&This->cs);
3810 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3813 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3815 LeaveCriticalSection(&This->cs);
3820 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3821 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3823 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3824 IBasicVideo *pBasicVideo;
3827 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3829 EnterCriticalSection(&This->cs);
3831 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3834 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3836 LeaveCriticalSection(&This->cs);
3841 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3844 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3845 IBasicVideo *pBasicVideo;
3848 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3850 EnterCriticalSection(&This->cs);
3852 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3855 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3857 LeaveCriticalSection(&This->cs);
3862 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3864 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3865 IBasicVideo *pBasicVideo;
3868 TRACE("(%p/%p)->()\n", This, iface);
3870 EnterCriticalSection(&This->cs);
3872 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3875 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3877 LeaveCriticalSection(&This->cs);
3882 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
3884 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3885 IBasicVideo *pBasicVideo;
3888 TRACE("(%p/%p)->()\n", This, iface);
3890 EnterCriticalSection(&This->cs);
3892 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3895 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3897 LeaveCriticalSection(&This->cs);
3902 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
3905 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3906 IBasicVideo2 *pBasicVideo2;
3909 TRACE("(%p/%p)->()\n", This, iface);
3911 EnterCriticalSection(&This->cs);
3913 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3916 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3918 LeaveCriticalSection(&This->cs);
3923 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3925 BasicVideo_QueryInterface,
3928 BasicVideo_GetTypeInfoCount,
3929 BasicVideo_GetTypeInfo,
3930 BasicVideo_GetIDsOfNames,
3932 BasicVideo_get_AvgTimePerFrame,
3933 BasicVideo_get_BitRate,
3934 BasicVideo_get_BitErrorRate,
3935 BasicVideo_get_VideoWidth,
3936 BasicVideo_get_VideoHeight,
3937 BasicVideo_put_SourceLeft,
3938 BasicVideo_get_SourceLeft,
3939 BasicVideo_put_SourceWidth,
3940 BasicVideo_get_SourceWidth,
3941 BasicVideo_put_SourceTop,
3942 BasicVideo_get_SourceTop,
3943 BasicVideo_put_SourceHeight,
3944 BasicVideo_get_SourceHeight,
3945 BasicVideo_put_DestinationLeft,
3946 BasicVideo_get_DestinationLeft,
3947 BasicVideo_put_DestinationWidth,
3948 BasicVideo_get_DestinationWidth,
3949 BasicVideo_put_DestinationTop,
3950 BasicVideo_get_DestinationTop,
3951 BasicVideo_put_DestinationHeight,
3952 BasicVideo_get_DestinationHeight,
3953 BasicVideo_SetSourcePosition,
3954 BasicVideo_GetSourcePosition,
3955 BasicVideo_SetDefaultSourcePosition,
3956 BasicVideo_SetDestinationPosition,
3957 BasicVideo_GetDestinationPosition,
3958 BasicVideo_SetDefaultDestinationPosition,
3959 BasicVideo_GetVideoSize,
3960 BasicVideo_GetVideoPaletteEntries,
3961 BasicVideo_GetCurrentImage,
3962 BasicVideo_IsUsingDefaultSource,
3963 BasicVideo_IsUsingDefaultDestination,
3964 BasicVideo2_GetPreferredAspectRatio
3967 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
3969 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
3972 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
3974 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3976 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3978 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3981 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
3983 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3985 TRACE("(%p/%p)->()\n", This, iface);
3987 return IUnknown_AddRef(This->outer_unk);
3990 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
3992 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3994 TRACE("(%p/%p)->()\n", This, iface);
3996 return IUnknown_Release(This->outer_unk);
3999 /*** IDispatch methods ***/
4000 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4002 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4003 IVideoWindow *pVideoWindow;
4006 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4008 EnterCriticalSection(&This->cs);
4010 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4013 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4015 LeaveCriticalSection(&This->cs);
4020 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4021 ITypeInfo **ppTInfo)
4023 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4024 IVideoWindow *pVideoWindow;
4027 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4029 EnterCriticalSection(&This->cs);
4031 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4034 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4036 LeaveCriticalSection(&This->cs);
4041 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4042 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4044 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4045 IVideoWindow *pVideoWindow;
4048 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4050 EnterCriticalSection(&This->cs);
4052 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4055 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4057 LeaveCriticalSection(&This->cs);
4062 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4063 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4066 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4067 IVideoWindow *pVideoWindow;
4070 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4072 EnterCriticalSection(&This->cs);
4074 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4077 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4079 LeaveCriticalSection(&This->cs);
4085 /*** IVideoWindow methods ***/
4086 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4088 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4089 IVideoWindow *pVideoWindow;
4092 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4094 EnterCriticalSection(&This->cs);
4096 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4099 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4101 LeaveCriticalSection(&This->cs);
4106 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4108 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4109 IVideoWindow *pVideoWindow;
4112 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4114 EnterCriticalSection(&This->cs);
4116 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4119 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4121 LeaveCriticalSection(&This->cs);
4126 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4128 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4129 IVideoWindow *pVideoWindow;
4132 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4134 EnterCriticalSection(&This->cs);
4136 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4139 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4141 LeaveCriticalSection(&This->cs);
4146 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4148 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4149 IVideoWindow *pVideoWindow;
4152 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4154 EnterCriticalSection(&This->cs);
4156 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4159 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4161 LeaveCriticalSection(&This->cs);
4166 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4168 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4169 IVideoWindow *pVideoWindow;
4172 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4174 EnterCriticalSection(&This->cs);
4176 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4179 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4181 LeaveCriticalSection(&This->cs);
4186 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4188 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4189 IVideoWindow *pVideoWindow;
4192 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4194 EnterCriticalSection(&This->cs);
4196 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4199 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4201 LeaveCriticalSection(&This->cs);
4206 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4208 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4209 IVideoWindow *pVideoWindow;
4212 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4214 EnterCriticalSection(&This->cs);
4216 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4219 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4221 LeaveCriticalSection(&This->cs);
4226 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4228 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4229 IVideoWindow *pVideoWindow;
4232 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4234 EnterCriticalSection(&This->cs);
4236 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4239 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4241 LeaveCriticalSection(&This->cs);
4246 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4248 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4249 IVideoWindow *pVideoWindow;
4252 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4254 EnterCriticalSection(&This->cs);
4256 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4259 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4261 LeaveCriticalSection(&This->cs);
4266 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4268 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4269 IVideoWindow *pVideoWindow;
4272 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4274 EnterCriticalSection(&This->cs);
4276 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4279 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4281 LeaveCriticalSection(&This->cs);
4286 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4288 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4289 IVideoWindow *pVideoWindow;
4292 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4294 EnterCriticalSection(&This->cs);
4296 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4299 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4301 LeaveCriticalSection(&This->cs);
4306 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4307 LONG *pBackgroundPalette)
4309 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4310 IVideoWindow *pVideoWindow;
4313 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4315 EnterCriticalSection(&This->cs);
4317 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4320 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4322 LeaveCriticalSection(&This->cs);
4327 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4329 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4330 IVideoWindow *pVideoWindow;
4333 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4335 EnterCriticalSection(&This->cs);
4337 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4340 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4342 LeaveCriticalSection(&This->cs);
4347 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4349 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4350 IVideoWindow *pVideoWindow;
4353 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4355 EnterCriticalSection(&This->cs);
4357 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4360 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4362 LeaveCriticalSection(&This->cs);
4367 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4369 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4370 IVideoWindow *pVideoWindow;
4373 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4375 EnterCriticalSection(&This->cs);
4377 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4380 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4382 LeaveCriticalSection(&This->cs);
4387 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4389 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4390 IVideoWindow *pVideoWindow;
4393 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4395 EnterCriticalSection(&This->cs);
4397 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4400 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4402 LeaveCriticalSection(&This->cs);
4407 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4409 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4410 IVideoWindow *pVideoWindow;
4413 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4415 EnterCriticalSection(&This->cs);
4417 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4420 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4422 LeaveCriticalSection(&This->cs);
4427 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4429 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4430 IVideoWindow *pVideoWindow;
4433 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4435 EnterCriticalSection(&This->cs);
4437 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4440 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4442 LeaveCriticalSection(&This->cs);
4447 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4449 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4450 IVideoWindow *pVideoWindow;
4453 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4455 EnterCriticalSection(&This->cs);
4457 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4460 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4462 LeaveCriticalSection(&This->cs);
4467 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4469 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4470 IVideoWindow *pVideoWindow;
4473 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4475 EnterCriticalSection(&This->cs);
4477 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4480 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4482 LeaveCriticalSection(&This->cs);
4487 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4489 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4490 IVideoWindow *pVideoWindow;
4493 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4495 EnterCriticalSection(&This->cs);
4497 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4500 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4502 LeaveCriticalSection(&This->cs);
4507 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4509 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4510 IVideoWindow *pVideoWindow;
4513 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4515 EnterCriticalSection(&This->cs);
4517 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4520 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4522 LeaveCriticalSection(&This->cs);
4527 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4529 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4530 IVideoWindow *pVideoWindow;
4533 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4535 EnterCriticalSection(&This->cs);
4537 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4540 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4542 LeaveCriticalSection(&This->cs);
4547 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4549 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4550 IVideoWindow *pVideoWindow;
4553 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4555 EnterCriticalSection(&This->cs);
4557 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4560 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4562 LeaveCriticalSection(&This->cs);
4567 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4569 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4570 IVideoWindow *pVideoWindow;
4573 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4575 EnterCriticalSection(&This->cs);
4577 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4580 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4582 LeaveCriticalSection(&This->cs);
4587 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4589 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4590 IVideoWindow *pVideoWindow;
4593 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4595 EnterCriticalSection(&This->cs);
4597 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4600 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4602 LeaveCriticalSection(&This->cs);
4607 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4609 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4610 IVideoWindow *pVideoWindow;
4613 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4615 EnterCriticalSection(&This->cs);
4617 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4620 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4622 LeaveCriticalSection(&This->cs);
4627 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4629 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4630 IVideoWindow *pVideoWindow;
4633 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4635 EnterCriticalSection(&This->cs);
4637 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4640 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4642 LeaveCriticalSection(&This->cs);
4647 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4649 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4650 IVideoWindow *pVideoWindow;
4653 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4655 EnterCriticalSection(&This->cs);
4657 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4660 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4662 LeaveCriticalSection(&This->cs);
4667 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4669 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4670 IVideoWindow *pVideoWindow;
4673 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4675 EnterCriticalSection(&This->cs);
4677 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4680 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4682 LeaveCriticalSection(&This->cs);
4687 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4689 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4690 IVideoWindow *pVideoWindow;
4693 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4695 EnterCriticalSection(&This->cs);
4697 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4700 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4702 LeaveCriticalSection(&This->cs);
4707 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4708 LONG_PTR wParam, LONG_PTR lParam)
4710 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4711 IVideoWindow *pVideoWindow;
4714 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4716 EnterCriticalSection(&This->cs);
4718 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4721 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4723 LeaveCriticalSection(&This->cs);
4728 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4729 LONG Width, LONG Height)
4731 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4732 IVideoWindow *pVideoWindow;
4735 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4737 EnterCriticalSection(&This->cs);
4739 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4742 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4744 LeaveCriticalSection(&This->cs);
4749 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4750 LONG *pWidth, LONG *pHeight)
4752 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4753 IVideoWindow *pVideoWindow;
4756 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4758 EnterCriticalSection(&This->cs);
4760 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4763 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4765 LeaveCriticalSection(&This->cs);
4770 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4773 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4774 IVideoWindow *pVideoWindow;
4777 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4779 EnterCriticalSection(&This->cs);
4781 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4784 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4786 LeaveCriticalSection(&This->cs);
4791 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4794 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4795 IVideoWindow *pVideoWindow;
4798 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4800 EnterCriticalSection(&This->cs);
4802 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4805 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4807 LeaveCriticalSection(&This->cs);
4812 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4813 LONG *pWidth, LONG *pHeight)
4815 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4816 IVideoWindow *pVideoWindow;
4819 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4821 EnterCriticalSection(&This->cs);
4823 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4826 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4828 LeaveCriticalSection(&This->cs);
4833 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4835 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4836 IVideoWindow *pVideoWindow;
4839 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4841 EnterCriticalSection(&This->cs);
4843 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4846 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4848 LeaveCriticalSection(&This->cs);
4853 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4855 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4856 IVideoWindow *pVideoWindow;
4859 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4861 EnterCriticalSection(&This->cs);
4863 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4866 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4868 LeaveCriticalSection(&This->cs);
4874 static const IVideoWindowVtbl IVideoWindow_VTable =
4876 VideoWindow_QueryInterface,
4878 VideoWindow_Release,
4879 VideoWindow_GetTypeInfoCount,
4880 VideoWindow_GetTypeInfo,
4881 VideoWindow_GetIDsOfNames,
4883 VideoWindow_put_Caption,
4884 VideoWindow_get_Caption,
4885 VideoWindow_put_WindowStyle,
4886 VideoWindow_get_WindowStyle,
4887 VideoWindow_put_WindowStyleEx,
4888 VideoWindow_get_WindowStyleEx,
4889 VideoWindow_put_AutoShow,
4890 VideoWindow_get_AutoShow,
4891 VideoWindow_put_WindowState,
4892 VideoWindow_get_WindowState,
4893 VideoWindow_put_BackgroundPalette,
4894 VideoWindow_get_BackgroundPalette,
4895 VideoWindow_put_Visible,
4896 VideoWindow_get_Visible,
4897 VideoWindow_put_Left,
4898 VideoWindow_get_Left,
4899 VideoWindow_put_Width,
4900 VideoWindow_get_Width,
4901 VideoWindow_put_Top,
4902 VideoWindow_get_Top,
4903 VideoWindow_put_Height,
4904 VideoWindow_get_Height,
4905 VideoWindow_put_Owner,
4906 VideoWindow_get_Owner,
4907 VideoWindow_put_MessageDrain,
4908 VideoWindow_get_MessageDrain,
4909 VideoWindow_get_BorderColor,
4910 VideoWindow_put_BorderColor,
4911 VideoWindow_get_FullScreenMode,
4912 VideoWindow_put_FullScreenMode,
4913 VideoWindow_SetWindowForeground,
4914 VideoWindow_NotifyOwnerMessage,
4915 VideoWindow_SetWindowPosition,
4916 VideoWindow_GetWindowPosition,
4917 VideoWindow_GetMinIdealImageSize,
4918 VideoWindow_GetMaxIdealImageSize,
4919 VideoWindow_GetRestorePosition,
4920 VideoWindow_HideCursor,
4921 VideoWindow_IsCursorHidden
4924 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
4926 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
4929 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
4931 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4933 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4935 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4938 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
4940 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4942 TRACE("(%p/%p)->()\n", This, iface);
4944 return IUnknown_AddRef(This->outer_unk);
4947 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
4949 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4951 TRACE("(%p/%p)->()\n", This, iface);
4953 return IUnknown_Release(This->outer_unk);
4956 /*** IDispatch methods ***/
4957 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
4959 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4961 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4966 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
4967 ITypeInfo **ppTInfo)
4969 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4971 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4976 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
4977 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4979 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4981 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4986 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
4987 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4990 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4992 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4997 /*** IMediaEvent methods ***/
4998 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5000 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5002 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5004 *hEvent = (OAEVENT)This->evqueue.msg_event;
5009 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5010 LONG_PTR *lParam2, LONG msTimeout)
5012 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5015 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5017 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5019 *lEventCode = evt.lEventCode;
5020 *lParam1 = evt.lParam1;
5021 *lParam2 = evt.lParam2;
5029 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5032 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5034 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5036 if (This->state != State_Running)
5037 return VFW_E_WRONG_STATE;
5039 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5041 *pEvCode = This->CompletionStatus;
5049 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5051 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5053 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5055 if (lEvCode == EC_COMPLETE)
5056 This->HandleEcComplete = FALSE;
5057 else if (lEvCode == EC_REPAINT)
5058 This->HandleEcRepaint = FALSE;
5059 else if (lEvCode == EC_CLOCK_CHANGED)
5060 This->HandleEcClockChanged = FALSE;
5067 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5069 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5071 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5073 if (lEvCode == EC_COMPLETE)
5074 This->HandleEcComplete = TRUE;
5075 else if (lEvCode == EC_REPAINT)
5076 This->HandleEcRepaint = TRUE;
5077 else if (lEvCode == EC_CLOCK_CHANGED)
5078 This->HandleEcClockChanged = TRUE;
5085 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5086 LONG_PTR lParam1, LONG_PTR lParam2)
5088 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5090 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5095 /*** IMediaEventEx methods ***/
5096 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5097 LONG_PTR lInstanceData)
5099 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5101 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5103 This->notif.hWnd = (HWND)hwnd;
5104 This->notif.msg = lMsg;
5105 This->notif.instance = lInstanceData;
5110 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5112 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5114 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5116 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5117 return E_INVALIDARG;
5119 This->notif.disabled = lNoNotifyFlags;
5124 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5126 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5128 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5130 if (!lplNoNotifyFlags)
5133 *lplNoNotifyFlags = This->notif.disabled;
5139 static const IMediaEventExVtbl IMediaEventEx_VTable =
5141 MediaEvent_QueryInterface,
5144 MediaEvent_GetTypeInfoCount,
5145 MediaEvent_GetTypeInfo,
5146 MediaEvent_GetIDsOfNames,
5148 MediaEvent_GetEventHandle,
5149 MediaEvent_GetEvent,
5150 MediaEvent_WaitForCompletion,
5151 MediaEvent_CancelDefaultHandling,
5152 MediaEvent_RestoreDefaultHandling,
5153 MediaEvent_FreeEventParams,
5154 MediaEvent_SetNotifyWindow,
5155 MediaEvent_SetNotifyFlags,
5156 MediaEvent_GetNotifyFlags
5160 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5162 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5165 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5167 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5169 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5172 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5174 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5176 return IUnknown_AddRef(This->outer_unk);
5179 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5181 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5183 return IUnknown_Release(This->outer_unk);
5186 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5188 FIXME("(%p): stub\n", pClassID);
5193 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5195 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5197 return MediaControl_Stop(&This->IMediaControl_iface);
5200 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5202 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5204 return MediaControl_Pause(&This->IMediaControl_iface);
5207 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5209 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5212 FIXME("Run called with non-null tStart: %x%08x\n",
5213 (int)(tStart>>32), (int)tStart);
5215 return MediaControl_Run(&This->IMediaControl_iface);
5218 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
5219 FILTER_STATE *pState)
5221 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5223 return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
5226 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5228 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5232 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5234 EnterCriticalSection(&This->cs);
5236 for (i = 0;i < This->nFilters;i++)
5238 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5246 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5251 IReferenceClock_Release(This->refClock);
5252 This->refClock = pClock;
5254 IReferenceClock_AddRef(This->refClock);
5255 This->defaultclock = FALSE;
5257 if (This->HandleEcClockChanged)
5259 IMediaEventSink *pEventSink;
5262 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5263 if (SUCCEEDED(eshr))
5265 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5266 IMediaEventSink_Release(pEventSink);
5271 LeaveCriticalSection(&This->cs);
5276 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5278 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5280 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5285 EnterCriticalSection(&This->cs);
5287 *ppClock = This->refClock;
5289 IReferenceClock_AddRef(*ppClock);
5291 LeaveCriticalSection(&This->cs);
5296 static const IMediaFilterVtbl IMediaFilter_VTable =
5298 MediaFilter_QueryInterface,
5300 MediaFilter_Release,
5301 MediaFilter_GetClassID,
5305 MediaFilter_GetState,
5306 MediaFilter_SetSyncSource,
5307 MediaFilter_GetSyncSource
5310 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5312 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5315 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5317 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5319 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5322 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5324 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5326 return IUnknown_AddRef(This->outer_unk);
5329 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5331 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5333 return IUnknown_Release(This->outer_unk);
5336 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5337 LONG_PTR EventParam1, LONG_PTR EventParam2)
5339 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5342 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5344 /* We need thread safety here, let's use the events queue's one */
5345 EnterCriticalSection(&This->evqueue.msg_crst);
5347 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5349 TRACE("Process EC_COMPLETE notification\n");
5350 if (++This->EcCompleteCount == This->nRenderers)
5352 evt.lEventCode = EC_COMPLETE;
5355 TRACE("Send EC_COMPLETE to app\n");
5356 EventsQueue_PutEvent(&This->evqueue, &evt);
5357 if (!This->notif.disabled && This->notif.hWnd)
5359 TRACE("Send Window message\n");
5360 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5362 This->CompletionStatus = EC_COMPLETE;
5363 SetEvent(This->hEventCompletion);
5366 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5368 /* FIXME: Not handled yet */
5372 evt.lEventCode = EventCode;
5373 evt.lParam1 = EventParam1;
5374 evt.lParam2 = EventParam2;
5375 EventsQueue_PutEvent(&This->evqueue, &evt);
5376 if (!This->notif.disabled && This->notif.hWnd)
5377 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5380 LeaveCriticalSection(&This->evqueue.msg_crst);
5384 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5386 MediaEventSink_QueryInterface,
5387 MediaEventSink_AddRef,
5388 MediaEventSink_Release,
5389 MediaEventSink_Notify
5392 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5394 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5397 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5399 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5401 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5404 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5406 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5408 return IUnknown_AddRef(This->outer_unk);
5411 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5413 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5415 return IUnknown_Release(This->outer_unk);
5418 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5419 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5422 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5424 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5429 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5430 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5432 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5435 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5438 FIXME("The parameter hAbortEvent is not handled!\n");
5440 EnterCriticalSection(&This->cs);
5442 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5444 LeaveCriticalSection(&This->cs);
5449 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5451 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5453 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5458 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5460 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5462 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5467 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5469 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5471 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5476 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5478 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5480 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5485 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5486 IPinConnection *pConnection, HANDLE hEventAbort)
5488 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5490 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5495 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5498 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5500 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5505 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5508 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5510 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5515 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5518 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5520 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5525 static const IGraphConfigVtbl IGraphConfig_VTable =
5527 GraphConfig_QueryInterface,
5529 GraphConfig_Release,
5530 GraphConfig_Reconnect,
5531 GraphConfig_Reconfigure,
5532 GraphConfig_AddFilterToCache,
5533 GraphConfig_EnumCacheFilter,
5534 GraphConfig_RemoveFilterFromCache,
5535 GraphConfig_GetStartTime,
5536 GraphConfig_PushThroughData,
5537 GraphConfig_SetFilterFlags,
5538 GraphConfig_GetFilterFlags,
5539 GraphConfig_RemoveFilterEx
5542 static const IUnknownVtbl IInner_VTable =
5544 FilterGraphInner_QueryInterface,
5545 FilterGraphInner_AddRef,
5546 FilterGraphInner_Release
5549 /* This is the only function that actually creates a FilterGraph class... */
5550 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5552 IFilterGraphImpl *fimpl;
5555 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5559 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5560 fimpl->defaultclock = TRUE;
5561 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5562 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5563 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5564 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5565 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5566 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5567 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5568 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5569 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5570 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5571 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5572 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5573 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5575 fimpl->ppFiltersInGraph = NULL;
5576 fimpl->pFilterNames = NULL;
5577 fimpl->nFilters = 0;
5578 fimpl->filterCapacity = 0;
5579 fimpl->nameIndex = 1;
5580 fimpl->refClock = NULL;
5581 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5582 fimpl->HandleEcComplete = TRUE;
5583 fimpl->HandleEcRepaint = TRUE;
5584 fimpl->HandleEcClockChanged = TRUE;
5585 fimpl->notif.hWnd = 0;
5586 fimpl->notif.disabled = FALSE;
5587 fimpl->nRenderers = 0;
5588 fimpl->EcCompleteCount = 0;
5589 fimpl->refClockProvider = NULL;
5590 fimpl->state = State_Stopped;
5591 fimpl->pSite = NULL;
5592 EventsQueue_Init(&fimpl->evqueue);
5593 InitializeCriticalSection(&fimpl->cs);
5594 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5595 fimpl->nItfCacheEntries = 0;
5596 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5597 fimpl->start_time = fimpl->pause_time = 0;
5598 fimpl->stop_position = -1;
5599 fimpl->punkFilterMapper2 = NULL;
5600 fimpl->recursioncount = 0;
5603 fimpl->outer_unk = pUnkOuter;
5605 fimpl->outer_unk = &fimpl->IUnknown_inner;
5607 /* create Filtermapper aggregated. */
5608 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5609 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5612 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2,
5613 (void**)&fimpl->pFilterMapper2);
5616 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5617 IUnknown_Release(fimpl->outer_unk);
5620 ERR("Unable to create filter mapper (%x)\n", hr);
5621 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5622 CloseHandle(fimpl->hEventCompletion);
5623 EventsQueue_Destroy(&fimpl->evqueue);
5624 fimpl->cs.DebugInfo->Spare[0] = 0;
5625 DeleteCriticalSection(&fimpl->cs);
5626 CoTaskMemFree(fimpl);
5630 *ppObj = &fimpl->IUnknown_inner;
5634 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5636 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5637 return FilterGraph_create(pUnkOuter, ppObj);