ntdsapi: Fix building the tests with MSVC headers.
[wine/wine64.git] / dlls / quartz / filtergraph.c
blob9b375949c90318abf0b303c23278cc7f09c5fe16
1 /* DirectShow FilterGraph object (QUARTZ.DLL)
3 * Copyright 2002 Lionel Ulmer
4 * Copyright 2004 Christian Costa
6 * This file contains the (internal) driver registration functions,
7 * driver enumeration APIs and DirectDraw creation functions.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include <stdarg.h>
27 #define COBJMACROS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "dshow.h"
33 #include "wine/debug.h"
34 #include "quartz_private.h"
35 #include "ole2.h"
36 #include "olectl.h"
37 #include "strmif.h"
38 #include "vfwmsgs.h"
39 #include "evcode.h"
40 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 typedef struct {
46 HWND hWnd; /* Target window */
47 long msg; /* User window message */
48 long instance; /* User data */
49 int disabled; /* Disabled messages posting */
50 } WndNotify;
52 typedef struct {
53 long lEventCode; /* Event code */
54 LONG_PTR lParam1; /* Param1 */
55 LONG_PTR lParam2; /* Param2 */
56 } Event;
58 /* messages ring implementation for queuing events (taken from winmm) */
59 #define EVENTS_RING_BUFFER_INCREMENT 64
60 typedef struct {
61 Event* messages;
62 int ring_buffer_size;
63 int msg_tosave;
64 int msg_toget;
65 CRITICAL_SECTION msg_crst;
66 HANDLE msg_event; /* Signaled for no empty queue */
67 } EventsQueue;
69 static int EventsQueue_Init(EventsQueue* omr)
71 omr->msg_toget = 0;
72 omr->msg_tosave = 0;
73 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
74 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
75 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
76 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
78 InitializeCriticalSection(&omr->msg_crst);
79 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
80 return TRUE;
83 static int EventsQueue_Destroy(EventsQueue* omr)
85 CloseHandle(omr->msg_event);
86 CoTaskMemFree(omr->messages);
87 omr->msg_crst.DebugInfo->Spare[0] = 0;
88 DeleteCriticalSection(&omr->msg_crst);
89 return TRUE;
92 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
94 EnterCriticalSection(&omr->msg_crst);
95 if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
97 int old_ring_buffer_size = omr->ring_buffer_size;
98 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
99 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
100 omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
101 /* Now we need to rearrange the ring buffer so that the new
102 buffers just allocated are in between omr->msg_tosave and
103 omr->msg_toget.
105 if (omr->msg_tosave < omr->msg_toget)
107 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
108 &(omr->messages[omr->msg_toget]),
109 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
111 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
114 omr->messages[omr->msg_tosave] = *evt;
115 SetEvent(omr->msg_event);
116 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
117 LeaveCriticalSection(&omr->msg_crst);
118 return TRUE;
121 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
123 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
124 return FALSE;
126 EnterCriticalSection(&omr->msg_crst);
128 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
130 LeaveCriticalSection(&omr->msg_crst);
131 return FALSE;
134 *evt = omr->messages[omr->msg_toget];
135 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
137 /* Mark the buffer as empty if needed */
138 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
139 ResetEvent(omr->msg_event);
141 LeaveCriticalSection(&omr->msg_crst);
142 return TRUE;
145 #define MAX_ITF_CACHE_ENTRIES 3
146 typedef struct _ITF_CACHE_ENTRY {
147 const IID* riid;
148 IBaseFilter* filter;
149 IUnknown* iface;
150 } ITF_CACHE_ENTRY;
152 typedef struct _IFilterGraphImpl {
153 const IFilterGraph2Vtbl *IFilterGraph2_vtbl;
154 const IMediaControlVtbl *IMediaControl_vtbl;
155 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
156 const IBasicAudioVtbl *IBasicAudio_vtbl;
157 const IBasicVideoVtbl *IBasicVideo_vtbl;
158 const IVideoWindowVtbl *IVideoWindow_vtbl;
159 const IMediaEventExVtbl *IMediaEventEx_vtbl;
160 const IMediaFilterVtbl *IMediaFilter_vtbl;
161 const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
162 const IGraphConfigVtbl *IGraphConfig_vtbl;
163 const IMediaPositionVtbl *IMediaPosition_vtbl;
164 const IUnknownVtbl * IInner_vtbl;
165 /* IAMGraphStreams */
166 /* IAMStats */
167 /* IBasicVideo2 */
168 /* IFilterChain */
169 /* IFilterMapper2 */
170 /* IGraphVersion */
171 /* IQueueCommand */
172 /* IRegisterServiceProvider */
173 /* IResourceMananger */
174 /* IServiceProvider */
175 /* IVideoFrameStep */
177 LONG ref;
178 IFilterMapper2 * pFilterMapper2;
179 IBaseFilter ** ppFiltersInGraph;
180 LPWSTR * pFilterNames;
181 int nFilters;
182 int filterCapacity;
183 long nameIndex;
184 IReferenceClock *refClock;
185 EventsQueue evqueue;
186 HANDLE hEventCompletion;
187 int CompletionStatus;
188 WndNotify notif;
189 int nRenderers;
190 int EcCompleteCount;
191 int HandleEcComplete;
192 int HandleEcRepaint;
193 int HandleEcClockChanged;
194 OAFilterState state;
195 CRITICAL_SECTION cs;
196 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
197 int nItfCacheEntries;
198 IUnknown * pUnkOuter;
199 BOOL bUnkOuterValid;
200 BOOL bAggregatable;
201 GUID timeformatseek;
202 } IFilterGraphImpl;
204 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
205 REFIID riid, LPVOID * ppv);
206 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This);
207 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This);
209 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
210 REFIID riid,
211 LPVOID *ppvObj) {
212 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
213 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
215 if (This->bAggregatable)
216 This->bUnkOuterValid = TRUE;
218 if (IsEqualGUID(&IID_IUnknown, riid)) {
219 *ppvObj = &(This->IInner_vtbl);
220 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
221 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
222 IsEqualGUID(&IID_IFilterGraph2, riid) ||
223 IsEqualGUID(&IID_IGraphBuilder, riid)) {
224 *ppvObj = &(This->IFilterGraph2_vtbl);
225 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
226 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
227 *ppvObj = &(This->IMediaControl_vtbl);
228 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
229 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
230 *ppvObj = &(This->IMediaSeeking_vtbl);
231 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
232 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
233 *ppvObj = &(This->IBasicAudio_vtbl);
234 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
235 } else if (IsEqualGUID(&IID_IBasicVideo, riid)) {
236 *ppvObj = &(This->IBasicVideo_vtbl);
237 TRACE(" returning IBasicVideo interface (%p)\n", *ppvObj);
238 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
239 *ppvObj = &(This->IVideoWindow_vtbl);
240 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
241 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
242 IsEqualGUID(&IID_IMediaEventEx, riid)) {
243 *ppvObj = &(This->IMediaEventEx_vtbl);
244 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
245 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
246 IsEqualGUID(&IID_IPersist, riid)) {
247 *ppvObj = &(This->IMediaFilter_vtbl);
248 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
249 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
250 *ppvObj = &(This->IMediaEventSink_vtbl);
251 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
252 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
253 *ppvObj = &(This->IGraphConfig_vtbl);
254 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
255 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
256 *ppvObj = &(This->IMediaPosition_vtbl);
257 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
258 } else {
259 *ppvObj = NULL;
260 FIXME("unknown interface %s\n", debugstr_guid(riid));
261 return E_NOINTERFACE;
264 IUnknown_AddRef((IUnknown *)(*ppvObj));
265 return S_OK;
268 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) {
269 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
270 ULONG ref = InterlockedIncrement(&This->ref);
272 TRACE("(%p)->(): new ref = %d\n", This, ref);
274 return ref;
277 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) {
278 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
279 ULONG ref = InterlockedDecrement(&This->ref);
281 TRACE("(%p)->(): new ref = %d\n", This, ref);
283 if (ref == 0) {
284 int i;
286 IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl));
287 if (This->refClock)
288 IReferenceClock_Release(This->refClock);
290 while (This->nFilters)
291 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]);
293 for (i = 0; i < This->nItfCacheEntries; i++)
295 if (This->ItfCacheEntries[i].iface)
296 IUnknown_Release(This->ItfCacheEntries[i].iface);
298 IFilterMapper2_Release(This->pFilterMapper2);
299 CloseHandle(This->hEventCompletion);
300 EventsQueue_Destroy(&This->evqueue);
301 This->cs.DebugInfo->Spare[0] = 0;
302 DeleteCriticalSection(&This->cs);
303 CoTaskMemFree(This->ppFiltersInGraph);
304 CoTaskMemFree(This->pFilterNames);
305 CoTaskMemFree(This);
307 return ref;
311 /*** IUnknown methods ***/
312 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface,
313 REFIID riid,
314 LPVOID*ppvObj) {
315 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
317 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
318 return Filtergraph_QueryInterface(This, riid, ppvObj);
321 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) {
322 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
324 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
326 return Filtergraph_AddRef(This);
329 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) {
330 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
332 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
334 return Filtergraph_Release(This);
337 /*** IFilterGraph methods ***/
338 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
339 IBaseFilter *pFilter,
340 LPCWSTR pName) {
341 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
342 HRESULT hr;
343 int i,j;
344 WCHAR* wszFilterName = NULL;
345 int duplicate_name = FALSE;
347 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
349 if (!pFilter)
350 return E_POINTER;
352 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
354 if (pName)
356 /* Check if name already exists */
357 for(i = 0; i < This->nFilters; i++)
358 if (!strcmpW(This->pFilterNames[i], pName))
360 duplicate_name = TRUE;
361 break;
365 /* If no name given or name already existing, generate one */
366 if (!pName || duplicate_name)
368 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
369 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
371 for (j = 0; j < 10000 ; j++)
373 /* Create name */
374 if (pName)
375 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
376 else
377 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
378 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
380 /* Check if the generated name already exists */
381 for(i = 0; i < This->nFilters; i++)
382 if (!strcmpW(This->pFilterNames[i], wszFilterName))
383 break;
385 /* Compute next index and exit if generated name is suitable */
386 if (This->nameIndex++ == 10000)
387 This->nameIndex = 1;
388 if (i == This->nFilters)
389 break;
391 /* Unable to find a suitable name */
392 if (j == 10000)
394 CoTaskMemFree(wszFilterName);
395 return VFW_E_DUPLICATE_NAME;
398 else
399 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
401 if (This->nFilters + 1 > This->filterCapacity)
403 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
404 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
405 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
406 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
407 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
408 if (!This->filterCapacity)
410 CoTaskMemFree(This->ppFiltersInGraph);
411 CoTaskMemFree(This->pFilterNames);
413 This->ppFiltersInGraph = ppNewFilters;
414 This->pFilterNames = pNewNames;
415 This->filterCapacity = newCapacity;
418 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
420 if (SUCCEEDED(hr))
422 IBaseFilter_AddRef(pFilter);
423 This->ppFiltersInGraph[This->nFilters] = pFilter;
424 This->pFilterNames[This->nFilters] = wszFilterName;
425 This->nFilters++;
426 IBaseFilter_SetSyncSource(pFilter, This->refClock);
428 else
429 CoTaskMemFree(wszFilterName);
431 if (SUCCEEDED(hr) && duplicate_name)
432 return VFW_S_DUPLICATE_NAME;
434 return hr;
437 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface,
438 IBaseFilter *pFilter) {
439 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
440 int i;
441 HRESULT hr = E_FAIL;
443 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
445 /* FIXME: check graph is stopped */
447 for (i = 0; i < This->nFilters; i++)
449 if (This->ppFiltersInGraph[i] == pFilter)
451 IEnumPins *penumpins;
452 IBaseFilter_Stop(pFilter);
453 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
454 if (SUCCEEDED(hr)) {
455 IPin *ppin;
456 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) {
457 IPin *victim = NULL;
458 HRESULT h;
459 IPin_ConnectedTo(ppin, &victim);
460 if (victim)
462 h = IPin_Disconnect(victim);
463 TRACE("Disconnect other side: %08x\n", h);
464 if (h == VFW_E_NOT_STOPPED)
466 PIN_INFO pinfo;
467 IPin_QueryPinInfo(victim, &pinfo);
468 IBaseFilter_Stop(pinfo.pFilter);
469 IBaseFilter_Release(pinfo.pFilter);
470 h = IPin_Disconnect(victim);
471 TRACE("Disconnect retry: %08x\n", h);
473 IPin_Release(victim);
475 h = IPin_Disconnect(ppin);
476 TRACE("Disconnect 2: %08x\n", h);
478 IEnumPins_Release(penumpins);
481 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
482 if (SUCCEEDED(hr))
484 IBaseFilter_SetSyncSource(pFilter, NULL);
485 IBaseFilter_Release(pFilter);
486 CoTaskMemFree(This->pFilterNames[i]);
487 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
488 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
489 This->nFilters--;
490 /* Invalidate interfaces in the cache */
491 for (i = 0; i < This->nItfCacheEntries; i++)
492 if (pFilter == This->ItfCacheEntries[i].filter)
494 IUnknown_Release(This->ItfCacheEntries[i].iface);
495 This->ItfCacheEntries[i].iface = NULL;
496 This->ItfCacheEntries[i].filter = NULL;
498 return S_OK;
500 break;
504 return hr; /* FIXME: check this error code */
507 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface,
508 IEnumFilters **ppEnum) {
509 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
511 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
513 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
516 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
517 LPCWSTR pName,
518 IBaseFilter **ppFilter) {
519 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
520 int i;
522 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
524 if (!ppFilter)
525 return E_POINTER;
527 for (i = 0; i < This->nFilters; i++)
529 if (!strcmpW(pName, This->pFilterNames[i]))
531 *ppFilter = This->ppFiltersInGraph[i];
532 IBaseFilter_AddRef(*ppFilter);
533 return S_OK;
537 *ppFilter = NULL;
538 return VFW_E_NOT_FOUND;
541 /* NOTE: despite the implication, it doesn't matter which
542 * way round you put in the input and output pins */
543 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface,
544 IPin *ppinIn,
545 IPin *ppinOut,
546 const AM_MEDIA_TYPE *pmt) {
547 PIN_DIRECTION dir;
548 HRESULT hr;
550 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
552 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
554 /* FIXME: check pins are in graph */
556 if (TRACE_ON(quartz))
558 PIN_INFO PinInfo;
560 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
561 if (FAILED(hr))
562 return hr;
564 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
565 IBaseFilter_Release(PinInfo.pFilter);
567 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
568 if (FAILED(hr))
569 return hr;
571 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
572 IBaseFilter_Release(PinInfo.pFilter);
575 hr = IPin_QueryDirection(ppinIn, &dir);
576 if (SUCCEEDED(hr))
578 if (dir == PINDIR_INPUT)
579 hr = IPin_Connect(ppinOut, ppinIn, pmt);
580 else
581 hr = IPin_Connect(ppinIn, ppinOut, pmt);
584 return hr;
587 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface,
588 IPin *ppin) {
589 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
590 IPin *pConnectedTo = NULL;
591 HRESULT hr;
592 PIN_DIRECTION pindir;
594 IPin_QueryDirection(ppin, &pindir);
595 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
596 if (FAILED(hr)) {
597 TRACE("Querying connected to failed: %x\n", hr);
598 return hr;
600 IPin_Disconnect(ppin);
601 IPin_Disconnect(pConnectedTo);
602 if (pindir == PINDIR_INPUT)
603 hr = IPin_Connect(pConnectedTo, ppin, NULL);
604 else
605 hr = IPin_Connect(ppin, pConnectedTo, NULL);
606 IPin_Release(pConnectedTo);
607 if (FAILED(hr))
608 ERR("Reconnecting pins failed, pins are not connected now..\n");
609 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
610 return hr;
613 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface,
614 IPin *ppin) {
615 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
617 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
619 return IPin_Disconnect(ppin);
622 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) {
623 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
624 IReferenceClock *pClock = NULL;
625 HRESULT hr;
627 TRACE("(%p/%p)->() semi-stub\n", iface, This);
629 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
631 if (SUCCEEDED(hr))
633 hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock);
634 IReferenceClock_Release(pClock);
637 return hr;
640 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
642 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
643 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
644 IPropertyBag * pPropBagCat = NULL;
645 HRESULT hr;
647 VariantInit(pvar);
648 V_VT(pvar) = VT_BSTR;
650 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
652 if (SUCCEEDED(hr))
653 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
655 if (SUCCEEDED(hr))
656 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
658 if (SUCCEEDED(hr))
659 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
661 if (SUCCEEDED(hr))
662 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
664 if (pPropBagCat)
665 IPropertyBag_Release(pPropBagCat);
667 return hr;
670 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
672 HRESULT hr;
673 ULONG nb = 0;
675 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
676 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
677 if (hr == S_OK) {
678 /* Rendered input */
679 } else if (hr == S_FALSE) {
680 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
681 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
682 if (hr != S_OK) {
683 ERR("Error (%x)\n", hr);
685 } else if (hr == E_NOTIMPL) {
686 /* Input connected to all outputs */
687 IEnumPins* penumpins;
688 IPin* ppin;
689 int i = 0;
690 TRACE("E_NOTIMPL\n");
691 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
692 if (FAILED(hr)) {
693 ERR("filter Enumpins failed (%x)\n", hr);
694 return hr;
696 i = 0;
697 /* Count output pins */
698 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
699 PIN_DIRECTION pindir;
700 IPin_QueryDirection(ppin, &pindir);
701 if (pindir == PINDIR_OUTPUT)
702 i++;
703 IPin_Release(ppin);
705 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
706 /* Retrieve output pins */
707 IEnumPins_Reset(penumpins);
708 i = 0;
709 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
710 PIN_DIRECTION pindir;
711 IPin_QueryDirection(ppin, &pindir);
712 if (pindir == PINDIR_OUTPUT)
713 (*pppins)[i++] = ppin;
714 else
715 IPin_Release(ppin);
717 IEnumPins_Release(penumpins);
718 nb = i;
719 if (FAILED(hr)) {
720 ERR("Next failed (%x)\n", hr);
721 return hr;
723 } else if (FAILED(hr)) {
724 ERR("Cannot get internal connection (%x)\n", hr);
725 return hr;
728 *pnb = nb;
729 return S_OK;
732 /*** IGraphBuilder methods ***/
733 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface,
734 IPin *ppinOut,
735 IPin *ppinIn) {
736 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
737 HRESULT hr;
738 AM_MEDIA_TYPE* mt;
739 IEnumMediaTypes* penummt;
740 ULONG nbmt;
741 IEnumPins* penumpins;
742 IEnumMoniker* pEnumMoniker;
743 GUID tab[2];
744 ULONG nb;
745 IMoniker* pMoniker;
746 ULONG pin;
747 PIN_INFO PinInfo;
748 CLSID FilterCLSID;
750 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
752 if (TRACE_ON(quartz))
754 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
755 if (FAILED(hr))
756 return hr;
758 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
759 IBaseFilter_Release(PinInfo.pFilter);
761 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
762 if (FAILED(hr))
763 return hr;
765 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
766 IBaseFilter_Release(PinInfo.pFilter);
769 /* Try direct connection first */
770 hr = IPin_Connect(ppinOut, ppinIn, NULL);
771 if (SUCCEEDED(hr)) {
772 return S_OK;
774 TRACE("Direct connection failed, trying to insert other filters\n");
776 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
777 if (FAILED(hr))
778 return hr;
780 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
781 IBaseFilter_Release(PinInfo.pFilter);
782 if (FAILED(hr))
783 return hr;
785 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
786 * filter to the minor mediatype of input pin of the renderer */
787 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
788 if (FAILED(hr)) {
789 ERR("EnumMediaTypes (%x)\n", hr);
790 return hr;
793 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
794 if (FAILED(hr)) {
795 ERR("IEnumMediaTypes_Next (%x)\n", hr);
796 return hr;
799 if (!nbmt) {
800 ERR("No media type found!\n");
801 return S_OK;
803 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
804 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
806 /* Try to find a suitable filter that can connect to the pin to render */
807 tab[0] = mt->majortype;
808 tab[1] = mt->subtype;
809 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
810 if (FAILED(hr)) {
811 ERR("Unable to enum filters (%x)\n", hr);
812 return hr;
815 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
817 VARIANT var;
818 GUID clsid;
819 IPin** ppins;
820 IPin* ppinfilter = NULL;
821 IBaseFilter* pfilter = NULL;
823 hr = GetFilterInfo(pMoniker, &clsid, &var);
824 IMoniker_Release(pMoniker);
825 if (FAILED(hr)) {
826 ERR("Unable to retrieve filter info (%x)\n", hr);
827 goto error;
830 if (IsEqualGUID(&clsid, &FilterCLSID)) {
831 /* Skip filter (same as the one the output pin belongs to) */
832 goto error;
835 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
836 if (FAILED(hr)) {
837 ERR("Unable to create filter (%x), trying next one\n", hr);
838 goto error;
841 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
842 if (FAILED(hr)) {
843 ERR("Unable to add filter (%x)\n", hr);
844 IBaseFilter_Release(pfilter);
845 pfilter = NULL;
846 goto error;
849 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
850 if (FAILED(hr)) {
851 ERR("Enumpins (%x)\n", hr);
852 goto error;
855 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
856 IEnumPins_Release(penumpins);
858 if (FAILED(hr)) {
859 ERR("Next (%x)\n", hr);
860 goto error;
862 if (pin == 0) {
863 ERR("No Pin\n");
864 goto error;
867 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
868 if (FAILED(hr)) {
869 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
870 goto error;
872 TRACE("Successfully connected to filter, follow chain...\n");
874 /* Render all output pins of the filter by calling IFilterGraph2_Render on each of them */
875 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
877 if (SUCCEEDED(hr)) {
878 int i;
879 if (nb == 0) {
880 IPin_Disconnect(ppinOut);
881 goto error;
883 TRACE("pins to consider: %d\n", nb);
884 for(i = 0; i < nb; i++) {
885 TRACE("Processing pin %d\n", i);
886 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
887 if (FAILED(hr)) {
888 TRACE("Cannot render pin %p (%x)\n", ppinfilter, hr);
890 IPin_Release(ppins[i]);
891 if (SUCCEEDED(hr)) break;
893 while (++i < nb) IPin_Release(ppins[i]);
894 CoTaskMemFree(ppins);
895 IPin_Release(ppinfilter);
896 IBaseFilter_Release(pfilter);
897 break;
900 error:
901 if (ppinfilter) IPin_Release(ppinfilter);
902 if (pfilter) {
903 IFilterGraph2_RemoveFilter(iface, pfilter);
904 IBaseFilter_Release(pfilter);
908 IEnumMediaTypes_Release(penummt);
909 DeleteMediaType(mt);
911 return S_OK;
914 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface,
915 IPin *ppinOut) {
916 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
917 IEnumMediaTypes* penummt;
918 AM_MEDIA_TYPE* mt;
919 ULONG nbmt;
920 HRESULT hr;
922 IEnumMoniker* pEnumMoniker;
923 GUID tab[2];
924 ULONG nb;
925 IMoniker* pMoniker;
927 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
929 if (TRACE_ON(quartz))
931 PIN_INFO PinInfo;
933 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
934 if (FAILED(hr))
935 return hr;
937 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
938 IBaseFilter_Release(PinInfo.pFilter);
941 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
942 if (FAILED(hr)) {
943 ERR("EnumMediaTypes (%x)\n", hr);
944 return hr;
947 while(1)
949 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
950 if (FAILED(hr)) {
951 ERR("IEnumMediaTypes_Next (%x)\n", hr);
952 return hr;
954 if (!nbmt)
955 break;
956 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
957 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
959 /* Try to find a suitable renderer with the same media type */
960 tab[0] = mt->majortype;
961 tab[1] = GUID_NULL;
962 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL);
963 if (FAILED(hr)) {
964 ERR("Unable to enum filters (%x)\n", hr);
965 return hr;
968 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
970 VARIANT var;
971 GUID clsid;
972 IPin* ppinfilter;
973 IBaseFilter* pfilter = NULL;
974 IEnumPins* penumpins;
975 ULONG pin;
977 hr = GetFilterInfo(pMoniker, &clsid, &var);
978 IMoniker_Release(pMoniker);
979 if (FAILED(hr)) {
980 ERR("Unable to retrieve filter info (%x)\n", hr);
981 goto error;
984 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
985 if (FAILED(hr)) {
986 ERR("Unable to create filter (%x), trying next one\n", hr);
987 goto error;
990 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
991 if (FAILED(hr)) {
992 ERR("Unable to add filter (%x)\n", hr);
993 IBaseFilter_Release(pfilter);
994 pfilter = NULL;
995 goto error;
998 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
999 if (FAILED(hr)) {
1000 ERR("Splitter Enumpins (%x)\n", hr);
1001 goto error;
1003 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1004 IEnumPins_Release(penumpins);
1005 if (FAILED(hr)) {
1006 ERR("Next (%x)\n", hr);
1007 goto error;
1009 if (pin == 0) {
1010 ERR("No Pin\n");
1011 goto error;
1014 /* Connect the pin to render to the renderer */
1015 hr = IFilterGraph2_Connect(iface, ppinOut, ppinfilter);
1016 if (FAILED(hr)) {
1017 TRACE("Unable to connect to renderer (%x)\n", hr);
1018 IPin_Release(ppinfilter);
1019 goto error;
1021 IPin_Release(ppinfilter);
1022 IBaseFilter_Release(pfilter);
1023 pfilter = NULL;
1024 break;
1026 error:
1027 if (pfilter) {
1028 IFilterGraph2_RemoveFilter(iface, pfilter);
1029 IBaseFilter_Release(pfilter);
1033 DeleteMediaType(mt);
1034 break;
1037 IEnumMediaTypes_Release(penummt);
1039 return S_OK;
1042 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface,
1043 LPCWSTR lpcwstrFile,
1044 LPCWSTR lpcwstrPlayList) {
1045 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1046 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1047 IBaseFilter* preader = NULL;
1048 IBaseFilter* psplitter = NULL;
1049 IPin* ppinreader = NULL;
1050 IPin* ppinsplitter = NULL;
1051 IEnumPins* penumpins;
1052 ULONG pin;
1053 HRESULT hr;
1054 IEnumMoniker* pEnumMoniker = NULL;
1055 GUID tab[2];
1056 IPin** ppins = NULL;
1057 ULONG nb;
1058 IMoniker* pMoniker;
1059 IFileSourceFilter* pfile = NULL;
1060 AM_MEDIA_TYPE mt;
1061 WCHAR* filename;
1063 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1065 if (lpcwstrPlayList != NULL)
1066 return E_INVALIDARG;
1068 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1070 /* Retrieve file media type */
1071 if (SUCCEEDED(hr))
1072 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1073 if (SUCCEEDED(hr)) {
1074 hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1075 IFileSourceFilter_Release(pfile);
1078 if (SUCCEEDED(hr))
1079 hr = IBaseFilter_EnumPins(preader, &penumpins);
1080 if (SUCCEEDED(hr)) {
1081 hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin);
1082 IEnumPins_Release(penumpins);
1085 if (SUCCEEDED(hr)) {
1086 tab[0] = mt.majortype;
1087 tab[1] = mt.subtype;
1088 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1091 if (FAILED(hr))
1093 if (ppinreader)
1094 IPin_Release(ppinreader);
1095 if (pEnumMoniker)
1096 IEnumMoniker_Release(pEnumMoniker);
1097 if (preader) {
1098 IFilterGraph2_RemoveFilter(iface, preader);
1099 IBaseFilter_Release(preader);
1101 return hr;
1104 hr = VFW_E_CANNOT_RENDER;
1105 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1107 VARIANT var;
1108 GUID clsid;
1110 hr = GetFilterInfo(pMoniker, &clsid, &var);
1111 IMoniker_Release(pMoniker);
1112 if (FAILED(hr)) {
1113 ERR("Unable to retrieve filter info (%x)\n", hr);
1114 continue;
1117 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter);
1118 if (FAILED(hr)) {
1119 ERR("Unable to create filter (%x), trying next one\n", hr);
1120 continue;
1123 hr = IFilterGraph2_AddFilter(iface, psplitter, V_UNION(&var, bstrVal));
1124 if (FAILED(hr)) {
1125 ERR("Unable add filter (%x)\n", hr);
1126 IBaseFilter_Release(psplitter);
1127 continue;
1130 /* Connect file source and splitter filters together */
1131 /* Make the splitter analyze incoming data */
1133 hr = IBaseFilter_EnumPins(psplitter, &penumpins);
1134 if (SUCCEEDED(hr)) {
1135 hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin);
1136 IEnumPins_Release(penumpins);
1139 if (SUCCEEDED(hr))
1140 hr = IPin_Connect(ppinreader, ppinsplitter, NULL);
1142 /* Make sure there's some output pins in the filter */
1143 if (SUCCEEDED(hr))
1144 hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb);
1145 if (SUCCEEDED(hr)) {
1146 if(nb == 0) {
1147 IPin_Disconnect(ppinreader);
1148 TRACE("No output pins found in filter\n");
1149 hr = VFW_E_CANNOT_RENDER;
1153 if (ppinsplitter)
1154 IPin_Release(ppinsplitter);
1155 ppinsplitter = NULL;
1157 if (SUCCEEDED(hr)) {
1158 TRACE("Successfully connected to filter\n");
1159 break;
1162 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1164 if (ppins) {
1165 CoTaskMemFree(ppins);
1166 ppins = NULL;
1168 IFilterGraph2_RemoveFilter(iface, psplitter);
1169 IBaseFilter_Release(psplitter);
1170 psplitter = NULL;
1173 /* Render all output pin of the splitter by calling IFilterGraph2_Render on each of them */
1174 if (SUCCEEDED(hr)) {
1175 int partial = 0;
1176 int i;
1177 TRACE("pins to consider: %d\n", nb);
1178 for(i = 0; i < nb; i++) {
1179 TRACE("Processing pin %d\n", i);
1180 hr = IFilterGraph2_Render(iface, ppins[i]);
1181 if (FAILED(hr)) {
1182 ERR("Cannot render pin %p (%x)\n", ppins[i], hr);
1183 partial = 1;
1185 IPin_Release(ppins[i]);
1187 CoTaskMemFree(ppins);
1189 hr = (partial ? VFW_S_PARTIAL_RENDER : S_OK);
1192 IPin_Release(ppinreader);
1193 IBaseFilter_Release(preader);
1194 if (psplitter)
1195 IBaseFilter_Release(psplitter);
1197 return hr;
1200 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface,
1201 LPCWSTR lpcwstrFileName,
1202 LPCWSTR lpcwstrFilterName,
1203 IBaseFilter **ppFilter) {
1204 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1205 HRESULT hr;
1206 IBaseFilter* preader;
1207 IFileSourceFilter* pfile = NULL;
1208 AM_MEDIA_TYPE mt;
1209 WCHAR* filename;
1211 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1213 /* Instantiate a file source filter */
1214 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1215 if (FAILED(hr)) {
1216 ERR("Unable to create file source filter (%x)\n", hr);
1217 return hr;
1220 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1221 if (FAILED(hr)) {
1222 ERR("Unable add filter (%x)\n", hr);
1223 IBaseFilter_Release(preader);
1224 return hr;
1227 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1228 if (FAILED(hr)) {
1229 ERR("Unable to get IFileSourceInterface (%x)\n", hr);
1230 goto error;
1233 /* Load the file in the file source filter */
1234 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1235 if (FAILED(hr)) {
1236 ERR("Load (%x)\n", hr);
1237 goto error;
1240 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1241 if (FAILED(hr)) {
1242 ERR("GetCurFile (%x)\n", hr);
1243 goto error;
1245 TRACE("File %s\n", debugstr_w(filename));
1246 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1247 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1249 if (ppFilter)
1250 *ppFilter = preader;
1251 IFileSourceFilter_Release(pfile);
1253 return S_OK;
1255 error:
1256 if (pfile)
1257 IFileSourceFilter_Release(pfile);
1258 IFilterGraph2_RemoveFilter(iface, preader);
1259 IBaseFilter_Release(preader);
1261 return hr;
1264 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface,
1265 DWORD_PTR hFile) {
1266 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1268 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1270 return S_OK;
1273 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) {
1274 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1276 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1278 return S_OK;
1281 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) {
1282 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1284 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1286 return S_OK;
1289 /*** IFilterGraph2 methods ***/
1290 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1291 IMoniker *pMoniker,
1292 IBindCtx *pCtx,
1293 LPCWSTR lpcwstrFilterName,
1294 IBaseFilter **ppFilter) {
1295 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1297 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1299 return S_OK;
1302 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface,
1303 IPin *ppin,
1304 const AM_MEDIA_TYPE *pmt) {
1305 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1307 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1309 return S_OK;
1312 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface,
1313 IPin *pPinOut,
1314 DWORD dwFlags,
1315 DWORD *pvContext) {
1316 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1318 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1320 return S_OK;
1324 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1326 FilterGraph2_QueryInterface,
1327 FilterGraph2_AddRef,
1328 FilterGraph2_Release,
1329 FilterGraph2_AddFilter,
1330 FilterGraph2_RemoveFilter,
1331 FilterGraph2_EnumFilters,
1332 FilterGraph2_FindFilterByName,
1333 FilterGraph2_ConnectDirect,
1334 FilterGraph2_Reconnect,
1335 FilterGraph2_Disconnect,
1336 FilterGraph2_SetDefaultSyncSource,
1337 FilterGraph2_Connect,
1338 FilterGraph2_Render,
1339 FilterGraph2_RenderFile,
1340 FilterGraph2_AddSourceFilter,
1341 FilterGraph2_SetLogFile,
1342 FilterGraph2_Abort,
1343 FilterGraph2_ShouldOperationContinue,
1344 FilterGraph2_AddSourceFilterForMoniker,
1345 FilterGraph2_ReconnectEx,
1346 FilterGraph2_RenderEx
1349 /*** IUnknown methods ***/
1350 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface,
1351 REFIID riid,
1352 LPVOID*ppvObj) {
1353 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1355 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1357 return Filtergraph_QueryInterface(This, riid, ppvObj);
1360 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) {
1361 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1363 TRACE("(%p/%p)->()\n", This, iface);
1365 return Filtergraph_AddRef(This);
1368 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) {
1369 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1371 TRACE("(%p/%p)->()\n", This, iface);
1373 return Filtergraph_Release(This);
1377 /*** IDispatch methods ***/
1378 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface,
1379 UINT*pctinfo) {
1380 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1382 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1384 return S_OK;
1387 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface,
1388 UINT iTInfo,
1389 LCID lcid,
1390 ITypeInfo**ppTInfo) {
1391 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1393 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1395 return S_OK;
1398 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface,
1399 REFIID riid,
1400 LPOLESTR*rgszNames,
1401 UINT cNames,
1402 LCID lcid,
1403 DISPID*rgDispId) {
1404 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1406 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1408 return S_OK;
1411 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
1412 DISPID dispIdMember,
1413 REFIID riid,
1414 LCID lcid,
1415 WORD wFlags,
1416 DISPPARAMS*pDispParams,
1417 VARIANT*pVarResult,
1418 EXCEPINFO*pExepInfo,
1419 UINT*puArgErr) {
1420 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1422 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);
1424 return S_OK;
1427 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *);
1429 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter)
1431 HRESULT hr;
1432 IPin* pInputPin;
1433 IPin** ppPins;
1434 ULONG nb;
1435 ULONG i;
1436 PIN_INFO PinInfo;
1438 TRACE("%p %p\n", pGraph, pOutputPin);
1439 PinInfo.pFilter = NULL;
1441 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1443 if (SUCCEEDED(hr))
1445 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1446 if (SUCCEEDED(hr))
1447 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1448 IPin_Release(pInputPin);
1451 if (SUCCEEDED(hr))
1453 if (nb == 0)
1455 TRACE("Reached a renderer\n");
1456 /* Count renderers for end of stream notification */
1457 pGraph->nRenderers++;
1459 else
1461 for(i = 0; i < nb; i++)
1463 /* Explore the graph downstream from this pin
1464 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1465 * several input pins are connected to the same output (a MUX for instance). */
1466 ExploreGraph(pGraph, ppPins[i], FoundFilter);
1467 IPin_Release(ppPins[i]);
1470 CoTaskMemFree(ppPins);
1472 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1473 FoundFilter(PinInfo.pFilter);
1476 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1477 return hr;
1480 static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
1481 LONGLONG time = 0;
1482 IReferenceClock *clock = NULL;
1484 IBaseFilter_GetSyncSource(pFilter, &clock);
1485 if (clock)
1487 IReferenceClock_GetTime(clock, &time);
1488 if (time)
1489 /* Add 50 ms */
1490 time += 500000;
1491 if (time < 0)
1492 time = 0;
1493 IReferenceClock_Release(clock);
1496 return IBaseFilter_Run(pFilter, time);
1499 static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
1500 return IBaseFilter_Pause(pFilter);
1503 static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
1504 return IBaseFilter_Stop(pFilter);
1507 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) {
1508 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1509 int i;
1510 IBaseFilter* pfilter;
1511 IEnumPins* pEnum;
1512 HRESULT hr;
1513 IPin* pPin;
1514 DWORD dummy;
1515 PIN_DIRECTION dir;
1516 TRACE("(%p/%p)->()\n", This, iface);
1518 /* Explorer the graph from source filters to renderers, determine renderers
1519 * number and run filters from renderers to source filters */
1520 This->nRenderers = 0;
1521 ResetEvent(This->hEventCompletion);
1523 for(i = 0; i < This->nFilters; i++)
1525 BOOL source = TRUE;
1526 pfilter = This->ppFiltersInGraph[i];
1527 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1528 if (hr != S_OK)
1530 ERR("Enum pins failed %x\n", hr);
1531 continue;
1533 /* Check if it is a source filter */
1534 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1536 IPin_QueryDirection(pPin, &dir);
1537 IPin_Release(pPin);
1538 if (dir == PINDIR_INPUT)
1540 source = FALSE;
1541 break;
1544 if (source)
1546 TRACE("Found a source filter %p\n", pfilter);
1547 IEnumPins_Reset(pEnum);
1548 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1550 /* Explore the graph downstream from this pin */
1551 ExploreGraph(This, pPin, FoundFilter);
1552 IPin_Release(pPin);
1554 FoundFilter(pfilter);
1556 IEnumPins_Release(pEnum);
1559 return S_FALSE;
1562 /*** IMediaControl methods ***/
1563 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
1564 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1565 TRACE("(%p/%p)->()\n", This, iface);
1567 if (This->state == State_Running) return S_OK;
1569 EnterCriticalSection(&This->cs);
1570 SendFilterMessage(iface, SendRun);
1571 This->state = State_Running;
1572 LeaveCriticalSection(&This->cs);
1573 return S_FALSE;
1576 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
1577 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1578 TRACE("(%p/%p)->()\n", This, iface);
1580 if (This->state == State_Paused) return S_OK;
1582 EnterCriticalSection(&This->cs);
1583 SendFilterMessage(iface, SendPause);
1584 This->state = State_Paused;
1585 LeaveCriticalSection(&This->cs);
1586 return S_FALSE;
1589 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
1590 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1591 TRACE("(%p/%p)->()\n", This, iface);
1593 if (This->state == State_Stopped) return S_OK;
1595 EnterCriticalSection(&This->cs);
1596 if (This->state == State_Running) SendFilterMessage(iface, SendPause);
1597 SendFilterMessage(iface, SendStop);
1598 This->state = State_Stopped;
1599 LeaveCriticalSection(&This->cs);
1600 return S_OK;
1603 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
1604 LONG msTimeout,
1605 OAFilterState *pfs) {
1606 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1608 TRACE("(%p/%p)->(%d, %p): semi-stub !!!\n", This, iface, msTimeout, pfs);
1610 EnterCriticalSection(&This->cs);
1612 *pfs = This->state;
1614 LeaveCriticalSection(&This->cs);
1616 return S_OK;
1619 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface,
1620 BSTR strFilename) {
1621 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1623 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1625 return S_OK;
1628 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface,
1629 BSTR strFilename,
1630 IDispatch **ppUnk) {
1631 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1633 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1635 return S_OK;
1638 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface,
1639 IDispatch **ppUnk) {
1640 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1642 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1644 return S_OK;
1647 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface,
1648 IDispatch **ppUnk) {
1649 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1651 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1653 return S_OK;
1656 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) {
1657 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1659 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1661 return S_OK;
1665 static const IMediaControlVtbl IMediaControl_VTable =
1667 MediaControl_QueryInterface,
1668 MediaControl_AddRef,
1669 MediaControl_Release,
1670 MediaControl_GetTypeInfoCount,
1671 MediaControl_GetTypeInfo,
1672 MediaControl_GetIDsOfNames,
1673 MediaControl_Invoke,
1674 MediaControl_Run,
1675 MediaControl_Pause,
1676 MediaControl_Stop,
1677 MediaControl_GetState,
1678 MediaControl_RenderFile,
1679 MediaControl_AddSourceFilter,
1680 MediaControl_get_FilterCollection,
1681 MediaControl_get_RegFilterCollection,
1682 MediaControl_StopWhenReady
1686 /*** IUnknown methods ***/
1687 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface,
1688 REFIID riid,
1689 LPVOID*ppvObj) {
1690 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1692 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1694 return Filtergraph_QueryInterface(This, riid, ppvObj);
1697 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) {
1698 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1700 TRACE("(%p/%p)->()\n", This, iface);
1702 return Filtergraph_AddRef(This);
1705 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) {
1706 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1708 TRACE("(%p/%p)->()\n", This, iface);
1710 return Filtergraph_Release(This);
1713 typedef HRESULT WINAPI (*fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
1715 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
1716 BOOL allnotimpl = TRUE;
1717 int i;
1718 IBaseFilter* pfilter;
1719 IEnumPins* pEnum;
1720 HRESULT hr, hr_return = S_OK;
1721 IPin* pPin;
1722 DWORD dummy;
1723 PIN_DIRECTION dir;
1725 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
1726 /* Send a message to all renderers, they are responsible for broadcasting it further */
1728 for(i = 0; i < This->nFilters; i++)
1730 BOOL renderer = TRUE;
1731 pfilter = This->ppFiltersInGraph[i];
1732 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1733 if (hr != S_OK)
1735 ERR("Enum pins failed %x\n", hr);
1736 continue;
1738 /* Check if it is a source filter */
1739 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1741 IPin_QueryDirection(pPin, &dir);
1742 IPin_Release(pPin);
1743 if (dir != PINDIR_INPUT)
1745 renderer = FALSE;
1746 break;
1749 IEnumPins_Release(pEnum);
1750 if (renderer)
1752 IMediaSeeking *seek = NULL;
1753 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
1754 if (!seek)
1755 continue;
1756 hr = FoundSeek(This, seek, arg);
1757 IMediaSeeking_Release(seek);
1758 if (hr_return != E_NOTIMPL)
1759 allnotimpl = FALSE;
1760 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && !FAILED(hr_return)))
1761 hr_return = hr;
1765 if (allnotimpl)
1766 return E_NOTIMPL;
1767 return hr_return;
1770 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
1772 HRESULT hr;
1773 DWORD caps = 0;
1775 hr = IMediaSeeking_GetCapabilities(seek, &caps);
1776 if (FAILED(hr))
1777 return hr;
1779 /* Only add common capabilities everything supports */
1780 *(DWORD*)pcaps &= caps;
1782 return hr;
1785 /*** IMediaSeeking methods ***/
1786 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface,
1787 DWORD *pCapabilities) {
1788 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1789 HRESULT hr;
1790 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
1792 if (!pCapabilities)
1793 return E_POINTER;
1795 EnterCriticalSection(&This->cs);
1796 *pCapabilities = 0xffffffff;
1798 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
1799 LeaveCriticalSection(&This->cs);
1801 return hr;
1804 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface,
1805 DWORD *pCapabilities) {
1806 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1807 DWORD originalcaps;
1808 HRESULT hr;
1809 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
1811 if (!pCapabilities)
1812 return E_POINTER;
1814 EnterCriticalSection(&This->cs);
1815 originalcaps = *pCapabilities;
1816 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
1817 LeaveCriticalSection(&This->cs);
1819 if (FAILED(hr))
1820 return hr;
1822 if (!*pCapabilities)
1823 return E_FAIL;
1824 if (*pCapabilities != originalcaps)
1825 return S_FALSE;
1826 return S_OK;
1829 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface,
1830 const GUID *pFormat) {
1831 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1833 if (!pFormat)
1834 return E_POINTER;
1836 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
1838 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
1840 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
1841 return S_FALSE;
1844 return S_OK;
1847 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface,
1848 GUID *pFormat) {
1849 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1851 if (!pFormat)
1852 return E_POINTER;
1854 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
1855 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
1857 return S_OK;
1860 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface,
1861 GUID *pFormat) {
1862 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1864 if (!pFormat)
1865 return E_POINTER;
1867 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
1868 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
1870 return S_OK;
1873 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface,
1874 const GUID *pFormat) {
1875 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1877 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
1878 if (!pFormat)
1879 return E_POINTER;
1881 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
1882 return S_FALSE;
1884 return S_OK;
1887 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface,
1888 const GUID *pFormat) {
1889 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1891 if (!pFormat)
1892 return E_POINTER;
1894 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
1896 if (This->state != State_Stopped)
1897 return VFW_E_WRONG_STATE;
1899 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
1901 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
1902 return E_INVALIDARG;
1905 return S_OK;
1908 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
1910 HRESULT hr;
1911 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
1913 hr = IMediaSeeking_GetDuration(seek, &duration);
1914 if (FAILED(hr))
1915 return hr;
1917 /* FIXME: Minimum or maximum duration? Assuming minimum */
1918 if (duration > 0 && *pdur < duration)
1919 *pdur = duration;
1921 return hr;
1924 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface,
1925 LONGLONG *pDuration) {
1926 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1927 HRESULT hr;
1929 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
1931 if (!pDuration)
1932 return E_POINTER;
1934 EnterCriticalSection(&This->cs);
1935 *pDuration = -1;
1936 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
1937 LeaveCriticalSection(&This->cs);
1939 TRACE("--->%08x\n", hr);
1940 return hr;
1943 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
1944 LONGLONG *pStop) {
1945 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1947 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1949 return S_OK;
1952 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
1953 LONGLONG *pCurrent) {
1954 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1956 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent);
1958 return S_OK;
1961 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
1962 LONGLONG *pTarget,
1963 const GUID *pTargetFormat,
1964 LONGLONG Source,
1965 const GUID *pSourceFormat) {
1966 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1968 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
1969 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
1971 return S_OK;
1974 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
1975 LONGLONG *pCurrent,
1976 DWORD dwCurrentFlags,
1977 LONGLONG *pStop,
1978 DWORD dwStopFlags) {
1979 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1981 FIXME("(%p/%p)->(%p, %08x, %p, %08x): stub !!!\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1983 return S_OK;
1986 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
1987 LONGLONG *pCurrent,
1988 LONGLONG *pStop) {
1989 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1991 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pCurrent, pStop);
1993 return S_OK;
1996 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
1997 LONGLONG *pEarliest,
1998 LONGLONG *pLatest) {
1999 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2001 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2003 return S_OK;
2006 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
2007 double dRate) {
2008 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2010 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2012 return S_OK;
2015 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
2016 double *pdRate) {
2017 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2019 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2021 return S_OK;
2024 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
2025 LONGLONG *pllPreroll) {
2026 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2028 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2030 return S_OK;
2034 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2036 MediaSeeking_QueryInterface,
2037 MediaSeeking_AddRef,
2038 MediaSeeking_Release,
2039 MediaSeeking_GetCapabilities,
2040 MediaSeeking_CheckCapabilities,
2041 MediaSeeking_IsFormatSupported,
2042 MediaSeeking_QueryPreferredFormat,
2043 MediaSeeking_GetTimeFormat,
2044 MediaSeeking_IsUsingTimeFormat,
2045 MediaSeeking_SetTimeFormat,
2046 MediaSeeking_GetDuration,
2047 MediaSeeking_GetStopPosition,
2048 MediaSeeking_GetCurrentPosition,
2049 MediaSeeking_ConvertTimeFormat,
2050 MediaSeeking_SetPositions,
2051 MediaSeeking_GetPositions,
2052 MediaSeeking_GetAvailable,
2053 MediaSeeking_SetRate,
2054 MediaSeeking_GetRate,
2055 MediaSeeking_GetPreroll
2058 /*** IUnknown methods ***/
2059 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
2060 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2062 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2064 return Filtergraph_QueryInterface(This, riid, ppvObj);
2067 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
2068 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2070 TRACE("(%p/%p)->()\n", This, iface);
2072 return Filtergraph_AddRef(This);
2075 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
2076 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2078 TRACE("(%p/%p)->()\n", This, iface);
2080 return Filtergraph_Release(This);
2083 /*** IDispatch methods ***/
2084 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2085 FIXME("(%p) stub!\n", iface);
2086 return E_NOTIMPL;
2089 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2090 FIXME("(%p) stub!\n", iface);
2091 return E_NOTIMPL;
2094 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2095 FIXME("(%p) stub!\n", iface);
2096 return E_NOTIMPL;
2099 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2100 FIXME("(%p) stub!\n", iface);
2101 return E_NOTIMPL;
2104 /*** IMediaPosition methods ***/
2105 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
2106 FIXME("(%p)->(%p) stub!\n", iface, plength);
2107 return E_NOTIMPL;
2110 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
2111 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2112 return E_NOTIMPL;
2115 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
2116 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2117 return E_NOTIMPL;
2120 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
2121 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2122 return E_NOTIMPL;
2125 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
2126 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2127 return E_NOTIMPL;
2130 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2131 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2132 return E_NOTIMPL;
2135 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2136 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2137 return E_NOTIMPL;
2140 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
2141 FIXME("(%p)->(%f) stub!\n", iface, dRate);
2142 return E_NOTIMPL;
2145 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
2146 FIXME("(%p)->(%p) stub!\n", iface, pdRate);
2147 return E_NOTIMPL;
2150 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2151 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2152 return E_NOTIMPL;
2155 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2156 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2157 return E_NOTIMPL;
2161 static const IMediaPositionVtbl IMediaPosition_VTable =
2163 MediaPosition_QueryInterface,
2164 MediaPosition_AddRef,
2165 MediaPosition_Release,
2166 MediaPosition_GetTypeInfoCount,
2167 MediaPosition_GetTypeInfo,
2168 MediaPosition_GetIDsOfNames,
2169 MediaPosition_Invoke,
2170 MediaPosition_get_Duration,
2171 MediaPosition_put_CurrentPosition,
2172 MediaPosition_get_CurrentPosition,
2173 MediaPosition_get_StopTime,
2174 MediaPosition_put_StopTime,
2175 MediaPosition_get_PrerollTime,
2176 MediaPosition_put_PrerollTime,
2177 MediaPosition_put_Rate,
2178 MediaPosition_get_Rate,
2179 MediaPosition_CanSeekForward,
2180 MediaPosition_CanSeekBackward
2183 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2185 HRESULT hr = E_NOINTERFACE;
2186 int i;
2187 int entry;
2189 /* Check if the interface type is already registered */
2190 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2191 if (riid == pGraph->ItfCacheEntries[entry].riid)
2193 if (pGraph->ItfCacheEntries[entry].iface)
2195 /* Return the interface if available */
2196 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2197 return S_OK;
2199 break;
2202 if (entry >= MAX_ITF_CACHE_ENTRIES)
2204 FIXME("Not enough space to store interface in the cache\n");
2205 return E_OUTOFMEMORY;
2208 /* Find a filter supporting the requested interface */
2209 for (i = 0; i < pGraph->nFilters; i++)
2211 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2212 if (hr == S_OK)
2214 pGraph->ItfCacheEntries[entry].riid = riid;
2215 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2216 pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
2217 if (entry >= pGraph->nItfCacheEntries)
2218 pGraph->nItfCacheEntries++;
2219 return S_OK;
2221 if (hr != E_NOINTERFACE)
2222 return hr;
2225 return hr;
2228 /*** IUnknown methods ***/
2229 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
2230 REFIID riid,
2231 LPVOID*ppvObj) {
2232 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2234 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2236 return Filtergraph_QueryInterface(This, riid, ppvObj);
2239 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
2240 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2242 TRACE("(%p/%p)->()\n", This, iface);
2244 return Filtergraph_AddRef(This);
2247 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
2248 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2250 TRACE("(%p/%p)->()\n", This, iface);
2252 return Filtergraph_Release(This);
2255 /*** IDispatch methods ***/
2256 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
2257 UINT*pctinfo) {
2258 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2259 IBasicAudio* pBasicAudio;
2260 HRESULT hr;
2262 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2264 EnterCriticalSection(&This->cs);
2266 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2268 if (hr == S_OK)
2269 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2271 LeaveCriticalSection(&This->cs);
2273 return hr;
2276 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2277 UINT iTInfo,
2278 LCID lcid,
2279 ITypeInfo**ppTInfo) {
2280 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2281 IBasicAudio* pBasicAudio;
2282 HRESULT hr;
2284 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2286 EnterCriticalSection(&This->cs);
2288 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2290 if (hr == S_OK)
2291 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2293 LeaveCriticalSection(&This->cs);
2295 return hr;
2298 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2299 REFIID riid,
2300 LPOLESTR*rgszNames,
2301 UINT cNames,
2302 LCID lcid,
2303 DISPID*rgDispId) {
2304 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2305 IBasicAudio* pBasicAudio;
2306 HRESULT hr;
2308 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2310 EnterCriticalSection(&This->cs);
2312 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2314 if (hr == S_OK)
2315 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2317 LeaveCriticalSection(&This->cs);
2319 return hr;
2322 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2323 DISPID dispIdMember,
2324 REFIID riid,
2325 LCID lcid,
2326 WORD wFlags,
2327 DISPPARAMS*pDispParams,
2328 VARIANT*pVarResult,
2329 EXCEPINFO*pExepInfo,
2330 UINT*puArgErr) {
2331 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2332 IBasicAudio* pBasicAudio;
2333 HRESULT hr;
2335 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);
2337 EnterCriticalSection(&This->cs);
2339 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2341 if (hr == S_OK)
2342 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2344 LeaveCriticalSection(&This->cs);
2346 return hr;
2349 /*** IBasicAudio methods ***/
2350 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2351 long lVolume) {
2352 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2353 IBasicAudio* pBasicAudio;
2354 HRESULT hr;
2356 TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2358 EnterCriticalSection(&This->cs);
2360 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2362 if (hr == S_OK)
2363 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2365 LeaveCriticalSection(&This->cs);
2367 return hr;
2370 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2371 long *plVolume) {
2372 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2373 IBasicAudio* pBasicAudio;
2374 HRESULT hr;
2376 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2378 EnterCriticalSection(&This->cs);
2380 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2382 if (hr == S_OK)
2383 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2385 LeaveCriticalSection(&This->cs);
2387 return hr;
2390 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2391 long lBalance) {
2392 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2393 IBasicAudio* pBasicAudio;
2394 HRESULT hr;
2396 TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2398 EnterCriticalSection(&This->cs);
2400 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2402 if (hr == S_OK)
2403 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2405 LeaveCriticalSection(&This->cs);
2407 return hr;
2410 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2411 long *plBalance) {
2412 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2413 IBasicAudio* pBasicAudio;
2414 HRESULT hr;
2416 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2418 EnterCriticalSection(&This->cs);
2420 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2422 if (hr == S_OK)
2423 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2425 LeaveCriticalSection(&This->cs);
2427 return hr;
2430 static const IBasicAudioVtbl IBasicAudio_VTable =
2432 BasicAudio_QueryInterface,
2433 BasicAudio_AddRef,
2434 BasicAudio_Release,
2435 BasicAudio_GetTypeInfoCount,
2436 BasicAudio_GetTypeInfo,
2437 BasicAudio_GetIDsOfNames,
2438 BasicAudio_Invoke,
2439 BasicAudio_put_Volume,
2440 BasicAudio_get_Volume,
2441 BasicAudio_put_Balance,
2442 BasicAudio_get_Balance
2445 /*** IUnknown methods ***/
2446 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface,
2447 REFIID riid,
2448 LPVOID*ppvObj) {
2449 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2451 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2453 return Filtergraph_QueryInterface(This, riid, ppvObj);
2456 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) {
2457 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2459 TRACE("(%p/%p)->()\n", This, iface);
2461 return Filtergraph_AddRef(This);
2464 static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) {
2465 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2467 TRACE("(%p/%p)->()\n", This, iface);
2469 return Filtergraph_Release(This);
2472 /*** IDispatch methods ***/
2473 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface,
2474 UINT*pctinfo) {
2475 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2476 IBasicVideo* pBasicVideo;
2477 HRESULT hr;
2479 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2481 EnterCriticalSection(&This->cs);
2483 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2485 if (hr == S_OK)
2486 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2488 LeaveCriticalSection(&This->cs);
2490 return hr;
2493 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface,
2494 UINT iTInfo,
2495 LCID lcid,
2496 ITypeInfo**ppTInfo) {
2497 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2498 IBasicVideo* pBasicVideo;
2499 HRESULT hr;
2501 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2503 EnterCriticalSection(&This->cs);
2505 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2507 if (hr == S_OK)
2508 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2510 LeaveCriticalSection(&This->cs);
2512 return hr;
2515 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface,
2516 REFIID riid,
2517 LPOLESTR*rgszNames,
2518 UINT cNames,
2519 LCID lcid,
2520 DISPID*rgDispId) {
2521 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2522 IBasicVideo* pBasicVideo;
2523 HRESULT hr;
2525 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2527 EnterCriticalSection(&This->cs);
2529 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2531 if (hr == S_OK)
2532 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
2534 LeaveCriticalSection(&This->cs);
2536 return hr;
2539 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface,
2540 DISPID dispIdMember,
2541 REFIID riid,
2542 LCID lcid,
2543 WORD wFlags,
2544 DISPPARAMS*pDispParams,
2545 VARIANT*pVarResult,
2546 EXCEPINFO*pExepInfo,
2547 UINT*puArgErr) {
2548 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2549 IBasicVideo* pBasicVideo;
2550 HRESULT hr;
2552 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);
2554 EnterCriticalSection(&This->cs);
2556 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2558 if (hr == S_OK)
2559 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2561 LeaveCriticalSection(&This->cs);
2563 return hr;
2566 /*** IBasicVideo methods ***/
2567 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface,
2568 REFTIME *pAvgTimePerFrame) {
2569 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2570 IBasicVideo* pBasicVideo;
2571 HRESULT hr;
2573 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
2575 EnterCriticalSection(&This->cs);
2577 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2579 if (hr == S_OK)
2580 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
2582 LeaveCriticalSection(&This->cs);
2584 return hr;
2587 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface,
2588 long *pBitRate) {
2589 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2590 IBasicVideo* pBasicVideo;
2591 HRESULT hr;
2593 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
2595 EnterCriticalSection(&This->cs);
2597 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2599 if (hr == S_OK)
2600 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
2602 LeaveCriticalSection(&This->cs);
2604 return hr;
2607 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface,
2608 long *pBitErrorRate) {
2609 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2610 IBasicVideo* pBasicVideo;
2611 HRESULT hr;
2613 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
2615 EnterCriticalSection(&This->cs);
2617 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2619 if (hr == S_OK)
2620 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
2622 LeaveCriticalSection(&This->cs);
2624 return hr;
2627 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface,
2628 long *pVideoWidth) {
2629 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2630 IBasicVideo* pBasicVideo;
2631 HRESULT hr;
2633 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
2635 EnterCriticalSection(&This->cs);
2637 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2639 if (hr == S_OK)
2640 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
2642 LeaveCriticalSection(&This->cs);
2644 return hr;
2647 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface,
2648 long *pVideoHeight) {
2649 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2650 IBasicVideo* pBasicVideo;
2651 HRESULT hr;
2653 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
2655 EnterCriticalSection(&This->cs);
2657 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2659 if (hr == S_OK)
2660 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
2662 LeaveCriticalSection(&This->cs);
2664 return hr;
2667 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface,
2668 long SourceLeft) {
2669 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2670 IBasicVideo* pBasicVideo;
2671 HRESULT hr;
2673 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
2675 EnterCriticalSection(&This->cs);
2677 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2679 if (hr == S_OK)
2680 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
2682 LeaveCriticalSection(&This->cs);
2684 return hr;
2687 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface,
2688 long *pSourceLeft) {
2689 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2690 IBasicVideo* pBasicVideo;
2691 HRESULT hr;
2693 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
2695 EnterCriticalSection(&This->cs);
2697 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2699 if (hr == S_OK)
2700 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
2702 LeaveCriticalSection(&This->cs);
2704 return hr;
2707 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface,
2708 long SourceWidth) {
2709 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2710 IBasicVideo* pBasicVideo;
2711 HRESULT hr;
2713 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
2715 EnterCriticalSection(&This->cs);
2717 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2719 if (hr == S_OK)
2720 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
2722 LeaveCriticalSection(&This->cs);
2724 return hr;
2727 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface,
2728 long *pSourceWidth) {
2729 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2730 IBasicVideo* pBasicVideo;
2731 HRESULT hr;
2733 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
2735 EnterCriticalSection(&This->cs);
2737 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2739 if (hr == S_OK)
2740 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
2742 LeaveCriticalSection(&This->cs);
2744 return hr;
2747 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface,
2748 long SourceTop) {
2749 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2750 IBasicVideo* pBasicVideo;
2751 HRESULT hr;
2753 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
2755 EnterCriticalSection(&This->cs);
2757 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2759 if (hr == S_OK)
2760 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
2762 LeaveCriticalSection(&This->cs);
2764 return hr;
2767 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface,
2768 long *pSourceTop) {
2769 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2770 IBasicVideo* pBasicVideo;
2771 HRESULT hr;
2773 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
2775 EnterCriticalSection(&This->cs);
2777 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2779 if (hr == S_OK)
2780 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
2782 LeaveCriticalSection(&This->cs);
2784 return hr;
2787 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface,
2788 long SourceHeight) {
2789 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2790 IBasicVideo* pBasicVideo;
2791 HRESULT hr;
2793 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
2795 EnterCriticalSection(&This->cs);
2797 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2799 if (hr == S_OK)
2800 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
2802 LeaveCriticalSection(&This->cs);
2804 return hr;
2807 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface,
2808 long *pSourceHeight) {
2809 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2810 IBasicVideo* pBasicVideo;
2811 HRESULT hr;
2813 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
2815 EnterCriticalSection(&This->cs);
2817 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2819 if (hr == S_OK)
2820 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
2822 LeaveCriticalSection(&This->cs);
2824 return hr;
2827 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface,
2828 long DestinationLeft) {
2829 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2830 IBasicVideo* pBasicVideo;
2831 HRESULT hr;
2833 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
2835 EnterCriticalSection(&This->cs);
2837 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2839 if (hr == S_OK)
2840 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
2842 LeaveCriticalSection(&This->cs);
2844 return hr;
2847 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface,
2848 long *pDestinationLeft) {
2849 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2850 IBasicVideo* pBasicVideo;
2851 HRESULT hr;
2853 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
2855 EnterCriticalSection(&This->cs);
2857 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2859 if (hr == S_OK)
2860 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
2862 LeaveCriticalSection(&This->cs);
2864 return hr;
2867 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface,
2868 long DestinationWidth) {
2869 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2870 IBasicVideo* pBasicVideo;
2871 HRESULT hr;
2873 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
2875 EnterCriticalSection(&This->cs);
2877 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2879 if (hr == S_OK)
2880 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
2882 LeaveCriticalSection(&This->cs);
2884 return hr;
2887 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface,
2888 long *pDestinationWidth) {
2889 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2890 IBasicVideo* pBasicVideo;
2891 HRESULT hr;
2893 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
2895 EnterCriticalSection(&This->cs);
2897 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2899 if (hr == S_OK)
2900 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
2902 LeaveCriticalSection(&This->cs);
2904 return hr;
2907 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface,
2908 long DestinationTop) {
2909 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2910 IBasicVideo* pBasicVideo;
2911 HRESULT hr;
2913 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
2915 EnterCriticalSection(&This->cs);
2917 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2919 if (hr == S_OK)
2920 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
2922 LeaveCriticalSection(&This->cs);
2924 return hr;
2927 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface,
2928 long *pDestinationTop) {
2929 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2930 IBasicVideo* pBasicVideo;
2931 HRESULT hr;
2933 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
2935 EnterCriticalSection(&This->cs);
2937 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2939 if (hr == S_OK)
2940 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
2942 LeaveCriticalSection(&This->cs);
2944 return hr;
2947 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface,
2948 long DestinationHeight) {
2949 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2950 IBasicVideo* pBasicVideo;
2951 HRESULT hr;
2953 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
2955 EnterCriticalSection(&This->cs);
2957 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2959 if (hr == S_OK)
2960 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
2962 LeaveCriticalSection(&This->cs);
2964 return hr;
2967 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface,
2968 long *pDestinationHeight) {
2969 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2970 IBasicVideo* pBasicVideo;
2971 HRESULT hr;
2973 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
2975 EnterCriticalSection(&This->cs);
2977 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2979 if (hr == S_OK)
2980 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
2982 LeaveCriticalSection(&This->cs);
2984 return hr;
2987 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface,
2988 long Left,
2989 long Top,
2990 long Width,
2991 long Height) {
2992 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2993 IBasicVideo* pBasicVideo;
2994 HRESULT hr;
2996 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
2998 EnterCriticalSection(&This->cs);
3000 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3002 if (hr == S_OK)
3003 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3005 LeaveCriticalSection(&This->cs);
3007 return hr;
3010 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface,
3011 long *pLeft,
3012 long *pTop,
3013 long *pWidth,
3014 long *pHeight) {
3015 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3016 IBasicVideo* pBasicVideo;
3017 HRESULT hr;
3019 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3021 EnterCriticalSection(&This->cs);
3023 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3025 if (hr == S_OK)
3026 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3028 LeaveCriticalSection(&This->cs);
3030 return hr;
3033 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) {
3034 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3035 IBasicVideo* pBasicVideo;
3036 HRESULT hr;
3038 TRACE("(%p/%p)->()\n", This, iface);
3040 EnterCriticalSection(&This->cs);
3042 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3044 if (hr == S_OK)
3045 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3047 LeaveCriticalSection(&This->cs);
3049 return hr;
3052 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface,
3053 long Left,
3054 long Top,
3055 long Width,
3056 long Height) {
3057 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3058 IBasicVideo* pBasicVideo;
3059 HRESULT hr;
3061 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3063 EnterCriticalSection(&This->cs);
3065 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3067 if (hr == S_OK)
3068 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3070 LeaveCriticalSection(&This->cs);
3072 return hr;
3075 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface,
3076 long *pLeft,
3077 long *pTop,
3078 long *pWidth,
3079 long *pHeight) {
3080 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3081 IBasicVideo* pBasicVideo;
3082 HRESULT hr;
3084 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3086 EnterCriticalSection(&This->cs);
3088 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3090 if (hr == S_OK)
3091 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3093 LeaveCriticalSection(&This->cs);
3095 return hr;
3098 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
3099 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3100 IBasicVideo* pBasicVideo;
3101 HRESULT hr;
3103 TRACE("(%p/%p)->()\n", This, iface);
3105 EnterCriticalSection(&This->cs);
3107 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3109 if (hr == S_OK)
3110 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3112 LeaveCriticalSection(&This->cs);
3114 return hr;
3117 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface,
3118 long *pWidth,
3119 long *pHeight) {
3120 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3121 IBasicVideo* pBasicVideo;
3122 HRESULT hr;
3124 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3126 EnterCriticalSection(&This->cs);
3128 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3130 if (hr == S_OK)
3131 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3133 LeaveCriticalSection(&This->cs);
3135 return hr;
3138 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface,
3139 long StartIndex,
3140 long Entries,
3141 long *pRetrieved,
3142 long *pPalette) {
3143 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3144 IBasicVideo* pBasicVideo;
3145 HRESULT hr;
3147 TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3149 EnterCriticalSection(&This->cs);
3151 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3153 if (hr == S_OK)
3154 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3156 LeaveCriticalSection(&This->cs);
3158 return hr;
3161 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface,
3162 long *pBufferSize,
3163 long *pDIBImage) {
3164 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3165 IBasicVideo* pBasicVideo;
3166 HRESULT hr;
3168 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3170 EnterCriticalSection(&This->cs);
3172 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3174 if (hr == S_OK)
3175 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3177 LeaveCriticalSection(&This->cs);
3179 return hr;
3182 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) {
3183 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3184 IBasicVideo* pBasicVideo;
3185 HRESULT hr;
3187 TRACE("(%p/%p)->()\n", This, iface);
3189 EnterCriticalSection(&This->cs);
3191 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3193 if (hr == S_OK)
3194 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3196 LeaveCriticalSection(&This->cs);
3198 return hr;
3201 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) {
3202 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3203 IBasicVideo* pBasicVideo;
3204 HRESULT hr;
3206 TRACE("(%p/%p)->()\n", This, iface);
3208 EnterCriticalSection(&This->cs);
3210 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3212 if (hr == S_OK)
3213 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3215 LeaveCriticalSection(&This->cs);
3217 return hr;
3221 static const IBasicVideoVtbl IBasicVideo_VTable =
3223 BasicVideo_QueryInterface,
3224 BasicVideo_AddRef,
3225 BasicVideo_Release,
3226 BasicVideo_GetTypeInfoCount,
3227 BasicVideo_GetTypeInfo,
3228 BasicVideo_GetIDsOfNames,
3229 BasicVideo_Invoke,
3230 BasicVideo_get_AvgTimePerFrame,
3231 BasicVideo_get_BitRate,
3232 BasicVideo_get_BitErrorRate,
3233 BasicVideo_get_VideoWidth,
3234 BasicVideo_get_VideoHeight,
3235 BasicVideo_put_SourceLeft,
3236 BasicVideo_get_SourceLeft,
3237 BasicVideo_put_SourceWidth,
3238 BasicVideo_get_SourceWidth,
3239 BasicVideo_put_SourceTop,
3240 BasicVideo_get_SourceTop,
3241 BasicVideo_put_SourceHeight,
3242 BasicVideo_get_SourceHeight,
3243 BasicVideo_put_DestinationLeft,
3244 BasicVideo_get_DestinationLeft,
3245 BasicVideo_put_DestinationWidth,
3246 BasicVideo_get_DestinationWidth,
3247 BasicVideo_put_DestinationTop,
3248 BasicVideo_get_DestinationTop,
3249 BasicVideo_put_DestinationHeight,
3250 BasicVideo_get_DestinationHeight,
3251 BasicVideo_SetSourcePosition,
3252 BasicVideo_GetSourcePosition,
3253 BasicVideo_SetDefaultSourcePosition,
3254 BasicVideo_SetDestinationPosition,
3255 BasicVideo_GetDestinationPosition,
3256 BasicVideo_SetDefaultDestinationPosition,
3257 BasicVideo_GetVideoSize,
3258 BasicVideo_GetVideoPaletteEntries,
3259 BasicVideo_GetCurrentImage,
3260 BasicVideo_IsUsingDefaultSource,
3261 BasicVideo_IsUsingDefaultDestination
3265 /*** IUnknown methods ***/
3266 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3267 REFIID riid,
3268 LPVOID*ppvObj) {
3269 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3271 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3273 return Filtergraph_QueryInterface(This, riid, ppvObj);
3276 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3277 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3279 TRACE("(%p/%p)->()\n", This, iface);
3281 return Filtergraph_AddRef(This);
3284 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3285 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3287 TRACE("(%p/%p)->()\n", This, iface);
3289 return Filtergraph_Release(This);
3292 /*** IDispatch methods ***/
3293 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3294 UINT*pctinfo) {
3295 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3296 IVideoWindow* pVideoWindow;
3297 HRESULT hr;
3299 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3301 EnterCriticalSection(&This->cs);
3303 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3305 if (hr == S_OK)
3306 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3308 LeaveCriticalSection(&This->cs);
3310 return hr;
3313 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3314 UINT iTInfo,
3315 LCID lcid,
3316 ITypeInfo**ppTInfo) {
3317 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3318 IVideoWindow* pVideoWindow;
3319 HRESULT hr;
3321 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3323 EnterCriticalSection(&This->cs);
3325 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3327 if (hr == S_OK)
3328 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3330 LeaveCriticalSection(&This->cs);
3332 return hr;
3335 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3336 REFIID riid,
3337 LPOLESTR*rgszNames,
3338 UINT cNames,
3339 LCID lcid,
3340 DISPID*rgDispId) {
3341 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3342 IVideoWindow* pVideoWindow;
3343 HRESULT hr;
3345 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3347 EnterCriticalSection(&This->cs);
3349 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3351 if (hr == S_OK)
3352 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3354 LeaveCriticalSection(&This->cs);
3356 return hr;
3359 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3360 DISPID dispIdMember,
3361 REFIID riid,
3362 LCID lcid,
3363 WORD wFlags,
3364 DISPPARAMS*pDispParams,
3365 VARIANT*pVarResult,
3366 EXCEPINFO*pExepInfo,
3367 UINT*puArgErr) {
3368 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3369 IVideoWindow* pVideoWindow;
3370 HRESULT hr;
3372 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);
3374 EnterCriticalSection(&This->cs);
3376 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3378 if (hr == S_OK)
3379 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3381 LeaveCriticalSection(&This->cs);
3383 return hr;
3387 /*** IVideoWindow methods ***/
3388 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3389 BSTR strCaption) {
3390 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3391 IVideoWindow* pVideoWindow;
3392 HRESULT hr;
3394 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3396 EnterCriticalSection(&This->cs);
3398 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3400 if (hr == S_OK)
3401 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3403 LeaveCriticalSection(&This->cs);
3405 return hr;
3408 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3409 BSTR *strCaption) {
3410 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3411 IVideoWindow* pVideoWindow;
3412 HRESULT hr;
3414 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3416 EnterCriticalSection(&This->cs);
3418 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3420 if (hr == S_OK)
3421 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3423 LeaveCriticalSection(&This->cs);
3425 return hr;
3428 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3429 long WindowStyle) {
3430 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3431 IVideoWindow* pVideoWindow;
3432 HRESULT hr;
3434 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3436 EnterCriticalSection(&This->cs);
3438 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3440 if (hr == S_OK)
3441 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3443 LeaveCriticalSection(&This->cs);
3445 return hr;
3448 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3449 long *WindowStyle) {
3450 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3451 IVideoWindow* pVideoWindow;
3452 HRESULT hr;
3454 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3456 EnterCriticalSection(&This->cs);
3458 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3460 if (hr == S_OK)
3461 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3463 LeaveCriticalSection(&This->cs);
3465 return hr;
3468 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3469 long WindowStyleEx) {
3470 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3471 IVideoWindow* pVideoWindow;
3472 HRESULT hr;
3474 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3476 EnterCriticalSection(&This->cs);
3478 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3480 if (hr == S_OK)
3481 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3483 LeaveCriticalSection(&This->cs);
3485 return hr;
3488 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3489 long *WindowStyleEx) {
3490 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3491 IVideoWindow* pVideoWindow;
3492 HRESULT hr;
3494 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3496 EnterCriticalSection(&This->cs);
3498 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3500 if (hr == S_OK)
3501 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
3503 LeaveCriticalSection(&This->cs);
3505 return hr;
3508 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
3509 long AutoShow) {
3510 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3511 IVideoWindow* pVideoWindow;
3512 HRESULT hr;
3514 TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
3516 EnterCriticalSection(&This->cs);
3518 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3520 if (hr == S_OK)
3521 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
3523 LeaveCriticalSection(&This->cs);
3525 return hr;
3528 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
3529 long *AutoShow) {
3530 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3531 IVideoWindow* pVideoWindow;
3532 HRESULT hr;
3534 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
3536 EnterCriticalSection(&This->cs);
3538 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3540 if (hr == S_OK)
3541 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
3543 LeaveCriticalSection(&This->cs);
3545 return hr;
3548 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
3549 long WindowState) {
3550 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3551 IVideoWindow* pVideoWindow;
3552 HRESULT hr;
3554 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
3556 EnterCriticalSection(&This->cs);
3558 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3560 if (hr == S_OK)
3561 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
3563 LeaveCriticalSection(&This->cs);
3565 return hr;
3568 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
3569 long *WindowState) {
3570 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3571 IVideoWindow* pVideoWindow;
3572 HRESULT hr;
3574 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
3576 EnterCriticalSection(&This->cs);
3578 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3580 if (hr == S_OK)
3581 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
3583 LeaveCriticalSection(&This->cs);
3585 return hr;
3588 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
3589 long BackgroundPalette) {
3590 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3591 IVideoWindow* pVideoWindow;
3592 HRESULT hr;
3594 TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
3596 EnterCriticalSection(&This->cs);
3598 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3600 if (hr == S_OK)
3601 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
3603 LeaveCriticalSection(&This->cs);
3605 return hr;
3608 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
3609 long *pBackgroundPalette) {
3610 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3611 IVideoWindow* pVideoWindow;
3612 HRESULT hr;
3614 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
3616 EnterCriticalSection(&This->cs);
3618 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3620 if (hr == S_OK)
3621 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
3623 LeaveCriticalSection(&This->cs);
3625 return hr;
3628 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
3629 long Visible) {
3630 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3631 IVideoWindow* pVideoWindow;
3632 HRESULT hr;
3634 TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
3636 EnterCriticalSection(&This->cs);
3638 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3640 if (hr == S_OK)
3641 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
3643 LeaveCriticalSection(&This->cs);
3645 return hr;
3648 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
3649 long *pVisible) {
3650 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3651 IVideoWindow* pVideoWindow;
3652 HRESULT hr;
3654 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
3656 EnterCriticalSection(&This->cs);
3658 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3660 if (hr == S_OK)
3661 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
3663 LeaveCriticalSection(&This->cs);
3665 return hr;
3668 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
3669 long Left) {
3670 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3671 IVideoWindow* pVideoWindow;
3672 HRESULT hr;
3674 TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
3676 EnterCriticalSection(&This->cs);
3678 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3680 if (hr == S_OK)
3681 hr = IVideoWindow_put_Left(pVideoWindow, Left);
3683 LeaveCriticalSection(&This->cs);
3685 return hr;
3688 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
3689 long *pLeft) {
3690 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3691 IVideoWindow* pVideoWindow;
3692 HRESULT hr;
3694 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
3696 EnterCriticalSection(&This->cs);
3698 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3700 if (hr == S_OK)
3701 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
3703 LeaveCriticalSection(&This->cs);
3705 return hr;
3708 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
3709 long Width) {
3710 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3711 IVideoWindow* pVideoWindow;
3712 HRESULT hr;
3714 TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
3716 EnterCriticalSection(&This->cs);
3718 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3720 if (hr == S_OK)
3721 hr = IVideoWindow_put_Width(pVideoWindow, Width);
3723 LeaveCriticalSection(&This->cs);
3725 return hr;
3728 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
3729 long *pWidth) {
3730 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3731 IVideoWindow* pVideoWindow;
3732 HRESULT hr;
3734 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
3736 EnterCriticalSection(&This->cs);
3738 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3740 if (hr == S_OK)
3741 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
3743 LeaveCriticalSection(&This->cs);
3745 return hr;
3748 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
3749 long Top) {
3750 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3751 IVideoWindow* pVideoWindow;
3752 HRESULT hr;
3754 TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
3756 EnterCriticalSection(&This->cs);
3758 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3760 if (hr == S_OK)
3761 hr = IVideoWindow_put_Top(pVideoWindow, Top);
3763 LeaveCriticalSection(&This->cs);
3765 return hr;
3768 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
3769 long *pTop) {
3770 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3771 IVideoWindow* pVideoWindow;
3772 HRESULT hr;
3774 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
3776 EnterCriticalSection(&This->cs);
3778 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3780 if (hr == S_OK)
3781 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
3783 LeaveCriticalSection(&This->cs);
3785 return hr;
3788 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
3789 long Height) {
3790 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3791 IVideoWindow* pVideoWindow;
3792 HRESULT hr;
3794 TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
3796 EnterCriticalSection(&This->cs);
3798 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3800 if (hr == S_OK)
3801 hr = IVideoWindow_put_Height(pVideoWindow, Height);
3803 LeaveCriticalSection(&This->cs);
3805 return hr;
3808 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
3809 long *pHeight) {
3810 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3811 IVideoWindow* pVideoWindow;
3812 HRESULT hr;
3814 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
3816 EnterCriticalSection(&This->cs);
3818 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3820 if (hr == S_OK)
3821 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
3823 LeaveCriticalSection(&This->cs);
3825 return hr;
3828 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
3829 OAHWND Owner) {
3830 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3831 IVideoWindow* pVideoWindow;
3832 HRESULT hr;
3834 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
3836 EnterCriticalSection(&This->cs);
3838 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3840 if (hr == S_OK)
3841 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
3843 LeaveCriticalSection(&This->cs);
3845 return hr;
3848 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
3849 OAHWND *Owner) {
3850 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3851 IVideoWindow* pVideoWindow;
3852 HRESULT hr;
3854 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
3856 EnterCriticalSection(&This->cs);
3858 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3860 if (hr == S_OK)
3861 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
3863 LeaveCriticalSection(&This->cs);
3865 return hr;
3868 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
3869 OAHWND Drain) {
3870 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3871 IVideoWindow* pVideoWindow;
3872 HRESULT hr;
3874 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
3876 EnterCriticalSection(&This->cs);
3878 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3880 if (hr == S_OK)
3881 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
3883 LeaveCriticalSection(&This->cs);
3885 return hr;
3888 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
3889 OAHWND *Drain) {
3890 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3891 IVideoWindow* pVideoWindow;
3892 HRESULT hr;
3894 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
3896 EnterCriticalSection(&This->cs);
3898 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3900 if (hr == S_OK)
3901 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
3903 LeaveCriticalSection(&This->cs);
3905 return hr;
3908 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
3909 long *Color) {
3910 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3911 IVideoWindow* pVideoWindow;
3912 HRESULT hr;
3914 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
3916 EnterCriticalSection(&This->cs);
3918 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3920 if (hr == S_OK)
3921 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
3923 LeaveCriticalSection(&This->cs);
3925 return hr;
3928 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
3929 long Color) {
3930 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3931 IVideoWindow* pVideoWindow;
3932 HRESULT hr;
3934 TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
3936 EnterCriticalSection(&This->cs);
3938 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3940 if (hr == S_OK)
3941 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
3943 LeaveCriticalSection(&This->cs);
3945 return hr;
3948 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
3949 long *FullScreenMode) {
3950 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3951 IVideoWindow* pVideoWindow;
3952 HRESULT hr;
3954 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
3956 EnterCriticalSection(&This->cs);
3958 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3960 if (hr == S_OK)
3961 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
3963 LeaveCriticalSection(&This->cs);
3965 return hr;
3968 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
3969 long FullScreenMode) {
3970 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3971 IVideoWindow* pVideoWindow;
3972 HRESULT hr;
3974 TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
3976 EnterCriticalSection(&This->cs);
3978 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3980 if (hr == S_OK)
3981 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
3983 LeaveCriticalSection(&This->cs);
3985 return hr;
3988 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
3989 long Focus) {
3990 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3991 IVideoWindow* pVideoWindow;
3992 HRESULT hr;
3994 TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
3996 EnterCriticalSection(&This->cs);
3998 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4000 if (hr == S_OK)
4001 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4003 LeaveCriticalSection(&This->cs);
4005 return hr;
4008 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
4009 OAHWND hwnd,
4010 long uMsg,
4011 LONG_PTR wParam,
4012 LONG_PTR lParam) {
4013 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4014 IVideoWindow* pVideoWindow;
4015 HRESULT hr;
4017 TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
4019 EnterCriticalSection(&This->cs);
4021 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4023 if (hr == S_OK)
4024 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4026 LeaveCriticalSection(&This->cs);
4028 return hr;
4031 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
4032 long Left,
4033 long Top,
4034 long Width,
4035 long Height) {
4036 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4037 IVideoWindow* pVideoWindow;
4038 HRESULT hr;
4040 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
4042 EnterCriticalSection(&This->cs);
4044 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4046 if (hr == S_OK)
4047 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4049 LeaveCriticalSection(&This->cs);
4051 return hr;
4054 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
4055 long *pLeft,
4056 long *pTop,
4057 long *pWidth,
4058 long *pHeight) {
4059 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4060 IVideoWindow* pVideoWindow;
4061 HRESULT hr;
4063 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4065 EnterCriticalSection(&This->cs);
4067 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4069 if (hr == S_OK)
4070 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4072 LeaveCriticalSection(&This->cs);
4074 return hr;
4077 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
4078 long *pWidth,
4079 long *pHeight) {
4080 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4081 IVideoWindow* pVideoWindow;
4082 HRESULT hr;
4084 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4086 EnterCriticalSection(&This->cs);
4088 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4090 if (hr == S_OK)
4091 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4093 LeaveCriticalSection(&This->cs);
4095 return hr;
4098 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
4099 long *pWidth,
4100 long *pHeight) {
4101 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4102 IVideoWindow* pVideoWindow;
4103 HRESULT hr;
4105 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4107 EnterCriticalSection(&This->cs);
4109 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4111 if (hr == S_OK)
4112 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4114 LeaveCriticalSection(&This->cs);
4116 return hr;
4119 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
4120 long *pLeft,
4121 long *pTop,
4122 long *pWidth,
4123 long *pHeight) {
4124 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4125 IVideoWindow* pVideoWindow;
4126 HRESULT hr;
4128 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4130 EnterCriticalSection(&This->cs);
4132 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4134 if (hr == S_OK)
4135 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4137 LeaveCriticalSection(&This->cs);
4139 return hr;
4142 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
4143 long HideCursor) {
4144 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4145 IVideoWindow* pVideoWindow;
4146 HRESULT hr;
4148 TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
4150 EnterCriticalSection(&This->cs);
4152 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4154 if (hr == S_OK)
4155 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4157 LeaveCriticalSection(&This->cs);
4159 return hr;
4162 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
4163 long *CursorHidden) {
4164 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4165 IVideoWindow* pVideoWindow;
4166 HRESULT hr;
4168 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4170 EnterCriticalSection(&This->cs);
4172 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4174 if (hr == S_OK)
4175 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4177 LeaveCriticalSection(&This->cs);
4179 return hr;
4183 static const IVideoWindowVtbl IVideoWindow_VTable =
4185 VideoWindow_QueryInterface,
4186 VideoWindow_AddRef,
4187 VideoWindow_Release,
4188 VideoWindow_GetTypeInfoCount,
4189 VideoWindow_GetTypeInfo,
4190 VideoWindow_GetIDsOfNames,
4191 VideoWindow_Invoke,
4192 VideoWindow_put_Caption,
4193 VideoWindow_get_Caption,
4194 VideoWindow_put_WindowStyle,
4195 VideoWindow_get_WindowStyle,
4196 VideoWindow_put_WindowStyleEx,
4197 VideoWindow_get_WindowStyleEx,
4198 VideoWindow_put_AutoShow,
4199 VideoWindow_get_AutoShow,
4200 VideoWindow_put_WindowState,
4201 VideoWindow_get_WindowState,
4202 VideoWindow_put_BackgroundPalette,
4203 VideoWindow_get_BackgroundPalette,
4204 VideoWindow_put_Visible,
4205 VideoWindow_get_Visible,
4206 VideoWindow_put_Left,
4207 VideoWindow_get_Left,
4208 VideoWindow_put_Width,
4209 VideoWindow_get_Width,
4210 VideoWindow_put_Top,
4211 VideoWindow_get_Top,
4212 VideoWindow_put_Height,
4213 VideoWindow_get_Height,
4214 VideoWindow_put_Owner,
4215 VideoWindow_get_Owner,
4216 VideoWindow_put_MessageDrain,
4217 VideoWindow_get_MessageDrain,
4218 VideoWindow_get_BorderColor,
4219 VideoWindow_put_BorderColor,
4220 VideoWindow_get_FullScreenMode,
4221 VideoWindow_put_FullScreenMode,
4222 VideoWindow_SetWindowForeground,
4223 VideoWindow_NotifyOwnerMessage,
4224 VideoWindow_SetWindowPosition,
4225 VideoWindow_GetWindowPosition,
4226 VideoWindow_GetMinIdealImageSize,
4227 VideoWindow_GetMaxIdealImageSize,
4228 VideoWindow_GetRestorePosition,
4229 VideoWindow_HideCursor,
4230 VideoWindow_IsCursorHidden
4234 /*** IUnknown methods ***/
4235 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
4236 REFIID riid,
4237 LPVOID*ppvObj) {
4238 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4240 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4242 return Filtergraph_QueryInterface(This, riid, ppvObj);
4245 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
4246 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4248 TRACE("(%p/%p)->()\n", This, iface);
4250 return Filtergraph_AddRef(This);
4253 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
4254 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4256 TRACE("(%p/%p)->()\n", This, iface);
4258 return Filtergraph_Release(This);
4261 /*** IDispatch methods ***/
4262 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4263 UINT*pctinfo) {
4264 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4266 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4268 return S_OK;
4271 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4272 UINT iTInfo,
4273 LCID lcid,
4274 ITypeInfo**ppTInfo) {
4275 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4277 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4279 return S_OK;
4282 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4283 REFIID riid,
4284 LPOLESTR*rgszNames,
4285 UINT cNames,
4286 LCID lcid,
4287 DISPID*rgDispId) {
4288 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4290 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4292 return S_OK;
4295 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4296 DISPID dispIdMember,
4297 REFIID riid,
4298 LCID lcid,
4299 WORD wFlags,
4300 DISPPARAMS*pDispParams,
4301 VARIANT*pVarResult,
4302 EXCEPINFO*pExepInfo,
4303 UINT*puArgErr) {
4304 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4306 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);
4308 return S_OK;
4311 /*** IMediaEvent methods ***/
4312 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4313 OAEVENT *hEvent) {
4314 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4316 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4318 *hEvent = (OAEVENT)This->evqueue.msg_event;
4320 return S_OK;
4323 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4324 long *lEventCode,
4325 LONG_PTR *lParam1,
4326 LONG_PTR *lParam2,
4327 long msTimeout) {
4328 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4329 Event evt;
4331 TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4333 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4335 *lEventCode = evt.lEventCode;
4336 *lParam1 = evt.lParam1;
4337 *lParam2 = evt.lParam2;
4338 return S_OK;
4341 *lEventCode = 0;
4342 return E_ABORT;
4345 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4346 long msTimeout,
4347 long *pEvCode) {
4348 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4350 TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4352 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4354 *pEvCode = This->CompletionStatus;
4355 return S_OK;
4358 *pEvCode = 0;
4359 return E_ABORT;
4362 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4363 long lEvCode) {
4364 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4366 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4368 if (lEvCode == EC_COMPLETE)
4369 This->HandleEcComplete = FALSE;
4370 else if (lEvCode == EC_REPAINT)
4371 This->HandleEcRepaint = FALSE;
4372 else if (lEvCode == EC_CLOCK_CHANGED)
4373 This->HandleEcClockChanged = FALSE;
4374 else
4375 return S_FALSE;
4377 return S_OK;
4380 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4381 long lEvCode) {
4382 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4384 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4386 if (lEvCode == EC_COMPLETE)
4387 This->HandleEcComplete = TRUE;
4388 else if (lEvCode == EC_REPAINT)
4389 This->HandleEcRepaint = TRUE;
4390 else if (lEvCode == EC_CLOCK_CHANGED)
4391 This->HandleEcClockChanged = TRUE;
4392 else
4393 return S_FALSE;
4395 return S_OK;
4398 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4399 long lEvCode,
4400 LONG_PTR lParam1,
4401 LONG_PTR lParam2) {
4402 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4404 TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4406 return S_OK;
4409 /*** IMediaEventEx methods ***/
4410 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4411 OAHWND hwnd,
4412 long lMsg,
4413 LONG_PTR lInstanceData) {
4414 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4416 TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4418 This->notif.hWnd = (HWND)hwnd;
4419 This->notif.msg = lMsg;
4420 This->notif.instance = (long) lInstanceData;
4422 return S_OK;
4425 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4426 long lNoNotifyFlags) {
4427 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4429 TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4431 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4432 return E_INVALIDARG;
4434 This->notif.disabled = lNoNotifyFlags;
4436 return S_OK;
4439 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4440 long *lplNoNotifyFlags) {
4441 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4443 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4445 if (!lplNoNotifyFlags)
4446 return E_POINTER;
4448 *lplNoNotifyFlags = This->notif.disabled;
4450 return S_OK;
4454 static const IMediaEventExVtbl IMediaEventEx_VTable =
4456 MediaEvent_QueryInterface,
4457 MediaEvent_AddRef,
4458 MediaEvent_Release,
4459 MediaEvent_GetTypeInfoCount,
4460 MediaEvent_GetTypeInfo,
4461 MediaEvent_GetIDsOfNames,
4462 MediaEvent_Invoke,
4463 MediaEvent_GetEventHandle,
4464 MediaEvent_GetEvent,
4465 MediaEvent_WaitForCompletion,
4466 MediaEvent_CancelDefaultHandling,
4467 MediaEvent_RestoreDefaultHandling,
4468 MediaEvent_FreeEventParams,
4469 MediaEvent_SetNotifyWindow,
4470 MediaEvent_SetNotifyFlags,
4471 MediaEvent_GetNotifyFlags
4475 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4477 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4479 return Filtergraph_QueryInterface(This, riid, ppv);
4482 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4484 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4486 return Filtergraph_AddRef(This);
4489 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4491 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4493 return Filtergraph_Release(This);
4496 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4498 FIXME("(%p): stub\n", pClassID);
4500 return E_NOTIMPL;
4503 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
4505 FIXME("(): stub\n");
4507 return E_NOTIMPL;
4510 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
4512 FIXME("(): stub\n");
4514 return E_NOTIMPL;
4517 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
4519 FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
4521 return E_NOTIMPL;
4524 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
4526 FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
4528 return E_NOTIMPL;
4531 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
4533 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4534 HRESULT hr = S_OK;
4535 int i;
4537 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
4539 EnterCriticalSection(&This->cs);
4541 for (i = 0;i < This->nFilters;i++)
4543 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
4544 if (FAILED(hr))
4545 break;
4548 if (FAILED(hr))
4550 for(;i >= 0;i--)
4551 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
4553 else
4555 if (This->refClock)
4556 IReferenceClock_Release(This->refClock);
4557 This->refClock = pClock;
4558 if (This->refClock)
4559 IReferenceClock_AddRef(This->refClock);
4561 if (This->HandleEcClockChanged)
4563 IMediaEventSink *pEventSink;
4564 HRESULT eshr;
4566 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
4567 if (SUCCEEDED(eshr))
4569 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
4570 IMediaEventSink_Release(pEventSink);
4575 LeaveCriticalSection(&This->cs);
4577 return hr;
4580 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
4582 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4584 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
4586 if (!ppClock)
4587 return E_POINTER;
4589 EnterCriticalSection(&This->cs);
4591 *ppClock = This->refClock;
4592 if (*ppClock)
4593 IReferenceClock_AddRef(*ppClock);
4595 LeaveCriticalSection(&This->cs);
4597 return S_OK;
4600 static const IMediaFilterVtbl IMediaFilter_VTable =
4602 MediaFilter_QueryInterface,
4603 MediaFilter_AddRef,
4604 MediaFilter_Release,
4605 MediaFilter_GetClassID,
4606 MediaFilter_Stop,
4607 MediaFilter_Pause,
4608 MediaFilter_Run,
4609 MediaFilter_GetState,
4610 MediaFilter_SetSyncSource,
4611 MediaFilter_GetSyncSource
4614 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
4616 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4618 return Filtergraph_QueryInterface(This, riid, ppv);
4621 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
4623 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4625 return Filtergraph_AddRef(This);
4628 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
4630 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4632 return Filtergraph_Release(This);
4635 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
4637 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4638 Event evt;
4640 TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
4642 /* We need thread safety here, let's use the events queue's one */
4643 EnterCriticalSection(&This->evqueue.msg_crst);
4645 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
4647 TRACE("Process EC_COMPLETE notification\n");
4648 if (++This->EcCompleteCount == This->nRenderers)
4650 evt.lEventCode = EC_COMPLETE;
4651 evt.lParam1 = S_OK;
4652 evt.lParam2 = 0;
4653 TRACE("Send EC_COMPLETE to app\n");
4654 EventsQueue_PutEvent(&This->evqueue, &evt);
4655 if (!This->notif.disabled && This->notif.hWnd)
4657 TRACE("Send Window message\n");
4658 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4660 This->CompletionStatus = EC_COMPLETE;
4661 SetEvent(This->hEventCompletion);
4664 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
4666 /* FIXME: Not handled yet */
4668 else
4670 evt.lEventCode = EventCode;
4671 evt.lParam1 = EventParam1;
4672 evt.lParam2 = EventParam2;
4673 EventsQueue_PutEvent(&This->evqueue, &evt);
4674 if (!This->notif.disabled && This->notif.hWnd)
4675 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4678 LeaveCriticalSection(&This->evqueue.msg_crst);
4679 return S_OK;
4682 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
4684 MediaEventSink_QueryInterface,
4685 MediaEventSink_AddRef,
4686 MediaEventSink_Release,
4687 MediaEventSink_Notify
4690 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
4692 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4694 return Filtergraph_QueryInterface(This, riid, ppv);
4697 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
4699 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4701 return Filtergraph_AddRef(This);
4704 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
4706 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4708 return Filtergraph_Release(This);
4711 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
4712 IPin* pOutputPin,
4713 IPin* pInputPin,
4714 const AM_MEDIA_TYPE* pmtFirstConnection,
4715 IBaseFilter* pUsingFilter,
4716 HANDLE hAbortEvent,
4717 DWORD dwFlags)
4719 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4721 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
4723 return E_NOTIMPL;
4726 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
4727 IGraphConfigCallback* pCallback,
4728 PVOID pvContext,
4729 DWORD dwFlags,
4730 HANDLE hAbortEvent)
4732 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4734 FIXME("(%p)->(%p, %p, %x, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
4736 return E_NOTIMPL;
4739 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
4740 IBaseFilter* pFilter)
4742 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4744 FIXME("(%p)->(%p): stub!\n", This, pFilter);
4746 return E_NOTIMPL;
4749 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
4750 IEnumFilters** pEnum)
4752 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4754 FIXME("(%p)->(%p): stub!\n", This, pEnum);
4756 return E_NOTIMPL;
4759 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
4760 IBaseFilter* pFilter)
4762 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4764 FIXME("(%p)->(%p): stub!\n", This, pFilter);
4766 return E_NOTIMPL;
4769 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
4770 REFERENCE_TIME* prtStart)
4772 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4774 FIXME("(%p)->(%p): stub!\n", This, prtStart);
4776 return E_NOTIMPL;
4779 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
4780 IPin* pOutputPin,
4781 IPinConnection* pConnection,
4782 HANDLE hEventAbort)
4784 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4786 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
4788 return E_NOTIMPL;
4791 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
4792 IBaseFilter* pFilter,
4793 DWORD dwFlags)
4795 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4797 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4799 return E_NOTIMPL;
4802 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
4803 IBaseFilter* pFilter,
4804 DWORD* dwFlags)
4806 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4808 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
4810 return E_NOTIMPL;
4813 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
4814 IBaseFilter* pFilter,
4815 DWORD dwFlags)
4817 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4819 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4821 return E_NOTIMPL;
4824 static const IGraphConfigVtbl IGraphConfig_VTable =
4826 GraphConfig_QueryInterface,
4827 GraphConfig_AddRef,
4828 GraphConfig_Release,
4829 GraphConfig_Reconnect,
4830 GraphConfig_Reconfigure,
4831 GraphConfig_AddFilterToCache,
4832 GraphConfig_EnumCacheFilter,
4833 GraphConfig_RemoveFilterFromCache,
4834 GraphConfig_GetStartTime,
4835 GraphConfig_PushThroughData,
4836 GraphConfig_SetFilterFlags,
4837 GraphConfig_GetFilterFlags,
4838 GraphConfig_RemoveFilterEx
4841 static const IUnknownVtbl IInner_VTable =
4843 FilterGraphInner_QueryInterface,
4844 FilterGraphInner_AddRef,
4845 FilterGraphInner_Release
4848 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
4849 REFIID riid,
4850 LPVOID * ppv) {
4851 if (This->bAggregatable)
4852 This->bUnkOuterValid = TRUE;
4854 if (This->pUnkOuter)
4856 if (This->bAggregatable)
4857 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
4859 if (IsEqualIID(riid, &IID_IUnknown))
4861 HRESULT hr;
4863 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4864 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4865 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4866 This->bAggregatable = TRUE;
4867 return hr;
4870 *ppv = NULL;
4871 return E_NOINTERFACE;
4874 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4877 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This) {
4878 if (This->pUnkOuter && This->bUnkOuterValid)
4879 return IUnknown_AddRef(This->pUnkOuter);
4880 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4883 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This) {
4884 if (This->pUnkOuter && This->bUnkOuterValid)
4885 return IUnknown_Release(This->pUnkOuter);
4886 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4889 /* This is the only function that actually creates a FilterGraph class... */
4890 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4892 IFilterGraphImpl *fimpl;
4893 HRESULT hr;
4895 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
4897 *ppObj = NULL;
4899 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
4900 fimpl->pUnkOuter = pUnkOuter;
4901 fimpl->bUnkOuterValid = FALSE;
4902 fimpl->bAggregatable = FALSE;
4903 fimpl->IInner_vtbl = &IInner_VTable;
4904 fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable;
4905 fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
4906 fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
4907 fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
4908 fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
4909 fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
4910 fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
4911 fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
4912 fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
4913 fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
4914 fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
4915 fimpl->ref = 1;
4916 fimpl->ppFiltersInGraph = NULL;
4917 fimpl->pFilterNames = NULL;
4918 fimpl->nFilters = 0;
4919 fimpl->filterCapacity = 0;
4920 fimpl->nameIndex = 1;
4921 fimpl->refClock = NULL;
4922 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
4923 fimpl->HandleEcComplete = TRUE;
4924 fimpl->HandleEcRepaint = TRUE;
4925 fimpl->HandleEcClockChanged = TRUE;
4926 fimpl->notif.hWnd = 0;
4927 fimpl->notif.disabled = FALSE;
4928 fimpl->nRenderers = 0;
4929 fimpl->EcCompleteCount = 0;
4930 fimpl->state = State_Stopped;
4931 EventsQueue_Init(&fimpl->evqueue);
4932 InitializeCriticalSection(&fimpl->cs);
4933 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
4934 fimpl->nItfCacheEntries = 0;
4935 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
4937 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
4938 if (FAILED(hr)) {
4939 ERR("Unable to create filter mapper (%x)\n", hr);
4940 return hr;
4942 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
4944 *ppObj = fimpl;
4945 return S_OK;
4948 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4950 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
4951 return FilterGraph_create(pUnkOuter, ppObj);