push 0661da64275a0e67e1a41492b8d7716e364e773c
[wine/hacks.git] / dlls / quartz / filtergraph.c
blobc53771edef531eccc1f6a0bd1c77e1adfa028695
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 "winreg.h"
33 #include "shlwapi.h"
34 #include "dshow.h"
35 #include "wine/debug.h"
36 #include "quartz_private.h"
37 #include "ole2.h"
38 #include "olectl.h"
39 #include "strmif.h"
40 #include "vfwmsgs.h"
41 #include "evcode.h"
42 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
47 typedef struct {
48 HWND hWnd; /* Target window */
49 long msg; /* User window message */
50 long instance; /* User data */
51 int disabled; /* Disabled messages posting */
52 } WndNotify;
54 typedef struct {
55 long lEventCode; /* Event code */
56 LONG_PTR lParam1; /* Param1 */
57 LONG_PTR lParam2; /* Param2 */
58 } Event;
60 /* messages ring implementation for queuing events (taken from winmm) */
61 #define EVENTS_RING_BUFFER_INCREMENT 64
62 typedef struct {
63 Event* messages;
64 int ring_buffer_size;
65 int msg_tosave;
66 int msg_toget;
67 CRITICAL_SECTION msg_crst;
68 HANDLE msg_event; /* Signaled for no empty queue */
69 } EventsQueue;
71 static int EventsQueue_Init(EventsQueue* omr)
73 omr->msg_toget = 0;
74 omr->msg_tosave = 0;
75 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
76 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
77 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
78 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
80 InitializeCriticalSection(&omr->msg_crst);
81 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
82 return TRUE;
85 static int EventsQueue_Destroy(EventsQueue* omr)
87 CloseHandle(omr->msg_event);
88 CoTaskMemFree(omr->messages);
89 omr->msg_crst.DebugInfo->Spare[0] = 0;
90 DeleteCriticalSection(&omr->msg_crst);
91 return TRUE;
94 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
96 EnterCriticalSection(&omr->msg_crst);
97 if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
99 int old_ring_buffer_size = omr->ring_buffer_size;
100 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
101 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
102 omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
103 /* Now we need to rearrange the ring buffer so that the new
104 buffers just allocated are in between omr->msg_tosave and
105 omr->msg_toget.
107 if (omr->msg_tosave < omr->msg_toget)
109 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
110 &(omr->messages[omr->msg_toget]),
111 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
113 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
116 omr->messages[omr->msg_tosave] = *evt;
117 SetEvent(omr->msg_event);
118 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
119 LeaveCriticalSection(&omr->msg_crst);
120 return TRUE;
123 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
125 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
126 return FALSE;
128 EnterCriticalSection(&omr->msg_crst);
130 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
132 LeaveCriticalSection(&omr->msg_crst);
133 return FALSE;
136 *evt = omr->messages[omr->msg_toget];
137 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
139 /* Mark the buffer as empty if needed */
140 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
141 ResetEvent(omr->msg_event);
143 LeaveCriticalSection(&omr->msg_crst);
144 return TRUE;
147 #define MAX_ITF_CACHE_ENTRIES 3
148 typedef struct _ITF_CACHE_ENTRY {
149 const IID* riid;
150 IBaseFilter* filter;
151 IUnknown* iface;
152 } ITF_CACHE_ENTRY;
154 typedef struct _IFilterGraphImpl {
155 const IFilterGraph2Vtbl *IFilterGraph2_vtbl;
156 const IMediaControlVtbl *IMediaControl_vtbl;
157 const IMediaSeekingVtbl *IMediaSeeking_vtbl;
158 const IBasicAudioVtbl *IBasicAudio_vtbl;
159 const IBasicVideo2Vtbl *IBasicVideo_vtbl;
160 const IVideoWindowVtbl *IVideoWindow_vtbl;
161 const IMediaEventExVtbl *IMediaEventEx_vtbl;
162 const IMediaFilterVtbl *IMediaFilter_vtbl;
163 const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
164 const IGraphConfigVtbl *IGraphConfig_vtbl;
165 const IMediaPositionVtbl *IMediaPosition_vtbl;
166 const IUnknownVtbl * IInner_vtbl;
167 /* IAMGraphStreams */
168 /* IAMStats */
169 /* IFilterChain */
170 /* IFilterMapper2 */
171 /* IGraphVersion */
172 /* IQueueCommand */
173 /* IRegisterServiceProvider */
174 /* IResourceMananger */
175 /* IServiceProvider */
176 /* IVideoFrameStep */
178 LONG ref;
179 IUnknown *punkFilterMapper2;
180 IFilterMapper2 * pFilterMapper2;
181 IBaseFilter ** ppFiltersInGraph;
182 LPWSTR * pFilterNames;
183 int nFilters;
184 int filterCapacity;
185 long nameIndex;
186 IReferenceClock *refClock;
187 EventsQueue evqueue;
188 HANDLE hEventCompletion;
189 int CompletionStatus;
190 WndNotify notif;
191 int nRenderers;
192 int EcCompleteCount;
193 int HandleEcComplete;
194 int HandleEcRepaint;
195 int HandleEcClockChanged;
196 OAFilterState state;
197 CRITICAL_SECTION cs;
198 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
199 int nItfCacheEntries;
200 IUnknown * pUnkOuter;
201 BOOL bUnkOuterValid;
202 BOOL bAggregatable;
203 GUID timeformatseek;
204 LONGLONG start_time;
205 LONGLONG position;
206 LONGLONG stop_position;
207 LONG recursioncount;
208 } IFilterGraphImpl;
210 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
211 REFIID riid, LPVOID * ppv);
212 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This);
213 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This);
215 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
216 REFIID riid,
217 LPVOID *ppvObj) {
218 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
219 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
221 if (This->bAggregatable)
222 This->bUnkOuterValid = TRUE;
224 if (IsEqualGUID(&IID_IUnknown, riid)) {
225 *ppvObj = &(This->IInner_vtbl);
226 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
227 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
228 IsEqualGUID(&IID_IFilterGraph2, riid) ||
229 IsEqualGUID(&IID_IGraphBuilder, riid)) {
230 *ppvObj = &(This->IFilterGraph2_vtbl);
231 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
232 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
233 *ppvObj = &(This->IMediaControl_vtbl);
234 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
235 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
236 *ppvObj = &(This->IMediaSeeking_vtbl);
237 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
238 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
239 *ppvObj = &(This->IBasicAudio_vtbl);
240 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
241 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
242 IsEqualGUID(&IID_IBasicVideo2, riid)) {
243 *ppvObj = &(This->IBasicVideo_vtbl);
244 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
245 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
246 *ppvObj = &(This->IVideoWindow_vtbl);
247 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
248 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
249 IsEqualGUID(&IID_IMediaEventEx, riid)) {
250 *ppvObj = &(This->IMediaEventEx_vtbl);
251 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
252 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
253 IsEqualGUID(&IID_IPersist, riid)) {
254 *ppvObj = &(This->IMediaFilter_vtbl);
255 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
256 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
257 *ppvObj = &(This->IMediaEventSink_vtbl);
258 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
259 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
260 *ppvObj = &(This->IGraphConfig_vtbl);
261 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
262 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
263 *ppvObj = &(This->IMediaPosition_vtbl);
264 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
265 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
266 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
267 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
268 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
269 *ppvObj = This->pFilterMapper2;
270 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
271 } else {
272 *ppvObj = NULL;
273 FIXME("unknown interface %s\n", debugstr_guid(riid));
274 return E_NOINTERFACE;
277 IUnknown_AddRef((IUnknown *)(*ppvObj));
278 return S_OK;
281 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) {
282 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
283 ULONG ref = InterlockedIncrement(&This->ref);
285 TRACE("(%p)->(): new ref = %d\n", This, ref);
287 return ref;
290 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface)
292 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface);
293 ULONG ref = InterlockedDecrement(&This->ref);
295 TRACE("(%p)->(): new ref = %d\n", This, ref);
297 if (ref == 0) {
298 int i;
300 This->ref = 1; /* guard against reentrancy (aggregation). */
302 IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl));
304 while (This->nFilters)
305 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]);
307 if (This->refClock)
308 IReferenceClock_Release(This->refClock);
310 for (i = 0; i < This->nItfCacheEntries; i++)
312 if (This->ItfCacheEntries[i].iface)
313 IUnknown_Release(This->ItfCacheEntries[i].iface);
316 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 interface below.
318 * NOTE: Filtergraph_AddRef isn't suitable, because bUnkOuterValid may be FALSE but punkOuter non-NULL
319 * and already passed as punkOuter to filtermapper in FilterGraph_create - this will happen in case of
320 * CoCreateInstance of filtergraph with non-null pUnkOuter and REFIID other than IID_Unknown that is
321 * cleaning up after error. */
322 if (This->pUnkOuter) IUnknown_AddRef(This->pUnkOuter);
323 else IUnknown_AddRef((IUnknown*)&This->IInner_vtbl);
325 IFilterMapper2_Release(This->pFilterMapper2);
326 IUnknown_Release(This->punkFilterMapper2);
328 CloseHandle(This->hEventCompletion);
329 EventsQueue_Destroy(&This->evqueue);
330 This->cs.DebugInfo->Spare[0] = 0;
331 DeleteCriticalSection(&This->cs);
332 CoTaskMemFree(This->ppFiltersInGraph);
333 CoTaskMemFree(This->pFilterNames);
334 CoTaskMemFree(This);
336 return ref;
340 /*** IUnknown methods ***/
341 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface,
342 REFIID riid,
343 LPVOID*ppvObj) {
344 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
346 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
347 return Filtergraph_QueryInterface(This, riid, ppvObj);
350 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) {
351 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
353 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
355 return Filtergraph_AddRef(This);
358 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) {
359 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
361 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
363 return Filtergraph_Release(This);
366 /*** IFilterGraph methods ***/
367 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
368 IBaseFilter *pFilter,
369 LPCWSTR pName) {
370 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
371 HRESULT hr;
372 int i,j;
373 WCHAR* wszFilterName = NULL;
374 int duplicate_name = FALSE;
376 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
378 if (!pFilter)
379 return E_POINTER;
381 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
383 if (pName)
385 /* Check if name already exists */
386 for(i = 0; i < This->nFilters; i++)
387 if (!strcmpW(This->pFilterNames[i], pName))
389 duplicate_name = TRUE;
390 break;
394 /* If no name given or name already existing, generate one */
395 if (!pName || duplicate_name)
397 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
398 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
400 for (j = 0; j < 10000 ; j++)
402 /* Create name */
403 if (pName)
404 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
405 else
406 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
407 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
409 /* Check if the generated name already exists */
410 for(i = 0; i < This->nFilters; i++)
411 if (!strcmpW(This->pFilterNames[i], wszFilterName))
412 break;
414 /* Compute next index and exit if generated name is suitable */
415 if (This->nameIndex++ == 10000)
416 This->nameIndex = 1;
417 if (i == This->nFilters)
418 break;
420 /* Unable to find a suitable name */
421 if (j == 10000)
423 CoTaskMemFree(wszFilterName);
424 return VFW_E_DUPLICATE_NAME;
427 else
428 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
430 if (This->nFilters + 1 > This->filterCapacity)
432 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
433 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
434 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
435 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
436 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
437 if (This->filterCapacity)
439 CoTaskMemFree(This->ppFiltersInGraph);
440 CoTaskMemFree(This->pFilterNames);
442 This->ppFiltersInGraph = ppNewFilters;
443 This->pFilterNames = pNewNames;
444 This->filterCapacity = newCapacity;
447 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
449 if (SUCCEEDED(hr))
451 IBaseFilter_AddRef(pFilter);
452 This->ppFiltersInGraph[This->nFilters] = pFilter;
453 This->pFilterNames[This->nFilters] = wszFilterName;
454 This->nFilters++;
455 IBaseFilter_SetSyncSource(pFilter, This->refClock);
457 else
458 CoTaskMemFree(wszFilterName);
460 if (SUCCEEDED(hr) && duplicate_name)
461 return VFW_S_DUPLICATE_NAME;
463 return hr;
466 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
468 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
469 int i;
470 HRESULT hr = E_FAIL;
472 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
474 /* FIXME: check graph is stopped */
476 for (i = 0; i < This->nFilters; i++)
478 if (This->ppFiltersInGraph[i] == pFilter)
480 IEnumPins *penumpins = NULL;
481 FILTER_STATE state;
483 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
484 IBaseFilter_GetState(pFilter, 0, &state);
485 if (state == State_Running)
486 IBaseFilter_Pause(pFilter);
487 if (state != State_Stopped)
488 IBaseFilter_Stop(pFilter);
490 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
491 if (SUCCEEDED(hr)) {
492 IPin *ppin;
493 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
495 IPin *victim = NULL;
496 HRESULT h;
497 IPin_ConnectedTo(ppin, &victim);
498 if (victim)
500 h = IPin_Disconnect(victim);
501 TRACE("Disconnect other side: %08x\n", h);
502 if (h == VFW_E_NOT_STOPPED)
504 PIN_INFO pinfo;
505 IPin_QueryPinInfo(victim, &pinfo);
507 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
508 if (state == State_Running)
509 IBaseFilter_Pause(pinfo.pFilter);
510 IBaseFilter_Stop(pinfo.pFilter);
511 IBaseFilter_Release(pinfo.pFilter);
512 h = IPin_Disconnect(victim);
513 TRACE("Disconnect retry: %08x\n", h);
515 IPin_Release(victim);
517 h = IPin_Disconnect(ppin);
518 TRACE("Disconnect 2: %08x\n", h);
520 IPin_Release(ppin);
522 IEnumPins_Release(penumpins);
525 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
526 if (SUCCEEDED(hr))
528 IBaseFilter_SetSyncSource(pFilter, NULL);
529 IBaseFilter_Release(pFilter);
530 CoTaskMemFree(This->pFilterNames[i]);
531 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
532 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
533 This->nFilters--;
534 /* Invalidate interfaces in the cache */
535 for (i = 0; i < This->nItfCacheEntries; i++)
536 if (pFilter == This->ItfCacheEntries[i].filter)
538 IUnknown_Release(This->ItfCacheEntries[i].iface);
539 This->ItfCacheEntries[i].iface = NULL;
540 This->ItfCacheEntries[i].filter = NULL;
542 return S_OK;
544 break;
548 return hr; /* FIXME: check this error code */
551 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface,
552 IEnumFilters **ppEnum) {
553 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
555 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
557 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
560 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
561 LPCWSTR pName,
562 IBaseFilter **ppFilter) {
563 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
564 int i;
566 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
568 if (!ppFilter)
569 return E_POINTER;
571 for (i = 0; i < This->nFilters; i++)
573 if (!strcmpW(pName, This->pFilterNames[i]))
575 *ppFilter = This->ppFiltersInGraph[i];
576 IBaseFilter_AddRef(*ppFilter);
577 return S_OK;
581 *ppFilter = NULL;
582 return VFW_E_NOT_FOUND;
585 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
586 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
588 static HRESULT WINAPI CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
590 #if 1
591 HRESULT hr;
592 PIN_INFO info_out, info_in;
594 hr = IPin_QueryPinInfo(out, &info_out);
595 if (FAILED(hr))
596 return hr;
597 if (info_out.dir != PINDIR_OUTPUT)
599 IBaseFilter_Release(info_out.pFilter);
600 return E_UNEXPECTED;
603 hr = IPin_QueryPinInfo(in, &info_in);
604 if (SUCCEEDED(hr))
605 IBaseFilter_Release(info_in.pFilter);
606 if (FAILED(hr))
607 goto out;
608 if (info_in.dir != PINDIR_INPUT)
610 hr = E_UNEXPECTED;
611 goto out;
614 if (info_out.pFilter == info_in.pFilter)
615 hr = VFW_E_CIRCULAR_GRAPH;
616 else
618 IEnumPins *enumpins;
619 IPin *test;
621 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
622 if (FAILED(hr))
623 goto out;
625 IEnumPins_Reset(enumpins);
626 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
628 PIN_DIRECTION dir = PINDIR_OUTPUT;
629 IPin_QueryDirection(test, &dir);
630 if (dir == PINDIR_INPUT)
632 IPin *victim = NULL;
633 IPin_ConnectedTo(test, &victim);
634 if (victim)
636 hr = CheckCircularConnection(This, victim, in);
637 IPin_Release(victim);
638 if (FAILED(hr))
640 IPin_Release(test);
641 break;
645 IPin_Release(test);
647 IEnumPins_Release(enumpins);
650 out:
651 IBaseFilter_Release(info_out.pFilter);
652 if (FAILED(hr))
653 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
654 return hr;
655 #else
656 /* Debugging filtergraphs not enabled */
657 return S_OK;
658 #endif
662 /* NOTE: despite the implication, it doesn't matter which
663 * way round you put in the input and output pins */
664 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface,
665 IPin *ppinIn,
666 IPin *ppinOut,
667 const AM_MEDIA_TYPE *pmt) {
668 PIN_DIRECTION dir;
669 HRESULT hr;
671 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
673 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
675 /* FIXME: check pins are in graph */
677 if (TRACE_ON(quartz))
679 PIN_INFO PinInfo;
681 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
682 if (FAILED(hr))
683 return hr;
685 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
686 IBaseFilter_Release(PinInfo.pFilter);
688 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
689 if (FAILED(hr))
690 return hr;
692 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
693 IBaseFilter_Release(PinInfo.pFilter);
696 hr = IPin_QueryDirection(ppinIn, &dir);
697 if (SUCCEEDED(hr))
699 if (dir == PINDIR_INPUT)
701 hr = CheckCircularConnection(This, ppinOut, ppinIn);
702 if (SUCCEEDED(hr))
703 hr = IPin_Connect(ppinOut, ppinIn, pmt);
705 else
707 hr = CheckCircularConnection(This, ppinIn, ppinOut);
708 if (SUCCEEDED(hr))
709 hr = IPin_Connect(ppinIn, ppinOut, pmt);
713 return hr;
716 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface,
717 IPin *ppin) {
718 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
719 IPin *pConnectedTo = NULL;
720 HRESULT hr;
721 PIN_DIRECTION pindir;
723 IPin_QueryDirection(ppin, &pindir);
724 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
725 if (FAILED(hr)) {
726 TRACE("Querying connected to failed: %x\n", hr);
727 return hr;
729 IPin_Disconnect(ppin);
730 IPin_Disconnect(pConnectedTo);
731 if (pindir == PINDIR_INPUT)
732 hr = IPin_Connect(pConnectedTo, ppin, NULL);
733 else
734 hr = IPin_Connect(ppin, pConnectedTo, NULL);
735 IPin_Release(pConnectedTo);
736 if (FAILED(hr))
737 WARN("Reconnecting pins failed, pins are not connected now..\n");
738 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
739 return hr;
742 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
744 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
746 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
748 if (!ppin)
749 return E_POINTER;
751 return IPin_Disconnect(ppin);
754 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) {
755 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
756 IReferenceClock *pClock = NULL;
757 HRESULT hr;
759 TRACE("(%p/%p)->() semi-stub\n", iface, This);
761 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
763 if (SUCCEEDED(hr))
765 hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock);
766 IReferenceClock_Release(pClock);
769 return hr;
772 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
774 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
775 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
776 IPropertyBag * pPropBagCat = NULL;
777 HRESULT hr;
779 VariantInit(pvar);
781 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
783 if (SUCCEEDED(hr))
784 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
786 if (SUCCEEDED(hr))
787 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
789 VariantClear(pvar);
791 if (SUCCEEDED(hr))
792 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
794 if (SUCCEEDED(hr))
795 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
797 if (pPropBagCat)
798 IPropertyBag_Release(pPropBagCat);
800 return hr;
803 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
805 HRESULT hr;
806 ULONG nb = 0;
808 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
809 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
810 if (hr == S_OK) {
811 /* Rendered input */
812 } else if (hr == S_FALSE) {
813 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
814 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
815 if (hr != S_OK) {
816 WARN("Error (%x)\n", hr);
818 } else if (hr == E_NOTIMPL) {
819 /* Input connected to all outputs */
820 IEnumPins* penumpins;
821 IPin* ppin;
822 int i = 0;
823 TRACE("E_NOTIMPL\n");
824 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
825 if (FAILED(hr)) {
826 WARN("filter Enumpins failed (%x)\n", hr);
827 return hr;
829 i = 0;
830 /* Count output pins */
831 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
832 PIN_DIRECTION pindir;
833 IPin_QueryDirection(ppin, &pindir);
834 if (pindir == PINDIR_OUTPUT)
835 i++;
836 IPin_Release(ppin);
838 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
839 /* Retrieve output pins */
840 IEnumPins_Reset(penumpins);
841 i = 0;
842 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
843 PIN_DIRECTION pindir;
844 IPin_QueryDirection(ppin, &pindir);
845 if (pindir == PINDIR_OUTPUT)
846 (*pppins)[i++] = ppin;
847 else
848 IPin_Release(ppin);
850 IEnumPins_Release(penumpins);
851 nb = i;
852 if (FAILED(hr)) {
853 WARN("Next failed (%x)\n", hr);
854 return hr;
856 } else if (FAILED(hr)) {
857 WARN("Cannot get internal connection (%x)\n", hr);
858 return hr;
861 *pnb = nb;
862 return S_OK;
865 /*** IGraphBuilder methods ***/
866 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
868 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
869 HRESULT hr;
870 AM_MEDIA_TYPE* mt;
871 IEnumMediaTypes* penummt;
872 ULONG nbmt;
873 IEnumPins* penumpins;
874 IEnumMoniker* pEnumMoniker;
875 GUID tab[2];
876 ULONG nb;
877 IMoniker* pMoniker;
878 ULONG pin;
879 PIN_INFO PinInfo;
880 CLSID FilterCLSID;
881 PIN_DIRECTION dir;
883 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
885 if (TRACE_ON(quartz))
887 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
888 if (FAILED(hr))
889 return hr;
891 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
892 IBaseFilter_Release(PinInfo.pFilter);
894 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
895 if (FAILED(hr))
896 return hr;
898 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
899 IBaseFilter_Release(PinInfo.pFilter);
902 EnterCriticalSection(&This->cs);
903 ++This->recursioncount;
904 if (This->recursioncount >= 5)
906 WARN("Recursion count has reached %d\n", This->recursioncount);
907 hr = VFW_E_CANNOT_CONNECT;
908 goto out;
911 hr = IPin_QueryDirection(ppinOut, &dir);
912 if (FAILED(hr))
913 goto out;
915 if (dir == PINDIR_INPUT)
917 IPin *temp;
919 temp = ppinIn;
920 ppinIn = ppinOut;
921 ppinOut = temp;
924 hr = CheckCircularConnection(This, ppinOut, ppinIn);
925 if (FAILED(hr))
926 goto out;
928 /* Try direct connection first */
929 hr = IPin_Connect(ppinOut, ppinIn, NULL);
930 if (SUCCEEDED(hr))
931 goto out;
933 TRACE("Direct connection failed, trying to render using extra filters\n");
935 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
936 if (FAILED(hr))
937 goto out;
939 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
940 IBaseFilter_Release(PinInfo.pFilter);
941 if (FAILED(hr))
942 goto out;
944 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
945 * filter to the minor mediatype of input pin of the renderer */
946 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
947 if (FAILED(hr))
949 WARN("EnumMediaTypes (%x)\n", hr);
950 goto out;
953 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
954 if (FAILED(hr)) {
955 WARN("IEnumMediaTypes_Next (%x)\n", hr);
956 goto out;
959 if (!nbmt)
961 WARN("No media type found!\n");
962 hr = VFW_E_INVALIDMEDIATYPE;
963 goto out;
965 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
966 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
968 /* Try to find a suitable filter that can connect to the pin to render */
969 tab[0] = mt->majortype;
970 tab[1] = mt->subtype;
971 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
972 if (FAILED(hr)) {
973 WARN("Unable to enum filters (%x)\n", hr);
974 goto out;
977 hr = VFW_E_CANNOT_RENDER;
978 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
980 VARIANT var;
981 GUID clsid;
982 IPin** ppins;
983 IPin* ppinfilter = NULL;
984 IBaseFilter* pfilter = NULL;
986 hr = GetFilterInfo(pMoniker, &clsid, &var);
987 IMoniker_Release(pMoniker);
988 if (FAILED(hr)) {
989 WARN("Unable to retrieve filter info (%x)\n", hr);
990 goto error;
993 if (IsEqualGUID(&clsid, &FilterCLSID)) {
994 /* Skip filter (same as the one the output pin belongs to) */
995 goto error;
998 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
999 if (FAILED(hr)) {
1000 WARN("Unable to create filter (%x), trying next one\n", hr);
1001 goto error;
1004 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1005 if (FAILED(hr)) {
1006 WARN("Unable to add filter (%x)\n", hr);
1007 IBaseFilter_Release(pfilter);
1008 pfilter = NULL;
1009 goto error;
1012 VariantClear(&var);
1014 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1015 if (FAILED(hr)) {
1016 WARN("Enumpins (%x)\n", hr);
1017 goto error;
1020 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1021 IEnumPins_Release(penumpins);
1023 if (FAILED(hr)) {
1024 WARN("Obtaining next pin: (%x)\n", hr);
1025 goto error;
1027 if (pin == 0) {
1028 WARN("Cannot use this filter: no pins\n");
1029 goto error;
1032 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1033 if (FAILED(hr)) {
1034 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1035 goto error;
1037 TRACE("Successfully connected to filter, follow chain...\n");
1039 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
1040 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1042 if (SUCCEEDED(hr)) {
1043 unsigned int i;
1044 if (nb == 0) {
1045 IPin_Disconnect(ppinfilter);
1046 IPin_Disconnect(ppinOut);
1047 goto error;
1049 TRACE("pins to consider: %d\n", nb);
1050 for(i = 0; i < nb; i++)
1052 LPWSTR pinname = NULL;
1054 TRACE("Processing pin %u\n", i);
1056 hr = IPin_QueryId(ppins[i], &pinname);
1057 if (SUCCEEDED(hr))
1059 if (pinname[0] == '~')
1061 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1062 hr = E_FAIL;
1064 else
1065 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1066 CoTaskMemFree(pinname);
1069 if (FAILED(hr)) {
1070 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1072 IPin_Release(ppins[i]);
1073 if (SUCCEEDED(hr)) break;
1075 while (++i < nb) IPin_Release(ppins[i]);
1076 CoTaskMemFree(ppins);
1077 IPin_Release(ppinfilter);
1078 IBaseFilter_Release(pfilter);
1079 if (FAILED(hr))
1081 IPin_Disconnect(ppinfilter);
1082 IPin_Disconnect(ppinOut);
1083 IFilterGraph2_RemoveFilter(iface, pfilter);
1084 continue;
1086 break;
1089 error:
1090 VariantClear(&var);
1091 if (ppinfilter) IPin_Release(ppinfilter);
1092 if (pfilter) {
1093 IFilterGraph2_RemoveFilter(iface, pfilter);
1094 IBaseFilter_Release(pfilter);
1098 IEnumMediaTypes_Release(penummt);
1099 DeleteMediaType(mt);
1101 out:
1102 --This->recursioncount;
1103 LeaveCriticalSection(&This->cs);
1104 TRACE("--> %08x\n", hr);
1105 return SUCCEEDED(hr) ? S_OK : hr;
1108 static HRESULT WINAPI FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1110 /* This pin has been connected now, try to call render on all pins that aren't connected */
1111 IPin *to = NULL;
1112 PIN_INFO info;
1113 IEnumPins *enumpins = NULL;
1114 BOOL renderany = FALSE;
1115 BOOL renderall = TRUE;
1117 IPin_QueryPinInfo(ppinOut, &info);
1119 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1120 /* Don't need to hold a reference, IEnumPins does */
1121 IBaseFilter_Release(info.pFilter);
1123 IEnumPins_Reset(enumpins);
1124 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1126 PIN_DIRECTION dir = PINDIR_INPUT;
1128 IPin_QueryDirection(to, &dir);
1130 if (dir == PINDIR_OUTPUT)
1132 IPin *out = NULL;
1134 IPin_ConnectedTo(to, &out);
1135 if (!out)
1137 HRESULT hr;
1138 hr = IFilterGraph2_Render((IFilterGraph2 *)&This->IFilterGraph2_vtbl, to);
1139 if (SUCCEEDED(hr))
1140 renderany = TRUE;
1141 else
1142 renderall = FALSE;
1144 else
1145 IPin_Release(out);
1148 IPin_Release(to);
1151 IEnumPins_Release(enumpins);
1153 if (renderall)
1154 return S_OK;
1156 if (renderany)
1157 return VFW_S_PARTIAL_RENDER;
1159 return VFW_E_CANNOT_RENDER;
1162 /* Ogg hates me if I create a direct rendering method
1164 * It can only connect to a pin properly once, so use a recursive method that does
1166 * +----+ --- (PIN 1) (Render is called on this pin)
1167 * | |
1168 * +----+ --- (PIN 2)
1170 * Enumerate possible renderers that EXACTLY match the requested type
1172 * If none is available, try to add intermediate filters that can connect to the input pin
1173 * then call Render on that intermediate pin's output pins
1174 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1175 * and another filter that can connect to the input pin is tried
1176 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1177 * It's recursive, but fun!
1180 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1182 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1183 IEnumMediaTypes* penummt;
1184 AM_MEDIA_TYPE* mt;
1185 ULONG nbmt;
1186 HRESULT hr;
1188 IEnumMoniker* pEnumMoniker;
1189 GUID tab[4];
1190 ULONG nb;
1191 IMoniker* pMoniker;
1192 INT x;
1194 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1196 if (TRACE_ON(quartz))
1198 PIN_INFO PinInfo;
1200 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1201 if (FAILED(hr))
1202 return hr;
1204 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1205 IBaseFilter_Release(PinInfo.pFilter);
1208 /* Try to find out if there is a renderer for the specified subtype already, and use that
1210 EnterCriticalSection(&This->cs);
1211 for (x = 0; x < This->nFilters; ++x)
1213 IEnumPins *enumpins = NULL;
1214 IPin *pin = NULL;
1216 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1218 if (FAILED(hr) || !enumpins)
1219 continue;
1221 IEnumPins_Reset(enumpins);
1222 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1224 IPin *to = NULL;
1225 PIN_DIRECTION dir = PINDIR_OUTPUT;
1227 IPin_QueryDirection(pin, &dir);
1228 if (dir != PINDIR_INPUT)
1230 IPin_Release(pin);
1231 continue;
1233 IPin_ConnectedTo(pin, &to);
1235 if (to == NULL)
1237 hr = IPin_Connect(ppinOut, pin, NULL);
1238 if (SUCCEEDED(hr))
1240 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1241 IPin_Release(pin);
1243 hr = FilterGraph2_RenderRecurse(This, pin);
1244 if (FAILED(hr))
1246 IPin_Disconnect(ppinOut);
1247 IPin_Disconnect(pin);
1248 continue;
1250 IEnumPins_Release(enumpins);
1251 LeaveCriticalSection(&This->cs);
1252 return hr;
1254 WARN("Could not connect!\n");
1256 else
1257 IPin_Release(to);
1259 IPin_Release(pin);
1261 IEnumPins_Release(enumpins);
1264 LeaveCriticalSection(&This->cs);
1266 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1267 if (FAILED(hr)) {
1268 WARN("EnumMediaTypes (%x)\n", hr);
1269 return hr;
1272 IEnumMediaTypes_Reset(penummt);
1274 /* Looks like no existing renderer of the kind exists
1275 * Try adding new ones
1277 tab[0] = tab[1] = GUID_NULL;
1278 while (SUCCEEDED(hr))
1280 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1281 if (FAILED(hr)) {
1282 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1283 break;
1285 if (!nbmt)
1287 hr = VFW_E_CANNOT_RENDER;
1288 break;
1290 else
1292 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1293 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1295 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1296 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1298 DeleteMediaType(mt);
1299 continue;
1302 /* Try to find a suitable renderer with the same media type */
1303 tab[0] = mt->majortype;
1304 tab[1] = mt->subtype;
1305 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1306 if (FAILED(hr))
1308 WARN("Unable to enum filters (%x)\n", hr);
1309 break;
1312 hr = E_FAIL;
1314 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1316 VARIANT var;
1317 GUID clsid;
1318 IPin* ppinfilter;
1319 IBaseFilter* pfilter = NULL;
1320 IEnumPins* penumpins;
1321 ULONG pin;
1323 hr = GetFilterInfo(pMoniker, &clsid, &var);
1324 IMoniker_Release(pMoniker);
1325 if (FAILED(hr)) {
1326 WARN("Unable to retrieve filter info (%x)\n", hr);
1327 goto error;
1330 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
1331 if (FAILED(hr))
1333 WARN("Unable to create filter (%x), trying next one\n", hr);
1334 goto error;
1337 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1338 if (FAILED(hr)) {
1339 WARN("Unable to add filter (%x)\n", hr);
1340 IBaseFilter_Release(pfilter);
1341 pfilter = NULL;
1342 goto error;
1345 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1346 if (FAILED(hr)) {
1347 WARN("Splitter Enumpins (%x)\n", hr);
1348 goto error;
1350 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1351 IEnumPins_Release(penumpins);
1352 if (FAILED(hr)) {
1353 WARN("Next (%x)\n", hr);
1354 goto error;
1356 if (pin == 0) {
1357 WARN("No Pin\n");
1358 hr = E_FAIL;
1359 goto error;
1362 /* Connect the pin to the "Renderer" */
1363 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1364 IPin_Release(ppinfilter);
1366 if (FAILED(hr)) {
1367 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1368 goto error;
1370 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1372 VariantClear(&var);
1374 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1375 if (FAILED(hr)) {
1376 WARN("Unable to connect recursively (%x)\n", hr);
1377 goto error;
1379 IBaseFilter_Release(pfilter);
1380 break;
1382 error:
1383 VariantClear(&var);
1384 if (pfilter) {
1385 IFilterGraph2_RemoveFilter(iface, pfilter);
1386 IBaseFilter_Release(pfilter);
1388 if (SUCCEEDED(hr)) DebugBreak();
1391 IEnumMoniker_Release(pEnumMoniker);
1392 if (nbmt)
1393 DeleteMediaType(mt);
1394 if (SUCCEEDED(hr))
1395 break;
1396 hr = S_OK;
1399 IEnumMediaTypes_Release(penummt);
1400 return hr;
1403 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface,
1404 LPCWSTR lpcwstrFile,
1405 LPCWSTR lpcwstrPlayList)
1407 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1408 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1409 IBaseFilter* preader = NULL;
1410 IPin* ppinreader = NULL;
1411 IEnumPins* penumpins = NULL;
1412 HRESULT hr;
1413 BOOL partial = FALSE;
1414 HRESULT any = FALSE;
1416 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1418 if (lpcwstrPlayList != NULL)
1419 return E_INVALIDARG;
1421 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1422 if (FAILED(hr))
1423 return hr;
1425 if (SUCCEEDED(hr))
1426 hr = IBaseFilter_EnumPins(preader, &penumpins);
1427 if (SUCCEEDED(hr))
1429 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1431 PIN_DIRECTION dir;
1433 IPin_QueryDirection(ppinreader, &dir);
1434 if (dir == PINDIR_OUTPUT)
1436 INT i;
1438 hr = IFilterGraph2_Render(iface, ppinreader);
1439 TRACE("Render %08x\n", hr);
1441 for (i = 0; i < This->nFilters; ++i)
1442 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1444 if (SUCCEEDED(hr))
1445 any = TRUE;
1446 if (hr != S_OK)
1447 partial = TRUE;
1449 IPin_Release(ppinreader);
1451 IEnumPins_Release(penumpins);
1453 if (!any)
1454 hr = VFW_E_CANNOT_RENDER;
1455 else if (partial)
1456 hr = VFW_S_PARTIAL_RENDER;
1457 else
1458 hr = S_OK;
1460 IBaseFilter_Release(preader);
1462 TRACE("--> %08x\n", hr);
1463 return hr;
1466 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1467 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1469 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1470 HRESULT hr = S_OK;
1471 HKEY extkey;
1472 LONG lRet;
1474 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
1475 hr = HRESULT_FROM_WIN32(lRet);
1477 if (SUCCEEDED(hr))
1479 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
1480 WCHAR *ext = PathFindExtensionW(pszFileName);
1481 WCHAR clsid_key[39];
1482 GUID clsid;
1483 DWORD size = sizeof(clsid_key);
1484 HKEY pathkey;
1486 if (!ext)
1488 CloseHandle(extkey);
1489 return E_FAIL;
1492 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
1493 hr = HRESULT_FROM_WIN32(lRet);
1494 CloseHandle(extkey);
1495 if (FAILED(hr))
1496 return hr;
1498 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
1499 hr = HRESULT_FROM_WIN32(lRet);
1500 CloseHandle(pathkey);
1501 if (FAILED(hr))
1502 return hr;
1504 CLSIDFromString(clsid_key, &clsid);
1506 TRACE("CLSID: %s\n", debugstr_guid(&clsid));
1507 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1508 if (SUCCEEDED(hr))
1510 IFileSourceFilter *source = NULL;
1511 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1512 if (SUCCEEDED(hr))
1513 IFileSourceFilter_Release(source);
1514 else
1515 IBaseFilter_Release(*filter);
1518 if (FAILED(hr))
1519 *filter = NULL;
1520 return hr;
1523 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface,
1524 LPCWSTR lpcwstrFileName,
1525 LPCWSTR lpcwstrFilterName,
1526 IBaseFilter **ppFilter) {
1527 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1528 HRESULT hr;
1529 IBaseFilter* preader;
1530 IFileSourceFilter* pfile = NULL;
1531 AM_MEDIA_TYPE mt;
1532 WCHAR* filename;
1534 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1536 /* Try from file name first, then fall back to default asynchronous reader */
1537 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1539 if (FAILED(hr))
1540 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1541 if (FAILED(hr)) {
1542 WARN("Unable to create file source filter (%x)\n", hr);
1543 return hr;
1546 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1547 if (FAILED(hr)) {
1548 WARN("Unable add filter (%x)\n", hr);
1549 IBaseFilter_Release(preader);
1550 return hr;
1553 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1554 if (FAILED(hr)) {
1555 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1556 goto error;
1559 /* Load the file in the file source filter */
1560 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1561 if (FAILED(hr)) {
1562 WARN("Load (%x)\n", hr);
1563 goto error;
1566 IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1567 if (FAILED(hr)) {
1568 WARN("GetCurFile (%x)\n", hr);
1569 goto error;
1572 TRACE("File %s\n", debugstr_w(filename));
1573 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1574 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1576 if (ppFilter)
1577 *ppFilter = preader;
1578 IFileSourceFilter_Release(pfile);
1580 return S_OK;
1582 error:
1583 if (pfile)
1584 IFileSourceFilter_Release(pfile);
1585 IFilterGraph2_RemoveFilter(iface, preader);
1586 IBaseFilter_Release(preader);
1588 return hr;
1591 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface,
1592 DWORD_PTR hFile) {
1593 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1595 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1597 return S_OK;
1600 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) {
1601 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1603 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1605 return S_OK;
1608 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) {
1609 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1611 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1613 return S_OK;
1616 /*** IFilterGraph2 methods ***/
1617 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1618 IMoniker *pMoniker,
1619 IBindCtx *pCtx,
1620 LPCWSTR lpcwstrFilterName,
1621 IBaseFilter **ppFilter) {
1622 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1624 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1626 return S_OK;
1629 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface,
1630 IPin *ppin,
1631 const AM_MEDIA_TYPE *pmt) {
1632 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1634 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1636 return S_OK;
1639 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface,
1640 IPin *pPinOut,
1641 DWORD dwFlags,
1642 DWORD *pvContext) {
1643 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
1645 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1647 return S_OK;
1651 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1653 FilterGraph2_QueryInterface,
1654 FilterGraph2_AddRef,
1655 FilterGraph2_Release,
1656 FilterGraph2_AddFilter,
1657 FilterGraph2_RemoveFilter,
1658 FilterGraph2_EnumFilters,
1659 FilterGraph2_FindFilterByName,
1660 FilterGraph2_ConnectDirect,
1661 FilterGraph2_Reconnect,
1662 FilterGraph2_Disconnect,
1663 FilterGraph2_SetDefaultSyncSource,
1664 FilterGraph2_Connect,
1665 FilterGraph2_Render,
1666 FilterGraph2_RenderFile,
1667 FilterGraph2_AddSourceFilter,
1668 FilterGraph2_SetLogFile,
1669 FilterGraph2_Abort,
1670 FilterGraph2_ShouldOperationContinue,
1671 FilterGraph2_AddSourceFilterForMoniker,
1672 FilterGraph2_ReconnectEx,
1673 FilterGraph2_RenderEx
1676 /*** IUnknown methods ***/
1677 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface,
1678 REFIID riid,
1679 LPVOID*ppvObj) {
1680 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1682 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1684 return Filtergraph_QueryInterface(This, riid, ppvObj);
1687 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) {
1688 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1690 TRACE("(%p/%p)->()\n", This, iface);
1692 return Filtergraph_AddRef(This);
1695 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) {
1696 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1698 TRACE("(%p/%p)->()\n", This, iface);
1700 return Filtergraph_Release(This);
1704 /*** IDispatch methods ***/
1705 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface,
1706 UINT*pctinfo) {
1707 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1709 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1711 return S_OK;
1714 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface,
1715 UINT iTInfo,
1716 LCID lcid,
1717 ITypeInfo**ppTInfo) {
1718 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1720 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1722 return S_OK;
1725 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface,
1726 REFIID riid,
1727 LPOLESTR*rgszNames,
1728 UINT cNames,
1729 LCID lcid,
1730 DISPID*rgDispId) {
1731 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1733 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1735 return S_OK;
1738 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
1739 DISPID dispIdMember,
1740 REFIID riid,
1741 LCID lcid,
1742 WORD wFlags,
1743 DISPPARAMS*pDispParams,
1744 VARIANT*pVarResult,
1745 EXCEPINFO*pExepInfo,
1746 UINT*puArgErr) {
1747 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1749 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);
1751 return S_OK;
1754 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1756 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1758 HRESULT hr;
1759 IPin* pInputPin;
1760 IPin** ppPins;
1761 ULONG nb;
1762 ULONG i;
1763 PIN_INFO PinInfo;
1765 TRACE("%p %p\n", pGraph, pOutputPin);
1766 PinInfo.pFilter = NULL;
1768 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1770 if (SUCCEEDED(hr))
1772 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1773 if (SUCCEEDED(hr))
1774 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1775 IPin_Release(pInputPin);
1778 if (SUCCEEDED(hr))
1780 if (nb == 0)
1782 TRACE("Reached a renderer\n");
1783 /* Count renderers for end of stream notification */
1784 pGraph->nRenderers++;
1786 else
1788 for(i = 0; i < nb; i++)
1790 /* Explore the graph downstream from this pin
1791 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1792 * several input pins are connected to the same output (a MUX for instance). */
1793 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1794 IPin_Release(ppPins[i]);
1797 CoTaskMemFree(ppPins);
1799 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1801 FoundFilter(PinInfo.pFilter, data);
1804 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1805 return hr;
1808 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1810 LONGLONG time = 0;
1811 IReferenceClock *clock = NULL;
1813 IBaseFilter_GetSyncSource(pFilter, &clock);
1814 if (clock)
1816 IReferenceClock_GetTime(clock, &time);
1817 if (time)
1818 /* Add 50 ms */
1819 time += 500000;
1820 if (time < 0)
1821 time = 0;
1822 IReferenceClock_Release(clock);
1825 return IBaseFilter_Run(pFilter, time);
1828 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1830 return IBaseFilter_Pause(pFilter);
1833 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1835 return IBaseFilter_Stop(pFilter);
1838 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1840 FILTER_STATE state;
1841 DWORD time_end = data;
1842 DWORD time_now = GetTickCount();
1843 LONG wait;
1845 if (time_end == INFINITE)
1847 wait = INFINITE;
1849 else if (time_end > time_now)
1851 wait = time_end - time_now;
1853 else
1854 wait = 0;
1856 return IBaseFilter_GetState(pFilter, wait, &state);
1860 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data)
1862 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1863 int i;
1864 IBaseFilter* pfilter;
1865 IEnumPins* pEnum;
1866 HRESULT hr;
1867 IPin* pPin;
1868 DWORD dummy;
1869 PIN_DIRECTION dir;
1870 TRACE("(%p/%p)->()\n", This, iface);
1872 /* Explorer the graph from source filters to renderers, determine renderers
1873 * number and run filters from renderers to source filters */
1874 This->nRenderers = 0;
1875 ResetEvent(This->hEventCompletion);
1877 for(i = 0; i < This->nFilters; i++)
1879 BOOL source = TRUE;
1880 pfilter = This->ppFiltersInGraph[i];
1881 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1882 if (hr != S_OK)
1884 WARN("Enum pins failed %x\n", hr);
1885 continue;
1887 /* Check if it is a source filter */
1888 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1890 IPin_QueryDirection(pPin, &dir);
1891 IPin_Release(pPin);
1892 if (dir == PINDIR_INPUT)
1894 source = FALSE;
1895 break;
1898 if (source)
1900 TRACE("Found a source filter %p\n", pfilter);
1901 IEnumPins_Reset(pEnum);
1902 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1904 /* Explore the graph downstream from this pin */
1905 ExploreGraph(This, pPin, FoundFilter, data);
1906 IPin_Release(pPin);
1908 FoundFilter(pfilter, data);
1910 IEnumPins_Release(pEnum);
1913 return S_FALSE;
1916 /*** IMediaControl methods ***/
1917 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
1918 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1919 TRACE("(%p/%p)->()\n", This, iface);
1921 if (This->state == State_Running) return S_OK;
1923 EnterCriticalSection(&This->cs);
1924 if (This->state == State_Stopped)
1925 This->EcCompleteCount = 0;
1927 if (This->refClock)
1929 IReferenceClock_GetTime(This->refClock, &This->start_time);
1930 This->start_time += 500000;
1932 else This->position = This->start_time = 0;
1934 SendFilterMessage(iface, SendRun, 0);
1935 This->state = State_Running;
1936 LeaveCriticalSection(&This->cs);
1937 return S_FALSE;
1940 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
1941 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1942 TRACE("(%p/%p)->()\n", This, iface);
1944 if (This->state == State_Paused) return S_OK;
1946 EnterCriticalSection(&This->cs);
1947 if (This->state == State_Stopped)
1948 This->EcCompleteCount = 0;
1950 if (This->state == State_Running && This->refClock)
1952 LONGLONG time = This->start_time;
1953 IReferenceClock_GetTime(This->refClock, &time);
1954 This->position += time - This->start_time;
1957 SendFilterMessage(iface, SendPause, 0);
1958 This->state = State_Paused;
1959 LeaveCriticalSection(&This->cs);
1960 return S_FALSE;
1963 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
1964 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1965 TRACE("(%p/%p)->()\n", This, iface);
1967 if (This->state == State_Stopped) return S_OK;
1969 EnterCriticalSection(&This->cs);
1970 if (This->state == State_Running && This->refClock)
1972 LONGLONG time = This->start_time;
1973 IReferenceClock_GetTime(This->refClock, &time);
1974 This->position += time - This->start_time;
1977 if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0);
1978 SendFilterMessage(iface, SendStop, 0);
1979 This->state = State_Stopped;
1980 LeaveCriticalSection(&This->cs);
1981 return S_OK;
1984 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
1985 LONG msTimeout,
1986 OAFilterState *pfs) {
1987 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1988 DWORD end;
1990 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
1992 if (!pfs)
1993 return E_POINTER;
1995 EnterCriticalSection(&This->cs);
1997 *pfs = This->state;
1998 if (msTimeout > 0)
2000 end = GetTickCount() + msTimeout;
2002 else if (msTimeout < 0)
2004 end = INFINITE;
2006 else
2008 end = 0;
2010 if (end)
2011 SendFilterMessage(iface, SendGetState, end);
2013 LeaveCriticalSection(&This->cs);
2015 return S_OK;
2018 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface,
2019 BSTR strFilename) {
2020 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2022 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
2024 return S_OK;
2027 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface,
2028 BSTR strFilename,
2029 IDispatch **ppUnk) {
2030 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2032 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2034 return S_OK;
2037 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface,
2038 IDispatch **ppUnk) {
2039 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2041 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2043 return S_OK;
2046 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface,
2047 IDispatch **ppUnk) {
2048 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2050 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2052 return S_OK;
2055 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) {
2056 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
2058 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2060 return S_OK;
2064 static const IMediaControlVtbl IMediaControl_VTable =
2066 MediaControl_QueryInterface,
2067 MediaControl_AddRef,
2068 MediaControl_Release,
2069 MediaControl_GetTypeInfoCount,
2070 MediaControl_GetTypeInfo,
2071 MediaControl_GetIDsOfNames,
2072 MediaControl_Invoke,
2073 MediaControl_Run,
2074 MediaControl_Pause,
2075 MediaControl_Stop,
2076 MediaControl_GetState,
2077 MediaControl_RenderFile,
2078 MediaControl_AddSourceFilter,
2079 MediaControl_get_FilterCollection,
2080 MediaControl_get_RegFilterCollection,
2081 MediaControl_StopWhenReady
2085 /*** IUnknown methods ***/
2086 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface,
2087 REFIID riid,
2088 LPVOID*ppvObj) {
2089 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2091 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2093 return Filtergraph_QueryInterface(This, riid, ppvObj);
2096 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) {
2097 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2099 TRACE("(%p/%p)->()\n", This, iface);
2101 return Filtergraph_AddRef(This);
2104 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) {
2105 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2107 TRACE("(%p/%p)->()\n", This, iface);
2109 return Filtergraph_Release(This);
2112 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2114 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2115 BOOL allnotimpl = TRUE;
2116 int i;
2117 IBaseFilter* pfilter;
2118 IEnumPins* pEnum;
2119 HRESULT hr, hr_return = S_OK;
2120 IPin* pPin;
2121 DWORD dummy;
2122 PIN_DIRECTION dir;
2124 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2125 /* Send a message to all renderers, they are responsible for broadcasting it further */
2127 for(i = 0; i < This->nFilters; i++)
2129 BOOL renderer = TRUE;
2130 pfilter = This->ppFiltersInGraph[i];
2131 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
2132 if (hr != S_OK)
2134 WARN("Enum pins failed %x\n", hr);
2135 continue;
2137 /* Check if it is a source filter */
2138 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2140 IPin_QueryDirection(pPin, &dir);
2141 IPin_Release(pPin);
2142 if (dir != PINDIR_INPUT)
2144 renderer = FALSE;
2145 break;
2148 IEnumPins_Release(pEnum);
2149 if (renderer)
2151 IMediaSeeking *seek = NULL;
2152 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2153 if (!seek)
2154 continue;
2156 hr = FoundSeek(This, seek, arg);
2158 IMediaSeeking_Release(seek);
2159 if (hr_return != E_NOTIMPL)
2160 allnotimpl = FALSE;
2161 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2162 hr_return = hr;
2166 if (allnotimpl)
2167 return E_NOTIMPL;
2168 return hr_return;
2171 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2173 HRESULT hr;
2174 DWORD caps = 0;
2176 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2177 if (FAILED(hr))
2178 return hr;
2180 /* Only add common capabilities everything supports */
2181 *(DWORD*)pcaps &= caps;
2183 return hr;
2186 /*** IMediaSeeking methods ***/
2187 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface,
2188 DWORD *pCapabilities) {
2189 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2190 HRESULT hr;
2191 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2193 if (!pCapabilities)
2194 return E_POINTER;
2196 EnterCriticalSection(&This->cs);
2197 *pCapabilities = 0xffffffff;
2199 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2200 LeaveCriticalSection(&This->cs);
2202 return hr;
2205 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface,
2206 DWORD *pCapabilities) {
2207 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2208 DWORD originalcaps;
2209 HRESULT hr;
2210 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2212 if (!pCapabilities)
2213 return E_POINTER;
2215 EnterCriticalSection(&This->cs);
2216 originalcaps = *pCapabilities;
2217 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2218 LeaveCriticalSection(&This->cs);
2220 if (FAILED(hr))
2221 return hr;
2223 if (!*pCapabilities)
2224 return E_FAIL;
2225 if (*pCapabilities != originalcaps)
2226 return S_FALSE;
2227 return S_OK;
2230 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface,
2231 const GUID *pFormat) {
2232 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2234 if (!pFormat)
2235 return E_POINTER;
2237 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2239 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2241 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2242 return S_FALSE;
2245 return S_OK;
2248 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface,
2249 GUID *pFormat) {
2250 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2252 if (!pFormat)
2253 return E_POINTER;
2255 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2256 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2258 return S_OK;
2261 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface,
2262 GUID *pFormat) {
2263 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2265 if (!pFormat)
2266 return E_POINTER;
2268 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2269 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2271 return S_OK;
2274 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface,
2275 const GUID *pFormat) {
2276 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2278 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2279 if (!pFormat)
2280 return E_POINTER;
2282 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2283 return S_FALSE;
2285 return S_OK;
2288 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface,
2289 const GUID *pFormat) {
2290 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2292 if (!pFormat)
2293 return E_POINTER;
2295 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2297 if (This->state != State_Stopped)
2298 return VFW_E_WRONG_STATE;
2300 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2302 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2303 return E_INVALIDARG;
2306 return S_OK;
2309 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2311 HRESULT hr;
2312 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2314 hr = IMediaSeeking_GetDuration(seek, &duration);
2315 if (FAILED(hr))
2316 return hr;
2318 /* FIXME: Minimum or maximum duration? Assuming minimum */
2319 if (duration > 0 && *pdur < duration)
2320 *pdur = duration;
2322 return hr;
2325 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface,
2326 LONGLONG *pDuration) {
2327 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2328 HRESULT hr;
2330 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2332 if (!pDuration)
2333 return E_POINTER;
2335 EnterCriticalSection(&This->cs);
2336 *pDuration = -1;
2337 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2338 LeaveCriticalSection(&This->cs);
2340 TRACE("--->%08x\n", hr);
2341 return hr;
2344 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
2345 LONGLONG *pStop) {
2346 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2347 HRESULT hr = S_OK;
2349 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2351 if (!pStop)
2352 return E_POINTER;
2354 EnterCriticalSection(&This->cs);
2355 if (This->stop_position < 0)
2356 /* Stop position not set, use duration instead */
2357 hr = IMediaSeeking_GetDuration(iface, pStop);
2358 else
2359 *pStop = This->stop_position;
2361 LeaveCriticalSection(&This->cs);
2363 return hr;
2366 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
2367 LONGLONG *pCurrent) {
2368 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2369 LONGLONG time = 0;
2371 if (!pCurrent)
2372 return E_POINTER;
2374 EnterCriticalSection(&This->cs);
2375 if (This->state == State_Running && This->refClock)
2377 IReferenceClock_GetTime(This->refClock, &time);
2378 if (time)
2379 time += This->position - This->start_time;
2380 if (time < This->position)
2381 time = This->position;
2382 *pCurrent = time;
2384 else
2385 *pCurrent = This->position;
2386 LeaveCriticalSection(&This->cs);
2388 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2390 return S_OK;
2393 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
2394 LONGLONG *pTarget,
2395 const GUID *pTargetFormat,
2396 LONGLONG Source,
2397 const GUID *pSourceFormat) {
2398 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2400 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2401 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2403 return S_OK;
2406 struct pos_args {
2407 LONGLONG* current, *stop;
2408 DWORD curflags, stopflags;
2411 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2413 struct pos_args *args = (void*)pargs;
2415 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2418 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
2419 LONGLONG *pCurrent,
2420 DWORD dwCurrentFlags,
2421 LONGLONG *pStop,
2422 DWORD dwStopFlags) {
2423 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2424 HRESULT hr = S_OK;
2425 FILTER_STATE state;
2426 struct pos_args args;
2428 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2430 EnterCriticalSection(&This->cs);
2431 state = This->state;
2432 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2434 if ((dwCurrentFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2436 This->position = *pCurrent;
2438 else if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2439 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2441 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2442 This->stop_position = *pStop;
2443 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2444 FIXME("Stop position not handled yet!\n");
2446 args.current = pCurrent;
2447 args.stop = pStop;
2448 args.curflags = dwCurrentFlags;
2449 args.stopflags = dwStopFlags;
2450 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2452 if (This->refClock && ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning))
2454 /* Update start time, prevents weird jumps */
2455 IReferenceClock_GetTime(This->refClock, &This->start_time);
2457 LeaveCriticalSection(&This->cs);
2459 return hr;
2462 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
2463 LONGLONG *pCurrent,
2464 LONGLONG *pStop) {
2465 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2466 HRESULT hr;
2468 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2469 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2470 if (SUCCEEDED(hr))
2471 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2473 return hr;
2476 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
2477 LONGLONG *pEarliest,
2478 LONGLONG *pLatest) {
2479 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2481 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2483 return S_OK;
2486 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
2487 double dRate) {
2488 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2490 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2492 return S_OK;
2495 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
2496 double *pdRate) {
2497 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2499 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2501 return S_OK;
2504 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
2505 LONGLONG *pllPreroll) {
2506 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2508 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2510 return S_OK;
2514 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2516 MediaSeeking_QueryInterface,
2517 MediaSeeking_AddRef,
2518 MediaSeeking_Release,
2519 MediaSeeking_GetCapabilities,
2520 MediaSeeking_CheckCapabilities,
2521 MediaSeeking_IsFormatSupported,
2522 MediaSeeking_QueryPreferredFormat,
2523 MediaSeeking_GetTimeFormat,
2524 MediaSeeking_IsUsingTimeFormat,
2525 MediaSeeking_SetTimeFormat,
2526 MediaSeeking_GetDuration,
2527 MediaSeeking_GetStopPosition,
2528 MediaSeeking_GetCurrentPosition,
2529 MediaSeeking_ConvertTimeFormat,
2530 MediaSeeking_SetPositions,
2531 MediaSeeking_GetPositions,
2532 MediaSeeking_GetAvailable,
2533 MediaSeeking_SetRate,
2534 MediaSeeking_GetRate,
2535 MediaSeeking_GetPreroll
2538 /*** IUnknown methods ***/
2539 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
2540 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2542 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2544 return Filtergraph_QueryInterface(This, riid, ppvObj);
2547 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
2548 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2550 TRACE("(%p/%p)->()\n", This, iface);
2552 return Filtergraph_AddRef(This);
2555 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
2556 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2558 TRACE("(%p/%p)->()\n", This, iface);
2560 return Filtergraph_Release(This);
2563 /*** IDispatch methods ***/
2564 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2565 FIXME("(%p) stub!\n", iface);
2566 return E_NOTIMPL;
2569 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2570 FIXME("(%p) stub!\n", iface);
2571 return E_NOTIMPL;
2574 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2575 FIXME("(%p) stub!\n", iface);
2576 return E_NOTIMPL;
2579 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2580 FIXME("(%p) stub!\n", iface);
2581 return E_NOTIMPL;
2584 /*** IMediaPosition methods ***/
2585 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
2586 FIXME("(%p)->(%p) stub!\n", iface, plength);
2587 return E_NOTIMPL;
2590 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
2591 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2592 LONGLONG reftime = llTime;
2594 return IMediaSeeking_SetPositions((IMediaSeeking *)&This->IMediaSeeking_vtbl, &reftime, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2597 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
2598 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2599 return E_NOTIMPL;
2602 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
2603 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2604 return E_NOTIMPL;
2607 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
2608 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2609 return E_NOTIMPL;
2612 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2613 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2614 return E_NOTIMPL;
2617 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2618 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2619 return E_NOTIMPL;
2622 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
2623 FIXME("(%p)->(%f) stub!\n", iface, dRate);
2624 return E_NOTIMPL;
2627 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
2628 FIXME("(%p)->(%p) stub!\n", iface, pdRate);
2629 return E_NOTIMPL;
2632 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2633 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2634 return E_NOTIMPL;
2637 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2638 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2639 return E_NOTIMPL;
2643 static const IMediaPositionVtbl IMediaPosition_VTable =
2645 MediaPosition_QueryInterface,
2646 MediaPosition_AddRef,
2647 MediaPosition_Release,
2648 MediaPosition_GetTypeInfoCount,
2649 MediaPosition_GetTypeInfo,
2650 MediaPosition_GetIDsOfNames,
2651 MediaPosition_Invoke,
2652 MediaPosition_get_Duration,
2653 MediaPosition_put_CurrentPosition,
2654 MediaPosition_get_CurrentPosition,
2655 MediaPosition_get_StopTime,
2656 MediaPosition_put_StopTime,
2657 MediaPosition_get_PrerollTime,
2658 MediaPosition_put_PrerollTime,
2659 MediaPosition_put_Rate,
2660 MediaPosition_get_Rate,
2661 MediaPosition_CanSeekForward,
2662 MediaPosition_CanSeekBackward
2665 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2667 HRESULT hr = E_NOINTERFACE;
2668 int i;
2669 int entry;
2671 /* Check if the interface type is already registered */
2672 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2673 if (riid == pGraph->ItfCacheEntries[entry].riid)
2675 if (pGraph->ItfCacheEntries[entry].iface)
2677 /* Return the interface if available */
2678 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2679 return S_OK;
2681 break;
2684 if (entry >= MAX_ITF_CACHE_ENTRIES)
2686 FIXME("Not enough space to store interface in the cache\n");
2687 return E_OUTOFMEMORY;
2690 /* Find a filter supporting the requested interface */
2691 for (i = 0; i < pGraph->nFilters; i++)
2693 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2694 if (hr == S_OK)
2696 pGraph->ItfCacheEntries[entry].riid = riid;
2697 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2698 pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
2699 if (entry >= pGraph->nItfCacheEntries)
2700 pGraph->nItfCacheEntries++;
2701 return S_OK;
2703 if (hr != E_NOINTERFACE)
2704 return hr;
2707 return hr;
2710 /*** IUnknown methods ***/
2711 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
2712 REFIID riid,
2713 LPVOID*ppvObj) {
2714 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2716 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2718 return Filtergraph_QueryInterface(This, riid, ppvObj);
2721 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
2722 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2724 TRACE("(%p/%p)->()\n", This, iface);
2726 return Filtergraph_AddRef(This);
2729 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
2730 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2732 TRACE("(%p/%p)->()\n", This, iface);
2734 return Filtergraph_Release(This);
2737 /*** IDispatch methods ***/
2738 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
2739 UINT*pctinfo) {
2740 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2741 IBasicAudio* pBasicAudio;
2742 HRESULT hr;
2744 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2746 EnterCriticalSection(&This->cs);
2748 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2750 if (hr == S_OK)
2751 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2753 LeaveCriticalSection(&This->cs);
2755 return hr;
2758 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2759 UINT iTInfo,
2760 LCID lcid,
2761 ITypeInfo**ppTInfo) {
2762 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2763 IBasicAudio* pBasicAudio;
2764 HRESULT hr;
2766 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2768 EnterCriticalSection(&This->cs);
2770 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2772 if (hr == S_OK)
2773 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2775 LeaveCriticalSection(&This->cs);
2777 return hr;
2780 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2781 REFIID riid,
2782 LPOLESTR*rgszNames,
2783 UINT cNames,
2784 LCID lcid,
2785 DISPID*rgDispId) {
2786 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2787 IBasicAudio* pBasicAudio;
2788 HRESULT hr;
2790 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2792 EnterCriticalSection(&This->cs);
2794 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2796 if (hr == S_OK)
2797 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2799 LeaveCriticalSection(&This->cs);
2801 return hr;
2804 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2805 DISPID dispIdMember,
2806 REFIID riid,
2807 LCID lcid,
2808 WORD wFlags,
2809 DISPPARAMS*pDispParams,
2810 VARIANT*pVarResult,
2811 EXCEPINFO*pExepInfo,
2812 UINT*puArgErr) {
2813 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2814 IBasicAudio* pBasicAudio;
2815 HRESULT hr;
2817 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);
2819 EnterCriticalSection(&This->cs);
2821 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2823 if (hr == S_OK)
2824 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2826 LeaveCriticalSection(&This->cs);
2828 return hr;
2831 /*** IBasicAudio methods ***/
2832 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2833 long lVolume) {
2834 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2835 IBasicAudio* pBasicAudio;
2836 HRESULT hr;
2838 TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2840 EnterCriticalSection(&This->cs);
2842 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2844 if (hr == S_OK)
2845 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2847 LeaveCriticalSection(&This->cs);
2849 return hr;
2852 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2853 long *plVolume) {
2854 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2855 IBasicAudio* pBasicAudio;
2856 HRESULT hr;
2858 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2860 EnterCriticalSection(&This->cs);
2862 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2864 if (hr == S_OK)
2865 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2867 LeaveCriticalSection(&This->cs);
2869 return hr;
2872 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2873 long lBalance) {
2874 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2875 IBasicAudio* pBasicAudio;
2876 HRESULT hr;
2878 TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2880 EnterCriticalSection(&This->cs);
2882 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2884 if (hr == S_OK)
2885 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2887 LeaveCriticalSection(&This->cs);
2889 return hr;
2892 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2893 long *plBalance) {
2894 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2895 IBasicAudio* pBasicAudio;
2896 HRESULT hr;
2898 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2900 EnterCriticalSection(&This->cs);
2902 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2904 if (hr == S_OK)
2905 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2907 LeaveCriticalSection(&This->cs);
2909 return hr;
2912 static const IBasicAudioVtbl IBasicAudio_VTable =
2914 BasicAudio_QueryInterface,
2915 BasicAudio_AddRef,
2916 BasicAudio_Release,
2917 BasicAudio_GetTypeInfoCount,
2918 BasicAudio_GetTypeInfo,
2919 BasicAudio_GetIDsOfNames,
2920 BasicAudio_Invoke,
2921 BasicAudio_put_Volume,
2922 BasicAudio_get_Volume,
2923 BasicAudio_put_Balance,
2924 BasicAudio_get_Balance
2927 /*** IUnknown methods ***/
2928 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface,
2929 REFIID riid,
2930 LPVOID*ppvObj) {
2931 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2933 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2935 return Filtergraph_QueryInterface(This, riid, ppvObj);
2938 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) {
2939 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2941 TRACE("(%p/%p)->()\n", This, iface);
2943 return Filtergraph_AddRef(This);
2946 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) {
2947 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2949 TRACE("(%p/%p)->()\n", This, iface);
2951 return Filtergraph_Release(This);
2954 /*** IDispatch methods ***/
2955 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface,
2956 UINT*pctinfo) {
2957 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2958 IBasicVideo* pBasicVideo;
2959 HRESULT hr;
2961 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2963 EnterCriticalSection(&This->cs);
2965 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2967 if (hr == S_OK)
2968 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2970 LeaveCriticalSection(&This->cs);
2972 return hr;
2975 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface,
2976 UINT iTInfo,
2977 LCID lcid,
2978 ITypeInfo**ppTInfo) {
2979 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2980 IBasicVideo* pBasicVideo;
2981 HRESULT hr;
2983 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2985 EnterCriticalSection(&This->cs);
2987 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2989 if (hr == S_OK)
2990 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2992 LeaveCriticalSection(&This->cs);
2994 return hr;
2997 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface,
2998 REFIID riid,
2999 LPOLESTR*rgszNames,
3000 UINT cNames,
3001 LCID lcid,
3002 DISPID*rgDispId) {
3003 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3004 IBasicVideo* pBasicVideo;
3005 HRESULT hr;
3007 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3009 EnterCriticalSection(&This->cs);
3011 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3013 if (hr == S_OK)
3014 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3016 LeaveCriticalSection(&This->cs);
3018 return hr;
3021 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface,
3022 DISPID dispIdMember,
3023 REFIID riid,
3024 LCID lcid,
3025 WORD wFlags,
3026 DISPPARAMS*pDispParams,
3027 VARIANT*pVarResult,
3028 EXCEPINFO*pExepInfo,
3029 UINT*puArgErr) {
3030 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3031 IBasicVideo* pBasicVideo;
3032 HRESULT hr;
3034 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);
3036 EnterCriticalSection(&This->cs);
3038 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3040 if (hr == S_OK)
3041 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3043 LeaveCriticalSection(&This->cs);
3045 return hr;
3048 /*** IBasicVideo methods ***/
3049 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface,
3050 REFTIME *pAvgTimePerFrame) {
3051 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3052 IBasicVideo* pBasicVideo;
3053 HRESULT hr;
3055 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3057 EnterCriticalSection(&This->cs);
3059 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3061 if (hr == S_OK)
3062 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3064 LeaveCriticalSection(&This->cs);
3066 return hr;
3069 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface,
3070 long *pBitRate) {
3071 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3072 IBasicVideo* pBasicVideo;
3073 HRESULT hr;
3075 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3077 EnterCriticalSection(&This->cs);
3079 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3081 if (hr == S_OK)
3082 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3084 LeaveCriticalSection(&This->cs);
3086 return hr;
3089 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface,
3090 long *pBitErrorRate) {
3091 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3092 IBasicVideo* pBasicVideo;
3093 HRESULT hr;
3095 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3097 EnterCriticalSection(&This->cs);
3099 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3101 if (hr == S_OK)
3102 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3104 LeaveCriticalSection(&This->cs);
3106 return hr;
3109 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface,
3110 long *pVideoWidth) {
3111 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3112 IBasicVideo* pBasicVideo;
3113 HRESULT hr;
3115 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3117 EnterCriticalSection(&This->cs);
3119 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3121 if (hr == S_OK)
3122 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3124 LeaveCriticalSection(&This->cs);
3126 return hr;
3129 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface,
3130 long *pVideoHeight) {
3131 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3132 IBasicVideo* pBasicVideo;
3133 HRESULT hr;
3135 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3137 EnterCriticalSection(&This->cs);
3139 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3141 if (hr == S_OK)
3142 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3144 LeaveCriticalSection(&This->cs);
3146 return hr;
3149 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface,
3150 long SourceLeft) {
3151 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3152 IBasicVideo* pBasicVideo;
3153 HRESULT hr;
3155 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
3157 EnterCriticalSection(&This->cs);
3159 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3161 if (hr == S_OK)
3162 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3164 LeaveCriticalSection(&This->cs);
3166 return hr;
3169 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface,
3170 long *pSourceLeft) {
3171 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3172 IBasicVideo* pBasicVideo;
3173 HRESULT hr;
3175 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3177 EnterCriticalSection(&This->cs);
3179 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3181 if (hr == S_OK)
3182 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3184 LeaveCriticalSection(&This->cs);
3186 return hr;
3189 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface,
3190 long SourceWidth) {
3191 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3192 IBasicVideo* pBasicVideo;
3193 HRESULT hr;
3195 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
3197 EnterCriticalSection(&This->cs);
3199 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3201 if (hr == S_OK)
3202 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3204 LeaveCriticalSection(&This->cs);
3206 return hr;
3209 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface,
3210 long *pSourceWidth) {
3211 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3212 IBasicVideo* pBasicVideo;
3213 HRESULT hr;
3215 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3217 EnterCriticalSection(&This->cs);
3219 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3221 if (hr == S_OK)
3222 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3224 LeaveCriticalSection(&This->cs);
3226 return hr;
3229 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface,
3230 long SourceTop) {
3231 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3232 IBasicVideo* pBasicVideo;
3233 HRESULT hr;
3235 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
3237 EnterCriticalSection(&This->cs);
3239 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3241 if (hr == S_OK)
3242 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3244 LeaveCriticalSection(&This->cs);
3246 return hr;
3249 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface,
3250 long *pSourceTop) {
3251 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3252 IBasicVideo* pBasicVideo;
3253 HRESULT hr;
3255 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3257 EnterCriticalSection(&This->cs);
3259 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3261 if (hr == S_OK)
3262 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3264 LeaveCriticalSection(&This->cs);
3266 return hr;
3269 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface,
3270 long SourceHeight) {
3271 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3272 IBasicVideo* pBasicVideo;
3273 HRESULT hr;
3275 TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
3277 EnterCriticalSection(&This->cs);
3279 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3281 if (hr == S_OK)
3282 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3284 LeaveCriticalSection(&This->cs);
3286 return hr;
3289 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface,
3290 long *pSourceHeight) {
3291 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3292 IBasicVideo* pBasicVideo;
3293 HRESULT hr;
3295 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3297 EnterCriticalSection(&This->cs);
3299 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3301 if (hr == S_OK)
3302 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3304 LeaveCriticalSection(&This->cs);
3306 return hr;
3309 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface,
3310 long DestinationLeft) {
3311 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3312 IBasicVideo* pBasicVideo;
3313 HRESULT hr;
3315 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
3317 EnterCriticalSection(&This->cs);
3319 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3321 if (hr == S_OK)
3322 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3324 LeaveCriticalSection(&This->cs);
3326 return hr;
3329 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface,
3330 long *pDestinationLeft) {
3331 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3332 IBasicVideo* pBasicVideo;
3333 HRESULT hr;
3335 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3337 EnterCriticalSection(&This->cs);
3339 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3341 if (hr == S_OK)
3342 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3344 LeaveCriticalSection(&This->cs);
3346 return hr;
3349 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface,
3350 long DestinationWidth) {
3351 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3352 IBasicVideo* pBasicVideo;
3353 HRESULT hr;
3355 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
3357 EnterCriticalSection(&This->cs);
3359 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3361 if (hr == S_OK)
3362 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3364 LeaveCriticalSection(&This->cs);
3366 return hr;
3369 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface,
3370 long *pDestinationWidth) {
3371 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3372 IBasicVideo* pBasicVideo;
3373 HRESULT hr;
3375 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3377 EnterCriticalSection(&This->cs);
3379 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3381 if (hr == S_OK)
3382 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3384 LeaveCriticalSection(&This->cs);
3386 return hr;
3389 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface,
3390 long DestinationTop) {
3391 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3392 IBasicVideo* pBasicVideo;
3393 HRESULT hr;
3395 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
3397 EnterCriticalSection(&This->cs);
3399 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3401 if (hr == S_OK)
3402 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3404 LeaveCriticalSection(&This->cs);
3406 return hr;
3409 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface,
3410 long *pDestinationTop) {
3411 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3412 IBasicVideo* pBasicVideo;
3413 HRESULT hr;
3415 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3417 EnterCriticalSection(&This->cs);
3419 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3421 if (hr == S_OK)
3422 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3424 LeaveCriticalSection(&This->cs);
3426 return hr;
3429 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface,
3430 long DestinationHeight) {
3431 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3432 IBasicVideo* pBasicVideo;
3433 HRESULT hr;
3435 TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
3437 EnterCriticalSection(&This->cs);
3439 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3441 if (hr == S_OK)
3442 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3444 LeaveCriticalSection(&This->cs);
3446 return hr;
3449 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3450 long *pDestinationHeight) {
3451 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3452 IBasicVideo* pBasicVideo;
3453 HRESULT hr;
3455 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3457 EnterCriticalSection(&This->cs);
3459 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3461 if (hr == S_OK)
3462 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3464 LeaveCriticalSection(&This->cs);
3466 return hr;
3469 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface,
3470 long Left,
3471 long Top,
3472 long Width,
3473 long Height) {
3474 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3475 IBasicVideo* pBasicVideo;
3476 HRESULT hr;
3478 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3480 EnterCriticalSection(&This->cs);
3482 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3484 if (hr == S_OK)
3485 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3487 LeaveCriticalSection(&This->cs);
3489 return hr;
3492 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface,
3493 long *pLeft,
3494 long *pTop,
3495 long *pWidth,
3496 long *pHeight) {
3497 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3498 IBasicVideo* pBasicVideo;
3499 HRESULT hr;
3501 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3503 EnterCriticalSection(&This->cs);
3505 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3507 if (hr == S_OK)
3508 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3510 LeaveCriticalSection(&This->cs);
3512 return hr;
3515 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) {
3516 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3517 IBasicVideo* pBasicVideo;
3518 HRESULT hr;
3520 TRACE("(%p/%p)->()\n", This, iface);
3522 EnterCriticalSection(&This->cs);
3524 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3526 if (hr == S_OK)
3527 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3529 LeaveCriticalSection(&This->cs);
3531 return hr;
3534 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface,
3535 long Left,
3536 long Top,
3537 long Width,
3538 long Height) {
3539 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3540 IBasicVideo* pBasicVideo;
3541 HRESULT hr;
3543 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3545 EnterCriticalSection(&This->cs);
3547 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3549 if (hr == S_OK)
3550 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3552 LeaveCriticalSection(&This->cs);
3554 return hr;
3557 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface,
3558 long *pLeft,
3559 long *pTop,
3560 long *pWidth,
3561 long *pHeight) {
3562 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3563 IBasicVideo* pBasicVideo;
3564 HRESULT hr;
3566 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3568 EnterCriticalSection(&This->cs);
3570 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3572 if (hr == S_OK)
3573 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3575 LeaveCriticalSection(&This->cs);
3577 return hr;
3580 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) {
3581 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3582 IBasicVideo* pBasicVideo;
3583 HRESULT hr;
3585 TRACE("(%p/%p)->()\n", This, iface);
3587 EnterCriticalSection(&This->cs);
3589 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3591 if (hr == S_OK)
3592 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3594 LeaveCriticalSection(&This->cs);
3596 return hr;
3599 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface,
3600 long *pWidth,
3601 long *pHeight) {
3602 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3603 IBasicVideo* pBasicVideo;
3604 HRESULT hr;
3606 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3608 EnterCriticalSection(&This->cs);
3610 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3612 if (hr == S_OK)
3613 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3615 LeaveCriticalSection(&This->cs);
3617 return hr;
3620 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface,
3621 long StartIndex,
3622 long Entries,
3623 long *pRetrieved,
3624 long *pPalette) {
3625 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3626 IBasicVideo* pBasicVideo;
3627 HRESULT hr;
3629 TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3631 EnterCriticalSection(&This->cs);
3633 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3635 if (hr == S_OK)
3636 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3638 LeaveCriticalSection(&This->cs);
3640 return hr;
3643 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface,
3644 long *pBufferSize,
3645 long *pDIBImage) {
3646 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3647 IBasicVideo* pBasicVideo;
3648 HRESULT hr;
3650 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3652 EnterCriticalSection(&This->cs);
3654 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3656 if (hr == S_OK)
3657 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3659 LeaveCriticalSection(&This->cs);
3661 return hr;
3664 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) {
3665 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3666 IBasicVideo* pBasicVideo;
3667 HRESULT hr;
3669 TRACE("(%p/%p)->()\n", This, iface);
3671 EnterCriticalSection(&This->cs);
3673 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3675 if (hr == S_OK)
3676 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3678 LeaveCriticalSection(&This->cs);
3680 return hr;
3683 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) {
3684 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3685 IBasicVideo* pBasicVideo;
3686 HRESULT hr;
3688 TRACE("(%p/%p)->()\n", This, iface);
3690 EnterCriticalSection(&This->cs);
3692 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3694 if (hr == S_OK)
3695 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3697 LeaveCriticalSection(&This->cs);
3699 return hr;
3702 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, LONG *plAspectY) {
3703 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3704 IBasicVideo2 *pBasicVideo2;
3705 HRESULT hr;
3707 TRACE("(%p/%p)->()\n", This, iface);
3709 EnterCriticalSection(&This->cs);
3711 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3713 if (hr == S_OK)
3714 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3716 LeaveCriticalSection(&This->cs);
3718 return hr;
3721 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3723 BasicVideo_QueryInterface,
3724 BasicVideo_AddRef,
3725 BasicVideo_Release,
3726 BasicVideo_GetTypeInfoCount,
3727 BasicVideo_GetTypeInfo,
3728 BasicVideo_GetIDsOfNames,
3729 BasicVideo_Invoke,
3730 BasicVideo_get_AvgTimePerFrame,
3731 BasicVideo_get_BitRate,
3732 BasicVideo_get_BitErrorRate,
3733 BasicVideo_get_VideoWidth,
3734 BasicVideo_get_VideoHeight,
3735 BasicVideo_put_SourceLeft,
3736 BasicVideo_get_SourceLeft,
3737 BasicVideo_put_SourceWidth,
3738 BasicVideo_get_SourceWidth,
3739 BasicVideo_put_SourceTop,
3740 BasicVideo_get_SourceTop,
3741 BasicVideo_put_SourceHeight,
3742 BasicVideo_get_SourceHeight,
3743 BasicVideo_put_DestinationLeft,
3744 BasicVideo_get_DestinationLeft,
3745 BasicVideo_put_DestinationWidth,
3746 BasicVideo_get_DestinationWidth,
3747 BasicVideo_put_DestinationTop,
3748 BasicVideo_get_DestinationTop,
3749 BasicVideo_put_DestinationHeight,
3750 BasicVideo_get_DestinationHeight,
3751 BasicVideo_SetSourcePosition,
3752 BasicVideo_GetSourcePosition,
3753 BasicVideo_SetDefaultSourcePosition,
3754 BasicVideo_SetDestinationPosition,
3755 BasicVideo_GetDestinationPosition,
3756 BasicVideo_SetDefaultDestinationPosition,
3757 BasicVideo_GetVideoSize,
3758 BasicVideo_GetVideoPaletteEntries,
3759 BasicVideo_GetCurrentImage,
3760 BasicVideo_IsUsingDefaultSource,
3761 BasicVideo_IsUsingDefaultDestination,
3762 BasicVideo2_GetPreferredAspectRatio
3766 /*** IUnknown methods ***/
3767 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3768 REFIID riid,
3769 LPVOID*ppvObj) {
3770 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3772 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3774 return Filtergraph_QueryInterface(This, riid, ppvObj);
3777 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3778 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3780 TRACE("(%p/%p)->()\n", This, iface);
3782 return Filtergraph_AddRef(This);
3785 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3786 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3788 TRACE("(%p/%p)->()\n", This, iface);
3790 return Filtergraph_Release(This);
3793 /*** IDispatch methods ***/
3794 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3795 UINT*pctinfo) {
3796 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3797 IVideoWindow* pVideoWindow;
3798 HRESULT hr;
3800 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3802 EnterCriticalSection(&This->cs);
3804 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3806 if (hr == S_OK)
3807 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3809 LeaveCriticalSection(&This->cs);
3811 return hr;
3814 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3815 UINT iTInfo,
3816 LCID lcid,
3817 ITypeInfo**ppTInfo) {
3818 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3819 IVideoWindow* pVideoWindow;
3820 HRESULT hr;
3822 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3824 EnterCriticalSection(&This->cs);
3826 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3828 if (hr == S_OK)
3829 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3831 LeaveCriticalSection(&This->cs);
3833 return hr;
3836 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3837 REFIID riid,
3838 LPOLESTR*rgszNames,
3839 UINT cNames,
3840 LCID lcid,
3841 DISPID*rgDispId) {
3842 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3843 IVideoWindow* pVideoWindow;
3844 HRESULT hr;
3846 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3848 EnterCriticalSection(&This->cs);
3850 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3852 if (hr == S_OK)
3853 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3855 LeaveCriticalSection(&This->cs);
3857 return hr;
3860 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3861 DISPID dispIdMember,
3862 REFIID riid,
3863 LCID lcid,
3864 WORD wFlags,
3865 DISPPARAMS*pDispParams,
3866 VARIANT*pVarResult,
3867 EXCEPINFO*pExepInfo,
3868 UINT*puArgErr) {
3869 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3870 IVideoWindow* pVideoWindow;
3871 HRESULT hr;
3873 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);
3875 EnterCriticalSection(&This->cs);
3877 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3879 if (hr == S_OK)
3880 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3882 LeaveCriticalSection(&This->cs);
3884 return hr;
3888 /*** IVideoWindow methods ***/
3889 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3890 BSTR strCaption) {
3891 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3892 IVideoWindow* pVideoWindow;
3893 HRESULT hr;
3895 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3897 EnterCriticalSection(&This->cs);
3899 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3901 if (hr == S_OK)
3902 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3904 LeaveCriticalSection(&This->cs);
3906 return hr;
3909 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3910 BSTR *strCaption) {
3911 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3912 IVideoWindow* pVideoWindow;
3913 HRESULT hr;
3915 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3917 EnterCriticalSection(&This->cs);
3919 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3921 if (hr == S_OK)
3922 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3924 LeaveCriticalSection(&This->cs);
3926 return hr;
3929 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3930 long WindowStyle) {
3931 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3932 IVideoWindow* pVideoWindow;
3933 HRESULT hr;
3935 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3937 EnterCriticalSection(&This->cs);
3939 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3941 if (hr == S_OK)
3942 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3944 LeaveCriticalSection(&This->cs);
3946 return hr;
3949 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3950 long *WindowStyle) {
3951 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3952 IVideoWindow* pVideoWindow;
3953 HRESULT hr;
3955 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3957 EnterCriticalSection(&This->cs);
3959 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3961 if (hr == S_OK)
3962 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3964 LeaveCriticalSection(&This->cs);
3966 return hr;
3969 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3970 long WindowStyleEx) {
3971 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3972 IVideoWindow* pVideoWindow;
3973 HRESULT hr;
3975 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3977 EnterCriticalSection(&This->cs);
3979 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3981 if (hr == S_OK)
3982 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3984 LeaveCriticalSection(&This->cs);
3986 return hr;
3989 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3990 long *WindowStyleEx) {
3991 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3992 IVideoWindow* pVideoWindow;
3993 HRESULT hr;
3995 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3997 EnterCriticalSection(&This->cs);
3999 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4001 if (hr == S_OK)
4002 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4004 LeaveCriticalSection(&This->cs);
4006 return hr;
4009 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
4010 long AutoShow) {
4011 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4012 IVideoWindow* pVideoWindow;
4013 HRESULT hr;
4015 TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
4017 EnterCriticalSection(&This->cs);
4019 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4021 if (hr == S_OK)
4022 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4024 LeaveCriticalSection(&This->cs);
4026 return hr;
4029 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
4030 long *AutoShow) {
4031 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4032 IVideoWindow* pVideoWindow;
4033 HRESULT hr;
4035 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4037 EnterCriticalSection(&This->cs);
4039 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4041 if (hr == S_OK)
4042 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4044 LeaveCriticalSection(&This->cs);
4046 return hr;
4049 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
4050 long WindowState) {
4051 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4052 IVideoWindow* pVideoWindow;
4053 HRESULT hr;
4055 TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
4057 EnterCriticalSection(&This->cs);
4059 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4061 if (hr == S_OK)
4062 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4064 LeaveCriticalSection(&This->cs);
4066 return hr;
4069 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
4070 long *WindowState) {
4071 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4072 IVideoWindow* pVideoWindow;
4073 HRESULT hr;
4075 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4077 EnterCriticalSection(&This->cs);
4079 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4081 if (hr == S_OK)
4082 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4084 LeaveCriticalSection(&This->cs);
4086 return hr;
4089 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
4090 long BackgroundPalette) {
4091 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4092 IVideoWindow* pVideoWindow;
4093 HRESULT hr;
4095 TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
4097 EnterCriticalSection(&This->cs);
4099 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4101 if (hr == S_OK)
4102 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4104 LeaveCriticalSection(&This->cs);
4106 return hr;
4109 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4110 long *pBackgroundPalette) {
4111 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4112 IVideoWindow* pVideoWindow;
4113 HRESULT hr;
4115 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4117 EnterCriticalSection(&This->cs);
4119 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4121 if (hr == S_OK)
4122 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4124 LeaveCriticalSection(&This->cs);
4126 return hr;
4129 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
4130 long Visible) {
4131 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4132 IVideoWindow* pVideoWindow;
4133 HRESULT hr;
4135 TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
4137 EnterCriticalSection(&This->cs);
4139 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4141 if (hr == S_OK)
4142 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4144 LeaveCriticalSection(&This->cs);
4146 return hr;
4149 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
4150 long *pVisible) {
4151 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4152 IVideoWindow* pVideoWindow;
4153 HRESULT hr;
4155 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4157 EnterCriticalSection(&This->cs);
4159 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4161 if (hr == S_OK)
4162 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4164 LeaveCriticalSection(&This->cs);
4166 return hr;
4169 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
4170 long Left) {
4171 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4172 IVideoWindow* pVideoWindow;
4173 HRESULT hr;
4175 TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
4177 EnterCriticalSection(&This->cs);
4179 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4181 if (hr == S_OK)
4182 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4184 LeaveCriticalSection(&This->cs);
4186 return hr;
4189 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
4190 long *pLeft) {
4191 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4192 IVideoWindow* pVideoWindow;
4193 HRESULT hr;
4195 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4197 EnterCriticalSection(&This->cs);
4199 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4201 if (hr == S_OK)
4202 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4204 LeaveCriticalSection(&This->cs);
4206 return hr;
4209 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
4210 long Width) {
4211 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4212 IVideoWindow* pVideoWindow;
4213 HRESULT hr;
4215 TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
4217 EnterCriticalSection(&This->cs);
4219 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4221 if (hr == S_OK)
4222 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4224 LeaveCriticalSection(&This->cs);
4226 return hr;
4229 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
4230 long *pWidth) {
4231 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4232 IVideoWindow* pVideoWindow;
4233 HRESULT hr;
4235 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4237 EnterCriticalSection(&This->cs);
4239 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4241 if (hr == S_OK)
4242 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4244 LeaveCriticalSection(&This->cs);
4246 return hr;
4249 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
4250 long Top) {
4251 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4252 IVideoWindow* pVideoWindow;
4253 HRESULT hr;
4255 TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
4257 EnterCriticalSection(&This->cs);
4259 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4261 if (hr == S_OK)
4262 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4264 LeaveCriticalSection(&This->cs);
4266 return hr;
4269 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
4270 long *pTop) {
4271 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4272 IVideoWindow* pVideoWindow;
4273 HRESULT hr;
4275 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4277 EnterCriticalSection(&This->cs);
4279 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4281 if (hr == S_OK)
4282 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4284 LeaveCriticalSection(&This->cs);
4286 return hr;
4289 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
4290 long Height) {
4291 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4292 IVideoWindow* pVideoWindow;
4293 HRESULT hr;
4295 TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
4297 EnterCriticalSection(&This->cs);
4299 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4301 if (hr == S_OK)
4302 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4304 LeaveCriticalSection(&This->cs);
4306 return hr;
4309 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
4310 long *pHeight) {
4311 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4312 IVideoWindow* pVideoWindow;
4313 HRESULT hr;
4315 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4317 EnterCriticalSection(&This->cs);
4319 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4321 if (hr == S_OK)
4322 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4324 LeaveCriticalSection(&This->cs);
4326 return hr;
4329 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
4330 OAHWND Owner) {
4331 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4332 IVideoWindow* pVideoWindow;
4333 HRESULT hr;
4335 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4337 EnterCriticalSection(&This->cs);
4339 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4341 if (hr == S_OK)
4342 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4344 LeaveCriticalSection(&This->cs);
4346 return hr;
4349 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
4350 OAHWND *Owner) {
4351 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4352 IVideoWindow* pVideoWindow;
4353 HRESULT hr;
4355 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4357 EnterCriticalSection(&This->cs);
4359 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4361 if (hr == S_OK)
4362 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4364 LeaveCriticalSection(&This->cs);
4366 return hr;
4369 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
4370 OAHWND Drain) {
4371 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4372 IVideoWindow* pVideoWindow;
4373 HRESULT hr;
4375 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4377 EnterCriticalSection(&This->cs);
4379 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4381 if (hr == S_OK)
4382 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4384 LeaveCriticalSection(&This->cs);
4386 return hr;
4389 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
4390 OAHWND *Drain) {
4391 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4392 IVideoWindow* pVideoWindow;
4393 HRESULT hr;
4395 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4397 EnterCriticalSection(&This->cs);
4399 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4401 if (hr == S_OK)
4402 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4404 LeaveCriticalSection(&This->cs);
4406 return hr;
4409 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
4410 long *Color) {
4411 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4412 IVideoWindow* pVideoWindow;
4413 HRESULT hr;
4415 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4417 EnterCriticalSection(&This->cs);
4419 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4421 if (hr == S_OK)
4422 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4424 LeaveCriticalSection(&This->cs);
4426 return hr;
4429 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
4430 long Color) {
4431 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4432 IVideoWindow* pVideoWindow;
4433 HRESULT hr;
4435 TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
4437 EnterCriticalSection(&This->cs);
4439 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4441 if (hr == S_OK)
4442 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4444 LeaveCriticalSection(&This->cs);
4446 return hr;
4449 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
4450 long *FullScreenMode) {
4451 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4452 IVideoWindow* pVideoWindow;
4453 HRESULT hr;
4455 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4457 EnterCriticalSection(&This->cs);
4459 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4461 if (hr == S_OK)
4462 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4464 LeaveCriticalSection(&This->cs);
4466 return hr;
4469 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
4470 long FullScreenMode) {
4471 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4472 IVideoWindow* pVideoWindow;
4473 HRESULT hr;
4475 TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
4477 EnterCriticalSection(&This->cs);
4479 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4481 if (hr == S_OK)
4482 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4484 LeaveCriticalSection(&This->cs);
4486 return hr;
4489 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
4490 long Focus) {
4491 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4492 IVideoWindow* pVideoWindow;
4493 HRESULT hr;
4495 TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
4497 EnterCriticalSection(&This->cs);
4499 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4501 if (hr == S_OK)
4502 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4504 LeaveCriticalSection(&This->cs);
4506 return hr;
4509 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
4510 OAHWND hwnd,
4511 long uMsg,
4512 LONG_PTR wParam,
4513 LONG_PTR lParam) {
4514 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4515 IVideoWindow* pVideoWindow;
4516 HRESULT hr;
4518 TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
4520 EnterCriticalSection(&This->cs);
4522 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4524 if (hr == S_OK)
4525 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4527 LeaveCriticalSection(&This->cs);
4529 return hr;
4532 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
4533 long Left,
4534 long Top,
4535 long Width,
4536 long Height) {
4537 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4538 IVideoWindow* pVideoWindow;
4539 HRESULT hr;
4541 TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
4543 EnterCriticalSection(&This->cs);
4545 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4547 if (hr == S_OK)
4548 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4550 LeaveCriticalSection(&This->cs);
4552 return hr;
4555 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
4556 long *pLeft,
4557 long *pTop,
4558 long *pWidth,
4559 long *pHeight) {
4560 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4561 IVideoWindow* pVideoWindow;
4562 HRESULT hr;
4564 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4566 EnterCriticalSection(&This->cs);
4568 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4570 if (hr == S_OK)
4571 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4573 LeaveCriticalSection(&This->cs);
4575 return hr;
4578 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
4579 long *pWidth,
4580 long *pHeight) {
4581 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4582 IVideoWindow* pVideoWindow;
4583 HRESULT hr;
4585 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4587 EnterCriticalSection(&This->cs);
4589 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4591 if (hr == S_OK)
4592 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4594 LeaveCriticalSection(&This->cs);
4596 return hr;
4599 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
4600 long *pWidth,
4601 long *pHeight) {
4602 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4603 IVideoWindow* pVideoWindow;
4604 HRESULT hr;
4606 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4608 EnterCriticalSection(&This->cs);
4610 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4612 if (hr == S_OK)
4613 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4615 LeaveCriticalSection(&This->cs);
4617 return hr;
4620 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
4621 long *pLeft,
4622 long *pTop,
4623 long *pWidth,
4624 long *pHeight) {
4625 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4626 IVideoWindow* pVideoWindow;
4627 HRESULT hr;
4629 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4631 EnterCriticalSection(&This->cs);
4633 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4635 if (hr == S_OK)
4636 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4638 LeaveCriticalSection(&This->cs);
4640 return hr;
4643 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
4644 long HideCursor) {
4645 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4646 IVideoWindow* pVideoWindow;
4647 HRESULT hr;
4649 TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
4651 EnterCriticalSection(&This->cs);
4653 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4655 if (hr == S_OK)
4656 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4658 LeaveCriticalSection(&This->cs);
4660 return hr;
4663 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
4664 long *CursorHidden) {
4665 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4666 IVideoWindow* pVideoWindow;
4667 HRESULT hr;
4669 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4671 EnterCriticalSection(&This->cs);
4673 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4675 if (hr == S_OK)
4676 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4678 LeaveCriticalSection(&This->cs);
4680 return hr;
4684 static const IVideoWindowVtbl IVideoWindow_VTable =
4686 VideoWindow_QueryInterface,
4687 VideoWindow_AddRef,
4688 VideoWindow_Release,
4689 VideoWindow_GetTypeInfoCount,
4690 VideoWindow_GetTypeInfo,
4691 VideoWindow_GetIDsOfNames,
4692 VideoWindow_Invoke,
4693 VideoWindow_put_Caption,
4694 VideoWindow_get_Caption,
4695 VideoWindow_put_WindowStyle,
4696 VideoWindow_get_WindowStyle,
4697 VideoWindow_put_WindowStyleEx,
4698 VideoWindow_get_WindowStyleEx,
4699 VideoWindow_put_AutoShow,
4700 VideoWindow_get_AutoShow,
4701 VideoWindow_put_WindowState,
4702 VideoWindow_get_WindowState,
4703 VideoWindow_put_BackgroundPalette,
4704 VideoWindow_get_BackgroundPalette,
4705 VideoWindow_put_Visible,
4706 VideoWindow_get_Visible,
4707 VideoWindow_put_Left,
4708 VideoWindow_get_Left,
4709 VideoWindow_put_Width,
4710 VideoWindow_get_Width,
4711 VideoWindow_put_Top,
4712 VideoWindow_get_Top,
4713 VideoWindow_put_Height,
4714 VideoWindow_get_Height,
4715 VideoWindow_put_Owner,
4716 VideoWindow_get_Owner,
4717 VideoWindow_put_MessageDrain,
4718 VideoWindow_get_MessageDrain,
4719 VideoWindow_get_BorderColor,
4720 VideoWindow_put_BorderColor,
4721 VideoWindow_get_FullScreenMode,
4722 VideoWindow_put_FullScreenMode,
4723 VideoWindow_SetWindowForeground,
4724 VideoWindow_NotifyOwnerMessage,
4725 VideoWindow_SetWindowPosition,
4726 VideoWindow_GetWindowPosition,
4727 VideoWindow_GetMinIdealImageSize,
4728 VideoWindow_GetMaxIdealImageSize,
4729 VideoWindow_GetRestorePosition,
4730 VideoWindow_HideCursor,
4731 VideoWindow_IsCursorHidden
4735 /*** IUnknown methods ***/
4736 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
4737 REFIID riid,
4738 LPVOID*ppvObj) {
4739 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4741 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4743 return Filtergraph_QueryInterface(This, riid, ppvObj);
4746 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
4747 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4749 TRACE("(%p/%p)->()\n", This, iface);
4751 return Filtergraph_AddRef(This);
4754 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
4755 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4757 TRACE("(%p/%p)->()\n", This, iface);
4759 return Filtergraph_Release(This);
4762 /*** IDispatch methods ***/
4763 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4764 UINT*pctinfo) {
4765 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4767 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4769 return S_OK;
4772 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4773 UINT iTInfo,
4774 LCID lcid,
4775 ITypeInfo**ppTInfo) {
4776 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4778 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4780 return S_OK;
4783 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4784 REFIID riid,
4785 LPOLESTR*rgszNames,
4786 UINT cNames,
4787 LCID lcid,
4788 DISPID*rgDispId) {
4789 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4791 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4793 return S_OK;
4796 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4797 DISPID dispIdMember,
4798 REFIID riid,
4799 LCID lcid,
4800 WORD wFlags,
4801 DISPPARAMS*pDispParams,
4802 VARIANT*pVarResult,
4803 EXCEPINFO*pExepInfo,
4804 UINT*puArgErr) {
4805 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4807 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);
4809 return S_OK;
4812 /*** IMediaEvent methods ***/
4813 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4814 OAEVENT *hEvent) {
4815 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4817 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4819 *hEvent = (OAEVENT)This->evqueue.msg_event;
4821 return S_OK;
4824 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4825 long *lEventCode,
4826 LONG_PTR *lParam1,
4827 LONG_PTR *lParam2,
4828 long msTimeout) {
4829 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4830 Event evt;
4832 TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4834 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4836 *lEventCode = evt.lEventCode;
4837 *lParam1 = evt.lParam1;
4838 *lParam2 = evt.lParam2;
4839 return S_OK;
4842 *lEventCode = 0;
4843 return E_ABORT;
4846 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4847 long msTimeout,
4848 long *pEvCode) {
4849 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4851 TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4853 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4855 *pEvCode = This->CompletionStatus;
4856 return S_OK;
4859 *pEvCode = 0;
4860 return E_ABORT;
4863 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4864 long lEvCode) {
4865 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4867 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4869 if (lEvCode == EC_COMPLETE)
4870 This->HandleEcComplete = FALSE;
4871 else if (lEvCode == EC_REPAINT)
4872 This->HandleEcRepaint = FALSE;
4873 else if (lEvCode == EC_CLOCK_CHANGED)
4874 This->HandleEcClockChanged = FALSE;
4875 else
4876 return S_FALSE;
4878 return S_OK;
4881 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4882 long lEvCode) {
4883 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4885 TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4887 if (lEvCode == EC_COMPLETE)
4888 This->HandleEcComplete = TRUE;
4889 else if (lEvCode == EC_REPAINT)
4890 This->HandleEcRepaint = TRUE;
4891 else if (lEvCode == EC_CLOCK_CHANGED)
4892 This->HandleEcClockChanged = TRUE;
4893 else
4894 return S_FALSE;
4896 return S_OK;
4899 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4900 long lEvCode,
4901 LONG_PTR lParam1,
4902 LONG_PTR lParam2) {
4903 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4905 TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4907 return S_OK;
4910 /*** IMediaEventEx methods ***/
4911 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4912 OAHWND hwnd,
4913 long lMsg,
4914 LONG_PTR lInstanceData) {
4915 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4917 TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4919 This->notif.hWnd = (HWND)hwnd;
4920 This->notif.msg = lMsg;
4921 This->notif.instance = (long) lInstanceData;
4923 return S_OK;
4926 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4927 long lNoNotifyFlags) {
4928 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4930 TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4932 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4933 return E_INVALIDARG;
4935 This->notif.disabled = lNoNotifyFlags;
4937 return S_OK;
4940 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4941 long *lplNoNotifyFlags) {
4942 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4944 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4946 if (!lplNoNotifyFlags)
4947 return E_POINTER;
4949 *lplNoNotifyFlags = This->notif.disabled;
4951 return S_OK;
4955 static const IMediaEventExVtbl IMediaEventEx_VTable =
4957 MediaEvent_QueryInterface,
4958 MediaEvent_AddRef,
4959 MediaEvent_Release,
4960 MediaEvent_GetTypeInfoCount,
4961 MediaEvent_GetTypeInfo,
4962 MediaEvent_GetIDsOfNames,
4963 MediaEvent_Invoke,
4964 MediaEvent_GetEventHandle,
4965 MediaEvent_GetEvent,
4966 MediaEvent_WaitForCompletion,
4967 MediaEvent_CancelDefaultHandling,
4968 MediaEvent_RestoreDefaultHandling,
4969 MediaEvent_FreeEventParams,
4970 MediaEvent_SetNotifyWindow,
4971 MediaEvent_SetNotifyFlags,
4972 MediaEvent_GetNotifyFlags
4976 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4978 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4980 return Filtergraph_QueryInterface(This, riid, ppv);
4983 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4985 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4987 return Filtergraph_AddRef(This);
4990 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4992 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4994 return Filtergraph_Release(This);
4997 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4999 FIXME("(%p): stub\n", pClassID);
5001 return E_NOTIMPL;
5004 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5006 FIXME("(): stub\n");
5008 return E_NOTIMPL;
5011 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5013 FIXME("(): stub\n");
5015 return E_NOTIMPL;
5018 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5020 FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
5022 return E_NOTIMPL;
5025 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
5027 FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
5029 return E_NOTIMPL;
5032 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5034 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
5035 HRESULT hr = S_OK;
5036 int i;
5038 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5040 EnterCriticalSection(&This->cs);
5042 for (i = 0;i < This->nFilters;i++)
5044 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5045 if (FAILED(hr))
5046 break;
5049 if (FAILED(hr))
5051 for(;i >= 0;i--)
5052 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5054 else
5056 if (This->refClock)
5057 IReferenceClock_Release(This->refClock);
5058 This->refClock = pClock;
5059 if (This->refClock)
5060 IReferenceClock_AddRef(This->refClock);
5062 if (This->HandleEcClockChanged)
5064 IMediaEventSink *pEventSink;
5065 HRESULT eshr;
5067 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
5068 if (SUCCEEDED(eshr))
5070 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5071 IMediaEventSink_Release(pEventSink);
5076 LeaveCriticalSection(&This->cs);
5078 return hr;
5081 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5083 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
5085 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5087 if (!ppClock)
5088 return E_POINTER;
5090 EnterCriticalSection(&This->cs);
5092 *ppClock = This->refClock;
5093 if (*ppClock)
5094 IReferenceClock_AddRef(*ppClock);
5096 LeaveCriticalSection(&This->cs);
5098 return S_OK;
5101 static const IMediaFilterVtbl IMediaFilter_VTable =
5103 MediaFilter_QueryInterface,
5104 MediaFilter_AddRef,
5105 MediaFilter_Release,
5106 MediaFilter_GetClassID,
5107 MediaFilter_Stop,
5108 MediaFilter_Pause,
5109 MediaFilter_Run,
5110 MediaFilter_GetState,
5111 MediaFilter_SetSyncSource,
5112 MediaFilter_GetSyncSource
5115 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
5117 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5119 return Filtergraph_QueryInterface(This, riid, ppv);
5122 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5124 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5126 return Filtergraph_AddRef(This);
5129 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5131 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5133 return Filtergraph_Release(This);
5136 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
5138 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
5139 Event evt;
5141 TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5143 /* We need thread safety here, let's use the events queue's one */
5144 EnterCriticalSection(&This->evqueue.msg_crst);
5146 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5148 TRACE("Process EC_COMPLETE notification\n");
5149 if (++This->EcCompleteCount == This->nRenderers)
5151 evt.lEventCode = EC_COMPLETE;
5152 evt.lParam1 = S_OK;
5153 evt.lParam2 = 0;
5154 TRACE("Send EC_COMPLETE to app\n");
5155 EventsQueue_PutEvent(&This->evqueue, &evt);
5156 if (!This->notif.disabled && This->notif.hWnd)
5158 TRACE("Send Window message\n");
5159 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5161 This->CompletionStatus = EC_COMPLETE;
5162 SetEvent(This->hEventCompletion);
5165 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5167 /* FIXME: Not handled yet */
5169 else
5171 evt.lEventCode = EventCode;
5172 evt.lParam1 = EventParam1;
5173 evt.lParam2 = EventParam2;
5174 EventsQueue_PutEvent(&This->evqueue, &evt);
5175 if (!This->notif.disabled && This->notif.hWnd)
5176 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5179 LeaveCriticalSection(&This->evqueue.msg_crst);
5180 return S_OK;
5183 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5185 MediaEventSink_QueryInterface,
5186 MediaEventSink_AddRef,
5187 MediaEventSink_Release,
5188 MediaEventSink_Notify
5191 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
5193 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5195 return Filtergraph_QueryInterface(This, riid, ppv);
5198 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5200 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5202 return Filtergraph_AddRef(This);
5205 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5207 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5209 return Filtergraph_Release(This);
5212 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
5213 IPin* pOutputPin,
5214 IPin* pInputPin,
5215 const AM_MEDIA_TYPE* pmtFirstConnection,
5216 IBaseFilter* pUsingFilter,
5217 HANDLE hAbortEvent,
5218 DWORD dwFlags)
5220 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5222 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5224 return E_NOTIMPL;
5227 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
5228 IGraphConfigCallback* pCallback,
5229 PVOID pvContext,
5230 DWORD dwFlags,
5231 HANDLE hAbortEvent)
5233 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5234 HRESULT hr;
5236 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5238 if (hAbortEvent)
5239 FIXME("The parameter hAbortEvent is not handled!\n");
5241 EnterCriticalSection(&This->cs);
5243 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5245 LeaveCriticalSection(&This->cs);
5247 return hr;
5250 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
5251 IBaseFilter* pFilter)
5253 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5255 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5257 return E_NOTIMPL;
5260 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
5261 IEnumFilters** pEnum)
5263 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5265 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5267 return E_NOTIMPL;
5270 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
5271 IBaseFilter* pFilter)
5273 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5275 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5277 return E_NOTIMPL;
5280 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
5281 REFERENCE_TIME* prtStart)
5283 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5285 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5287 return E_NOTIMPL;
5290 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
5291 IPin* pOutputPin,
5292 IPinConnection* pConnection,
5293 HANDLE hEventAbort)
5295 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5297 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5299 return E_NOTIMPL;
5302 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
5303 IBaseFilter* pFilter,
5304 DWORD dwFlags)
5306 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5308 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5310 return E_NOTIMPL;
5313 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
5314 IBaseFilter* pFilter,
5315 DWORD* dwFlags)
5317 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5319 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5321 return E_NOTIMPL;
5324 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
5325 IBaseFilter* pFilter,
5326 DWORD dwFlags)
5328 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
5330 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5332 return E_NOTIMPL;
5335 static const IGraphConfigVtbl IGraphConfig_VTable =
5337 GraphConfig_QueryInterface,
5338 GraphConfig_AddRef,
5339 GraphConfig_Release,
5340 GraphConfig_Reconnect,
5341 GraphConfig_Reconfigure,
5342 GraphConfig_AddFilterToCache,
5343 GraphConfig_EnumCacheFilter,
5344 GraphConfig_RemoveFilterFromCache,
5345 GraphConfig_GetStartTime,
5346 GraphConfig_PushThroughData,
5347 GraphConfig_SetFilterFlags,
5348 GraphConfig_GetFilterFlags,
5349 GraphConfig_RemoveFilterEx
5352 static const IUnknownVtbl IInner_VTable =
5354 FilterGraphInner_QueryInterface,
5355 FilterGraphInner_AddRef,
5356 FilterGraphInner_Release
5359 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
5360 REFIID riid,
5361 LPVOID * ppv) {
5362 if (This->bAggregatable)
5363 This->bUnkOuterValid = TRUE;
5365 if (This->pUnkOuter)
5367 if (This->bAggregatable)
5368 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
5370 if (IsEqualIID(riid, &IID_IUnknown))
5372 HRESULT hr;
5374 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5375 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5376 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5377 This->bAggregatable = TRUE;
5378 return hr;
5381 *ppv = NULL;
5382 return E_NOINTERFACE;
5385 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
5388 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This) {
5389 if (This->pUnkOuter && This->bUnkOuterValid)
5390 return IUnknown_AddRef(This->pUnkOuter);
5391 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
5394 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This) {
5395 if (This->pUnkOuter && This->bUnkOuterValid)
5396 return IUnknown_Release(This->pUnkOuter);
5397 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
5400 /* This is the only function that actually creates a FilterGraph class... */
5401 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5403 IFilterGraphImpl *fimpl;
5404 HRESULT hr;
5406 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5408 *ppObj = NULL;
5410 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5411 fimpl->pUnkOuter = pUnkOuter;
5412 fimpl->bUnkOuterValid = FALSE;
5413 fimpl->bAggregatable = FALSE;
5414 fimpl->IInner_vtbl = &IInner_VTable;
5415 fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable;
5416 fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
5417 fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
5418 fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
5419 fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
5420 fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
5421 fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
5422 fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
5423 fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
5424 fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
5425 fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
5426 fimpl->ref = 1;
5427 fimpl->ppFiltersInGraph = NULL;
5428 fimpl->pFilterNames = NULL;
5429 fimpl->nFilters = 0;
5430 fimpl->filterCapacity = 0;
5431 fimpl->nameIndex = 1;
5432 fimpl->refClock = NULL;
5433 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5434 fimpl->HandleEcComplete = TRUE;
5435 fimpl->HandleEcRepaint = TRUE;
5436 fimpl->HandleEcClockChanged = TRUE;
5437 fimpl->notif.hWnd = 0;
5438 fimpl->notif.disabled = FALSE;
5439 fimpl->nRenderers = 0;
5440 fimpl->EcCompleteCount = 0;
5441 fimpl->state = State_Stopped;
5442 EventsQueue_Init(&fimpl->evqueue);
5443 InitializeCriticalSection(&fimpl->cs);
5444 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5445 fimpl->nItfCacheEntries = 0;
5446 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5447 fimpl->start_time = fimpl->position = 0;
5448 fimpl->stop_position = -1;
5449 fimpl->punkFilterMapper2 = NULL;
5450 fimpl->recursioncount = 0;
5452 /* create Filtermapper aggregated. */
5453 hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER,
5454 &IID_IUnknown, (LPVOID*)&fimpl->punkFilterMapper2);
5456 if (SUCCEEDED(hr)) {
5457 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
5460 if (SUCCEEDED(hr)) {
5461 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5462 if (pUnkOuter) IUnknown_Release(pUnkOuter);
5463 else IUnknown_Release((IUnknown*)&fimpl->IInner_vtbl);
5466 if (FAILED(hr)) {
5467 ERR("Unable to create filter mapper (%x)\n", hr);
5468 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5469 CloseHandle(fimpl->hEventCompletion);
5470 EventsQueue_Destroy(&fimpl->evqueue);
5471 fimpl->cs.DebugInfo->Spare[0] = 0;
5472 DeleteCriticalSection(&fimpl->cs);
5473 CoTaskMemFree(fimpl);
5474 return hr;
5476 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
5478 *ppObj = fimpl;
5479 return S_OK;
5482 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5484 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5485 return FilterGraph_create(pUnkOuter, ppObj);