winemenubuilder: Fix encoder method argument.
[wine.git] / dlls / quartz / filtergraph.c
blob7abffa5045a5d944b8fb0bb096dedbcedc3e7192
1 /* DirectShow FilterGraph object (QUARTZ.DLL)
3 * Copyright 2002 Lionel Ulmer
4 * Copyright 2004 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdarg.h>
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "shlwapi.h"
31 #include "dshow.h"
32 #include "wine/debug.h"
33 #include "quartz_private.h"
34 #include "ole2.h"
35 #include "olectl.h"
36 #include "strmif.h"
37 #include "vfwmsgs.h"
38 #include "evcode.h"
39 #include "wine/heap.h"
40 #include "wine/list.h"
41 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
46 typedef struct {
47 HWND hWnd; /* Target window */
48 UINT msg; /* User window message */
49 LONG_PTR instance; /* User data */
50 int disabled; /* Disabled messages posting */
51 } WndNotify;
53 typedef struct {
54 LONG lEventCode; /* Event code */
55 LONG_PTR lParam1; /* Param1 */
56 LONG_PTR lParam2; /* Param2 */
57 } Event;
59 /* messages ring implementation for queuing events (taken from winmm) */
60 #define EVENTS_RING_BUFFER_INCREMENT 64
61 typedef struct {
62 Event* messages;
63 int ring_buffer_size;
64 int msg_tosave;
65 int msg_toget;
66 CRITICAL_SECTION msg_crst;
67 HANDLE msg_event; /* Signaled for no empty queue */
68 } EventsQueue;
70 static int EventsQueue_Init(EventsQueue* omr)
72 omr->msg_toget = 0;
73 omr->msg_tosave = 0;
74 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
75 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
76 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
77 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
79 InitializeCriticalSection(&omr->msg_crst);
80 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
81 return TRUE;
84 static int EventsQueue_Destroy(EventsQueue* omr)
86 CloseHandle(omr->msg_event);
87 CoTaskMemFree(omr->messages);
88 omr->msg_crst.DebugInfo->Spare[0] = 0;
89 DeleteCriticalSection(&omr->msg_crst);
90 return TRUE;
93 static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
95 EnterCriticalSection(&omr->msg_crst);
96 if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))
98 int old_ring_buffer_size = omr->ring_buffer_size;
99 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
100 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
101 omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event));
102 /* Now we need to rearrange the ring buffer so that the new
103 buffers just allocated are in between omr->msg_tosave and
104 omr->msg_toget.
106 if (omr->msg_tosave < omr->msg_toget)
108 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
109 &(omr->messages[omr->msg_toget]),
110 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
112 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
115 omr->messages[omr->msg_tosave] = *evt;
116 SetEvent(omr->msg_event);
117 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
118 LeaveCriticalSection(&omr->msg_crst);
119 return TRUE;
122 static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
124 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
125 return FALSE;
127 EnterCriticalSection(&omr->msg_crst);
129 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
131 LeaveCriticalSection(&omr->msg_crst);
132 return FALSE;
135 *evt = omr->messages[omr->msg_toget];
136 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
138 /* Mark the buffer as empty if needed */
139 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
140 ResetEvent(omr->msg_event);
142 LeaveCriticalSection(&omr->msg_crst);
143 return TRUE;
146 #define MAX_ITF_CACHE_ENTRIES 3
147 typedef struct _ITF_CACHE_ENTRY {
148 const IID* riid;
149 IBaseFilter* filter;
150 IUnknown* iface;
151 } ITF_CACHE_ENTRY;
153 struct filter
155 struct list entry;
156 IBaseFilter *filter;
157 WCHAR *name;
160 typedef struct _IFilterGraphImpl {
161 IUnknown IUnknown_inner;
162 IFilterGraph2 IFilterGraph2_iface;
163 IMediaControl IMediaControl_iface;
164 IMediaSeeking IMediaSeeking_iface;
165 IBasicAudio IBasicAudio_iface;
166 IBasicVideo2 IBasicVideo2_iface;
167 IVideoWindow IVideoWindow_iface;
168 IMediaEventEx IMediaEventEx_iface;
169 IMediaFilter IMediaFilter_iface;
170 IMediaEventSink IMediaEventSink_iface;
171 IGraphConfig IGraphConfig_iface;
172 IMediaPosition IMediaPosition_iface;
173 IObjectWithSite IObjectWithSite_iface;
174 IGraphVersion IGraphVersion_iface;
175 /* IAMGraphStreams */
176 /* IAMStats */
177 /* IFilterChain */
178 /* IFilterMapper2 */
179 /* IQueueCommand */
180 /* IRegisterServiceProvider */
181 /* IResourceMananger */
182 /* IServiceProvider */
183 /* IVideoFrameStep */
185 IUnknown *outer_unk;
186 LONG ref;
187 IUnknown *punkFilterMapper2;
188 struct list filters;
189 LONG nameIndex;
190 IReferenceClock *refClock;
191 IBaseFilter *refClockProvider;
192 EventsQueue evqueue;
193 HANDLE hEventCompletion;
194 int CompletionStatus;
195 WndNotify notif;
196 int nRenderers;
197 int EcCompleteCount;
198 int HandleEcComplete;
199 int HandleEcRepaint;
200 int HandleEcClockChanged;
201 OAFilterState state;
202 CRITICAL_SECTION cs;
203 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
204 int nItfCacheEntries;
205 BOOL defaultclock;
206 GUID timeformatseek;
207 REFERENCE_TIME start_time;
208 REFERENCE_TIME pause_time;
209 LONGLONG stop_position;
210 LONG recursioncount;
211 IUnknown *pSite;
212 LONG version;
213 } IFilterGraphImpl;
215 struct enum_filters
217 IEnumFilters IEnumFilters_iface;
218 LONG ref;
219 IFilterGraphImpl *graph;
220 LONG version;
221 struct list *cursor;
224 static HRESULT create_enum_filters(IFilterGraphImpl *graph, struct list *cursor, IEnumFilters **out);
226 static inline struct enum_filters *impl_from_IEnumFilters(IEnumFilters *iface)
228 return CONTAINING_RECORD(iface, struct enum_filters, IEnumFilters_iface);
231 static HRESULT WINAPI EnumFilters_QueryInterface(IEnumFilters *iface, REFIID iid, void **out)
233 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
234 TRACE("enum_filters %p, iid %s, out %p.\n", enum_filters, qzdebugstr_guid(iid), out);
236 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumFilters))
238 IEnumFilters_AddRef(*out = iface);
239 return S_OK;
242 WARN("%s not implemented, returning E_NOINTERFACE.\n", qzdebugstr_guid(iid));
243 *out = NULL;
244 return E_NOINTERFACE;
247 static ULONG WINAPI EnumFilters_AddRef(IEnumFilters *iface)
249 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
250 ULONG ref = InterlockedIncrement(&enum_filters->ref);
252 TRACE("%p increasing refcount to %u.\n", enum_filters, ref);
254 return ref;
257 static ULONG WINAPI EnumFilters_Release(IEnumFilters *iface)
259 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
260 ULONG ref = InterlockedDecrement(&enum_filters->ref);
262 TRACE("%p decreasing refcount to %u.\n", enum_filters, ref);
264 if (!ref)
266 IUnknown_Release(enum_filters->graph->outer_unk);
267 heap_free(enum_filters);
270 return ref;
273 static HRESULT WINAPI EnumFilters_Next(IEnumFilters *iface, ULONG count,
274 IBaseFilter **filters, ULONG *fetched)
276 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
277 unsigned int i = 0;
279 TRACE("enum_filters %p, count %u, filters %p, fetched %p.\n",
280 enum_filters, count, filters, fetched);
282 if (enum_filters->version != enum_filters->graph->version)
283 return VFW_E_ENUM_OUT_OF_SYNC;
285 if (!filters)
286 return E_POINTER;
288 for (i = 0; i < count; ++i)
290 struct filter *filter = LIST_ENTRY(enum_filters->cursor, struct filter, entry);
292 if (!enum_filters->cursor)
293 break;
295 IBaseFilter_AddRef(filters[i] = filter->filter);
296 enum_filters->cursor = list_next(&enum_filters->graph->filters, enum_filters->cursor);
299 if (fetched)
300 *fetched = i;
302 return (i == count) ? S_OK : S_FALSE;
305 static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
307 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
309 TRACE("enum_filters %p, count %u.\n", enum_filters, count);
311 if (!enum_filters->cursor)
312 return S_FALSE;
314 while (count--)
316 if (!(enum_filters->cursor = list_next(&enum_filters->graph->filters, enum_filters->cursor)))
317 return S_FALSE;
320 return S_OK;
323 static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
325 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
327 TRACE("enum_filters %p.\n", enum_filters);
329 enum_filters->cursor = list_head(&enum_filters->graph->filters);
330 enum_filters->version = enum_filters->graph->version;
331 return S_OK;
334 static HRESULT WINAPI EnumFilters_Clone(IEnumFilters *iface, IEnumFilters **out)
336 struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
338 TRACE("enum_filters %p, out %p.\n", enum_filters, out);
340 return create_enum_filters(enum_filters->graph, enum_filters->cursor, out);
343 static const IEnumFiltersVtbl EnumFilters_vtbl =
345 EnumFilters_QueryInterface,
346 EnumFilters_AddRef,
347 EnumFilters_Release,
348 EnumFilters_Next,
349 EnumFilters_Skip,
350 EnumFilters_Reset,
351 EnumFilters_Clone,
354 static HRESULT create_enum_filters(IFilterGraphImpl *graph, struct list *cursor, IEnumFilters **out)
356 struct enum_filters *enum_filters;
358 if (!(enum_filters = heap_alloc(sizeof(*enum_filters))))
359 return E_OUTOFMEMORY;
361 enum_filters->IEnumFilters_iface.lpVtbl = &EnumFilters_vtbl;
362 enum_filters->ref = 1;
363 enum_filters->cursor = cursor;
364 enum_filters->graph = graph;
365 IUnknown_AddRef(graph->outer_unk);
366 enum_filters->version = graph->version;
368 *out = &enum_filters->IEnumFilters_iface;
369 return S_OK;
372 static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface)
374 return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner);
377 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObj)
379 IFilterGraphImpl *This = impl_from_IUnknown(iface);
380 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj);
382 if (IsEqualGUID(&IID_IUnknown, riid)) {
383 *ppvObj = &This->IUnknown_inner;
384 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
385 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
386 IsEqualGUID(&IID_IFilterGraph2, riid) ||
387 IsEqualGUID(&IID_IGraphBuilder, riid)) {
388 *ppvObj = &This->IFilterGraph2_iface;
389 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
390 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
391 *ppvObj = &This->IMediaControl_iface;
392 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
393 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
394 *ppvObj = &This->IMediaSeeking_iface;
395 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
396 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
397 *ppvObj = &This->IBasicAudio_iface;
398 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
399 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
400 IsEqualGUID(&IID_IBasicVideo2, riid)) {
401 *ppvObj = &This->IBasicVideo2_iface;
402 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
403 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
404 *ppvObj = &This->IVideoWindow_iface;
405 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
406 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
407 IsEqualGUID(&IID_IMediaEventEx, riid)) {
408 *ppvObj = &This->IMediaEventEx_iface;
409 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
410 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
411 IsEqualGUID(&IID_IPersist, riid)) {
412 *ppvObj = &This->IMediaFilter_iface;
413 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
414 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
415 *ppvObj = &This->IMediaEventSink_iface;
416 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
417 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
418 *ppvObj = &This->IGraphConfig_iface;
419 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
420 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
421 *ppvObj = &This->IMediaPosition_iface;
422 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
423 } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) {
424 *ppvObj = &This->IObjectWithSite_iface;
425 TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj);
426 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
427 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
428 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
429 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
430 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
431 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
432 } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
433 TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
434 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
435 } else if (IsEqualGUID(&IID_IGraphVersion, riid)) {
436 *ppvObj = &This->IGraphVersion_iface;
437 TRACE(" returning IGraphVersion interface (%p)\n", *ppvObj);
438 } else {
439 *ppvObj = NULL;
440 FIXME("unknown interface %s\n", debugstr_guid(riid));
441 return E_NOINTERFACE;
444 IUnknown_AddRef((IUnknown *)*ppvObj);
445 return S_OK;
448 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown *iface)
450 IFilterGraphImpl *This = impl_from_IUnknown(iface);
451 ULONG ref = InterlockedIncrement(&This->ref);
453 TRACE("(%p)->(): new ref = %d\n", This, ref);
455 return ref;
458 static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
460 IFilterGraphImpl *This = impl_from_IUnknown(iface);
461 ULONG ref = InterlockedDecrement(&This->ref);
462 struct filter *filter, *next;
464 TRACE("(%p)->(): new ref = %d\n", This, ref);
466 if (ref == 0) {
467 int i;
469 This->ref = 1; /* guard against reentrancy (aggregation). */
471 IMediaControl_Stop(&This->IMediaControl_iface);
473 LIST_FOR_EACH_ENTRY_SAFE(filter, next, &This->filters, struct filter, entry)
475 IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, filter->filter);
478 if (This->refClock)
479 IReferenceClock_Release(This->refClock);
481 for (i = 0; i < This->nItfCacheEntries; i++)
483 if (This->ItfCacheEntries[i].iface)
484 IUnknown_Release(This->ItfCacheEntries[i].iface);
487 IUnknown_Release(This->punkFilterMapper2);
489 if (This->pSite) IUnknown_Release(This->pSite);
491 CloseHandle(This->hEventCompletion);
492 EventsQueue_Destroy(&This->evqueue);
493 This->cs.DebugInfo->Spare[0] = 0;
494 DeleteCriticalSection(&This->cs);
495 CoTaskMemFree(This);
497 return ref;
500 static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface)
502 return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface);
505 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj)
507 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
509 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
511 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
514 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface)
516 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
518 TRACE("(%p/%p)->()\n", This, iface);
520 return IUnknown_AddRef(This->outer_unk);
523 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
525 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
527 TRACE("(%p/%p)->()\n", This, iface);
529 return IUnknown_Release(This->outer_unk);
532 static IBaseFilter *find_filter_by_name(IFilterGraphImpl *graph, const WCHAR *name)
534 struct filter *filter;
536 LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
538 if (!strcmpW(filter->name, name))
539 return filter->filter;
542 return NULL;
545 /*** IFilterGraph methods ***/
546 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
547 LPCWSTR pName)
549 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
550 struct filter *entry;
551 HRESULT hr;
552 int j;
553 WCHAR* wszFilterName = NULL;
554 BOOL duplicate_name = FALSE;
556 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
558 if (!pFilter)
559 return E_POINTER;
561 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
563 if (pName && find_filter_by_name(This, pName))
564 duplicate_name = TRUE;
566 /* If no name given or name already existing, generate one */
567 if (!pName || duplicate_name)
569 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
570 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
572 for (j = 0; j < 10000 ; j++)
574 /* Create name */
575 if (pName)
576 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
577 else
578 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
579 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
581 if (This->nameIndex++ == 10000)
582 This->nameIndex = 1;
584 if (!find_filter_by_name(This, wszFilterName))
585 break;
587 /* Unable to find a suitable name */
588 if (j == 10000)
590 CoTaskMemFree(wszFilterName);
591 return VFW_E_DUPLICATE_NAME;
594 else
595 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
597 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)&This->IFilterGraph2_iface, wszFilterName);
598 if (FAILED(hr))
600 CoTaskMemFree(wszFilterName);
601 return hr;
604 if (!(entry = heap_alloc(sizeof(*entry))))
606 CoTaskMemFree(wszFilterName);
607 return E_OUTOFMEMORY;
610 IBaseFilter_AddRef(entry->filter = pFilter);
611 entry->name = wszFilterName;
612 list_add_head(&This->filters, &entry->entry);
613 This->version++;
615 return duplicate_name ? VFW_S_DUPLICATE_NAME : hr;
618 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
620 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
621 struct filter *entry;
622 int i;
623 HRESULT hr = E_FAIL;
625 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
627 /* FIXME: check graph is stopped */
629 LIST_FOR_EACH_ENTRY(entry, &This->filters, struct filter, entry)
631 if (entry->filter == pFilter)
633 IEnumPins *penumpins = NULL;
634 FILTER_STATE state;
636 if (This->defaultclock && This->refClockProvider == pFilter)
638 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
639 This->defaultclock = TRUE;
642 TRACE("Removing filter %s.\n", debugstr_w(entry->name));
643 IBaseFilter_GetState(pFilter, 0, &state);
644 if (state == State_Running)
645 IBaseFilter_Pause(pFilter);
646 if (state != State_Stopped)
647 IBaseFilter_Stop(pFilter);
649 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
650 if (SUCCEEDED(hr)) {
651 IPin *ppin;
652 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
654 IPin *victim = NULL;
655 HRESULT h;
656 IPin_ConnectedTo(ppin, &victim);
657 if (victim)
659 h = IPin_Disconnect(victim);
660 TRACE("Disconnect other side: %08x\n", h);
661 if (h == VFW_E_NOT_STOPPED)
663 PIN_INFO pinfo;
664 IPin_QueryPinInfo(victim, &pinfo);
666 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
667 if (state == State_Running)
668 IBaseFilter_Pause(pinfo.pFilter);
669 IBaseFilter_Stop(pinfo.pFilter);
670 IBaseFilter_Release(pinfo.pFilter);
671 h = IPin_Disconnect(victim);
672 TRACE("Disconnect retry: %08x\n", h);
674 IPin_Release(victim);
676 h = IPin_Disconnect(ppin);
677 TRACE("Disconnect 2: %08x\n", h);
679 IPin_Release(ppin);
681 IEnumPins_Release(penumpins);
684 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, NULL);
685 if (SUCCEEDED(hr))
687 IBaseFilter_SetSyncSource(pFilter, NULL);
688 IBaseFilter_Release(pFilter);
689 list_remove(&entry->entry);
690 heap_free(entry);
691 This->version++;
692 /* Invalidate interfaces in the cache */
693 for (i = 0; i < This->nItfCacheEntries; i++)
694 if (pFilter == This->ItfCacheEntries[i].filter)
696 IUnknown_Release(This->ItfCacheEntries[i].iface);
697 This->ItfCacheEntries[i].iface = NULL;
698 This->ItfCacheEntries[i].filter = NULL;
700 return S_OK;
702 break;
706 return hr; /* FIXME: check this error code */
709 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **out)
711 IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
713 TRACE("graph %p, out %p.\n", graph, out);
715 return create_enum_filters(graph, list_head(&graph->filters), out);
718 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
719 const WCHAR *name, IBaseFilter **filter)
721 IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
723 TRACE("graph %p, name %s, filter %p.\n", graph, debugstr_w(name), filter);
725 if (!filter)
726 return E_POINTER;
728 if ((*filter = find_filter_by_name(graph, name)))
730 IBaseFilter_AddRef(*filter);
731 return S_OK;
734 return VFW_E_NOT_FOUND;
737 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
738 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
740 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
742 #if 1
743 HRESULT hr;
744 PIN_INFO info_out, info_in;
746 hr = IPin_QueryPinInfo(out, &info_out);
747 if (FAILED(hr))
748 return hr;
749 if (info_out.dir != PINDIR_OUTPUT)
751 IBaseFilter_Release(info_out.pFilter);
752 return VFW_E_CANNOT_CONNECT;
755 hr = IPin_QueryPinInfo(in, &info_in);
756 if (SUCCEEDED(hr))
757 IBaseFilter_Release(info_in.pFilter);
758 if (FAILED(hr))
759 goto out;
760 if (info_in.dir != PINDIR_INPUT)
762 hr = VFW_E_CANNOT_CONNECT;
763 goto out;
766 if (info_out.pFilter == info_in.pFilter)
767 hr = VFW_E_CIRCULAR_GRAPH;
768 else
770 IEnumPins *enumpins;
771 IPin *test;
773 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
774 if (FAILED(hr))
775 goto out;
777 IEnumPins_Reset(enumpins);
778 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
780 PIN_DIRECTION dir = PINDIR_OUTPUT;
781 IPin_QueryDirection(test, &dir);
782 if (dir == PINDIR_INPUT)
784 IPin *victim = NULL;
785 IPin_ConnectedTo(test, &victim);
786 if (victim)
788 hr = CheckCircularConnection(This, victim, in);
789 IPin_Release(victim);
790 if (FAILED(hr))
792 IPin_Release(test);
793 break;
797 IPin_Release(test);
799 IEnumPins_Release(enumpins);
802 out:
803 IBaseFilter_Release(info_out.pFilter);
804 if (FAILED(hr))
805 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
806 return hr;
807 #else
808 /* Debugging filtergraphs not enabled */
809 return S_OK;
810 #endif
814 /* NOTE: despite the implication, it doesn't matter which
815 * way round you put in the input and output pins */
816 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut,
817 const AM_MEDIA_TYPE *pmt)
819 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
820 PIN_DIRECTION dir;
821 HRESULT hr;
823 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
825 /* FIXME: check pins are in graph */
827 if (TRACE_ON(quartz))
829 PIN_INFO PinInfo;
831 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
832 if (FAILED(hr))
833 return hr;
835 TRACE("Filter owning ppinIn(%p) => %p\n", ppinIn, PinInfo.pFilter);
836 IBaseFilter_Release(PinInfo.pFilter);
838 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
839 if (FAILED(hr))
840 return hr;
842 TRACE("Filter owning ppinOut(%p) => %p\n", ppinOut, PinInfo.pFilter);
843 IBaseFilter_Release(PinInfo.pFilter);
846 hr = IPin_QueryDirection(ppinIn, &dir);
847 if (SUCCEEDED(hr))
849 if (dir == PINDIR_INPUT)
851 hr = CheckCircularConnection(This, ppinOut, ppinIn);
852 if (SUCCEEDED(hr))
853 hr = IPin_Connect(ppinOut, ppinIn, pmt);
855 else
857 hr = CheckCircularConnection(This, ppinIn, ppinOut);
858 if (SUCCEEDED(hr))
859 hr = IPin_Connect(ppinIn, ppinOut, pmt);
863 return hr;
866 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin)
868 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
869 IPin *pConnectedTo = NULL;
870 HRESULT hr;
871 PIN_DIRECTION pindir;
873 IPin_QueryDirection(ppin, &pindir);
874 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
876 TRACE("(%p/%p)->(%p) -- %p\n", This, iface, ppin, pConnectedTo);
878 if (FAILED(hr)) {
879 TRACE("Querying connected to failed: %x\n", hr);
880 return hr;
882 IPin_Disconnect(ppin);
883 IPin_Disconnect(pConnectedTo);
884 if (pindir == PINDIR_INPUT)
885 hr = IPin_Connect(pConnectedTo, ppin, NULL);
886 else
887 hr = IPin_Connect(ppin, pConnectedTo, NULL);
888 IPin_Release(pConnectedTo);
889 if (FAILED(hr))
890 WARN("Reconnecting pins failed, pins are not connected now..\n");
891 TRACE("-> %08x\n", hr);
892 return hr;
895 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
897 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
899 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
901 if (!ppin)
902 return E_POINTER;
904 return IPin_Disconnect(ppin);
907 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
909 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
910 IReferenceClock *pClock = NULL;
911 struct filter *filter;
912 HRESULT hr = S_OK;
914 TRACE("(%p/%p)->() live sources not handled properly!\n", This, iface);
916 EnterCriticalSection(&This->cs);
918 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
920 DWORD miscflags;
921 IAMFilterMiscFlags *flags = NULL;
922 IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags);
923 if (!flags)
924 continue;
925 miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
926 IAMFilterMiscFlags_Release(flags);
927 if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
928 IBaseFilter_QueryInterface(filter->filter, &IID_IReferenceClock, (void **)&pClock);
929 if (pClock)
930 break;
933 if (!pClock)
935 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
936 This->refClockProvider = NULL;
938 else
940 filter = LIST_ENTRY(list_tail(&This->filters), struct filter, entry);
941 This->refClockProvider = filter->filter;
944 if (SUCCEEDED(hr))
946 hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock);
947 This->defaultclock = TRUE;
948 IReferenceClock_Release(pClock);
950 LeaveCriticalSection(&This->cs);
952 return hr;
955 static HRESULT GetFilterInfo(IMoniker* pMoniker, VARIANT* pvar)
957 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
958 IPropertyBag * pPropBagCat = NULL;
959 HRESULT hr;
961 VariantInit(pvar);
963 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
965 if (SUCCEEDED(hr))
966 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
968 if (SUCCEEDED(hr))
969 TRACE("Moniker = %s\n", debugstr_w(V_BSTR(pvar)));
971 if (pPropBagCat)
972 IPropertyBag_Release(pPropBagCat);
974 return hr;
977 /* Attempt to connect one of the output pins on filter to sink. Helper for
978 * FilterGraph2_Connect(). */
979 static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter, IPin *sink)
981 IEnumPins *enumpins;
982 PIN_INFO info;
983 HRESULT hr;
984 IPin *pin;
986 hr = IBaseFilter_EnumPins(filter, &enumpins);
987 if (FAILED(hr))
988 return hr;
990 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
992 IPin_QueryPinInfo(pin, &info);
993 IBaseFilter_Release(info.pFilter);
994 if (info.dir == PINDIR_OUTPUT)
996 if (info.achName[0] == '~')
998 TRACE("Skipping non-rendered pin %s.\n", debugstr_w(info.achName));
999 IPin_Release(pin);
1000 continue;
1003 if (SUCCEEDED(IFilterGraph2_Connect(&graph->IFilterGraph2_iface, pin, sink)))
1005 IPin_Release(pin);
1006 IEnumPins_Release(enumpins);
1007 return S_OK;
1010 IPin_Release(pin);
1013 IEnumPins_Release(enumpins);
1014 return VFW_E_CANNOT_CONNECT;
1017 /*** IGraphBuilder methods ***/
1018 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
1020 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1021 struct filter *filter;
1022 HRESULT hr;
1023 IPin *pin;
1024 AM_MEDIA_TYPE* mt = NULL;
1025 IEnumMediaTypes* penummt = NULL;
1026 ULONG nbmt;
1027 IEnumPins* penumpins;
1028 IEnumMoniker* pEnumMoniker;
1029 GUID tab[2];
1030 IMoniker* pMoniker;
1031 PIN_INFO PinInfo;
1032 PIN_DIRECTION dir;
1033 IFilterMapper2 *pFilterMapper2 = NULL;
1035 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
1037 if(!ppinOut || !ppinIn)
1038 return E_POINTER;
1040 if (TRACE_ON(quartz))
1042 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
1043 if (FAILED(hr))
1044 return hr;
1046 TRACE("Filter owning ppinIn(%p) => %p\n", ppinIn, PinInfo.pFilter);
1047 IBaseFilter_Release(PinInfo.pFilter);
1049 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1050 if (FAILED(hr))
1051 return hr;
1053 TRACE("Filter owning ppinOut(%p) => %p\n", ppinOut, PinInfo.pFilter);
1054 IBaseFilter_Release(PinInfo.pFilter);
1057 EnterCriticalSection(&This->cs);
1058 ++This->recursioncount;
1059 if (This->recursioncount >= 5)
1061 WARN("Recursion count has reached %d\n", This->recursioncount);
1062 hr = VFW_E_CANNOT_CONNECT;
1063 goto out;
1066 hr = IPin_QueryDirection(ppinOut, &dir);
1067 if (FAILED(hr))
1068 goto out;
1070 if (dir == PINDIR_INPUT)
1072 IPin *temp;
1074 TRACE("Directions seem backwards, swapping pins\n");
1076 temp = ppinIn;
1077 ppinIn = ppinOut;
1078 ppinOut = temp;
1081 hr = CheckCircularConnection(This, ppinOut, ppinIn);
1082 if (FAILED(hr))
1083 goto out;
1085 /* Try direct connection first */
1086 hr = IPin_Connect(ppinOut, ppinIn, NULL);
1088 /* If direct connection succeeded, we should propagate that return value.
1089 * If it returned VFW_E_NOT_CONNECTED or VFW_E_NO_AUDIO_HARDWARE, then don't
1090 * even bother trying intermediate filters, since they won't succeed. */
1091 if (SUCCEEDED(hr) || hr == VFW_E_NOT_CONNECTED || hr == VFW_E_NO_AUDIO_HARDWARE)
1092 goto out;
1094 TRACE("Direct connection failed, trying to render using extra filters\n");
1096 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1098 hr = IBaseFilter_EnumPins(filter->filter, &penumpins);
1099 if (FAILED(hr))
1100 goto out;
1102 while (IEnumPins_Next(penumpins, 1, &pin, NULL) == S_OK)
1104 IPin_QueryDirection(pin, &dir);
1105 if (dir == PINDIR_INPUT && SUCCEEDED(IFilterGraph2_ConnectDirect(iface,
1106 ppinOut, pin, NULL)))
1108 if (SUCCEEDED(hr = connect_output_pin(This, filter->filter, ppinIn)))
1110 IPin_Release(pin);
1111 IEnumPins_Release(penumpins);
1112 goto out;
1115 IFilterGraph2_Disconnect(iface, pin);
1116 IFilterGraph2_Disconnect(iface, ppinOut);
1118 IPin_Release(pin);
1121 IEnumPins_Release(penumpins);
1124 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
1125 * filter to the minor mediatype of input pin of the renderer */
1126 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1127 if (FAILED(hr))
1129 WARN("EnumMediaTypes (%x)\n", hr);
1130 goto out;
1133 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1134 if (FAILED(hr)) {
1135 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1136 goto out;
1139 if (!nbmt)
1141 WARN("No media type found!\n");
1142 hr = VFW_E_INVALIDMEDIATYPE;
1143 goto out;
1145 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1146 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1148 hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
1149 if (FAILED(hr)) {
1150 WARN("Unable to get IFilterMapper2 (%x)\n", hr);
1151 goto out;
1154 /* Try to find a suitable filter that can connect to the pin to render */
1155 tab[0] = mt->majortype;
1156 tab[1] = mt->subtype;
1157 hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1158 if (FAILED(hr)) {
1159 WARN("Unable to enum filters (%x)\n", hr);
1160 goto out;
1163 hr = VFW_E_CANNOT_RENDER;
1164 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, NULL) == S_OK)
1166 VARIANT var;
1167 IPin* ppinfilter = NULL;
1168 IBaseFilter* pfilter = NULL;
1169 IAMGraphBuilderCallback *callback = NULL;
1171 hr = GetFilterInfo(pMoniker, &var);
1172 if (FAILED(hr)) {
1173 WARN("Unable to retrieve filter info (%x)\n", hr);
1174 goto error;
1177 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1178 IMoniker_Release(pMoniker);
1179 if (FAILED(hr)) {
1180 WARN("Unable to create filter (%x), trying next one\n", hr);
1181 goto error;
1184 if (This->pSite)
1186 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1187 if (callback)
1189 HRESULT rc;
1190 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1191 if (FAILED(rc))
1193 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1194 IAMGraphBuilderCallback_Release(callback);
1195 goto error;
1200 if (callback)
1202 HRESULT rc;
1203 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1204 IAMGraphBuilderCallback_Release(callback);
1205 if (FAILED(rc))
1207 IBaseFilter_Release(pfilter);
1208 pfilter = NULL;
1209 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1210 goto error;
1214 hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
1215 if (FAILED(hr)) {
1216 WARN("Unable to add filter (%x)\n", hr);
1217 IBaseFilter_Release(pfilter);
1218 pfilter = NULL;
1219 goto error;
1222 VariantClear(&var);
1224 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1225 if (FAILED(hr)) {
1226 WARN("Enumpins (%x)\n", hr);
1227 goto error;
1230 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, NULL);
1231 IEnumPins_Release(penumpins);
1233 if (FAILED(hr)) {
1234 WARN("Obtaining next pin: (%x)\n", hr);
1235 goto error;
1237 if (hr == S_FALSE) {
1238 WARN("Cannot use this filter: no pins\n");
1239 goto error;
1242 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1243 if (FAILED(hr)) {
1244 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1245 goto error;
1247 TRACE("Successfully connected to filter, follow chain...\n");
1249 if (SUCCEEDED(hr = connect_output_pin(This, pfilter, ppinIn)))
1251 IPin_Release(ppinfilter);
1252 IBaseFilter_Release(pfilter);
1253 break;
1256 error:
1257 VariantClear(&var);
1258 if (ppinfilter) IPin_Release(ppinfilter);
1259 if (pfilter) {
1260 IFilterGraph2_RemoveFilter(iface, pfilter);
1261 IBaseFilter_Release(pfilter);
1265 if (FAILED(hr))
1266 hr = VFW_E_CANNOT_CONNECT;
1268 IEnumMoniker_Release(pEnumMoniker);
1270 out:
1271 if (pFilterMapper2)
1272 IFilterMapper2_Release(pFilterMapper2);
1273 if (penummt)
1274 IEnumMediaTypes_Release(penummt);
1275 if (mt)
1276 DeleteMediaType(mt);
1277 --This->recursioncount;
1278 LeaveCriticalSection(&This->cs);
1279 TRACE("--> %08x\n", hr);
1280 return hr;
1283 /* Render all output pins of the given filter. Helper for FilterGraph2_Render(). */
1284 static HRESULT render_output_pins(IFilterGraphImpl *graph, IBaseFilter *filter)
1286 BOOL renderany = FALSE;
1287 BOOL renderall = TRUE;
1288 IEnumPins *enumpins;
1289 IPin *pin, *peer;
1290 PIN_INFO info;
1292 IBaseFilter_EnumPins(filter, &enumpins);
1293 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1295 IPin_QueryPinInfo(pin, &info);
1296 IBaseFilter_Release(info.pFilter);
1297 if (info.dir == PINDIR_OUTPUT)
1299 if (info.achName[0] == '~')
1301 TRACE("Skipping non-rendered pin %s.\n", debugstr_w(info.achName));
1302 IPin_Release(pin);
1303 continue;
1306 if (IPin_ConnectedTo(pin, &peer) == VFW_E_NOT_CONNECTED)
1308 HRESULT hr;
1309 hr = IFilterGraph2_Render(&graph->IFilterGraph2_iface, pin);
1310 if (SUCCEEDED(hr))
1311 renderany = TRUE;
1312 else
1313 renderall = FALSE;
1315 else
1316 IPin_Release(peer);
1319 IPin_Release(pin);
1322 IEnumPins_Release(enumpins);
1324 if (renderall)
1325 return S_OK;
1327 if (renderany)
1328 return VFW_S_PARTIAL_RENDER;
1330 return VFW_E_CANNOT_RENDER;
1333 /* Ogg hates me if I create a direct rendering method
1335 * It can only connect to a pin properly once, so use a recursive method that does
1337 * +----+ --- (PIN 1) (Render is called on this pin)
1338 * | |
1339 * +----+ --- (PIN 2)
1341 * Enumerate possible renderers that EXACTLY match the requested type
1343 * If none is available, try to add intermediate filters that can connect to the input pin
1344 * then call Render on that intermediate pin's output pins
1345 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1346 * and another filter that can connect to the input pin is tried
1347 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1348 * It's recursive, but fun!
1351 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1353 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1354 IEnumMediaTypes* penummt;
1355 struct filter *filter;
1356 AM_MEDIA_TYPE* mt;
1357 ULONG nbmt;
1358 HRESULT hr;
1360 IEnumMoniker* pEnumMoniker;
1361 GUID tab[4];
1362 ULONG nb;
1363 IMoniker* pMoniker;
1364 IFilterMapper2 *pFilterMapper2 = NULL;
1366 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1368 if (TRACE_ON(quartz))
1370 PIN_INFO PinInfo;
1372 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1373 if (FAILED(hr))
1374 return hr;
1376 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1377 IBaseFilter_Release(PinInfo.pFilter);
1380 /* Try to find out if there is a renderer for the specified subtype already, and use that
1382 EnterCriticalSection(&This->cs);
1383 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1385 IEnumPins *enumpins = NULL;
1386 IPin *pin = NULL;
1388 hr = IBaseFilter_EnumPins(filter->filter, &enumpins);
1390 if (FAILED(hr) || !enumpins)
1391 continue;
1393 IEnumPins_Reset(enumpins);
1394 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1396 IPin *to = NULL;
1397 PIN_DIRECTION dir = PINDIR_OUTPUT;
1399 IPin_QueryDirection(pin, &dir);
1400 if (dir != PINDIR_INPUT)
1402 IPin_Release(pin);
1403 continue;
1405 IPin_ConnectedTo(pin, &to);
1407 if (to == NULL)
1409 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1410 if (SUCCEEDED(hr))
1412 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1413 IPin_Release(pin);
1415 hr = render_output_pins(This, filter->filter);
1416 if (FAILED(hr))
1418 IPin_Disconnect(ppinOut);
1419 IPin_Disconnect(pin);
1420 continue;
1422 IEnumPins_Release(enumpins);
1423 LeaveCriticalSection(&This->cs);
1424 return hr;
1426 WARN("Could not connect!\n");
1428 else
1429 IPin_Release(to);
1431 IPin_Release(pin);
1433 IEnumPins_Release(enumpins);
1436 LeaveCriticalSection(&This->cs);
1438 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1439 if (FAILED(hr)) {
1440 WARN("EnumMediaTypes (%x)\n", hr);
1441 return hr;
1444 IEnumMediaTypes_Reset(penummt);
1446 /* Looks like no existing renderer of the kind exists
1447 * Try adding new ones
1449 tab[0] = tab[1] = GUID_NULL;
1450 while (SUCCEEDED(hr))
1452 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1453 if (FAILED(hr)) {
1454 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1455 break;
1457 if (!nbmt)
1459 hr = VFW_E_CANNOT_RENDER;
1460 break;
1462 else
1464 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1465 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1467 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1468 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1470 DeleteMediaType(mt);
1471 continue;
1474 if (pFilterMapper2 == NULL)
1476 hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
1477 if (FAILED(hr))
1479 WARN("Unable to query IFilterMapper2 (%x)\n", hr);
1480 break;
1484 /* Try to find a suitable renderer with the same media type */
1485 tab[0] = mt->majortype;
1486 tab[1] = mt->subtype;
1487 hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1488 if (FAILED(hr))
1490 WARN("Unable to enum filters (%x)\n", hr);
1491 break;
1494 hr = E_FAIL;
1496 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1498 VARIANT var;
1499 IPin* ppinfilter;
1500 IBaseFilter* pfilter = NULL;
1501 IEnumPins* penumpins = NULL;
1502 ULONG pin;
1504 hr = GetFilterInfo(pMoniker, &var);
1505 if (FAILED(hr)) {
1506 WARN("Unable to retrieve filter info (%x)\n", hr);
1507 goto error;
1510 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1511 IMoniker_Release(pMoniker);
1512 if (FAILED(hr))
1514 WARN("Unable to create filter (%x), trying next one\n", hr);
1515 goto error;
1518 hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
1519 if (FAILED(hr)) {
1520 WARN("Unable to add filter (%x)\n", hr);
1521 IBaseFilter_Release(pfilter);
1522 pfilter = NULL;
1523 goto error;
1526 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1527 if (FAILED(hr)) {
1528 WARN("Splitter Enumpins (%x)\n", hr);
1529 goto error;
1532 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1534 PIN_DIRECTION dir;
1536 if (pin == 0) {
1537 WARN("No Pin\n");
1538 hr = E_FAIL;
1539 goto error;
1542 hr = IPin_QueryDirection(ppinfilter, &dir);
1543 if (FAILED(hr)) {
1544 IPin_Release(ppinfilter);
1545 WARN("QueryDirection failed (%x)\n", hr);
1546 goto error;
1548 if (dir != PINDIR_INPUT) {
1549 IPin_Release(ppinfilter);
1550 continue; /* Wrong direction */
1553 /* Connect the pin to the "Renderer" */
1554 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1555 IPin_Release(ppinfilter);
1557 if (FAILED(hr)) {
1558 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_BSTR(&var)), hr);
1559 goto error;
1561 TRACE("Connected, recursing %s\n", debugstr_w(V_BSTR(&var)));
1563 VariantClear(&var);
1565 hr = render_output_pins(This, pfilter);
1566 if (FAILED(hr)) {
1567 WARN("Unable to connect recursively (%x)\n", hr);
1568 goto error;
1570 IBaseFilter_Release(pfilter);
1571 break;
1573 if (SUCCEEDED(hr)) {
1574 IEnumPins_Release(penumpins);
1575 break; /* out of IEnumMoniker_Next loop */
1578 /* IEnumPins_Next failed, all other failure case caught by goto error */
1579 WARN("IEnumPins_Next (%x)\n", hr);
1580 /* goto error */
1582 error:
1583 VariantClear(&var);
1584 if (penumpins)
1585 IEnumPins_Release(penumpins);
1586 if (pfilter) {
1587 IFilterGraph2_RemoveFilter(iface, pfilter);
1588 IBaseFilter_Release(pfilter);
1590 if (SUCCEEDED(hr)) DebugBreak();
1593 IEnumMoniker_Release(pEnumMoniker);
1594 if (nbmt)
1595 DeleteMediaType(mt);
1596 if (SUCCEEDED(hr))
1597 break;
1598 hr = S_OK;
1601 if (pFilterMapper2)
1602 IFilterMapper2_Release(pFilterMapper2);
1604 IEnumMediaTypes_Release(penummt);
1605 return hr;
1608 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1609 LPCWSTR lpcwstrPlayList)
1611 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1612 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1613 IBaseFilter* preader = NULL;
1614 IPin* ppinreader = NULL;
1615 IEnumPins* penumpins = NULL;
1616 struct filter *filter;
1617 HRESULT hr;
1618 BOOL partial = FALSE;
1619 BOOL any = FALSE;
1621 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1623 if (lpcwstrPlayList != NULL)
1624 return E_INVALIDARG;
1626 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1627 if (FAILED(hr))
1628 return hr;
1630 hr = IBaseFilter_EnumPins(preader, &penumpins);
1631 if (SUCCEEDED(hr))
1633 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1635 PIN_DIRECTION dir;
1637 IPin_QueryDirection(ppinreader, &dir);
1638 if (dir == PINDIR_OUTPUT)
1640 hr = IFilterGraph2_Render(iface, ppinreader);
1642 TRACE("Filters in chain:\n");
1643 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1644 TRACE("- %s.\n", debugstr_w(filter->name));
1646 if (SUCCEEDED(hr))
1647 any = TRUE;
1648 if (hr != S_OK)
1649 partial = TRUE;
1651 IPin_Release(ppinreader);
1653 IEnumPins_Release(penumpins);
1655 if (!any)
1656 hr = VFW_E_CANNOT_RENDER;
1657 else if (partial)
1658 hr = VFW_S_PARTIAL_RENDER;
1659 else
1660 hr = S_OK;
1662 IBaseFilter_Release(preader);
1664 TRACE("--> %08x\n", hr);
1665 return hr;
1668 static HRESULT CreateFilterInstanceAndLoadFile(GUID* clsid, LPCOLESTR pszFileName, IBaseFilter **filter)
1670 IFileSourceFilter *source = NULL;
1671 HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1672 TRACE("CLSID: %s\n", debugstr_guid(clsid));
1673 if (FAILED(hr))
1674 return hr;
1676 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1677 if (FAILED(hr))
1679 IBaseFilter_Release(*filter);
1680 return hr;
1683 /* Load the file in the file source filter */
1684 hr = IFileSourceFilter_Load(source, pszFileName, NULL);
1685 IFileSourceFilter_Release(source);
1686 if (FAILED(hr)) {
1687 WARN("Load (%x)\n", hr);
1688 IBaseFilter_Release(*filter);
1689 return hr;
1692 return hr;
1695 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1696 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1698 HRESULT hr;
1699 GUID clsid;
1700 IAsyncReader * pReader = NULL;
1701 IFileSourceFilter* pSource = NULL;
1702 IPin * pOutputPin = NULL;
1703 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
1705 /* Try to find a match without reading the file first */
1706 hr = GetClassMediaFile(NULL, pszFileName, NULL, NULL, &clsid);
1708 if (hr == S_OK)
1709 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1711 /* Now create a AyncReader instance, to check for signature bytes in the file */
1712 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1713 if (FAILED(hr))
1714 return hr;
1716 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID *)&pSource);
1717 if (FAILED(hr))
1719 IBaseFilter_Release(*filter);
1720 return hr;
1723 hr = IFileSourceFilter_Load(pSource, pszFileName, NULL);
1724 IFileSourceFilter_Release(pSource);
1725 if (FAILED(hr))
1727 IBaseFilter_Release(*filter);
1728 return hr;
1731 hr = IBaseFilter_FindPin(*filter, wszOutputPinName, &pOutputPin);
1732 if (FAILED(hr))
1734 IBaseFilter_Release(*filter);
1735 return hr;
1738 hr = IPin_QueryInterface(pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
1739 IPin_Release(pOutputPin);
1740 if (FAILED(hr))
1742 IBaseFilter_Release(*filter);
1743 return hr;
1746 /* Try again find a match */
1747 hr = GetClassMediaFile(pReader, pszFileName, NULL, NULL, &clsid);
1748 IAsyncReader_Release(pReader);
1750 if (hr == S_OK)
1752 /* Release the AsyncReader filter and create the matching one */
1753 IBaseFilter_Release(*filter);
1754 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1757 /* Return the AsyncReader filter */
1758 return S_OK;
1761 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1762 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1764 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1765 HRESULT hr;
1766 IBaseFilter* preader;
1767 IFileSourceFilter* pfile = NULL;
1768 AM_MEDIA_TYPE mt;
1769 WCHAR* filename;
1771 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1773 /* Try from file name first, then fall back to default asynchronous reader */
1774 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1775 if (FAILED(hr)) {
1776 WARN("Unable to create file source filter (%x)\n", hr);
1777 return hr;
1780 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1781 if (FAILED(hr)) {
1782 WARN("Unable add filter (%x)\n", hr);
1783 IBaseFilter_Release(preader);
1784 return hr;
1787 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1788 if (FAILED(hr)) {
1789 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1790 goto error;
1793 /* The file has been already loaded */
1794 hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1795 if (FAILED(hr)) {
1796 WARN("GetCurFile (%x)\n", hr);
1797 goto error;
1800 TRACE("File %s\n", debugstr_w(filename));
1801 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1802 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1804 if (ppFilter)
1805 *ppFilter = preader;
1806 IFileSourceFilter_Release(pfile);
1808 return S_OK;
1810 error:
1811 if (pfile)
1812 IFileSourceFilter_Release(pfile);
1813 IFilterGraph2_RemoveFilter(iface, preader);
1814 IBaseFilter_Release(preader);
1816 return hr;
1819 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1821 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1823 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1825 return S_OK;
1828 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1830 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1832 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1834 return S_OK;
1837 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1839 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1841 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1843 return S_OK;
1846 /*** IFilterGraph2 methods ***/
1847 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1848 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1850 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1851 HRESULT hr;
1852 IBaseFilter* pfilter;
1854 TRACE("(%p/%p)->(%p %p %s %p)\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1856 hr = IMoniker_BindToObject(pMoniker, pCtx, NULL, &IID_IBaseFilter, (void**)&pfilter);
1857 if(FAILED(hr)) {
1858 WARN("Unable to bind moniker to filter object (%x)\n", hr);
1859 return hr;
1862 hr = IFilterGraph2_AddFilter(iface, pfilter, lpcwstrFilterName);
1863 if (FAILED(hr)) {
1864 WARN("Unable to add filter (%x)\n", hr);
1865 IBaseFilter_Release(pfilter);
1866 return hr;
1869 if(ppFilter)
1870 *ppFilter = pfilter;
1871 else IBaseFilter_Release(pfilter);
1873 return S_OK;
1876 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1877 const AM_MEDIA_TYPE *pmt)
1879 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1881 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1883 return S_OK;
1886 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1887 DWORD *pvContext)
1889 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1891 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1893 return S_OK;
1897 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1899 FilterGraph2_QueryInterface,
1900 FilterGraph2_AddRef,
1901 FilterGraph2_Release,
1902 FilterGraph2_AddFilter,
1903 FilterGraph2_RemoveFilter,
1904 FilterGraph2_EnumFilters,
1905 FilterGraph2_FindFilterByName,
1906 FilterGraph2_ConnectDirect,
1907 FilterGraph2_Reconnect,
1908 FilterGraph2_Disconnect,
1909 FilterGraph2_SetDefaultSyncSource,
1910 FilterGraph2_Connect,
1911 FilterGraph2_Render,
1912 FilterGraph2_RenderFile,
1913 FilterGraph2_AddSourceFilter,
1914 FilterGraph2_SetLogFile,
1915 FilterGraph2_Abort,
1916 FilterGraph2_ShouldOperationContinue,
1917 FilterGraph2_AddSourceFilterForMoniker,
1918 FilterGraph2_ReconnectEx,
1919 FilterGraph2_RenderEx
1922 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
1924 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
1927 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
1929 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1931 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
1933 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1936 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
1938 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1940 TRACE("(%p/%p)->()\n", This, iface);
1942 return IUnknown_AddRef(This->outer_unk);
1945 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
1947 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1949 TRACE("(%p/%p)->()\n", This, iface);
1951 return IUnknown_Release(This->outer_unk);
1955 /*** IDispatch methods ***/
1956 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
1958 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1960 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1962 return S_OK;
1965 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
1966 ITypeInfo **ppTInfo)
1968 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1970 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1972 return S_OK;
1975 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
1976 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1978 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1980 TRACE("(%p/%p)->(%s, %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), rgszNames,
1981 cNames, lcid, rgDispId);
1983 return S_OK;
1986 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
1987 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
1988 UINT *puArgErr)
1990 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1992 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember,
1993 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1995 return S_OK;
1998 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
2000 static BOOL has_output_pins(IBaseFilter *filter)
2002 IEnumPins *enumpins;
2003 PIN_DIRECTION dir;
2004 IPin *pin;
2006 if (FAILED(IBaseFilter_EnumPins(filter, &enumpins)))
2007 return FALSE;
2009 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
2011 IPin_QueryDirection(pin, &dir);
2012 IPin_Release(pin);
2013 if (dir == PINDIR_OUTPUT)
2015 IEnumPins_Release(enumpins);
2016 return TRUE;
2020 IEnumPins_Release(enumpins);
2021 return FALSE;
2024 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
2026 IAMFilterMiscFlags *flags;
2027 IMediaSeeking *seeking;
2028 IEnumPins *enumpins;
2029 PIN_DIRECTION dir;
2030 HRESULT hr;
2031 IPin* pInputPin;
2032 PIN_INFO PinInfo;
2033 IPin *pin;
2035 TRACE("%p %p\n", pGraph, pOutputPin);
2036 PinInfo.pFilter = NULL;
2038 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
2040 if (SUCCEEDED(hr))
2042 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
2043 IPin_Release(pInputPin);
2046 if (SUCCEEDED(hr))
2047 hr = IBaseFilter_EnumPins(PinInfo.pFilter, &enumpins);
2049 if (SUCCEEDED(hr))
2051 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
2053 IPin_QueryDirection(pin, &dir);
2054 if (dir == PINDIR_OUTPUT)
2055 ExploreGraph(pGraph, pin, FoundFilter, data);
2056 IPin_Release(pin);
2059 IEnumPins_Release(enumpins);
2060 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
2062 if (SUCCEEDED(IBaseFilter_QueryInterface(PinInfo.pFilter,
2063 &IID_IAMFilterMiscFlags, (void **)&flags)))
2065 if (IAMFilterMiscFlags_GetMiscFlags(flags) & AM_FILTER_MISC_FLAGS_IS_RENDERER)
2066 pGraph->nRenderers++;
2067 IAMFilterMiscFlags_Release(flags);
2069 else if (SUCCEEDED(IBaseFilter_QueryInterface(PinInfo.pFilter,
2070 &IID_IMediaSeeking, (void **)&seeking)))
2072 if (!has_output_pins(PinInfo.pFilter))
2073 pGraph->nRenderers++;
2074 IMediaSeeking_Release(seeking);
2077 FoundFilter(PinInfo.pFilter, data);
2080 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
2081 return hr;
2084 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
2086 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
2087 return IBaseFilter_Run(pFilter, time);
2090 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
2092 return IBaseFilter_Pause(pFilter);
2095 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
2097 return IBaseFilter_Stop(pFilter);
2100 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
2102 FILTER_STATE state;
2103 DWORD time_end = data;
2104 DWORD time_now = GetTickCount();
2105 LONG wait;
2107 if (time_end == INFINITE)
2109 wait = INFINITE;
2111 else if (time_end > time_now)
2113 wait = time_end - time_now;
2115 else
2116 wait = 0;
2118 return IBaseFilter_GetState(pFilter, wait, &state);
2122 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
2124 struct filter *filter;
2125 IEnumPins* pEnum;
2126 HRESULT hr;
2127 IPin* pPin;
2128 DWORD dummy;
2129 PIN_DIRECTION dir;
2131 TRACE("(%p)->()\n", This);
2133 /* Explorer the graph from source filters to renderers, determine renderers
2134 * number and run filters from renderers to source filters */
2135 This->nRenderers = 0;
2136 ResetEvent(This->hEventCompletion);
2138 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
2140 BOOL source = TRUE;
2141 hr = IBaseFilter_EnumPins(filter->filter, &pEnum);
2142 if (hr != S_OK)
2144 WARN("Enum pins failed %x\n", hr);
2145 continue;
2147 /* Check if it is a source filter */
2148 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2150 IPin_QueryDirection(pPin, &dir);
2151 IPin_Release(pPin);
2152 if (dir == PINDIR_INPUT)
2154 source = FALSE;
2155 break;
2158 if (source)
2160 TRACE("Found source filter %p.\n", filter->filter);
2161 IEnumPins_Reset(pEnum);
2162 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2164 /* Explore the graph downstream from this pin */
2165 ExploreGraph(This, pPin, FoundFilter, data);
2166 IPin_Release(pPin);
2168 FoundFilter(filter->filter, data);
2170 IEnumPins_Release(pEnum);
2173 return S_FALSE;
2176 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
2178 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2180 return IMediaFilter_Run(&graph->IMediaFilter_iface, 0);
2183 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2185 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2187 return IMediaFilter_Pause(&graph->IMediaFilter_iface);
2190 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2192 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2194 return IMediaFilter_Stop(&graph->IMediaFilter_iface);
2197 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG timeout, OAFilterState *state)
2199 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2201 if (timeout < 0) timeout = INFINITE;
2203 return IMediaFilter_GetState(&graph->IMediaFilter_iface, timeout, (FILTER_STATE *)state);
2206 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2208 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2210 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename);
2212 return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL);
2215 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2216 IDispatch **ppUnk)
2218 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2220 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2222 return S_OK;
2225 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2227 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2229 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2231 return S_OK;
2234 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2236 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2238 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2240 return S_OK;
2243 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2245 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2247 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2249 return S_OK;
2253 static const IMediaControlVtbl IMediaControl_VTable =
2255 MediaControl_QueryInterface,
2256 MediaControl_AddRef,
2257 MediaControl_Release,
2258 MediaControl_GetTypeInfoCount,
2259 MediaControl_GetTypeInfo,
2260 MediaControl_GetIDsOfNames,
2261 MediaControl_Invoke,
2262 MediaControl_Run,
2263 MediaControl_Pause,
2264 MediaControl_Stop,
2265 MediaControl_GetState,
2266 MediaControl_RenderFile,
2267 MediaControl_AddSourceFilter,
2268 MediaControl_get_FilterCollection,
2269 MediaControl_get_RegFilterCollection,
2270 MediaControl_StopWhenReady
2273 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2275 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2278 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2280 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2282 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2284 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2287 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2289 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2291 TRACE("(%p/%p)->()\n", This, iface);
2293 return IUnknown_AddRef(This->outer_unk);
2296 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2298 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2300 TRACE("(%p/%p)->()\n", This, iface);
2302 return IUnknown_Release(This->outer_unk);
2305 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2307 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2308 BOOL allnotimpl = TRUE;
2309 HRESULT hr, hr_return = S_OK;
2310 struct filter *filter;
2312 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2313 /* Send a message to all renderers, they are responsible for broadcasting it further */
2315 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
2317 IMediaSeeking *seek = NULL;
2318 IAMFilterMiscFlags *flags = NULL;
2319 ULONG filterflags;
2320 IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags);
2321 if (!flags)
2322 continue;
2323 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2324 IAMFilterMiscFlags_Release(flags);
2325 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2326 continue;
2328 IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seek);
2329 if (!seek)
2330 continue;
2331 hr = FoundSeek(This, seek, arg);
2332 IMediaSeeking_Release(seek);
2333 if (hr_return != E_NOTIMPL)
2334 allnotimpl = FALSE;
2335 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2336 hr_return = hr;
2339 if (allnotimpl)
2340 return E_NOTIMPL;
2341 return hr_return;
2344 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2346 HRESULT hr;
2347 DWORD caps = 0;
2349 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2350 if (FAILED(hr))
2351 return hr;
2353 /* Only add common capabilities everything supports */
2354 *(DWORD*)pcaps &= caps;
2356 return hr;
2359 /*** IMediaSeeking methods ***/
2360 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2362 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2363 HRESULT hr;
2365 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2367 if (!pCapabilities)
2368 return E_POINTER;
2370 EnterCriticalSection(&This->cs);
2371 *pCapabilities = 0xffffffff;
2373 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2374 LeaveCriticalSection(&This->cs);
2376 return hr;
2379 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2381 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2382 DWORD originalcaps;
2383 HRESULT hr;
2385 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2387 if (!pCapabilities)
2388 return E_POINTER;
2390 EnterCriticalSection(&This->cs);
2391 originalcaps = *pCapabilities;
2392 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2393 LeaveCriticalSection(&This->cs);
2395 if (FAILED(hr))
2396 return hr;
2398 if (!*pCapabilities)
2399 return E_FAIL;
2400 if (*pCapabilities != originalcaps)
2401 return S_FALSE;
2402 return S_OK;
2405 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2407 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2409 if (!pFormat)
2410 return E_POINTER;
2412 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2414 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2416 WARN("Unhandled time format %s\n", debugstr_guid(pFormat));
2417 return S_FALSE;
2420 return S_OK;
2423 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2425 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2427 if (!pFormat)
2428 return E_POINTER;
2430 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2431 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2433 return S_OK;
2436 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2438 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2440 if (!pFormat)
2441 return E_POINTER;
2443 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2444 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2446 return S_OK;
2449 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2451 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2453 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2454 if (!pFormat)
2455 return E_POINTER;
2457 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2458 return S_FALSE;
2460 return S_OK;
2463 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2465 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2467 if (!pFormat)
2468 return E_POINTER;
2470 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2472 if (This->state != State_Stopped)
2473 return VFW_E_WRONG_STATE;
2475 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2477 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2478 return E_INVALIDARG;
2481 return S_OK;
2484 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2486 HRESULT hr;
2487 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2489 hr = IMediaSeeking_GetDuration(seek, &duration);
2490 if (FAILED(hr))
2491 return hr;
2493 if (*pdur < duration)
2494 *pdur = duration;
2495 return hr;
2498 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2500 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2501 HRESULT hr;
2503 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2505 if (!pDuration)
2506 return E_POINTER;
2508 EnterCriticalSection(&This->cs);
2509 *pDuration = 0;
2510 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2511 LeaveCriticalSection(&This->cs);
2513 TRACE("--->%08x\n", hr);
2514 return hr;
2517 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2519 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2520 HRESULT hr = S_OK;
2522 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2524 if (!pStop)
2525 return E_POINTER;
2527 EnterCriticalSection(&This->cs);
2528 if (This->stop_position < 0)
2529 /* Stop position not set, use duration instead */
2530 hr = IMediaSeeking_GetDuration(iface, pStop);
2531 else
2532 *pStop = This->stop_position;
2533 LeaveCriticalSection(&This->cs);
2535 return hr;
2538 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2540 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2541 LONGLONG time = 0;
2543 if (!pCurrent)
2544 return E_POINTER;
2546 EnterCriticalSection(&This->cs);
2547 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2549 IReferenceClock_GetTime(This->refClock, &time);
2550 if (time)
2551 time -= This->start_time;
2553 if (This->pause_time > 0)
2554 time += This->pause_time;
2555 *pCurrent = time;
2556 LeaveCriticalSection(&This->cs);
2558 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2560 return S_OK;
2563 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2564 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2566 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2568 TRACE("(%p/%p)->(%p, %s, 0x%s, %s)\n", This, iface, pTarget,
2569 debugstr_guid(pTargetFormat), wine_dbgstr_longlong(Source), debugstr_guid(pSourceFormat));
2571 if (!pSourceFormat)
2572 pSourceFormat = &This->timeformatseek;
2574 if (!pTargetFormat)
2575 pTargetFormat = &This->timeformatseek;
2577 if (IsEqualGUID(pTargetFormat, pSourceFormat))
2578 *pTarget = Source;
2579 else
2580 FIXME("conversion %s->%s not supported\n", debugstr_guid(pSourceFormat), debugstr_guid(pTargetFormat));
2582 return S_OK;
2585 struct pos_args {
2586 LONGLONG* current, *stop;
2587 DWORD curflags, stopflags;
2590 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2592 struct pos_args *args = (void*)pargs;
2594 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2597 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2598 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2600 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2601 HRESULT hr = S_OK;
2602 FILTER_STATE state;
2603 struct pos_args args;
2605 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2607 EnterCriticalSection(&This->cs);
2608 state = This->state;
2609 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2611 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2612 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2613 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2615 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2616 This->stop_position = *pStop;
2617 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2618 FIXME("Stop position not handled yet!\n");
2620 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2621 IMediaControl_Pause(&This->IMediaControl_iface);
2622 args.current = pCurrent;
2623 args.stop = pStop;
2624 args.curflags = dwCurrentFlags;
2625 args.stopflags = dwStopFlags;
2626 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2628 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2629 This->pause_time = This->start_time = -1;
2630 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2631 IMediaControl_Run(&This->IMediaControl_iface);
2632 LeaveCriticalSection(&This->cs);
2634 return hr;
2637 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2638 LONGLONG *pStop)
2640 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2641 HRESULT hr;
2643 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2644 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2645 if (SUCCEEDED(hr))
2646 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2648 return hr;
2651 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2652 LONGLONG *pLatest)
2654 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2656 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2658 return S_OK;
2661 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2663 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2665 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2667 return S_OK;
2670 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2672 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2674 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2676 if (!pdRate)
2677 return E_POINTER;
2679 *pdRate = 1.0;
2681 return S_OK;
2684 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2686 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2688 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2690 return S_OK;
2694 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2696 MediaSeeking_QueryInterface,
2697 MediaSeeking_AddRef,
2698 MediaSeeking_Release,
2699 MediaSeeking_GetCapabilities,
2700 MediaSeeking_CheckCapabilities,
2701 MediaSeeking_IsFormatSupported,
2702 MediaSeeking_QueryPreferredFormat,
2703 MediaSeeking_GetTimeFormat,
2704 MediaSeeking_IsUsingTimeFormat,
2705 MediaSeeking_SetTimeFormat,
2706 MediaSeeking_GetDuration,
2707 MediaSeeking_GetStopPosition,
2708 MediaSeeking_GetCurrentPosition,
2709 MediaSeeking_ConvertTimeFormat,
2710 MediaSeeking_SetPositions,
2711 MediaSeeking_GetPositions,
2712 MediaSeeking_GetAvailable,
2713 MediaSeeking_SetRate,
2714 MediaSeeking_GetRate,
2715 MediaSeeking_GetPreroll
2718 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2720 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2723 /*** IUnknown methods ***/
2724 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2726 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2728 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2730 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2733 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2735 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2737 TRACE("(%p/%p)->()\n", This, iface);
2739 return IUnknown_AddRef(This->outer_unk);
2742 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2744 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2746 TRACE("(%p/%p)->()\n", This, iface);
2748 return IUnknown_Release(This->outer_unk);
2751 /*** IDispatch methods ***/
2752 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo)
2754 FIXME("(%p) stub!\n", iface);
2755 return E_NOTIMPL;
2758 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2760 FIXME("(%p) stub!\n", iface);
2761 return E_NOTIMPL;
2764 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
2766 FIXME("(%p) stub!\n", iface);
2767 return E_NOTIMPL;
2770 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2772 FIXME("(%p) stub!\n", iface);
2773 return E_NOTIMPL;
2776 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2778 GUID time_format;
2779 HRESULT hr;
2781 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2782 if (FAILED(hr))
2783 return hr;
2784 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2786 FIXME("Unsupported time format.\n");
2787 return E_NOTIMPL;
2790 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2791 return S_OK;
2794 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2796 GUID time_format;
2797 HRESULT hr;
2799 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2800 if (FAILED(hr))
2801 return hr;
2802 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2804 FIXME("Unsupported time format.\n");
2805 return E_NOTIMPL;
2808 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2809 return S_OK;
2812 /*** IMediaPosition methods ***/
2813 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2815 LONGLONG duration;
2816 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2817 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2818 if (FAILED(hr))
2819 return hr;
2820 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2823 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2825 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2826 LONGLONG reftime;
2827 HRESULT hr;
2829 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2830 if (FAILED(hr))
2831 return hr;
2832 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2833 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2836 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2838 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2839 LONGLONG pos;
2840 HRESULT hr;
2842 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2843 if (FAILED(hr))
2844 return hr;
2845 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2848 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2850 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2851 LONGLONG pos;
2852 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2853 if (FAILED(hr))
2854 return hr;
2855 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2858 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2860 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2861 LONGLONG reftime;
2862 HRESULT hr;
2864 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2865 if (FAILED(hr))
2866 return hr;
2867 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2868 &reftime, AM_SEEKING_AbsolutePositioning);
2871 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime)
2873 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2874 return E_NOTIMPL;
2877 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime)
2879 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2880 return E_NOTIMPL;
2883 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2885 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2886 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2889 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2891 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2892 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2895 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward)
2897 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2898 return E_NOTIMPL;
2901 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward)
2903 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2904 return E_NOTIMPL;
2908 static const IMediaPositionVtbl IMediaPosition_VTable =
2910 MediaPosition_QueryInterface,
2911 MediaPosition_AddRef,
2912 MediaPosition_Release,
2913 MediaPosition_GetTypeInfoCount,
2914 MediaPosition_GetTypeInfo,
2915 MediaPosition_GetIDsOfNames,
2916 MediaPosition_Invoke,
2917 MediaPosition_get_Duration,
2918 MediaPosition_put_CurrentPosition,
2919 MediaPosition_get_CurrentPosition,
2920 MediaPosition_get_StopTime,
2921 MediaPosition_put_StopTime,
2922 MediaPosition_get_PrerollTime,
2923 MediaPosition_put_PrerollTime,
2924 MediaPosition_put_Rate,
2925 MediaPosition_get_Rate,
2926 MediaPosition_CanSeekForward,
2927 MediaPosition_CanSeekBackward
2930 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2932 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2935 /*** IUnknown methods ***/
2936 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2938 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2940 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2942 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2945 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2947 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2949 TRACE("(%p/%p)->()\n", This, iface);
2951 return IUnknown_AddRef(This->outer_unk);
2954 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2956 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2958 TRACE("(%p/%p)->()\n", This, iface);
2960 return IUnknown_Release(This->outer_unk);
2963 /*** IObjectWithSite methods ***/
2965 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2967 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2969 TRACE("(%p/%p)->()\n", This, iface);
2970 if (This->pSite) IUnknown_Release(This->pSite);
2971 This->pSite = pUnkSite;
2972 IUnknown_AddRef(This->pSite);
2973 return S_OK;
2976 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2978 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2980 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2982 *ppvSite = NULL;
2983 if (!This->pSite)
2984 return E_FAIL;
2985 else
2986 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2989 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2991 ObjectWithSite_QueryInterface,
2992 ObjectWithSite_AddRef,
2993 ObjectWithSite_Release,
2994 ObjectWithSite_SetSite,
2995 ObjectWithSite_GetSite,
2998 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
3000 struct filter *filter;
3001 HRESULT hr;
3002 int entry;
3004 /* Check if the interface type is already registered */
3005 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
3006 if (riid == pGraph->ItfCacheEntries[entry].riid)
3008 if (pGraph->ItfCacheEntries[entry].iface)
3010 /* Return the interface if available */
3011 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
3012 return S_OK;
3014 break;
3017 if (entry >= MAX_ITF_CACHE_ENTRIES)
3019 FIXME("Not enough space to store interface in the cache\n");
3020 return E_OUTOFMEMORY;
3023 /* Find a filter supporting the requested interface */
3024 LIST_FOR_EACH_ENTRY(filter, &pGraph->filters, struct filter, entry)
3026 hr = IBaseFilter_QueryInterface(filter->filter, riid, ppvObj);
3027 if (hr == S_OK)
3029 pGraph->ItfCacheEntries[entry].riid = riid;
3030 pGraph->ItfCacheEntries[entry].filter = filter->filter;
3031 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
3032 if (entry >= pGraph->nItfCacheEntries)
3033 pGraph->nItfCacheEntries++;
3034 return S_OK;
3036 if (hr != E_NOINTERFACE)
3037 return hr;
3040 return IsEqualGUID(riid, &IID_IBasicAudio) ? E_NOTIMPL : E_NOINTERFACE;
3043 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
3045 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
3048 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
3050 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3052 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
3054 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3057 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
3059 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3061 TRACE("(%p/%p)->()\n", This, iface);
3063 return IUnknown_AddRef(This->outer_unk);
3066 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
3068 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3070 TRACE("(%p/%p)->()\n", This, iface);
3072 return IUnknown_Release(This->outer_unk);
3075 /*** IDispatch methods ***/
3076 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
3078 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3079 IBasicAudio* pBasicAudio;
3080 HRESULT hr;
3082 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3084 EnterCriticalSection(&This->cs);
3086 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3088 if (hr == S_OK)
3089 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
3091 LeaveCriticalSection(&This->cs);
3093 return hr;
3096 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
3097 ITypeInfo **ppTInfo)
3099 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3100 IBasicAudio* pBasicAudio;
3101 HRESULT hr;
3103 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3105 EnterCriticalSection(&This->cs);
3107 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3109 if (hr == S_OK)
3110 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
3112 LeaveCriticalSection(&This->cs);
3114 return hr;
3117 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
3118 UINT cNames, LCID lcid, DISPID *rgDispId)
3120 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3121 IBasicAudio* pBasicAudio;
3122 HRESULT hr;
3124 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
3125 lcid, rgDispId);
3127 EnterCriticalSection(&This->cs);
3129 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3131 if (hr == S_OK)
3132 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3134 LeaveCriticalSection(&This->cs);
3136 return hr;
3139 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3140 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3141 UINT *puArgErr)
3143 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3144 IBasicAudio* pBasicAudio;
3145 HRESULT hr;
3147 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
3148 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3150 EnterCriticalSection(&This->cs);
3152 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3154 if (hr == S_OK)
3155 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3157 LeaveCriticalSection(&This->cs);
3159 return hr;
3162 /*** IBasicAudio methods ***/
3163 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3165 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3166 IBasicAudio* pBasicAudio;
3167 HRESULT hr;
3169 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3171 EnterCriticalSection(&This->cs);
3173 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3175 if (hr == S_OK)
3176 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3178 LeaveCriticalSection(&This->cs);
3180 return hr;
3183 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3185 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3186 IBasicAudio* pBasicAudio;
3187 HRESULT hr;
3189 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3191 EnterCriticalSection(&This->cs);
3193 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3195 if (hr == S_OK)
3196 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3198 LeaveCriticalSection(&This->cs);
3200 return hr;
3203 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3205 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3206 IBasicAudio* pBasicAudio;
3207 HRESULT hr;
3209 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3211 EnterCriticalSection(&This->cs);
3213 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3215 if (hr == S_OK)
3216 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3218 LeaveCriticalSection(&This->cs);
3220 return hr;
3223 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3225 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3226 IBasicAudio* pBasicAudio;
3227 HRESULT hr;
3229 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3231 EnterCriticalSection(&This->cs);
3233 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3235 if (hr == S_OK)
3236 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3238 LeaveCriticalSection(&This->cs);
3240 return hr;
3243 static const IBasicAudioVtbl IBasicAudio_VTable =
3245 BasicAudio_QueryInterface,
3246 BasicAudio_AddRef,
3247 BasicAudio_Release,
3248 BasicAudio_GetTypeInfoCount,
3249 BasicAudio_GetTypeInfo,
3250 BasicAudio_GetIDsOfNames,
3251 BasicAudio_Invoke,
3252 BasicAudio_put_Volume,
3253 BasicAudio_get_Volume,
3254 BasicAudio_put_Balance,
3255 BasicAudio_get_Balance
3258 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3260 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3263 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3265 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3267 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
3269 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3272 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3274 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3276 TRACE("(%p/%p)->()\n", This, iface);
3278 return IUnknown_AddRef(This->outer_unk);
3281 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3283 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3285 TRACE("(%p/%p)->()\n", This, iface);
3287 return IUnknown_Release(This->outer_unk);
3290 /*** IDispatch methods ***/
3291 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3293 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3294 IBasicVideo *pBasicVideo;
3295 HRESULT hr;
3297 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3299 EnterCriticalSection(&This->cs);
3301 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3303 if (hr == S_OK)
3304 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3306 LeaveCriticalSection(&This->cs);
3308 return hr;
3311 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3312 ITypeInfo **ppTInfo)
3314 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3315 IBasicVideo *pBasicVideo;
3316 HRESULT hr;
3318 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3320 EnterCriticalSection(&This->cs);
3322 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3324 if (hr == S_OK)
3325 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3327 LeaveCriticalSection(&This->cs);
3329 return hr;
3332 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3333 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3335 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3336 IBasicVideo *pBasicVideo;
3337 HRESULT hr;
3339 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
3340 lcid, rgDispId);
3342 EnterCriticalSection(&This->cs);
3344 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3346 if (hr == S_OK)
3347 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3349 LeaveCriticalSection(&This->cs);
3351 return hr;
3354 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3355 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3356 UINT *puArgErr)
3358 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3359 IBasicVideo *pBasicVideo;
3360 HRESULT hr;
3362 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
3363 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3365 EnterCriticalSection(&This->cs);
3367 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3369 if (hr == S_OK)
3370 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3372 LeaveCriticalSection(&This->cs);
3374 return hr;
3377 /*** IBasicVideo methods ***/
3378 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3380 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3381 IBasicVideo *pBasicVideo;
3382 HRESULT hr;
3384 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3386 EnterCriticalSection(&This->cs);
3388 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3390 if (hr == S_OK)
3391 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3393 LeaveCriticalSection(&This->cs);
3395 return hr;
3398 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3400 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3401 IBasicVideo *pBasicVideo;
3402 HRESULT hr;
3404 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3406 EnterCriticalSection(&This->cs);
3408 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3410 if (hr == S_OK)
3411 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3413 LeaveCriticalSection(&This->cs);
3415 return hr;
3418 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3420 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3421 IBasicVideo *pBasicVideo;
3422 HRESULT hr;
3424 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3426 EnterCriticalSection(&This->cs);
3428 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3430 if (hr == S_OK)
3431 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3433 LeaveCriticalSection(&This->cs);
3435 return hr;
3438 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3440 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3441 IBasicVideo *pBasicVideo;
3442 HRESULT hr;
3444 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3446 EnterCriticalSection(&This->cs);
3448 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3450 if (hr == S_OK)
3451 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3453 LeaveCriticalSection(&This->cs);
3455 return hr;
3458 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3460 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3461 IBasicVideo *pBasicVideo;
3462 HRESULT hr;
3464 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3466 EnterCriticalSection(&This->cs);
3468 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3470 if (hr == S_OK)
3471 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3473 LeaveCriticalSection(&This->cs);
3475 return hr;
3478 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3480 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3481 IBasicVideo *pBasicVideo;
3482 HRESULT hr;
3484 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3486 EnterCriticalSection(&This->cs);
3488 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3490 if (hr == S_OK)
3491 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3493 LeaveCriticalSection(&This->cs);
3495 return hr;
3498 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3500 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3501 IBasicVideo *pBasicVideo;
3502 HRESULT hr;
3504 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3506 EnterCriticalSection(&This->cs);
3508 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3510 if (hr == S_OK)
3511 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3513 LeaveCriticalSection(&This->cs);
3515 return hr;
3518 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3520 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3521 IBasicVideo *pBasicVideo;
3522 HRESULT hr;
3524 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3526 EnterCriticalSection(&This->cs);
3528 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3530 if (hr == S_OK)
3531 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3533 LeaveCriticalSection(&This->cs);
3535 return hr;
3538 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3540 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3541 IBasicVideo *pBasicVideo;
3542 HRESULT hr;
3544 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3546 EnterCriticalSection(&This->cs);
3548 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3550 if (hr == S_OK)
3551 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3553 LeaveCriticalSection(&This->cs);
3555 return hr;
3558 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3560 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3561 IBasicVideo *pBasicVideo;
3562 HRESULT hr;
3564 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3566 EnterCriticalSection(&This->cs);
3568 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3570 if (hr == S_OK)
3571 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3573 LeaveCriticalSection(&This->cs);
3575 return hr;
3578 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3580 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3581 IBasicVideo *pBasicVideo;
3582 HRESULT hr;
3584 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3586 EnterCriticalSection(&This->cs);
3588 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3590 if (hr == S_OK)
3591 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3593 LeaveCriticalSection(&This->cs);
3595 return hr;
3598 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3600 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3601 IBasicVideo *pBasicVideo;
3602 HRESULT hr;
3604 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3606 EnterCriticalSection(&This->cs);
3608 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3610 if (hr == S_OK)
3611 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3613 LeaveCriticalSection(&This->cs);
3615 return hr;
3618 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3620 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3621 IBasicVideo *pBasicVideo;
3622 HRESULT hr;
3624 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3626 EnterCriticalSection(&This->cs);
3628 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3630 if (hr == S_OK)
3631 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3633 LeaveCriticalSection(&This->cs);
3635 return hr;
3638 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3640 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3641 IBasicVideo *pBasicVideo;
3642 HRESULT hr;
3644 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3646 EnterCriticalSection(&This->cs);
3648 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3650 if (hr == S_OK)
3651 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3653 LeaveCriticalSection(&This->cs);
3655 return hr;
3658 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3660 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3661 IBasicVideo *pBasicVideo;
3662 HRESULT hr;
3664 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3666 EnterCriticalSection(&This->cs);
3668 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3670 if (hr == S_OK)
3671 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3673 LeaveCriticalSection(&This->cs);
3675 return hr;
3678 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3680 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3681 IBasicVideo *pBasicVideo;
3682 HRESULT hr;
3684 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3686 EnterCriticalSection(&This->cs);
3688 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3690 if (hr == S_OK)
3691 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3693 LeaveCriticalSection(&This->cs);
3695 return hr;
3698 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3700 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3701 IBasicVideo *pBasicVideo;
3702 HRESULT hr;
3704 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3706 EnterCriticalSection(&This->cs);
3708 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3710 if (hr == S_OK)
3711 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3713 LeaveCriticalSection(&This->cs);
3715 return hr;
3718 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3720 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3721 IBasicVideo *pBasicVideo;
3722 HRESULT hr;
3724 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3726 EnterCriticalSection(&This->cs);
3728 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3730 if (hr == S_OK)
3731 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3733 LeaveCriticalSection(&This->cs);
3735 return hr;
3738 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3740 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3741 IBasicVideo *pBasicVideo;
3742 HRESULT hr;
3744 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3746 EnterCriticalSection(&This->cs);
3748 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3750 if (hr == S_OK)
3751 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3753 LeaveCriticalSection(&This->cs);
3755 return hr;
3758 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3760 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3761 IBasicVideo *pBasicVideo;
3762 HRESULT hr;
3764 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3766 EnterCriticalSection(&This->cs);
3768 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3770 if (hr == S_OK)
3771 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3773 LeaveCriticalSection(&This->cs);
3775 return hr;
3778 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3779 LONG *pDestinationHeight)
3781 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3782 IBasicVideo *pBasicVideo;
3783 HRESULT hr;
3785 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3787 EnterCriticalSection(&This->cs);
3789 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3791 if (hr == S_OK)
3792 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3794 LeaveCriticalSection(&This->cs);
3796 return hr;
3799 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3800 LONG Width, LONG Height)
3802 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3803 IBasicVideo *pBasicVideo;
3804 HRESULT hr;
3806 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3808 EnterCriticalSection(&This->cs);
3810 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3812 if (hr == S_OK)
3813 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3815 LeaveCriticalSection(&This->cs);
3817 return hr;
3820 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3821 LONG *pWidth, LONG *pHeight)
3823 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3824 IBasicVideo *pBasicVideo;
3825 HRESULT hr;
3827 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3829 EnterCriticalSection(&This->cs);
3831 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3833 if (hr == S_OK)
3834 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3836 LeaveCriticalSection(&This->cs);
3838 return hr;
3841 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3843 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3844 IBasicVideo *pBasicVideo;
3845 HRESULT hr;
3847 TRACE("(%p/%p)->()\n", This, iface);
3849 EnterCriticalSection(&This->cs);
3851 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3853 if (hr == S_OK)
3854 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3856 LeaveCriticalSection(&This->cs);
3858 return hr;
3861 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3862 LONG Width, LONG Height)
3864 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3865 IBasicVideo *pBasicVideo;
3866 HRESULT hr;
3868 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3870 EnterCriticalSection(&This->cs);
3872 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3874 if (hr == S_OK)
3875 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3877 LeaveCriticalSection(&This->cs);
3879 return hr;
3882 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3883 LONG *pTop, LONG *pWidth, LONG *pHeight)
3885 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3886 IBasicVideo *pBasicVideo;
3887 HRESULT hr;
3889 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3891 EnterCriticalSection(&This->cs);
3893 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3895 if (hr == S_OK)
3896 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3898 LeaveCriticalSection(&This->cs);
3900 return hr;
3903 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3905 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3906 IBasicVideo *pBasicVideo;
3907 HRESULT hr;
3909 TRACE("(%p/%p)->()\n", This, iface);
3911 EnterCriticalSection(&This->cs);
3913 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3915 if (hr == S_OK)
3916 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3918 LeaveCriticalSection(&This->cs);
3920 return hr;
3923 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3925 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3926 IBasicVideo *pBasicVideo;
3927 HRESULT hr;
3929 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3931 EnterCriticalSection(&This->cs);
3933 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3935 if (hr == S_OK)
3936 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3938 LeaveCriticalSection(&This->cs);
3940 return hr;
3943 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3944 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3946 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3947 IBasicVideo *pBasicVideo;
3948 HRESULT hr;
3950 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3952 EnterCriticalSection(&This->cs);
3954 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3956 if (hr == S_OK)
3957 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3959 LeaveCriticalSection(&This->cs);
3961 return hr;
3964 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3965 LONG *pDIBImage)
3967 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3968 IBasicVideo *pBasicVideo;
3969 HRESULT hr;
3971 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3973 EnterCriticalSection(&This->cs);
3975 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3977 if (hr == S_OK)
3978 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3980 LeaveCriticalSection(&This->cs);
3982 return hr;
3985 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3987 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3988 IBasicVideo *pBasicVideo;
3989 HRESULT hr;
3991 TRACE("(%p/%p)->()\n", This, iface);
3993 EnterCriticalSection(&This->cs);
3995 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3997 if (hr == S_OK)
3998 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
4000 LeaveCriticalSection(&This->cs);
4002 return hr;
4005 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
4007 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4008 IBasicVideo *pBasicVideo;
4009 HRESULT hr;
4011 TRACE("(%p/%p)->()\n", This, iface);
4013 EnterCriticalSection(&This->cs);
4015 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
4017 if (hr == S_OK)
4018 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
4020 LeaveCriticalSection(&This->cs);
4022 return hr;
4025 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
4026 LONG *plAspectY)
4028 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4029 IBasicVideo2 *pBasicVideo2;
4030 HRESULT hr;
4032 TRACE("(%p/%p)->()\n", This, iface);
4034 EnterCriticalSection(&This->cs);
4036 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
4038 if (hr == S_OK)
4039 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
4041 LeaveCriticalSection(&This->cs);
4043 return hr;
4046 static const IBasicVideo2Vtbl IBasicVideo_VTable =
4048 BasicVideo_QueryInterface,
4049 BasicVideo_AddRef,
4050 BasicVideo_Release,
4051 BasicVideo_GetTypeInfoCount,
4052 BasicVideo_GetTypeInfo,
4053 BasicVideo_GetIDsOfNames,
4054 BasicVideo_Invoke,
4055 BasicVideo_get_AvgTimePerFrame,
4056 BasicVideo_get_BitRate,
4057 BasicVideo_get_BitErrorRate,
4058 BasicVideo_get_VideoWidth,
4059 BasicVideo_get_VideoHeight,
4060 BasicVideo_put_SourceLeft,
4061 BasicVideo_get_SourceLeft,
4062 BasicVideo_put_SourceWidth,
4063 BasicVideo_get_SourceWidth,
4064 BasicVideo_put_SourceTop,
4065 BasicVideo_get_SourceTop,
4066 BasicVideo_put_SourceHeight,
4067 BasicVideo_get_SourceHeight,
4068 BasicVideo_put_DestinationLeft,
4069 BasicVideo_get_DestinationLeft,
4070 BasicVideo_put_DestinationWidth,
4071 BasicVideo_get_DestinationWidth,
4072 BasicVideo_put_DestinationTop,
4073 BasicVideo_get_DestinationTop,
4074 BasicVideo_put_DestinationHeight,
4075 BasicVideo_get_DestinationHeight,
4076 BasicVideo_SetSourcePosition,
4077 BasicVideo_GetSourcePosition,
4078 BasicVideo_SetDefaultSourcePosition,
4079 BasicVideo_SetDestinationPosition,
4080 BasicVideo_GetDestinationPosition,
4081 BasicVideo_SetDefaultDestinationPosition,
4082 BasicVideo_GetVideoSize,
4083 BasicVideo_GetVideoPaletteEntries,
4084 BasicVideo_GetCurrentImage,
4085 BasicVideo_IsUsingDefaultSource,
4086 BasicVideo_IsUsingDefaultDestination,
4087 BasicVideo2_GetPreferredAspectRatio
4090 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
4092 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
4095 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
4097 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4099 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
4101 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4104 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
4106 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4108 TRACE("(%p/%p)->()\n", This, iface);
4110 return IUnknown_AddRef(This->outer_unk);
4113 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
4115 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4117 TRACE("(%p/%p)->()\n", This, iface);
4119 return IUnknown_Release(This->outer_unk);
4122 /*** IDispatch methods ***/
4123 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4125 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4126 IVideoWindow *pVideoWindow;
4127 HRESULT hr;
4129 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4131 EnterCriticalSection(&This->cs);
4133 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4135 if (hr == S_OK)
4136 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4138 LeaveCriticalSection(&This->cs);
4140 return hr;
4143 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4144 ITypeInfo **ppTInfo)
4146 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4147 IVideoWindow *pVideoWindow;
4148 HRESULT hr;
4150 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4152 EnterCriticalSection(&This->cs);
4154 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4156 if (hr == S_OK)
4157 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4159 LeaveCriticalSection(&This->cs);
4161 return hr;
4164 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4165 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4167 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4168 IVideoWindow *pVideoWindow;
4169 HRESULT hr;
4171 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
4172 lcid, rgDispId);
4174 EnterCriticalSection(&This->cs);
4176 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4178 if (hr == S_OK)
4179 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4181 LeaveCriticalSection(&This->cs);
4183 return hr;
4186 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4187 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4188 UINT*puArgErr)
4190 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4191 IVideoWindow *pVideoWindow;
4192 HRESULT hr;
4194 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
4195 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4197 EnterCriticalSection(&This->cs);
4199 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4201 if (hr == S_OK)
4202 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4204 LeaveCriticalSection(&This->cs);
4206 return hr;
4210 /*** IVideoWindow methods ***/
4211 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4213 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4214 IVideoWindow *pVideoWindow;
4215 HRESULT hr;
4217 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4219 EnterCriticalSection(&This->cs);
4221 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4223 if (hr == S_OK)
4224 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4226 LeaveCriticalSection(&This->cs);
4228 return hr;
4231 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4233 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4234 IVideoWindow *pVideoWindow;
4235 HRESULT hr;
4237 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4239 EnterCriticalSection(&This->cs);
4241 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4243 if (hr == S_OK)
4244 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4246 LeaveCriticalSection(&This->cs);
4248 return hr;
4251 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4253 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4254 IVideoWindow *pVideoWindow;
4255 HRESULT hr;
4257 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4259 EnterCriticalSection(&This->cs);
4261 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4263 if (hr == S_OK)
4264 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4266 LeaveCriticalSection(&This->cs);
4268 return hr;
4271 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4273 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4274 IVideoWindow *pVideoWindow;
4275 HRESULT hr;
4277 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4279 EnterCriticalSection(&This->cs);
4281 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4283 if (hr == S_OK)
4284 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4286 LeaveCriticalSection(&This->cs);
4288 return hr;
4291 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4293 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4294 IVideoWindow *pVideoWindow;
4295 HRESULT hr;
4297 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4299 EnterCriticalSection(&This->cs);
4301 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4303 if (hr == S_OK)
4304 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4306 LeaveCriticalSection(&This->cs);
4308 return hr;
4311 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4313 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4314 IVideoWindow *pVideoWindow;
4315 HRESULT hr;
4317 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4319 EnterCriticalSection(&This->cs);
4321 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4323 if (hr == S_OK)
4324 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4326 LeaveCriticalSection(&This->cs);
4328 return hr;
4331 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4333 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4334 IVideoWindow *pVideoWindow;
4335 HRESULT hr;
4337 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4339 EnterCriticalSection(&This->cs);
4341 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4343 if (hr == S_OK)
4344 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4346 LeaveCriticalSection(&This->cs);
4348 return hr;
4351 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4353 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4354 IVideoWindow *pVideoWindow;
4355 HRESULT hr;
4357 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4359 EnterCriticalSection(&This->cs);
4361 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4363 if (hr == S_OK)
4364 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4366 LeaveCriticalSection(&This->cs);
4368 return hr;
4371 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4373 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4374 IVideoWindow *pVideoWindow;
4375 HRESULT hr;
4377 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4379 EnterCriticalSection(&This->cs);
4381 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4383 if (hr == S_OK)
4384 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4386 LeaveCriticalSection(&This->cs);
4388 return hr;
4391 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4393 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4394 IVideoWindow *pVideoWindow;
4395 HRESULT hr;
4397 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4399 EnterCriticalSection(&This->cs);
4401 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4403 if (hr == S_OK)
4404 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4406 LeaveCriticalSection(&This->cs);
4408 return hr;
4411 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4413 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4414 IVideoWindow *pVideoWindow;
4415 HRESULT hr;
4417 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4419 EnterCriticalSection(&This->cs);
4421 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4423 if (hr == S_OK)
4424 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4426 LeaveCriticalSection(&This->cs);
4428 return hr;
4431 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4432 LONG *pBackgroundPalette)
4434 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4435 IVideoWindow *pVideoWindow;
4436 HRESULT hr;
4438 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4440 EnterCriticalSection(&This->cs);
4442 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4444 if (hr == S_OK)
4445 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4447 LeaveCriticalSection(&This->cs);
4449 return hr;
4452 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4454 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4455 IVideoWindow *pVideoWindow;
4456 HRESULT hr;
4458 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4460 EnterCriticalSection(&This->cs);
4462 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4464 if (hr == S_OK)
4465 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4467 LeaveCriticalSection(&This->cs);
4469 return hr;
4472 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4474 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4475 IVideoWindow *pVideoWindow;
4476 HRESULT hr;
4478 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4480 EnterCriticalSection(&This->cs);
4482 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4484 if (hr == S_OK)
4485 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4487 LeaveCriticalSection(&This->cs);
4489 return hr;
4492 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4494 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4495 IVideoWindow *pVideoWindow;
4496 HRESULT hr;
4498 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4500 EnterCriticalSection(&This->cs);
4502 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4504 if (hr == S_OK)
4505 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4507 LeaveCriticalSection(&This->cs);
4509 return hr;
4512 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4514 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4515 IVideoWindow *pVideoWindow;
4516 HRESULT hr;
4518 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4520 EnterCriticalSection(&This->cs);
4522 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4524 if (hr == S_OK)
4525 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4527 LeaveCriticalSection(&This->cs);
4529 return hr;
4532 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4534 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4535 IVideoWindow *pVideoWindow;
4536 HRESULT hr;
4538 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4540 EnterCriticalSection(&This->cs);
4542 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4544 if (hr == S_OK)
4545 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4547 LeaveCriticalSection(&This->cs);
4549 return hr;
4552 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4554 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4555 IVideoWindow *pVideoWindow;
4556 HRESULT hr;
4558 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4560 EnterCriticalSection(&This->cs);
4562 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4564 if (hr == S_OK)
4565 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4567 LeaveCriticalSection(&This->cs);
4569 return hr;
4572 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4574 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4575 IVideoWindow *pVideoWindow;
4576 HRESULT hr;
4578 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4580 EnterCriticalSection(&This->cs);
4582 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4584 if (hr == S_OK)
4585 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4587 LeaveCriticalSection(&This->cs);
4589 return hr;
4592 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4594 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4595 IVideoWindow *pVideoWindow;
4596 HRESULT hr;
4598 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4600 EnterCriticalSection(&This->cs);
4602 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4604 if (hr == S_OK)
4605 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4607 LeaveCriticalSection(&This->cs);
4609 return hr;
4612 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4614 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4615 IVideoWindow *pVideoWindow;
4616 HRESULT hr;
4618 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4620 EnterCriticalSection(&This->cs);
4622 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4624 if (hr == S_OK)
4625 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4627 LeaveCriticalSection(&This->cs);
4629 return hr;
4632 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4634 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4635 IVideoWindow *pVideoWindow;
4636 HRESULT hr;
4638 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4640 EnterCriticalSection(&This->cs);
4642 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4644 if (hr == S_OK)
4645 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4647 LeaveCriticalSection(&This->cs);
4649 return hr;
4652 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4654 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4655 IVideoWindow *pVideoWindow;
4656 HRESULT hr;
4658 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4660 EnterCriticalSection(&This->cs);
4662 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4664 if (hr == S_OK)
4665 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4667 LeaveCriticalSection(&This->cs);
4669 return hr;
4672 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4674 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4675 IVideoWindow *pVideoWindow;
4676 HRESULT hr;
4678 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4680 EnterCriticalSection(&This->cs);
4682 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4684 if (hr == S_OK)
4685 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4687 LeaveCriticalSection(&This->cs);
4689 return hr;
4692 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4694 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4695 IVideoWindow *pVideoWindow;
4696 HRESULT hr;
4698 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4700 EnterCriticalSection(&This->cs);
4702 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4704 if (hr == S_OK)
4705 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4707 LeaveCriticalSection(&This->cs);
4709 return hr;
4712 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4714 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4715 IVideoWindow *pVideoWindow;
4716 HRESULT hr;
4718 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4720 EnterCriticalSection(&This->cs);
4722 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4724 if (hr == S_OK)
4725 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4727 LeaveCriticalSection(&This->cs);
4729 return hr;
4732 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4734 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4735 IVideoWindow *pVideoWindow;
4736 HRESULT hr;
4738 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4740 EnterCriticalSection(&This->cs);
4742 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4744 if (hr == S_OK)
4745 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4747 LeaveCriticalSection(&This->cs);
4749 return hr;
4752 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4754 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4755 IVideoWindow *pVideoWindow;
4756 HRESULT hr;
4758 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4760 EnterCriticalSection(&This->cs);
4762 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4764 if (hr == S_OK)
4765 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4767 LeaveCriticalSection(&This->cs);
4769 return hr;
4772 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4774 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4775 IVideoWindow *pVideoWindow;
4776 HRESULT hr;
4778 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4780 EnterCriticalSection(&This->cs);
4782 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4784 if (hr == S_OK)
4785 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4787 LeaveCriticalSection(&This->cs);
4789 return hr;
4792 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4794 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4795 IVideoWindow *pVideoWindow;
4796 HRESULT hr;
4798 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4800 EnterCriticalSection(&This->cs);
4802 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4804 if (hr == S_OK)
4805 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4807 LeaveCriticalSection(&This->cs);
4809 return hr;
4812 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4814 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4815 IVideoWindow *pVideoWindow;
4816 HRESULT hr;
4818 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4820 EnterCriticalSection(&This->cs);
4822 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4824 if (hr == S_OK)
4825 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4827 LeaveCriticalSection(&This->cs);
4829 return hr;
4832 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4833 LONG_PTR wParam, LONG_PTR lParam)
4835 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4836 IVideoWindow *pVideoWindow;
4837 HRESULT hr;
4839 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4841 EnterCriticalSection(&This->cs);
4843 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4845 if (hr == S_OK)
4846 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4848 LeaveCriticalSection(&This->cs);
4850 return hr;
4853 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4854 LONG Width, LONG Height)
4856 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4857 IVideoWindow *pVideoWindow;
4858 HRESULT hr;
4860 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4862 EnterCriticalSection(&This->cs);
4864 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4866 if (hr == S_OK)
4867 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4869 LeaveCriticalSection(&This->cs);
4871 return hr;
4874 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4875 LONG *pWidth, LONG *pHeight)
4877 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4878 IVideoWindow *pVideoWindow;
4879 HRESULT hr;
4881 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4883 EnterCriticalSection(&This->cs);
4885 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4887 if (hr == S_OK)
4888 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4890 LeaveCriticalSection(&This->cs);
4892 return hr;
4895 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4896 LONG *pHeight)
4898 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4899 IVideoWindow *pVideoWindow;
4900 HRESULT hr;
4902 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4904 EnterCriticalSection(&This->cs);
4906 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4908 if (hr == S_OK)
4909 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4911 LeaveCriticalSection(&This->cs);
4913 return hr;
4916 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4917 LONG *pHeight)
4919 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4920 IVideoWindow *pVideoWindow;
4921 HRESULT hr;
4923 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4925 EnterCriticalSection(&This->cs);
4927 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4929 if (hr == S_OK)
4930 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4932 LeaveCriticalSection(&This->cs);
4934 return hr;
4937 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4938 LONG *pWidth, LONG *pHeight)
4940 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4941 IVideoWindow *pVideoWindow;
4942 HRESULT hr;
4944 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4946 EnterCriticalSection(&This->cs);
4948 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4950 if (hr == S_OK)
4951 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4953 LeaveCriticalSection(&This->cs);
4955 return hr;
4958 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4960 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4961 IVideoWindow *pVideoWindow;
4962 HRESULT hr;
4964 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4966 EnterCriticalSection(&This->cs);
4968 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4970 if (hr == S_OK)
4971 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4973 LeaveCriticalSection(&This->cs);
4975 return hr;
4978 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4980 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4981 IVideoWindow *pVideoWindow;
4982 HRESULT hr;
4984 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4986 EnterCriticalSection(&This->cs);
4988 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4990 if (hr == S_OK)
4991 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4993 LeaveCriticalSection(&This->cs);
4995 return hr;
4999 static const IVideoWindowVtbl IVideoWindow_VTable =
5001 VideoWindow_QueryInterface,
5002 VideoWindow_AddRef,
5003 VideoWindow_Release,
5004 VideoWindow_GetTypeInfoCount,
5005 VideoWindow_GetTypeInfo,
5006 VideoWindow_GetIDsOfNames,
5007 VideoWindow_Invoke,
5008 VideoWindow_put_Caption,
5009 VideoWindow_get_Caption,
5010 VideoWindow_put_WindowStyle,
5011 VideoWindow_get_WindowStyle,
5012 VideoWindow_put_WindowStyleEx,
5013 VideoWindow_get_WindowStyleEx,
5014 VideoWindow_put_AutoShow,
5015 VideoWindow_get_AutoShow,
5016 VideoWindow_put_WindowState,
5017 VideoWindow_get_WindowState,
5018 VideoWindow_put_BackgroundPalette,
5019 VideoWindow_get_BackgroundPalette,
5020 VideoWindow_put_Visible,
5021 VideoWindow_get_Visible,
5022 VideoWindow_put_Left,
5023 VideoWindow_get_Left,
5024 VideoWindow_put_Width,
5025 VideoWindow_get_Width,
5026 VideoWindow_put_Top,
5027 VideoWindow_get_Top,
5028 VideoWindow_put_Height,
5029 VideoWindow_get_Height,
5030 VideoWindow_put_Owner,
5031 VideoWindow_get_Owner,
5032 VideoWindow_put_MessageDrain,
5033 VideoWindow_get_MessageDrain,
5034 VideoWindow_get_BorderColor,
5035 VideoWindow_put_BorderColor,
5036 VideoWindow_get_FullScreenMode,
5037 VideoWindow_put_FullScreenMode,
5038 VideoWindow_SetWindowForeground,
5039 VideoWindow_NotifyOwnerMessage,
5040 VideoWindow_SetWindowPosition,
5041 VideoWindow_GetWindowPosition,
5042 VideoWindow_GetMinIdealImageSize,
5043 VideoWindow_GetMaxIdealImageSize,
5044 VideoWindow_GetRestorePosition,
5045 VideoWindow_HideCursor,
5046 VideoWindow_IsCursorHidden
5049 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
5051 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
5054 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
5056 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5058 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
5060 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
5063 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
5065 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5067 TRACE("(%p/%p)->()\n", This, iface);
5069 return IUnknown_AddRef(This->outer_unk);
5072 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
5074 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5076 TRACE("(%p/%p)->()\n", This, iface);
5078 return IUnknown_Release(This->outer_unk);
5081 /*** IDispatch methods ***/
5082 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
5084 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5086 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
5088 return S_OK;
5091 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
5092 ITypeInfo **ppTInfo)
5094 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5096 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
5098 return S_OK;
5101 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
5102 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
5104 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5106 TRACE("(%p/%p)->(%s, %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), rgszNames,
5107 cNames, lcid, rgDispId);
5109 return S_OK;
5112 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
5113 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
5114 UINT *puArgErr)
5116 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5118 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember,
5119 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
5121 return S_OK;
5124 /*** IMediaEvent methods ***/
5125 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5127 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5129 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5131 *hEvent = (OAEVENT)This->evqueue.msg_event;
5133 return S_OK;
5136 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5137 LONG_PTR *lParam2, LONG msTimeout)
5139 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5140 Event evt;
5142 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5144 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5146 *lEventCode = evt.lEventCode;
5147 *lParam1 = evt.lParam1;
5148 *lParam2 = evt.lParam2;
5149 return S_OK;
5152 *lEventCode = 0;
5153 return E_ABORT;
5156 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5157 LONG *pEvCode)
5159 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5161 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5163 if (This->state != State_Running)
5164 return VFW_E_WRONG_STATE;
5166 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5168 *pEvCode = This->CompletionStatus;
5169 return S_OK;
5172 *pEvCode = 0;
5173 return E_ABORT;
5176 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5178 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5180 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5182 if (lEvCode == EC_COMPLETE)
5183 This->HandleEcComplete = FALSE;
5184 else if (lEvCode == EC_REPAINT)
5185 This->HandleEcRepaint = FALSE;
5186 else if (lEvCode == EC_CLOCK_CHANGED)
5187 This->HandleEcClockChanged = FALSE;
5188 else
5189 return S_FALSE;
5191 return S_OK;
5194 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5196 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5198 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5200 if (lEvCode == EC_COMPLETE)
5201 This->HandleEcComplete = TRUE;
5202 else if (lEvCode == EC_REPAINT)
5203 This->HandleEcRepaint = TRUE;
5204 else if (lEvCode == EC_CLOCK_CHANGED)
5205 This->HandleEcClockChanged = TRUE;
5206 else
5207 return S_FALSE;
5209 return S_OK;
5212 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5213 LONG_PTR lParam1, LONG_PTR lParam2)
5215 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5217 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5219 return S_OK;
5222 /*** IMediaEventEx methods ***/
5223 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5224 LONG_PTR lInstanceData)
5226 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5228 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5230 This->notif.hWnd = (HWND)hwnd;
5231 This->notif.msg = lMsg;
5232 This->notif.instance = lInstanceData;
5234 return S_OK;
5237 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5239 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5241 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5243 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5244 return E_INVALIDARG;
5246 This->notif.disabled = lNoNotifyFlags;
5248 return S_OK;
5251 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5253 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5255 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5257 if (!lplNoNotifyFlags)
5258 return E_POINTER;
5260 *lplNoNotifyFlags = This->notif.disabled;
5262 return S_OK;
5266 static const IMediaEventExVtbl IMediaEventEx_VTable =
5268 MediaEvent_QueryInterface,
5269 MediaEvent_AddRef,
5270 MediaEvent_Release,
5271 MediaEvent_GetTypeInfoCount,
5272 MediaEvent_GetTypeInfo,
5273 MediaEvent_GetIDsOfNames,
5274 MediaEvent_Invoke,
5275 MediaEvent_GetEventHandle,
5276 MediaEvent_GetEvent,
5277 MediaEvent_WaitForCompletion,
5278 MediaEvent_CancelDefaultHandling,
5279 MediaEvent_RestoreDefaultHandling,
5280 MediaEvent_FreeEventParams,
5281 MediaEvent_SetNotifyWindow,
5282 MediaEvent_SetNotifyFlags,
5283 MediaEvent_GetNotifyFlags
5287 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5289 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5292 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5294 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5296 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5299 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5301 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5303 return IUnknown_AddRef(This->outer_unk);
5306 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5308 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5310 return IUnknown_Release(This->outer_unk);
5313 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5315 FIXME("(%p): stub\n", pClassID);
5317 return E_NOTIMPL;
5320 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5322 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5324 TRACE("graph %p.\n", graph);
5326 EnterCriticalSection(&graph->cs);
5328 if (graph->state == State_Stopped)
5330 LeaveCriticalSection(&graph->cs);
5331 return S_OK;
5334 if (graph->state == State_Running)
5335 SendFilterMessage(graph, SendPause, 0);
5336 SendFilterMessage(graph, SendStop, 0);
5337 graph->state = State_Stopped;
5339 LeaveCriticalSection(&graph->cs);
5340 return S_OK;
5343 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5345 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5347 TRACE("graph %p.\n", graph);
5349 EnterCriticalSection(&graph->cs);
5351 if (graph->state == State_Paused)
5353 LeaveCriticalSection(&graph->cs);
5354 return S_OK;
5357 if (graph->defaultclock && !graph->refClock)
5358 IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
5360 if (graph->state == State_Running && graph->refClock && graph->start_time >= 0)
5361 IReferenceClock_GetTime(graph->refClock, &graph->pause_time);
5362 else
5363 graph->pause_time = -1;
5365 SendFilterMessage(graph, SendPause, 0);
5366 graph->state = State_Paused;
5368 LeaveCriticalSection(&graph->cs);
5369 return S_FALSE;
5372 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME start)
5374 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5376 TRACE("graph %p, start %s.\n", graph, wine_dbgstr_longlong(start));
5378 EnterCriticalSection(&graph->cs);
5380 if (graph->state == State_Running)
5382 LeaveCriticalSection(&graph->cs);
5383 return S_OK;
5385 graph->EcCompleteCount = 0;
5387 if (graph->defaultclock && !graph->refClock)
5388 IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
5390 if (!start && graph->refClock)
5392 REFERENCE_TIME now;
5393 IReferenceClock_GetTime(graph->refClock, &now);
5394 if (graph->state == State_Stopped)
5395 graph->start_time = now + 500000;
5396 else if (graph->pause_time >= 0)
5397 graph->start_time += now - graph->pause_time;
5398 else
5399 graph->start_time = now;
5401 else
5402 graph->start_time = start;
5404 SendFilterMessage(graph, SendRun, (DWORD_PTR)&graph->start_time);
5405 graph->state = State_Running;
5407 LeaveCriticalSection(&graph->cs);
5408 return S_FALSE;
5411 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD timeout, FILTER_STATE *state)
5413 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5414 DWORD end;
5416 TRACE("graph %p, timeout %u, state %p.\n", graph, timeout, state);
5418 if (!state)
5419 return E_POINTER;
5421 EnterCriticalSection(&graph->cs);
5423 *state = graph->state;
5424 if (timeout > 0)
5425 end = GetTickCount() + timeout;
5426 else if (timeout == INFINITE)
5427 end = INFINITE;
5428 else
5429 end = 0;
5430 if (end)
5431 SendFilterMessage(graph, SendGetState, end);
5433 LeaveCriticalSection(&graph->cs);
5434 return S_OK;
5437 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5439 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5440 struct filter *filter;
5441 HRESULT hr = S_OK;
5443 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
5445 EnterCriticalSection(&This->cs);
5447 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
5449 hr = IBaseFilter_SetSyncSource(filter->filter, pClock);
5450 if (FAILED(hr))
5451 break;
5454 if (FAILED(hr))
5456 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
5457 IBaseFilter_SetSyncSource(filter->filter, This->refClock);
5459 else
5461 if (This->refClock)
5462 IReferenceClock_Release(This->refClock);
5463 This->refClock = pClock;
5464 if (This->refClock)
5465 IReferenceClock_AddRef(This->refClock);
5466 This->defaultclock = FALSE;
5468 if (This->HandleEcClockChanged)
5470 IMediaEventSink *pEventSink;
5471 HRESULT eshr;
5473 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (void **)&pEventSink);
5474 if (SUCCEEDED(eshr))
5476 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5477 IMediaEventSink_Release(pEventSink);
5482 LeaveCriticalSection(&This->cs);
5484 return hr;
5487 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5489 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5491 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
5493 if (!ppClock)
5494 return E_POINTER;
5496 EnterCriticalSection(&This->cs);
5498 *ppClock = This->refClock;
5499 if (*ppClock)
5500 IReferenceClock_AddRef(*ppClock);
5502 LeaveCriticalSection(&This->cs);
5504 return S_OK;
5507 static const IMediaFilterVtbl IMediaFilter_VTable =
5509 MediaFilter_QueryInterface,
5510 MediaFilter_AddRef,
5511 MediaFilter_Release,
5512 MediaFilter_GetClassID,
5513 MediaFilter_Stop,
5514 MediaFilter_Pause,
5515 MediaFilter_Run,
5516 MediaFilter_GetState,
5517 MediaFilter_SetSyncSource,
5518 MediaFilter_GetSyncSource
5521 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5523 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5526 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5528 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5530 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5533 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5535 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5537 return IUnknown_AddRef(This->outer_unk);
5540 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5542 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5544 return IUnknown_Release(This->outer_unk);
5547 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5548 LONG_PTR EventParam1, LONG_PTR EventParam2)
5550 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5551 Event evt;
5553 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5555 /* We need thread safety here, let's use the events queue's one */
5556 EnterCriticalSection(&This->evqueue.msg_crst);
5558 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5560 TRACE("Process EC_COMPLETE notification\n");
5561 if (++This->EcCompleteCount == This->nRenderers)
5563 evt.lEventCode = EC_COMPLETE;
5564 evt.lParam1 = S_OK;
5565 evt.lParam2 = 0;
5566 TRACE("Send EC_COMPLETE to app\n");
5567 EventsQueue_PutEvent(&This->evqueue, &evt);
5568 if (!This->notif.disabled && This->notif.hWnd)
5570 TRACE("Send Window message\n");
5571 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5573 This->CompletionStatus = EC_COMPLETE;
5574 SetEvent(This->hEventCompletion);
5577 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5579 /* FIXME: Not handled yet */
5581 else
5583 evt.lEventCode = EventCode;
5584 evt.lParam1 = EventParam1;
5585 evt.lParam2 = EventParam2;
5586 EventsQueue_PutEvent(&This->evqueue, &evt);
5587 if (!This->notif.disabled && This->notif.hWnd)
5588 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5591 LeaveCriticalSection(&This->evqueue.msg_crst);
5592 return S_OK;
5595 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5597 MediaEventSink_QueryInterface,
5598 MediaEventSink_AddRef,
5599 MediaEventSink_Release,
5600 MediaEventSink_Notify
5603 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5605 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5608 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5610 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5612 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5615 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5617 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5619 return IUnknown_AddRef(This->outer_unk);
5622 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5624 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5626 return IUnknown_Release(This->outer_unk);
5629 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5630 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5631 DWORD dwFlags)
5633 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5635 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5637 return E_NOTIMPL;
5640 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5641 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5643 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5644 HRESULT hr;
5646 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5648 if (hAbortEvent)
5649 FIXME("The parameter hAbortEvent is not handled!\n");
5651 EnterCriticalSection(&This->cs);
5653 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5655 LeaveCriticalSection(&This->cs);
5657 return hr;
5660 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5662 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5664 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5666 return E_NOTIMPL;
5669 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5671 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5673 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5675 return E_NOTIMPL;
5678 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5680 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5682 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5684 return E_NOTIMPL;
5687 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5689 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5691 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5693 return E_NOTIMPL;
5696 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5697 IPinConnection *pConnection, HANDLE hEventAbort)
5699 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5701 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5703 return E_NOTIMPL;
5706 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5707 DWORD dwFlags)
5709 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5711 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5713 return E_NOTIMPL;
5716 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5717 DWORD *dwFlags)
5719 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5721 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5723 return E_NOTIMPL;
5726 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5727 DWORD dwFlags)
5729 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5731 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5733 return E_NOTIMPL;
5736 static const IGraphConfigVtbl IGraphConfig_VTable =
5738 GraphConfig_QueryInterface,
5739 GraphConfig_AddRef,
5740 GraphConfig_Release,
5741 GraphConfig_Reconnect,
5742 GraphConfig_Reconfigure,
5743 GraphConfig_AddFilterToCache,
5744 GraphConfig_EnumCacheFilter,
5745 GraphConfig_RemoveFilterFromCache,
5746 GraphConfig_GetStartTime,
5747 GraphConfig_PushThroughData,
5748 GraphConfig_SetFilterFlags,
5749 GraphConfig_GetFilterFlags,
5750 GraphConfig_RemoveFilterEx
5753 static inline IFilterGraphImpl *impl_from_IGraphVersion(IGraphVersion *iface)
5755 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphVersion_iface);
5758 static HRESULT WINAPI GraphVersion_QueryInterface(IGraphVersion *iface, REFIID riid, void **ppv)
5760 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5762 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5765 static ULONG WINAPI GraphVersion_AddRef(IGraphVersion *iface)
5767 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5769 return IUnknown_AddRef(This->outer_unk);
5772 static ULONG WINAPI GraphVersion_Release(IGraphVersion *iface)
5774 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5776 return IUnknown_Release(This->outer_unk);
5779 static HRESULT WINAPI GraphVersion_QueryVersion(IGraphVersion *iface, LONG *pVersion)
5781 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5783 if(!pVersion)
5784 return E_POINTER;
5786 TRACE("(%p)->(%p): current version %i\n", This, pVersion, This->version);
5788 *pVersion = This->version;
5789 return S_OK;
5792 static const IGraphVersionVtbl IGraphVersion_VTable =
5794 GraphVersion_QueryInterface,
5795 GraphVersion_AddRef,
5796 GraphVersion_Release,
5797 GraphVersion_QueryVersion,
5800 static const IUnknownVtbl IInner_VTable =
5802 FilterGraphInner_QueryInterface,
5803 FilterGraphInner_AddRef,
5804 FilterGraphInner_Release
5807 /* This is the only function that actually creates a FilterGraph class... */
5808 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5810 IFilterGraphImpl *fimpl;
5811 HRESULT hr;
5813 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5815 *ppObj = NULL;
5817 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5818 fimpl->defaultclock = TRUE;
5819 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5820 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5821 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5822 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5823 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5824 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5825 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5826 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5827 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5828 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5829 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5830 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5831 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5832 fimpl->IGraphVersion_iface.lpVtbl = &IGraphVersion_VTable;
5833 fimpl->ref = 1;
5834 list_init(&fimpl->filters);
5835 fimpl->nameIndex = 1;
5836 fimpl->refClock = NULL;
5837 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5838 fimpl->HandleEcComplete = TRUE;
5839 fimpl->HandleEcRepaint = TRUE;
5840 fimpl->HandleEcClockChanged = TRUE;
5841 fimpl->notif.hWnd = 0;
5842 fimpl->notif.disabled = FALSE;
5843 fimpl->nRenderers = 0;
5844 fimpl->EcCompleteCount = 0;
5845 fimpl->refClockProvider = NULL;
5846 fimpl->state = State_Stopped;
5847 fimpl->pSite = NULL;
5848 EventsQueue_Init(&fimpl->evqueue);
5849 InitializeCriticalSection(&fimpl->cs);
5850 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5851 fimpl->nItfCacheEntries = 0;
5852 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5853 fimpl->start_time = fimpl->pause_time = 0;
5854 fimpl->stop_position = -1;
5855 fimpl->punkFilterMapper2 = NULL;
5856 fimpl->recursioncount = 0;
5857 fimpl->version = 0;
5859 if (pUnkOuter)
5860 fimpl->outer_unk = pUnkOuter;
5861 else
5862 fimpl->outer_unk = &fimpl->IUnknown_inner;
5864 /* create Filtermapper aggregated. */
5865 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5866 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5868 if (FAILED(hr)) {
5869 ERR("Unable to create filter mapper (%x)\n", hr);
5870 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5871 CloseHandle(fimpl->hEventCompletion);
5872 EventsQueue_Destroy(&fimpl->evqueue);
5873 fimpl->cs.DebugInfo->Spare[0] = 0;
5874 DeleteCriticalSection(&fimpl->cs);
5875 CoTaskMemFree(fimpl);
5876 return hr;
5879 *ppObj = &fimpl->IUnknown_inner;
5880 return S_OK;
5883 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5885 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5886 return FilterGraph_create(pUnkOuter, ppObj);