quartz/filtergraph: Implement IMediaControl state functions on top of IMediaFilter.
[wine.git] / dlls / quartz / filtergraph.c
blob4dfe5c081d70ca775c1007c1263109ed7efd3e10
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 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
979 HRESULT hr;
980 ULONG nb = 0;
982 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
983 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
984 if (hr == S_OK) {
985 /* Rendered input */
986 } else if (hr == S_FALSE) {
987 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
988 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
989 if (hr != S_OK) {
990 WARN("Error (%x)\n", hr);
992 } else if (hr == E_NOTIMPL) {
993 /* Input connected to all outputs */
994 IEnumPins* penumpins;
995 IPin* ppin;
996 int i = 0;
997 TRACE("E_NOTIMPL\n");
998 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
999 if (FAILED(hr)) {
1000 WARN("filter Enumpins failed (%x)\n", hr);
1001 return hr;
1003 i = 0;
1004 /* Count output pins */
1005 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
1006 PIN_DIRECTION pindir;
1007 IPin_QueryDirection(ppin, &pindir);
1008 if (pindir == PINDIR_OUTPUT)
1009 i++;
1010 IPin_Release(ppin);
1012 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
1013 /* Retrieve output pins */
1014 IEnumPins_Reset(penumpins);
1015 i = 0;
1016 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
1017 PIN_DIRECTION pindir;
1018 IPin_QueryDirection(ppin, &pindir);
1019 if (pindir == PINDIR_OUTPUT)
1020 (*pppins)[i++] = ppin;
1021 else
1022 IPin_Release(ppin);
1024 IEnumPins_Release(penumpins);
1025 nb = i;
1026 if (FAILED(hr)) {
1027 WARN("Next failed (%x)\n", hr);
1028 return hr;
1030 } else if (FAILED(hr)) {
1031 WARN("Cannot get internal connection (%x)\n", hr);
1032 return hr;
1035 *pnb = nb;
1036 return S_OK;
1039 /* Attempt to connect one of the output pins on filter to sink. Helper for
1040 * FilterGraph2_Connect(). */
1041 static HRESULT connect_output_pin(IFilterGraphImpl *graph, IBaseFilter *filter, IPin *sink)
1043 IEnumPins *enumpins;
1044 PIN_INFO info;
1045 HRESULT hr;
1046 IPin *pin;
1048 hr = IBaseFilter_EnumPins(filter, &enumpins);
1049 if (FAILED(hr))
1050 return hr;
1052 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1054 IPin_QueryPinInfo(pin, &info);
1055 IBaseFilter_Release(info.pFilter);
1056 if (info.dir == PINDIR_OUTPUT)
1058 if (info.achName[0] == '~')
1060 TRACE("Skipping non-rendered pin %s.\n", debugstr_w(info.achName));
1061 IPin_Release(pin);
1062 continue;
1065 if (SUCCEEDED(IFilterGraph2_Connect(&graph->IFilterGraph2_iface, pin, sink)))
1067 IPin_Release(pin);
1068 IEnumPins_Release(enumpins);
1069 return S_OK;
1072 IPin_Release(pin);
1075 IEnumPins_Release(enumpins);
1076 return VFW_E_CANNOT_CONNECT;
1079 /*** IGraphBuilder methods ***/
1080 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
1082 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1083 struct filter *filter;
1084 HRESULT hr;
1085 IPin *pin;
1086 AM_MEDIA_TYPE* mt = NULL;
1087 IEnumMediaTypes* penummt = NULL;
1088 ULONG nbmt;
1089 IEnumPins* penumpins;
1090 IEnumMoniker* pEnumMoniker;
1091 GUID tab[2];
1092 IMoniker* pMoniker;
1093 PIN_INFO PinInfo;
1094 CLSID FilterCLSID;
1095 PIN_DIRECTION dir;
1096 IFilterMapper2 *pFilterMapper2 = NULL;
1098 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
1100 if(!ppinOut || !ppinIn)
1101 return E_POINTER;
1103 if (TRACE_ON(quartz))
1105 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
1106 if (FAILED(hr))
1107 return hr;
1109 TRACE("Filter owning ppinIn(%p) => %p\n", ppinIn, PinInfo.pFilter);
1110 IBaseFilter_Release(PinInfo.pFilter);
1112 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1113 if (FAILED(hr))
1114 return hr;
1116 TRACE("Filter owning ppinOut(%p) => %p\n", ppinOut, PinInfo.pFilter);
1117 IBaseFilter_Release(PinInfo.pFilter);
1120 EnterCriticalSection(&This->cs);
1121 ++This->recursioncount;
1122 if (This->recursioncount >= 5)
1124 WARN("Recursion count has reached %d\n", This->recursioncount);
1125 hr = VFW_E_CANNOT_CONNECT;
1126 goto out;
1129 hr = IPin_QueryDirection(ppinOut, &dir);
1130 if (FAILED(hr))
1131 goto out;
1133 if (dir == PINDIR_INPUT)
1135 IPin *temp;
1137 TRACE("Directions seem backwards, swapping pins\n");
1139 temp = ppinIn;
1140 ppinIn = ppinOut;
1141 ppinOut = temp;
1144 hr = CheckCircularConnection(This, ppinOut, ppinIn);
1145 if (FAILED(hr))
1146 goto out;
1148 /* Try direct connection first */
1149 hr = IPin_Connect(ppinOut, ppinIn, NULL);
1151 /* If direct connection succeeded, we should propagate that return value.
1152 * If it returned VFW_E_NOT_CONNECTED or VFW_E_NO_AUDIO_HARDWARE, then don't
1153 * even bother trying intermediate filters, since they won't succeed. */
1154 if (SUCCEEDED(hr) || hr == VFW_E_NOT_CONNECTED || hr == VFW_E_NO_AUDIO_HARDWARE)
1155 goto out;
1157 TRACE("Direct connection failed, trying to render using extra filters\n");
1159 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1161 hr = IBaseFilter_EnumPins(filter->filter, &penumpins);
1162 if (FAILED(hr))
1163 goto out;
1165 while (IEnumPins_Next(penumpins, 1, &pin, NULL) == S_OK)
1167 IPin_QueryDirection(pin, &dir);
1168 if (dir == PINDIR_INPUT && SUCCEEDED(IFilterGraph2_ConnectDirect(iface,
1169 ppinOut, pin, NULL)))
1171 if (SUCCEEDED(hr = connect_output_pin(This, filter->filter, ppinIn)))
1173 IPin_Release(pin);
1174 IEnumPins_Release(penumpins);
1175 goto out;
1178 IFilterGraph2_Disconnect(iface, pin);
1179 IFilterGraph2_Disconnect(iface, ppinOut);
1181 IPin_Release(pin);
1184 IEnumPins_Release(penumpins);
1187 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
1188 if (FAILED(hr))
1189 goto out;
1191 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
1192 IBaseFilter_Release(PinInfo.pFilter);
1193 if (FAILED(hr))
1194 goto out;
1196 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
1197 * filter to the minor mediatype of input pin of the renderer */
1198 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1199 if (FAILED(hr))
1201 WARN("EnumMediaTypes (%x)\n", hr);
1202 goto out;
1205 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1206 if (FAILED(hr)) {
1207 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1208 goto out;
1211 if (!nbmt)
1213 WARN("No media type found!\n");
1214 hr = VFW_E_INVALIDMEDIATYPE;
1215 goto out;
1217 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1218 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1220 hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
1221 if (FAILED(hr)) {
1222 WARN("Unable to get IFilterMapper2 (%x)\n", hr);
1223 goto out;
1226 /* Try to find a suitable filter that can connect to the pin to render */
1227 tab[0] = mt->majortype;
1228 tab[1] = mt->subtype;
1229 hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1230 if (FAILED(hr)) {
1231 WARN("Unable to enum filters (%x)\n", hr);
1232 goto out;
1235 hr = VFW_E_CANNOT_RENDER;
1236 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, NULL) == S_OK)
1238 VARIANT var;
1239 GUID clsid;
1240 IPin* ppinfilter = NULL;
1241 IBaseFilter* pfilter = NULL;
1242 IAMGraphBuilderCallback *callback = NULL;
1244 hr = GetFilterInfo(pMoniker, &var);
1245 if (FAILED(hr)) {
1246 WARN("Unable to retrieve filter info (%x)\n", hr);
1247 goto error;
1250 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1251 IMoniker_Release(pMoniker);
1252 if (FAILED(hr)) {
1253 WARN("Unable to create filter (%x), trying next one\n", hr);
1254 goto error;
1257 hr = IBaseFilter_GetClassID(pfilter, &clsid);
1258 if (FAILED(hr))
1260 IBaseFilter_Release(pfilter);
1261 goto error;
1264 if (IsEqualGUID(&clsid, &FilterCLSID)) {
1265 /* Skip filter (same as the one the output pin belongs to) */
1266 IBaseFilter_Release(pfilter);
1267 pfilter = NULL;
1268 goto error;
1271 if (This->pSite)
1273 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1274 if (callback)
1276 HRESULT rc;
1277 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1278 if (FAILED(rc))
1280 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1281 IAMGraphBuilderCallback_Release(callback);
1282 goto error;
1287 if (callback)
1289 HRESULT rc;
1290 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1291 IAMGraphBuilderCallback_Release(callback);
1292 if (FAILED(rc))
1294 IBaseFilter_Release(pfilter);
1295 pfilter = NULL;
1296 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1297 goto error;
1301 hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
1302 if (FAILED(hr)) {
1303 WARN("Unable to add filter (%x)\n", hr);
1304 IBaseFilter_Release(pfilter);
1305 pfilter = NULL;
1306 goto error;
1309 VariantClear(&var);
1311 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1312 if (FAILED(hr)) {
1313 WARN("Enumpins (%x)\n", hr);
1314 goto error;
1317 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, NULL);
1318 IEnumPins_Release(penumpins);
1320 if (FAILED(hr)) {
1321 WARN("Obtaining next pin: (%x)\n", hr);
1322 goto error;
1324 if (hr == S_FALSE) {
1325 WARN("Cannot use this filter: no pins\n");
1326 goto error;
1329 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1330 if (FAILED(hr)) {
1331 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1332 goto error;
1334 TRACE("Successfully connected to filter, follow chain...\n");
1336 if (SUCCEEDED(hr = connect_output_pin(This, pfilter, ppinIn)))
1338 IPin_Release(ppinfilter);
1339 IBaseFilter_Release(pfilter);
1340 break;
1343 error:
1344 VariantClear(&var);
1345 if (ppinfilter) IPin_Release(ppinfilter);
1346 if (pfilter) {
1347 IFilterGraph2_RemoveFilter(iface, pfilter);
1348 IBaseFilter_Release(pfilter);
1352 if (FAILED(hr))
1353 hr = VFW_E_CANNOT_CONNECT;
1355 IEnumMoniker_Release(pEnumMoniker);
1357 out:
1358 if (pFilterMapper2)
1359 IFilterMapper2_Release(pFilterMapper2);
1360 if (penummt)
1361 IEnumMediaTypes_Release(penummt);
1362 if (mt)
1363 DeleteMediaType(mt);
1364 --This->recursioncount;
1365 LeaveCriticalSection(&This->cs);
1366 TRACE("--> %08x\n", hr);
1367 return hr;
1370 /* Render all output pins of the given filter. Helper for FilterGraph2_Render(). */
1371 static HRESULT render_output_pins(IFilterGraphImpl *graph, IBaseFilter *filter)
1373 BOOL renderany = FALSE;
1374 BOOL renderall = TRUE;
1375 IEnumPins *enumpins;
1376 IPin *pin, *peer;
1377 PIN_INFO info;
1379 IBaseFilter_EnumPins(filter, &enumpins);
1380 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1382 IPin_QueryPinInfo(pin, &info);
1383 IBaseFilter_Release(info.pFilter);
1384 if (info.dir == PINDIR_OUTPUT)
1386 if (info.achName[0] == '~')
1388 TRACE("Skipping non-rendered pin %s.\n", debugstr_w(info.achName));
1389 IPin_Release(pin);
1390 continue;
1393 if (IPin_ConnectedTo(pin, &peer) == VFW_E_NOT_CONNECTED)
1395 HRESULT hr;
1396 hr = IFilterGraph2_Render(&graph->IFilterGraph2_iface, pin);
1397 if (SUCCEEDED(hr))
1398 renderany = TRUE;
1399 else
1400 renderall = FALSE;
1402 else
1403 IPin_Release(peer);
1406 IPin_Release(pin);
1409 IEnumPins_Release(enumpins);
1411 if (renderall)
1412 return S_OK;
1414 if (renderany)
1415 return VFW_S_PARTIAL_RENDER;
1417 return VFW_E_CANNOT_RENDER;
1420 /* Ogg hates me if I create a direct rendering method
1422 * It can only connect to a pin properly once, so use a recursive method that does
1424 * +----+ --- (PIN 1) (Render is called on this pin)
1425 * | |
1426 * +----+ --- (PIN 2)
1428 * Enumerate possible renderers that EXACTLY match the requested type
1430 * If none is available, try to add intermediate filters that can connect to the input pin
1431 * then call Render on that intermediate pin's output pins
1432 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1433 * and another filter that can connect to the input pin is tried
1434 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1435 * It's recursive, but fun!
1438 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1440 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1441 IEnumMediaTypes* penummt;
1442 struct filter *filter;
1443 AM_MEDIA_TYPE* mt;
1444 ULONG nbmt;
1445 HRESULT hr;
1447 IEnumMoniker* pEnumMoniker;
1448 GUID tab[4];
1449 ULONG nb;
1450 IMoniker* pMoniker;
1451 IFilterMapper2 *pFilterMapper2 = NULL;
1453 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1455 if (TRACE_ON(quartz))
1457 PIN_INFO PinInfo;
1459 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1460 if (FAILED(hr))
1461 return hr;
1463 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1464 IBaseFilter_Release(PinInfo.pFilter);
1467 /* Try to find out if there is a renderer for the specified subtype already, and use that
1469 EnterCriticalSection(&This->cs);
1470 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1472 IEnumPins *enumpins = NULL;
1473 IPin *pin = NULL;
1475 hr = IBaseFilter_EnumPins(filter->filter, &enumpins);
1477 if (FAILED(hr) || !enumpins)
1478 continue;
1480 IEnumPins_Reset(enumpins);
1481 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1483 IPin *to = NULL;
1484 PIN_DIRECTION dir = PINDIR_OUTPUT;
1486 IPin_QueryDirection(pin, &dir);
1487 if (dir != PINDIR_INPUT)
1489 IPin_Release(pin);
1490 continue;
1492 IPin_ConnectedTo(pin, &to);
1494 if (to == NULL)
1496 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1497 if (SUCCEEDED(hr))
1499 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1500 IPin_Release(pin);
1502 hr = render_output_pins(This, filter->filter);
1503 if (FAILED(hr))
1505 IPin_Disconnect(ppinOut);
1506 IPin_Disconnect(pin);
1507 continue;
1509 IEnumPins_Release(enumpins);
1510 LeaveCriticalSection(&This->cs);
1511 return hr;
1513 WARN("Could not connect!\n");
1515 else
1516 IPin_Release(to);
1518 IPin_Release(pin);
1520 IEnumPins_Release(enumpins);
1523 LeaveCriticalSection(&This->cs);
1525 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1526 if (FAILED(hr)) {
1527 WARN("EnumMediaTypes (%x)\n", hr);
1528 return hr;
1531 IEnumMediaTypes_Reset(penummt);
1533 /* Looks like no existing renderer of the kind exists
1534 * Try adding new ones
1536 tab[0] = tab[1] = GUID_NULL;
1537 while (SUCCEEDED(hr))
1539 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1540 if (FAILED(hr)) {
1541 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1542 break;
1544 if (!nbmt)
1546 hr = VFW_E_CANNOT_RENDER;
1547 break;
1549 else
1551 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1552 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1554 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1555 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1557 DeleteMediaType(mt);
1558 continue;
1561 if (pFilterMapper2 == NULL)
1563 hr = IUnknown_QueryInterface(This->punkFilterMapper2, &IID_IFilterMapper2, (void**)&pFilterMapper2);
1564 if (FAILED(hr))
1566 WARN("Unable to query IFilterMapper2 (%x)\n", hr);
1567 break;
1571 /* Try to find a suitable renderer with the same media type */
1572 tab[0] = mt->majortype;
1573 tab[1] = mt->subtype;
1574 hr = IFilterMapper2_EnumMatchingFilters(pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1575 if (FAILED(hr))
1577 WARN("Unable to enum filters (%x)\n", hr);
1578 break;
1581 hr = E_FAIL;
1583 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1585 VARIANT var;
1586 IPin* ppinfilter;
1587 IBaseFilter* pfilter = NULL;
1588 IEnumPins* penumpins = NULL;
1589 ULONG pin;
1591 hr = GetFilterInfo(pMoniker, &var);
1592 if (FAILED(hr)) {
1593 WARN("Unable to retrieve filter info (%x)\n", hr);
1594 goto error;
1597 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1598 IMoniker_Release(pMoniker);
1599 if (FAILED(hr))
1601 WARN("Unable to create filter (%x), trying next one\n", hr);
1602 goto error;
1605 hr = IFilterGraph2_AddFilter(iface, pfilter, V_BSTR(&var));
1606 if (FAILED(hr)) {
1607 WARN("Unable to add filter (%x)\n", hr);
1608 IBaseFilter_Release(pfilter);
1609 pfilter = NULL;
1610 goto error;
1613 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1614 if (FAILED(hr)) {
1615 WARN("Splitter Enumpins (%x)\n", hr);
1616 goto error;
1619 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1621 PIN_DIRECTION dir;
1623 if (pin == 0) {
1624 WARN("No Pin\n");
1625 hr = E_FAIL;
1626 goto error;
1629 hr = IPin_QueryDirection(ppinfilter, &dir);
1630 if (FAILED(hr)) {
1631 IPin_Release(ppinfilter);
1632 WARN("QueryDirection failed (%x)\n", hr);
1633 goto error;
1635 if (dir != PINDIR_INPUT) {
1636 IPin_Release(ppinfilter);
1637 continue; /* Wrong direction */
1640 /* Connect the pin to the "Renderer" */
1641 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1642 IPin_Release(ppinfilter);
1644 if (FAILED(hr)) {
1645 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_BSTR(&var)), hr);
1646 goto error;
1648 TRACE("Connected, recursing %s\n", debugstr_w(V_BSTR(&var)));
1650 VariantClear(&var);
1652 hr = render_output_pins(This, pfilter);
1653 if (FAILED(hr)) {
1654 WARN("Unable to connect recursively (%x)\n", hr);
1655 goto error;
1657 IBaseFilter_Release(pfilter);
1658 break;
1660 if (SUCCEEDED(hr)) {
1661 IEnumPins_Release(penumpins);
1662 break; /* out of IEnumMoniker_Next loop */
1665 /* IEnumPins_Next failed, all other failure case caught by goto error */
1666 WARN("IEnumPins_Next (%x)\n", hr);
1667 /* goto error */
1669 error:
1670 VariantClear(&var);
1671 if (penumpins)
1672 IEnumPins_Release(penumpins);
1673 if (pfilter) {
1674 IFilterGraph2_RemoveFilter(iface, pfilter);
1675 IBaseFilter_Release(pfilter);
1677 if (SUCCEEDED(hr)) DebugBreak();
1680 IEnumMoniker_Release(pEnumMoniker);
1681 if (nbmt)
1682 DeleteMediaType(mt);
1683 if (SUCCEEDED(hr))
1684 break;
1685 hr = S_OK;
1688 if (pFilterMapper2)
1689 IFilterMapper2_Release(pFilterMapper2);
1691 IEnumMediaTypes_Release(penummt);
1692 return hr;
1695 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1696 LPCWSTR lpcwstrPlayList)
1698 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1699 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1700 IBaseFilter* preader = NULL;
1701 IPin* ppinreader = NULL;
1702 IEnumPins* penumpins = NULL;
1703 struct filter *filter;
1704 HRESULT hr;
1705 BOOL partial = FALSE;
1706 BOOL any = FALSE;
1708 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1710 if (lpcwstrPlayList != NULL)
1711 return E_INVALIDARG;
1713 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1714 if (FAILED(hr))
1715 return hr;
1717 hr = IBaseFilter_EnumPins(preader, &penumpins);
1718 if (SUCCEEDED(hr))
1720 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1722 PIN_DIRECTION dir;
1724 IPin_QueryDirection(ppinreader, &dir);
1725 if (dir == PINDIR_OUTPUT)
1727 hr = IFilterGraph2_Render(iface, ppinreader);
1729 TRACE("Filters in chain:\n");
1730 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
1731 TRACE("- %s.\n", debugstr_w(filter->name));
1733 if (SUCCEEDED(hr))
1734 any = TRUE;
1735 if (hr != S_OK)
1736 partial = TRUE;
1738 IPin_Release(ppinreader);
1740 IEnumPins_Release(penumpins);
1742 if (!any)
1743 hr = VFW_E_CANNOT_RENDER;
1744 else if (partial)
1745 hr = VFW_S_PARTIAL_RENDER;
1746 else
1747 hr = S_OK;
1749 IBaseFilter_Release(preader);
1751 TRACE("--> %08x\n", hr);
1752 return hr;
1755 static HRESULT CreateFilterInstanceAndLoadFile(GUID* clsid, LPCOLESTR pszFileName, IBaseFilter **filter)
1757 IFileSourceFilter *source = NULL;
1758 HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1759 TRACE("CLSID: %s\n", debugstr_guid(clsid));
1760 if (FAILED(hr))
1761 return hr;
1763 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1764 if (FAILED(hr))
1766 IBaseFilter_Release(*filter);
1767 return hr;
1770 /* Load the file in the file source filter */
1771 hr = IFileSourceFilter_Load(source, pszFileName, NULL);
1772 IFileSourceFilter_Release(source);
1773 if (FAILED(hr)) {
1774 WARN("Load (%x)\n", hr);
1775 IBaseFilter_Release(*filter);
1776 return hr;
1779 return hr;
1782 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1783 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1785 HRESULT hr;
1786 GUID clsid;
1787 IAsyncReader * pReader = NULL;
1788 IFileSourceFilter* pSource = NULL;
1789 IPin * pOutputPin = NULL;
1790 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
1792 /* Try to find a match without reading the file first */
1793 hr = GetClassMediaFile(NULL, pszFileName, NULL, NULL, &clsid);
1795 if (hr == S_OK)
1796 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1798 /* Now create a AyncReader instance, to check for signature bytes in the file */
1799 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1800 if (FAILED(hr))
1801 return hr;
1803 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID *)&pSource);
1804 if (FAILED(hr))
1806 IBaseFilter_Release(*filter);
1807 return hr;
1810 hr = IFileSourceFilter_Load(pSource, pszFileName, NULL);
1811 IFileSourceFilter_Release(pSource);
1812 if (FAILED(hr))
1814 IBaseFilter_Release(*filter);
1815 return hr;
1818 hr = IBaseFilter_FindPin(*filter, wszOutputPinName, &pOutputPin);
1819 if (FAILED(hr))
1821 IBaseFilter_Release(*filter);
1822 return hr;
1825 hr = IPin_QueryInterface(pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
1826 IPin_Release(pOutputPin);
1827 if (FAILED(hr))
1829 IBaseFilter_Release(*filter);
1830 return hr;
1833 /* Try again find a match */
1834 hr = GetClassMediaFile(pReader, pszFileName, NULL, NULL, &clsid);
1835 IAsyncReader_Release(pReader);
1837 if (hr == S_OK)
1839 /* Release the AsyncReader filter and create the matching one */
1840 IBaseFilter_Release(*filter);
1841 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1844 /* Return the AsyncReader filter */
1845 return S_OK;
1848 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1849 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1851 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1852 HRESULT hr;
1853 IBaseFilter* preader;
1854 IFileSourceFilter* pfile = NULL;
1855 AM_MEDIA_TYPE mt;
1856 WCHAR* filename;
1858 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1860 /* Try from file name first, then fall back to default asynchronous reader */
1861 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1862 if (FAILED(hr)) {
1863 WARN("Unable to create file source filter (%x)\n", hr);
1864 return hr;
1867 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1868 if (FAILED(hr)) {
1869 WARN("Unable add filter (%x)\n", hr);
1870 IBaseFilter_Release(preader);
1871 return hr;
1874 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1875 if (FAILED(hr)) {
1876 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1877 goto error;
1880 /* The file has been already loaded */
1881 hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1882 if (FAILED(hr)) {
1883 WARN("GetCurFile (%x)\n", hr);
1884 goto error;
1887 TRACE("File %s\n", debugstr_w(filename));
1888 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1889 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1891 if (ppFilter)
1892 *ppFilter = preader;
1893 IFileSourceFilter_Release(pfile);
1895 return S_OK;
1897 error:
1898 if (pfile)
1899 IFileSourceFilter_Release(pfile);
1900 IFilterGraph2_RemoveFilter(iface, preader);
1901 IBaseFilter_Release(preader);
1903 return hr;
1906 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1908 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1910 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1912 return S_OK;
1915 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1917 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1919 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1921 return S_OK;
1924 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1926 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1928 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1930 return S_OK;
1933 /*** IFilterGraph2 methods ***/
1934 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1935 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1937 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1938 HRESULT hr;
1939 IBaseFilter* pfilter;
1941 TRACE("(%p/%p)->(%p %p %s %p)\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1943 hr = IMoniker_BindToObject(pMoniker, pCtx, NULL, &IID_IBaseFilter, (void**)&pfilter);
1944 if(FAILED(hr)) {
1945 WARN("Unable to bind moniker to filter object (%x)\n", hr);
1946 return hr;
1949 hr = IFilterGraph2_AddFilter(iface, pfilter, lpcwstrFilterName);
1950 if (FAILED(hr)) {
1951 WARN("Unable to add filter (%x)\n", hr);
1952 IBaseFilter_Release(pfilter);
1953 return hr;
1956 if(ppFilter)
1957 *ppFilter = pfilter;
1958 else IBaseFilter_Release(pfilter);
1960 return S_OK;
1963 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1964 const AM_MEDIA_TYPE *pmt)
1966 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1968 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1970 return S_OK;
1973 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1974 DWORD *pvContext)
1976 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1978 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1980 return S_OK;
1984 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1986 FilterGraph2_QueryInterface,
1987 FilterGraph2_AddRef,
1988 FilterGraph2_Release,
1989 FilterGraph2_AddFilter,
1990 FilterGraph2_RemoveFilter,
1991 FilterGraph2_EnumFilters,
1992 FilterGraph2_FindFilterByName,
1993 FilterGraph2_ConnectDirect,
1994 FilterGraph2_Reconnect,
1995 FilterGraph2_Disconnect,
1996 FilterGraph2_SetDefaultSyncSource,
1997 FilterGraph2_Connect,
1998 FilterGraph2_Render,
1999 FilterGraph2_RenderFile,
2000 FilterGraph2_AddSourceFilter,
2001 FilterGraph2_SetLogFile,
2002 FilterGraph2_Abort,
2003 FilterGraph2_ShouldOperationContinue,
2004 FilterGraph2_AddSourceFilterForMoniker,
2005 FilterGraph2_ReconnectEx,
2006 FilterGraph2_RenderEx
2009 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
2011 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
2014 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
2016 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2018 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2020 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2023 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
2025 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2027 TRACE("(%p/%p)->()\n", This, iface);
2029 return IUnknown_AddRef(This->outer_unk);
2032 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
2034 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2036 TRACE("(%p/%p)->()\n", This, iface);
2038 return IUnknown_Release(This->outer_unk);
2042 /*** IDispatch methods ***/
2043 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
2045 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2047 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
2049 return S_OK;
2052 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
2053 ITypeInfo **ppTInfo)
2055 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2057 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
2059 return S_OK;
2062 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
2063 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2065 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2067 TRACE("(%p/%p)->(%s, %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), rgszNames,
2068 cNames, lcid, rgDispId);
2070 return S_OK;
2073 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
2074 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
2075 UINT *puArgErr)
2077 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2079 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember,
2080 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2082 return S_OK;
2085 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
2087 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
2089 HRESULT hr;
2090 IPin* pInputPin;
2091 IPin** ppPins;
2092 ULONG nb;
2093 ULONG i;
2094 PIN_INFO PinInfo;
2096 TRACE("%p %p\n", pGraph, pOutputPin);
2097 PinInfo.pFilter = NULL;
2099 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
2101 if (SUCCEEDED(hr))
2103 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
2104 if (SUCCEEDED(hr))
2105 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
2106 IPin_Release(pInputPin);
2109 if (SUCCEEDED(hr))
2111 if (nb == 0)
2113 TRACE("Reached a renderer\n");
2114 /* Count renderers for end of stream notification */
2115 pGraph->nRenderers++;
2117 else
2119 for(i = 0; i < nb; i++)
2121 /* Explore the graph downstream from this pin
2122 * FIXME: We should prevent exploring from a pin more than once. This can happens when
2123 * several input pins are connected to the same output (a MUX for instance). */
2124 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
2125 IPin_Release(ppPins[i]);
2128 CoTaskMemFree(ppPins);
2130 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
2132 FoundFilter(PinInfo.pFilter, data);
2135 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
2136 return hr;
2139 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
2141 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
2142 return IBaseFilter_Run(pFilter, time);
2145 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
2147 return IBaseFilter_Pause(pFilter);
2150 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
2152 return IBaseFilter_Stop(pFilter);
2155 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
2157 FILTER_STATE state;
2158 DWORD time_end = data;
2159 DWORD time_now = GetTickCount();
2160 LONG wait;
2162 if (time_end == INFINITE)
2164 wait = INFINITE;
2166 else if (time_end > time_now)
2168 wait = time_end - time_now;
2170 else
2171 wait = 0;
2173 return IBaseFilter_GetState(pFilter, wait, &state);
2177 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
2179 struct filter *filter;
2180 IEnumPins* pEnum;
2181 HRESULT hr;
2182 IPin* pPin;
2183 DWORD dummy;
2184 PIN_DIRECTION dir;
2186 TRACE("(%p)->()\n", This);
2188 /* Explorer the graph from source filters to renderers, determine renderers
2189 * number and run filters from renderers to source filters */
2190 This->nRenderers = 0;
2191 ResetEvent(This->hEventCompletion);
2193 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
2195 BOOL source = TRUE;
2196 hr = IBaseFilter_EnumPins(filter->filter, &pEnum);
2197 if (hr != S_OK)
2199 WARN("Enum pins failed %x\n", hr);
2200 continue;
2202 /* Check if it is a source filter */
2203 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2205 IPin_QueryDirection(pPin, &dir);
2206 IPin_Release(pPin);
2207 if (dir == PINDIR_INPUT)
2209 source = FALSE;
2210 break;
2213 if (source)
2215 TRACE("Found source filter %p.\n", filter->filter);
2216 IEnumPins_Reset(pEnum);
2217 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
2219 /* Explore the graph downstream from this pin */
2220 ExploreGraph(This, pPin, FoundFilter, data);
2221 IPin_Release(pPin);
2223 FoundFilter(filter->filter, data);
2225 IEnumPins_Release(pEnum);
2228 return S_FALSE;
2231 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
2233 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2235 return IMediaFilter_Run(&graph->IMediaFilter_iface, 0);
2238 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2240 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2242 return IMediaFilter_Pause(&graph->IMediaFilter_iface);
2245 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2247 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2249 return IMediaFilter_Stop(&graph->IMediaFilter_iface);
2252 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG timeout, OAFilterState *state)
2254 IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
2256 if (timeout < 0) timeout = INFINITE;
2258 return IMediaFilter_GetState(&graph->IMediaFilter_iface, timeout, (FILTER_STATE *)state);
2261 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2263 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2265 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename);
2267 return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL);
2270 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2271 IDispatch **ppUnk)
2273 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2275 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2277 return S_OK;
2280 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2282 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2284 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2286 return S_OK;
2289 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2291 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2293 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2295 return S_OK;
2298 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2300 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2302 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2304 return S_OK;
2308 static const IMediaControlVtbl IMediaControl_VTable =
2310 MediaControl_QueryInterface,
2311 MediaControl_AddRef,
2312 MediaControl_Release,
2313 MediaControl_GetTypeInfoCount,
2314 MediaControl_GetTypeInfo,
2315 MediaControl_GetIDsOfNames,
2316 MediaControl_Invoke,
2317 MediaControl_Run,
2318 MediaControl_Pause,
2319 MediaControl_Stop,
2320 MediaControl_GetState,
2321 MediaControl_RenderFile,
2322 MediaControl_AddSourceFilter,
2323 MediaControl_get_FilterCollection,
2324 MediaControl_get_RegFilterCollection,
2325 MediaControl_StopWhenReady
2328 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2330 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2333 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2335 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2337 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2339 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2342 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2344 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2346 TRACE("(%p/%p)->()\n", This, iface);
2348 return IUnknown_AddRef(This->outer_unk);
2351 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2353 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2355 TRACE("(%p/%p)->()\n", This, iface);
2357 return IUnknown_Release(This->outer_unk);
2360 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2362 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2363 BOOL allnotimpl = TRUE;
2364 HRESULT hr, hr_return = S_OK;
2365 struct filter *filter;
2367 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2368 /* Send a message to all renderers, they are responsible for broadcasting it further */
2370 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
2372 IMediaSeeking *seek = NULL;
2373 IAMFilterMiscFlags *flags = NULL;
2374 ULONG filterflags;
2375 IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags);
2376 if (!flags)
2377 continue;
2378 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2379 IAMFilterMiscFlags_Release(flags);
2380 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2381 continue;
2383 IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seek);
2384 if (!seek)
2385 continue;
2386 hr = FoundSeek(This, seek, arg);
2387 IMediaSeeking_Release(seek);
2388 if (hr_return != E_NOTIMPL)
2389 allnotimpl = FALSE;
2390 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2391 hr_return = hr;
2394 if (allnotimpl)
2395 return E_NOTIMPL;
2396 return hr_return;
2399 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2401 HRESULT hr;
2402 DWORD caps = 0;
2404 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2405 if (FAILED(hr))
2406 return hr;
2408 /* Only add common capabilities everything supports */
2409 *(DWORD*)pcaps &= caps;
2411 return hr;
2414 /*** IMediaSeeking methods ***/
2415 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2417 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2418 HRESULT hr;
2420 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2422 if (!pCapabilities)
2423 return E_POINTER;
2425 EnterCriticalSection(&This->cs);
2426 *pCapabilities = 0xffffffff;
2428 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2429 LeaveCriticalSection(&This->cs);
2431 return hr;
2434 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2436 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2437 DWORD originalcaps;
2438 HRESULT hr;
2440 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2442 if (!pCapabilities)
2443 return E_POINTER;
2445 EnterCriticalSection(&This->cs);
2446 originalcaps = *pCapabilities;
2447 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2448 LeaveCriticalSection(&This->cs);
2450 if (FAILED(hr))
2451 return hr;
2453 if (!*pCapabilities)
2454 return E_FAIL;
2455 if (*pCapabilities != originalcaps)
2456 return S_FALSE;
2457 return S_OK;
2460 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2462 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2464 if (!pFormat)
2465 return E_POINTER;
2467 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2469 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2471 WARN("Unhandled time format %s\n", debugstr_guid(pFormat));
2472 return S_FALSE;
2475 return S_OK;
2478 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2480 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2482 if (!pFormat)
2483 return E_POINTER;
2485 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2486 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2488 return S_OK;
2491 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2493 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2495 if (!pFormat)
2496 return E_POINTER;
2498 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2499 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2501 return S_OK;
2504 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2506 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2508 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2509 if (!pFormat)
2510 return E_POINTER;
2512 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2513 return S_FALSE;
2515 return S_OK;
2518 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2520 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2522 if (!pFormat)
2523 return E_POINTER;
2525 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2527 if (This->state != State_Stopped)
2528 return VFW_E_WRONG_STATE;
2530 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2532 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2533 return E_INVALIDARG;
2536 return S_OK;
2539 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2541 HRESULT hr;
2542 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2544 hr = IMediaSeeking_GetDuration(seek, &duration);
2545 if (FAILED(hr))
2546 return hr;
2548 if (*pdur < duration)
2549 *pdur = duration;
2550 return hr;
2553 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2555 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2556 HRESULT hr;
2558 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2560 if (!pDuration)
2561 return E_POINTER;
2563 EnterCriticalSection(&This->cs);
2564 *pDuration = 0;
2565 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2566 LeaveCriticalSection(&This->cs);
2568 TRACE("--->%08x\n", hr);
2569 return hr;
2572 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2574 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2575 HRESULT hr = S_OK;
2577 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2579 if (!pStop)
2580 return E_POINTER;
2582 EnterCriticalSection(&This->cs);
2583 if (This->stop_position < 0)
2584 /* Stop position not set, use duration instead */
2585 hr = IMediaSeeking_GetDuration(iface, pStop);
2586 else
2587 *pStop = This->stop_position;
2588 LeaveCriticalSection(&This->cs);
2590 return hr;
2593 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2595 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2596 LONGLONG time = 0;
2598 if (!pCurrent)
2599 return E_POINTER;
2601 EnterCriticalSection(&This->cs);
2602 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2604 IReferenceClock_GetTime(This->refClock, &time);
2605 if (time)
2606 time -= This->start_time;
2608 if (This->pause_time > 0)
2609 time += This->pause_time;
2610 *pCurrent = time;
2611 LeaveCriticalSection(&This->cs);
2613 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2615 return S_OK;
2618 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2619 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2621 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2623 TRACE("(%p/%p)->(%p, %s, 0x%s, %s)\n", This, iface, pTarget,
2624 debugstr_guid(pTargetFormat), wine_dbgstr_longlong(Source), debugstr_guid(pSourceFormat));
2626 if (!pSourceFormat)
2627 pSourceFormat = &This->timeformatseek;
2629 if (!pTargetFormat)
2630 pTargetFormat = &This->timeformatseek;
2632 if (IsEqualGUID(pTargetFormat, pSourceFormat))
2633 *pTarget = Source;
2634 else
2635 FIXME("conversion %s->%s not supported\n", debugstr_guid(pSourceFormat), debugstr_guid(pTargetFormat));
2637 return S_OK;
2640 struct pos_args {
2641 LONGLONG* current, *stop;
2642 DWORD curflags, stopflags;
2645 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2647 struct pos_args *args = (void*)pargs;
2649 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2652 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2653 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2655 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2656 HRESULT hr = S_OK;
2657 FILTER_STATE state;
2658 struct pos_args args;
2660 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2662 EnterCriticalSection(&This->cs);
2663 state = This->state;
2664 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2666 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2667 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2668 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2670 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2671 This->stop_position = *pStop;
2672 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2673 FIXME("Stop position not handled yet!\n");
2675 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2676 IMediaControl_Pause(&This->IMediaControl_iface);
2677 args.current = pCurrent;
2678 args.stop = pStop;
2679 args.curflags = dwCurrentFlags;
2680 args.stopflags = dwStopFlags;
2681 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2683 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2684 This->pause_time = This->start_time = -1;
2685 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2686 IMediaControl_Run(&This->IMediaControl_iface);
2687 LeaveCriticalSection(&This->cs);
2689 return hr;
2692 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2693 LONGLONG *pStop)
2695 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2696 HRESULT hr;
2698 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2699 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2700 if (SUCCEEDED(hr))
2701 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2703 return hr;
2706 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2707 LONGLONG *pLatest)
2709 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2711 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2713 return S_OK;
2716 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2718 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2720 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2722 return S_OK;
2725 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2727 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2729 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2731 if (!pdRate)
2732 return E_POINTER;
2734 *pdRate = 1.0;
2736 return S_OK;
2739 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2741 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2743 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2745 return S_OK;
2749 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2751 MediaSeeking_QueryInterface,
2752 MediaSeeking_AddRef,
2753 MediaSeeking_Release,
2754 MediaSeeking_GetCapabilities,
2755 MediaSeeking_CheckCapabilities,
2756 MediaSeeking_IsFormatSupported,
2757 MediaSeeking_QueryPreferredFormat,
2758 MediaSeeking_GetTimeFormat,
2759 MediaSeeking_IsUsingTimeFormat,
2760 MediaSeeking_SetTimeFormat,
2761 MediaSeeking_GetDuration,
2762 MediaSeeking_GetStopPosition,
2763 MediaSeeking_GetCurrentPosition,
2764 MediaSeeking_ConvertTimeFormat,
2765 MediaSeeking_SetPositions,
2766 MediaSeeking_GetPositions,
2767 MediaSeeking_GetAvailable,
2768 MediaSeeking_SetRate,
2769 MediaSeeking_GetRate,
2770 MediaSeeking_GetPreroll
2773 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2775 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2778 /*** IUnknown methods ***/
2779 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2781 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2783 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2785 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2788 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2790 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2792 TRACE("(%p/%p)->()\n", This, iface);
2794 return IUnknown_AddRef(This->outer_unk);
2797 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2799 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2801 TRACE("(%p/%p)->()\n", This, iface);
2803 return IUnknown_Release(This->outer_unk);
2806 /*** IDispatch methods ***/
2807 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo)
2809 FIXME("(%p) stub!\n", iface);
2810 return E_NOTIMPL;
2813 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2815 FIXME("(%p) stub!\n", iface);
2816 return E_NOTIMPL;
2819 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
2821 FIXME("(%p) stub!\n", iface);
2822 return E_NOTIMPL;
2825 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2827 FIXME("(%p) stub!\n", iface);
2828 return E_NOTIMPL;
2831 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2833 GUID time_format;
2834 HRESULT hr;
2836 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2837 if (FAILED(hr))
2838 return hr;
2839 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2841 FIXME("Unsupported time format.\n");
2842 return E_NOTIMPL;
2845 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2846 return S_OK;
2849 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2851 GUID time_format;
2852 HRESULT hr;
2854 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2855 if (FAILED(hr))
2856 return hr;
2857 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2859 FIXME("Unsupported time format.\n");
2860 return E_NOTIMPL;
2863 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2864 return S_OK;
2867 /*** IMediaPosition methods ***/
2868 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2870 LONGLONG duration;
2871 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2872 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2873 if (FAILED(hr))
2874 return hr;
2875 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2878 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2880 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2881 LONGLONG reftime;
2882 HRESULT hr;
2884 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2885 if (FAILED(hr))
2886 return hr;
2887 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2888 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2891 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2893 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2894 LONGLONG pos;
2895 HRESULT hr;
2897 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2898 if (FAILED(hr))
2899 return hr;
2900 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2903 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2905 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2906 LONGLONG pos;
2907 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2908 if (FAILED(hr))
2909 return hr;
2910 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2913 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2915 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2916 LONGLONG reftime;
2917 HRESULT hr;
2919 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2920 if (FAILED(hr))
2921 return hr;
2922 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2923 &reftime, AM_SEEKING_AbsolutePositioning);
2926 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime)
2928 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2929 return E_NOTIMPL;
2932 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime)
2934 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2935 return E_NOTIMPL;
2938 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2940 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2941 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2944 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2946 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2947 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2950 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward)
2952 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2953 return E_NOTIMPL;
2956 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward)
2958 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2959 return E_NOTIMPL;
2963 static const IMediaPositionVtbl IMediaPosition_VTable =
2965 MediaPosition_QueryInterface,
2966 MediaPosition_AddRef,
2967 MediaPosition_Release,
2968 MediaPosition_GetTypeInfoCount,
2969 MediaPosition_GetTypeInfo,
2970 MediaPosition_GetIDsOfNames,
2971 MediaPosition_Invoke,
2972 MediaPosition_get_Duration,
2973 MediaPosition_put_CurrentPosition,
2974 MediaPosition_get_CurrentPosition,
2975 MediaPosition_get_StopTime,
2976 MediaPosition_put_StopTime,
2977 MediaPosition_get_PrerollTime,
2978 MediaPosition_put_PrerollTime,
2979 MediaPosition_put_Rate,
2980 MediaPosition_get_Rate,
2981 MediaPosition_CanSeekForward,
2982 MediaPosition_CanSeekBackward
2985 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2987 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2990 /*** IUnknown methods ***/
2991 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2993 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2995 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
2997 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3000 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
3002 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
3004 TRACE("(%p/%p)->()\n", This, iface);
3006 return IUnknown_AddRef(This->outer_unk);
3009 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
3011 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
3013 TRACE("(%p/%p)->()\n", This, iface);
3015 return IUnknown_Release(This->outer_unk);
3018 /*** IObjectWithSite methods ***/
3020 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
3022 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
3024 TRACE("(%p/%p)->()\n", This, iface);
3025 if (This->pSite) IUnknown_Release(This->pSite);
3026 This->pSite = pUnkSite;
3027 IUnknown_AddRef(This->pSite);
3028 return S_OK;
3031 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
3033 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
3035 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
3037 *ppvSite = NULL;
3038 if (!This->pSite)
3039 return E_FAIL;
3040 else
3041 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
3044 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
3046 ObjectWithSite_QueryInterface,
3047 ObjectWithSite_AddRef,
3048 ObjectWithSite_Release,
3049 ObjectWithSite_SetSite,
3050 ObjectWithSite_GetSite,
3053 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
3055 struct filter *filter;
3056 HRESULT hr;
3057 int entry;
3059 /* Check if the interface type is already registered */
3060 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
3061 if (riid == pGraph->ItfCacheEntries[entry].riid)
3063 if (pGraph->ItfCacheEntries[entry].iface)
3065 /* Return the interface if available */
3066 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
3067 return S_OK;
3069 break;
3072 if (entry >= MAX_ITF_CACHE_ENTRIES)
3074 FIXME("Not enough space to store interface in the cache\n");
3075 return E_OUTOFMEMORY;
3078 /* Find a filter supporting the requested interface */
3079 LIST_FOR_EACH_ENTRY(filter, &pGraph->filters, struct filter, entry)
3081 hr = IBaseFilter_QueryInterface(filter->filter, riid, ppvObj);
3082 if (hr == S_OK)
3084 pGraph->ItfCacheEntries[entry].riid = riid;
3085 pGraph->ItfCacheEntries[entry].filter = filter->filter;
3086 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
3087 if (entry >= pGraph->nItfCacheEntries)
3088 pGraph->nItfCacheEntries++;
3089 return S_OK;
3091 if (hr != E_NOINTERFACE)
3092 return hr;
3095 return IsEqualGUID(riid, &IID_IBasicAudio) ? E_NOTIMPL : E_NOINTERFACE;
3098 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
3100 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
3103 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
3105 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3107 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
3109 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3112 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
3114 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3116 TRACE("(%p/%p)->()\n", This, iface);
3118 return IUnknown_AddRef(This->outer_unk);
3121 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
3123 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3125 TRACE("(%p/%p)->()\n", This, iface);
3127 return IUnknown_Release(This->outer_unk);
3130 /*** IDispatch methods ***/
3131 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
3133 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3134 IBasicAudio* pBasicAudio;
3135 HRESULT hr;
3137 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3139 EnterCriticalSection(&This->cs);
3141 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3143 if (hr == S_OK)
3144 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
3146 LeaveCriticalSection(&This->cs);
3148 return hr;
3151 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
3152 ITypeInfo **ppTInfo)
3154 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3155 IBasicAudio* pBasicAudio;
3156 HRESULT hr;
3158 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3160 EnterCriticalSection(&This->cs);
3162 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3164 if (hr == S_OK)
3165 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
3167 LeaveCriticalSection(&This->cs);
3169 return hr;
3172 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
3173 UINT cNames, LCID lcid, DISPID *rgDispId)
3175 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3176 IBasicAudio* pBasicAudio;
3177 HRESULT hr;
3179 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
3180 lcid, rgDispId);
3182 EnterCriticalSection(&This->cs);
3184 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3186 if (hr == S_OK)
3187 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3189 LeaveCriticalSection(&This->cs);
3191 return hr;
3194 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3195 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3196 UINT *puArgErr)
3198 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3199 IBasicAudio* pBasicAudio;
3200 HRESULT hr;
3202 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
3203 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3205 EnterCriticalSection(&This->cs);
3207 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3209 if (hr == S_OK)
3210 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3212 LeaveCriticalSection(&This->cs);
3214 return hr;
3217 /*** IBasicAudio methods ***/
3218 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3220 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3221 IBasicAudio* pBasicAudio;
3222 HRESULT hr;
3224 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3226 EnterCriticalSection(&This->cs);
3228 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3230 if (hr == S_OK)
3231 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3233 LeaveCriticalSection(&This->cs);
3235 return hr;
3238 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3240 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3241 IBasicAudio* pBasicAudio;
3242 HRESULT hr;
3244 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3246 EnterCriticalSection(&This->cs);
3248 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3250 if (hr == S_OK)
3251 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3253 LeaveCriticalSection(&This->cs);
3255 return hr;
3258 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3260 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3261 IBasicAudio* pBasicAudio;
3262 HRESULT hr;
3264 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3266 EnterCriticalSection(&This->cs);
3268 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3270 if (hr == S_OK)
3271 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3273 LeaveCriticalSection(&This->cs);
3275 return hr;
3278 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3280 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3281 IBasicAudio* pBasicAudio;
3282 HRESULT hr;
3284 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3286 EnterCriticalSection(&This->cs);
3288 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3290 if (hr == S_OK)
3291 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3293 LeaveCriticalSection(&This->cs);
3295 return hr;
3298 static const IBasicAudioVtbl IBasicAudio_VTable =
3300 BasicAudio_QueryInterface,
3301 BasicAudio_AddRef,
3302 BasicAudio_Release,
3303 BasicAudio_GetTypeInfoCount,
3304 BasicAudio_GetTypeInfo,
3305 BasicAudio_GetIDsOfNames,
3306 BasicAudio_Invoke,
3307 BasicAudio_put_Volume,
3308 BasicAudio_get_Volume,
3309 BasicAudio_put_Balance,
3310 BasicAudio_get_Balance
3313 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3315 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3318 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3320 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3322 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
3324 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3327 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3329 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3331 TRACE("(%p/%p)->()\n", This, iface);
3333 return IUnknown_AddRef(This->outer_unk);
3336 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3338 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3340 TRACE("(%p/%p)->()\n", This, iface);
3342 return IUnknown_Release(This->outer_unk);
3345 /*** IDispatch methods ***/
3346 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3348 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3349 IBasicVideo *pBasicVideo;
3350 HRESULT hr;
3352 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3354 EnterCriticalSection(&This->cs);
3356 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3358 if (hr == S_OK)
3359 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3361 LeaveCriticalSection(&This->cs);
3363 return hr;
3366 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3367 ITypeInfo **ppTInfo)
3369 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3370 IBasicVideo *pBasicVideo;
3371 HRESULT hr;
3373 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3375 EnterCriticalSection(&This->cs);
3377 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3379 if (hr == S_OK)
3380 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3382 LeaveCriticalSection(&This->cs);
3384 return hr;
3387 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3388 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3390 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3391 IBasicVideo *pBasicVideo;
3392 HRESULT hr;
3394 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
3395 lcid, rgDispId);
3397 EnterCriticalSection(&This->cs);
3399 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3401 if (hr == S_OK)
3402 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3404 LeaveCriticalSection(&This->cs);
3406 return hr;
3409 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3410 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3411 UINT *puArgErr)
3413 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3414 IBasicVideo *pBasicVideo;
3415 HRESULT hr;
3417 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
3418 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3420 EnterCriticalSection(&This->cs);
3422 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3424 if (hr == S_OK)
3425 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3427 LeaveCriticalSection(&This->cs);
3429 return hr;
3432 /*** IBasicVideo methods ***/
3433 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3435 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3436 IBasicVideo *pBasicVideo;
3437 HRESULT hr;
3439 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3441 EnterCriticalSection(&This->cs);
3443 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3445 if (hr == S_OK)
3446 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3448 LeaveCriticalSection(&This->cs);
3450 return hr;
3453 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3455 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3456 IBasicVideo *pBasicVideo;
3457 HRESULT hr;
3459 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3461 EnterCriticalSection(&This->cs);
3463 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3465 if (hr == S_OK)
3466 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3468 LeaveCriticalSection(&This->cs);
3470 return hr;
3473 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3475 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3476 IBasicVideo *pBasicVideo;
3477 HRESULT hr;
3479 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3481 EnterCriticalSection(&This->cs);
3483 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3485 if (hr == S_OK)
3486 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3488 LeaveCriticalSection(&This->cs);
3490 return hr;
3493 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3495 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3496 IBasicVideo *pBasicVideo;
3497 HRESULT hr;
3499 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3501 EnterCriticalSection(&This->cs);
3503 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3505 if (hr == S_OK)
3506 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3508 LeaveCriticalSection(&This->cs);
3510 return hr;
3513 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3515 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3516 IBasicVideo *pBasicVideo;
3517 HRESULT hr;
3519 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3521 EnterCriticalSection(&This->cs);
3523 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3525 if (hr == S_OK)
3526 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3528 LeaveCriticalSection(&This->cs);
3530 return hr;
3533 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3535 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3536 IBasicVideo *pBasicVideo;
3537 HRESULT hr;
3539 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3541 EnterCriticalSection(&This->cs);
3543 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3545 if (hr == S_OK)
3546 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3548 LeaveCriticalSection(&This->cs);
3550 return hr;
3553 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3555 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3556 IBasicVideo *pBasicVideo;
3557 HRESULT hr;
3559 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3561 EnterCriticalSection(&This->cs);
3563 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3565 if (hr == S_OK)
3566 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3568 LeaveCriticalSection(&This->cs);
3570 return hr;
3573 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3575 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3576 IBasicVideo *pBasicVideo;
3577 HRESULT hr;
3579 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3581 EnterCriticalSection(&This->cs);
3583 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3585 if (hr == S_OK)
3586 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3588 LeaveCriticalSection(&This->cs);
3590 return hr;
3593 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3595 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3596 IBasicVideo *pBasicVideo;
3597 HRESULT hr;
3599 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3601 EnterCriticalSection(&This->cs);
3603 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3605 if (hr == S_OK)
3606 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3608 LeaveCriticalSection(&This->cs);
3610 return hr;
3613 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3615 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3616 IBasicVideo *pBasicVideo;
3617 HRESULT hr;
3619 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3621 EnterCriticalSection(&This->cs);
3623 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3625 if (hr == S_OK)
3626 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3628 LeaveCriticalSection(&This->cs);
3630 return hr;
3633 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3635 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3636 IBasicVideo *pBasicVideo;
3637 HRESULT hr;
3639 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3641 EnterCriticalSection(&This->cs);
3643 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3645 if (hr == S_OK)
3646 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3648 LeaveCriticalSection(&This->cs);
3650 return hr;
3653 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3655 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3656 IBasicVideo *pBasicVideo;
3657 HRESULT hr;
3659 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3661 EnterCriticalSection(&This->cs);
3663 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3665 if (hr == S_OK)
3666 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3668 LeaveCriticalSection(&This->cs);
3670 return hr;
3673 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3675 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3676 IBasicVideo *pBasicVideo;
3677 HRESULT hr;
3679 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3681 EnterCriticalSection(&This->cs);
3683 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3685 if (hr == S_OK)
3686 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3688 LeaveCriticalSection(&This->cs);
3690 return hr;
3693 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3695 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3696 IBasicVideo *pBasicVideo;
3697 HRESULT hr;
3699 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3701 EnterCriticalSection(&This->cs);
3703 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3705 if (hr == S_OK)
3706 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3708 LeaveCriticalSection(&This->cs);
3710 return hr;
3713 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3715 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3716 IBasicVideo *pBasicVideo;
3717 HRESULT hr;
3719 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3721 EnterCriticalSection(&This->cs);
3723 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3725 if (hr == S_OK)
3726 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3728 LeaveCriticalSection(&This->cs);
3730 return hr;
3733 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3735 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3736 IBasicVideo *pBasicVideo;
3737 HRESULT hr;
3739 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3741 EnterCriticalSection(&This->cs);
3743 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3745 if (hr == S_OK)
3746 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3748 LeaveCriticalSection(&This->cs);
3750 return hr;
3753 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3755 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3756 IBasicVideo *pBasicVideo;
3757 HRESULT hr;
3759 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3761 EnterCriticalSection(&This->cs);
3763 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3765 if (hr == S_OK)
3766 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3768 LeaveCriticalSection(&This->cs);
3770 return hr;
3773 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3775 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3776 IBasicVideo *pBasicVideo;
3777 HRESULT hr;
3779 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3781 EnterCriticalSection(&This->cs);
3783 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3785 if (hr == S_OK)
3786 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3788 LeaveCriticalSection(&This->cs);
3790 return hr;
3793 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3795 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3796 IBasicVideo *pBasicVideo;
3797 HRESULT hr;
3799 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3801 EnterCriticalSection(&This->cs);
3803 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3805 if (hr == S_OK)
3806 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3808 LeaveCriticalSection(&This->cs);
3810 return hr;
3813 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3815 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3816 IBasicVideo *pBasicVideo;
3817 HRESULT hr;
3819 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3821 EnterCriticalSection(&This->cs);
3823 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3825 if (hr == S_OK)
3826 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3828 LeaveCriticalSection(&This->cs);
3830 return hr;
3833 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3834 LONG *pDestinationHeight)
3836 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3837 IBasicVideo *pBasicVideo;
3838 HRESULT hr;
3840 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3842 EnterCriticalSection(&This->cs);
3844 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3846 if (hr == S_OK)
3847 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3849 LeaveCriticalSection(&This->cs);
3851 return hr;
3854 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3855 LONG Width, LONG Height)
3857 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3858 IBasicVideo *pBasicVideo;
3859 HRESULT hr;
3861 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3863 EnterCriticalSection(&This->cs);
3865 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3867 if (hr == S_OK)
3868 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3870 LeaveCriticalSection(&This->cs);
3872 return hr;
3875 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3876 LONG *pWidth, LONG *pHeight)
3878 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3879 IBasicVideo *pBasicVideo;
3880 HRESULT hr;
3882 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3884 EnterCriticalSection(&This->cs);
3886 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3888 if (hr == S_OK)
3889 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3891 LeaveCriticalSection(&This->cs);
3893 return hr;
3896 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3898 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3899 IBasicVideo *pBasicVideo;
3900 HRESULT hr;
3902 TRACE("(%p/%p)->()\n", This, iface);
3904 EnterCriticalSection(&This->cs);
3906 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3908 if (hr == S_OK)
3909 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3911 LeaveCriticalSection(&This->cs);
3913 return hr;
3916 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3917 LONG Width, LONG Height)
3919 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3920 IBasicVideo *pBasicVideo;
3921 HRESULT hr;
3923 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3925 EnterCriticalSection(&This->cs);
3927 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3929 if (hr == S_OK)
3930 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3932 LeaveCriticalSection(&This->cs);
3934 return hr;
3937 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3938 LONG *pTop, LONG *pWidth, LONG *pHeight)
3940 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3941 IBasicVideo *pBasicVideo;
3942 HRESULT hr;
3944 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3946 EnterCriticalSection(&This->cs);
3948 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3950 if (hr == S_OK)
3951 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3953 LeaveCriticalSection(&This->cs);
3955 return hr;
3958 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3960 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3961 IBasicVideo *pBasicVideo;
3962 HRESULT hr;
3964 TRACE("(%p/%p)->()\n", This, iface);
3966 EnterCriticalSection(&This->cs);
3968 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3970 if (hr == S_OK)
3971 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3973 LeaveCriticalSection(&This->cs);
3975 return hr;
3978 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3980 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3981 IBasicVideo *pBasicVideo;
3982 HRESULT hr;
3984 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3986 EnterCriticalSection(&This->cs);
3988 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3990 if (hr == S_OK)
3991 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3993 LeaveCriticalSection(&This->cs);
3995 return hr;
3998 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3999 LONG Entries, LONG *pRetrieved, LONG *pPalette)
4001 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4002 IBasicVideo *pBasicVideo;
4003 HRESULT hr;
4005 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
4007 EnterCriticalSection(&This->cs);
4009 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
4011 if (hr == S_OK)
4012 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
4014 LeaveCriticalSection(&This->cs);
4016 return hr;
4019 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
4020 LONG *pDIBImage)
4022 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4023 IBasicVideo *pBasicVideo;
4024 HRESULT hr;
4026 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
4028 EnterCriticalSection(&This->cs);
4030 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
4032 if (hr == S_OK)
4033 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
4035 LeaveCriticalSection(&This->cs);
4037 return hr;
4040 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
4042 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4043 IBasicVideo *pBasicVideo;
4044 HRESULT hr;
4046 TRACE("(%p/%p)->()\n", This, iface);
4048 EnterCriticalSection(&This->cs);
4050 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
4052 if (hr == S_OK)
4053 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
4055 LeaveCriticalSection(&This->cs);
4057 return hr;
4060 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
4062 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4063 IBasicVideo *pBasicVideo;
4064 HRESULT hr;
4066 TRACE("(%p/%p)->()\n", This, iface);
4068 EnterCriticalSection(&This->cs);
4070 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
4072 if (hr == S_OK)
4073 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
4075 LeaveCriticalSection(&This->cs);
4077 return hr;
4080 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
4081 LONG *plAspectY)
4083 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
4084 IBasicVideo2 *pBasicVideo2;
4085 HRESULT hr;
4087 TRACE("(%p/%p)->()\n", This, iface);
4089 EnterCriticalSection(&This->cs);
4091 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
4093 if (hr == S_OK)
4094 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
4096 LeaveCriticalSection(&This->cs);
4098 return hr;
4101 static const IBasicVideo2Vtbl IBasicVideo_VTable =
4103 BasicVideo_QueryInterface,
4104 BasicVideo_AddRef,
4105 BasicVideo_Release,
4106 BasicVideo_GetTypeInfoCount,
4107 BasicVideo_GetTypeInfo,
4108 BasicVideo_GetIDsOfNames,
4109 BasicVideo_Invoke,
4110 BasicVideo_get_AvgTimePerFrame,
4111 BasicVideo_get_BitRate,
4112 BasicVideo_get_BitErrorRate,
4113 BasicVideo_get_VideoWidth,
4114 BasicVideo_get_VideoHeight,
4115 BasicVideo_put_SourceLeft,
4116 BasicVideo_get_SourceLeft,
4117 BasicVideo_put_SourceWidth,
4118 BasicVideo_get_SourceWidth,
4119 BasicVideo_put_SourceTop,
4120 BasicVideo_get_SourceTop,
4121 BasicVideo_put_SourceHeight,
4122 BasicVideo_get_SourceHeight,
4123 BasicVideo_put_DestinationLeft,
4124 BasicVideo_get_DestinationLeft,
4125 BasicVideo_put_DestinationWidth,
4126 BasicVideo_get_DestinationWidth,
4127 BasicVideo_put_DestinationTop,
4128 BasicVideo_get_DestinationTop,
4129 BasicVideo_put_DestinationHeight,
4130 BasicVideo_get_DestinationHeight,
4131 BasicVideo_SetSourcePosition,
4132 BasicVideo_GetSourcePosition,
4133 BasicVideo_SetDefaultSourcePosition,
4134 BasicVideo_SetDestinationPosition,
4135 BasicVideo_GetDestinationPosition,
4136 BasicVideo_SetDefaultDestinationPosition,
4137 BasicVideo_GetVideoSize,
4138 BasicVideo_GetVideoPaletteEntries,
4139 BasicVideo_GetCurrentImage,
4140 BasicVideo_IsUsingDefaultSource,
4141 BasicVideo_IsUsingDefaultDestination,
4142 BasicVideo2_GetPreferredAspectRatio
4145 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
4147 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
4150 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
4152 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4154 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
4156 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4159 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
4161 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4163 TRACE("(%p/%p)->()\n", This, iface);
4165 return IUnknown_AddRef(This->outer_unk);
4168 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
4170 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4172 TRACE("(%p/%p)->()\n", This, iface);
4174 return IUnknown_Release(This->outer_unk);
4177 /*** IDispatch methods ***/
4178 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
4180 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4181 IVideoWindow *pVideoWindow;
4182 HRESULT hr;
4184 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4186 EnterCriticalSection(&This->cs);
4188 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4190 if (hr == S_OK)
4191 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4193 LeaveCriticalSection(&This->cs);
4195 return hr;
4198 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4199 ITypeInfo **ppTInfo)
4201 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4202 IVideoWindow *pVideoWindow;
4203 HRESULT hr;
4205 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4207 EnterCriticalSection(&This->cs);
4209 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4211 if (hr == S_OK)
4212 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4214 LeaveCriticalSection(&This->cs);
4216 return hr;
4219 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4220 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4222 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4223 IVideoWindow *pVideoWindow;
4224 HRESULT hr;
4226 TRACE("(%p/%p)->(%s, %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), rgszNames, cNames,
4227 lcid, rgDispId);
4229 EnterCriticalSection(&This->cs);
4231 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4233 if (hr == S_OK)
4234 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4236 LeaveCriticalSection(&This->cs);
4238 return hr;
4241 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4242 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4243 UINT*puArgErr)
4245 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4246 IVideoWindow *pVideoWindow;
4247 HRESULT hr;
4249 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember,
4250 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4252 EnterCriticalSection(&This->cs);
4254 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4256 if (hr == S_OK)
4257 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4259 LeaveCriticalSection(&This->cs);
4261 return hr;
4265 /*** IVideoWindow methods ***/
4266 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4268 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4269 IVideoWindow *pVideoWindow;
4270 HRESULT hr;
4272 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4274 EnterCriticalSection(&This->cs);
4276 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4278 if (hr == S_OK)
4279 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4281 LeaveCriticalSection(&This->cs);
4283 return hr;
4286 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4288 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4289 IVideoWindow *pVideoWindow;
4290 HRESULT hr;
4292 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4294 EnterCriticalSection(&This->cs);
4296 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4298 if (hr == S_OK)
4299 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4301 LeaveCriticalSection(&This->cs);
4303 return hr;
4306 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4308 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4309 IVideoWindow *pVideoWindow;
4310 HRESULT hr;
4312 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4314 EnterCriticalSection(&This->cs);
4316 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4318 if (hr == S_OK)
4319 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4321 LeaveCriticalSection(&This->cs);
4323 return hr;
4326 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4328 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4329 IVideoWindow *pVideoWindow;
4330 HRESULT hr;
4332 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4334 EnterCriticalSection(&This->cs);
4336 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4338 if (hr == S_OK)
4339 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4341 LeaveCriticalSection(&This->cs);
4343 return hr;
4346 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4348 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4349 IVideoWindow *pVideoWindow;
4350 HRESULT hr;
4352 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4354 EnterCriticalSection(&This->cs);
4356 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4358 if (hr == S_OK)
4359 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4361 LeaveCriticalSection(&This->cs);
4363 return hr;
4366 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4368 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4369 IVideoWindow *pVideoWindow;
4370 HRESULT hr;
4372 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4374 EnterCriticalSection(&This->cs);
4376 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4378 if (hr == S_OK)
4379 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4381 LeaveCriticalSection(&This->cs);
4383 return hr;
4386 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4388 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4389 IVideoWindow *pVideoWindow;
4390 HRESULT hr;
4392 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4394 EnterCriticalSection(&This->cs);
4396 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4398 if (hr == S_OK)
4399 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4401 LeaveCriticalSection(&This->cs);
4403 return hr;
4406 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4408 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4409 IVideoWindow *pVideoWindow;
4410 HRESULT hr;
4412 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4414 EnterCriticalSection(&This->cs);
4416 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4418 if (hr == S_OK)
4419 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4421 LeaveCriticalSection(&This->cs);
4423 return hr;
4426 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4428 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4429 IVideoWindow *pVideoWindow;
4430 HRESULT hr;
4432 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4434 EnterCriticalSection(&This->cs);
4436 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4438 if (hr == S_OK)
4439 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4441 LeaveCriticalSection(&This->cs);
4443 return hr;
4446 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4448 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4449 IVideoWindow *pVideoWindow;
4450 HRESULT hr;
4452 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4454 EnterCriticalSection(&This->cs);
4456 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4458 if (hr == S_OK)
4459 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4461 LeaveCriticalSection(&This->cs);
4463 return hr;
4466 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4468 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4469 IVideoWindow *pVideoWindow;
4470 HRESULT hr;
4472 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4474 EnterCriticalSection(&This->cs);
4476 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4478 if (hr == S_OK)
4479 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4481 LeaveCriticalSection(&This->cs);
4483 return hr;
4486 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4487 LONG *pBackgroundPalette)
4489 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4490 IVideoWindow *pVideoWindow;
4491 HRESULT hr;
4493 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4495 EnterCriticalSection(&This->cs);
4497 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4499 if (hr == S_OK)
4500 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4502 LeaveCriticalSection(&This->cs);
4504 return hr;
4507 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4509 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4510 IVideoWindow *pVideoWindow;
4511 HRESULT hr;
4513 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4515 EnterCriticalSection(&This->cs);
4517 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4519 if (hr == S_OK)
4520 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4522 LeaveCriticalSection(&This->cs);
4524 return hr;
4527 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4529 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4530 IVideoWindow *pVideoWindow;
4531 HRESULT hr;
4533 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4535 EnterCriticalSection(&This->cs);
4537 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4539 if (hr == S_OK)
4540 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4542 LeaveCriticalSection(&This->cs);
4544 return hr;
4547 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4549 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4550 IVideoWindow *pVideoWindow;
4551 HRESULT hr;
4553 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4555 EnterCriticalSection(&This->cs);
4557 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4559 if (hr == S_OK)
4560 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4562 LeaveCriticalSection(&This->cs);
4564 return hr;
4567 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4569 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4570 IVideoWindow *pVideoWindow;
4571 HRESULT hr;
4573 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4575 EnterCriticalSection(&This->cs);
4577 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4579 if (hr == S_OK)
4580 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4582 LeaveCriticalSection(&This->cs);
4584 return hr;
4587 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4589 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4590 IVideoWindow *pVideoWindow;
4591 HRESULT hr;
4593 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4595 EnterCriticalSection(&This->cs);
4597 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4599 if (hr == S_OK)
4600 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4602 LeaveCriticalSection(&This->cs);
4604 return hr;
4607 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4609 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4610 IVideoWindow *pVideoWindow;
4611 HRESULT hr;
4613 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4615 EnterCriticalSection(&This->cs);
4617 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4619 if (hr == S_OK)
4620 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4622 LeaveCriticalSection(&This->cs);
4624 return hr;
4627 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4629 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4630 IVideoWindow *pVideoWindow;
4631 HRESULT hr;
4633 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4635 EnterCriticalSection(&This->cs);
4637 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4639 if (hr == S_OK)
4640 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4642 LeaveCriticalSection(&This->cs);
4644 return hr;
4647 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4649 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4650 IVideoWindow *pVideoWindow;
4651 HRESULT hr;
4653 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4655 EnterCriticalSection(&This->cs);
4657 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4659 if (hr == S_OK)
4660 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4662 LeaveCriticalSection(&This->cs);
4664 return hr;
4667 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4669 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4670 IVideoWindow *pVideoWindow;
4671 HRESULT hr;
4673 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4675 EnterCriticalSection(&This->cs);
4677 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4679 if (hr == S_OK)
4680 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4682 LeaveCriticalSection(&This->cs);
4684 return hr;
4687 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4689 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4690 IVideoWindow *pVideoWindow;
4691 HRESULT hr;
4693 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4695 EnterCriticalSection(&This->cs);
4697 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4699 if (hr == S_OK)
4700 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4702 LeaveCriticalSection(&This->cs);
4704 return hr;
4707 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4709 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4710 IVideoWindow *pVideoWindow;
4711 HRESULT hr;
4713 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4715 EnterCriticalSection(&This->cs);
4717 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4719 if (hr == S_OK)
4720 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4722 LeaveCriticalSection(&This->cs);
4724 return hr;
4727 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4729 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4730 IVideoWindow *pVideoWindow;
4731 HRESULT hr;
4733 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4735 EnterCriticalSection(&This->cs);
4737 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4739 if (hr == S_OK)
4740 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4742 LeaveCriticalSection(&This->cs);
4744 return hr;
4747 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4749 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4750 IVideoWindow *pVideoWindow;
4751 HRESULT hr;
4753 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4755 EnterCriticalSection(&This->cs);
4757 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4759 if (hr == S_OK)
4760 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4762 LeaveCriticalSection(&This->cs);
4764 return hr;
4767 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4769 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4770 IVideoWindow *pVideoWindow;
4771 HRESULT hr;
4773 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4775 EnterCriticalSection(&This->cs);
4777 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4779 if (hr == S_OK)
4780 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4782 LeaveCriticalSection(&This->cs);
4784 return hr;
4787 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4789 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4790 IVideoWindow *pVideoWindow;
4791 HRESULT hr;
4793 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4795 EnterCriticalSection(&This->cs);
4797 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4799 if (hr == S_OK)
4800 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4802 LeaveCriticalSection(&This->cs);
4804 return hr;
4807 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4809 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4810 IVideoWindow *pVideoWindow;
4811 HRESULT hr;
4813 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4815 EnterCriticalSection(&This->cs);
4817 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4819 if (hr == S_OK)
4820 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4822 LeaveCriticalSection(&This->cs);
4824 return hr;
4827 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4829 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4830 IVideoWindow *pVideoWindow;
4831 HRESULT hr;
4833 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4835 EnterCriticalSection(&This->cs);
4837 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4839 if (hr == S_OK)
4840 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4842 LeaveCriticalSection(&This->cs);
4844 return hr;
4847 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4849 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4850 IVideoWindow *pVideoWindow;
4851 HRESULT hr;
4853 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4855 EnterCriticalSection(&This->cs);
4857 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4859 if (hr == S_OK)
4860 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4862 LeaveCriticalSection(&This->cs);
4864 return hr;
4867 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4869 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4870 IVideoWindow *pVideoWindow;
4871 HRESULT hr;
4873 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4875 EnterCriticalSection(&This->cs);
4877 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4879 if (hr == S_OK)
4880 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4882 LeaveCriticalSection(&This->cs);
4884 return hr;
4887 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4888 LONG_PTR wParam, LONG_PTR lParam)
4890 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4891 IVideoWindow *pVideoWindow;
4892 HRESULT hr;
4894 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4896 EnterCriticalSection(&This->cs);
4898 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4900 if (hr == S_OK)
4901 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4903 LeaveCriticalSection(&This->cs);
4905 return hr;
4908 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4909 LONG Width, LONG Height)
4911 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4912 IVideoWindow *pVideoWindow;
4913 HRESULT hr;
4915 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4917 EnterCriticalSection(&This->cs);
4919 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4921 if (hr == S_OK)
4922 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4924 LeaveCriticalSection(&This->cs);
4926 return hr;
4929 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4930 LONG *pWidth, LONG *pHeight)
4932 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4933 IVideoWindow *pVideoWindow;
4934 HRESULT hr;
4936 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4938 EnterCriticalSection(&This->cs);
4940 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4942 if (hr == S_OK)
4943 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4945 LeaveCriticalSection(&This->cs);
4947 return hr;
4950 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4951 LONG *pHeight)
4953 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4954 IVideoWindow *pVideoWindow;
4955 HRESULT hr;
4957 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4959 EnterCriticalSection(&This->cs);
4961 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4963 if (hr == S_OK)
4964 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4966 LeaveCriticalSection(&This->cs);
4968 return hr;
4971 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4972 LONG *pHeight)
4974 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4975 IVideoWindow *pVideoWindow;
4976 HRESULT hr;
4978 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4980 EnterCriticalSection(&This->cs);
4982 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4984 if (hr == S_OK)
4985 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4987 LeaveCriticalSection(&This->cs);
4989 return hr;
4992 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4993 LONG *pWidth, LONG *pHeight)
4995 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4996 IVideoWindow *pVideoWindow;
4997 HRESULT hr;
4999 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
5001 EnterCriticalSection(&This->cs);
5003 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
5005 if (hr == S_OK)
5006 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
5008 LeaveCriticalSection(&This->cs);
5010 return hr;
5013 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
5015 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
5016 IVideoWindow *pVideoWindow;
5017 HRESULT hr;
5019 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
5021 EnterCriticalSection(&This->cs);
5023 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
5025 if (hr == S_OK)
5026 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
5028 LeaveCriticalSection(&This->cs);
5030 return hr;
5033 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
5035 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
5036 IVideoWindow *pVideoWindow;
5037 HRESULT hr;
5039 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
5041 EnterCriticalSection(&This->cs);
5043 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
5045 if (hr == S_OK)
5046 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
5048 LeaveCriticalSection(&This->cs);
5050 return hr;
5054 static const IVideoWindowVtbl IVideoWindow_VTable =
5056 VideoWindow_QueryInterface,
5057 VideoWindow_AddRef,
5058 VideoWindow_Release,
5059 VideoWindow_GetTypeInfoCount,
5060 VideoWindow_GetTypeInfo,
5061 VideoWindow_GetIDsOfNames,
5062 VideoWindow_Invoke,
5063 VideoWindow_put_Caption,
5064 VideoWindow_get_Caption,
5065 VideoWindow_put_WindowStyle,
5066 VideoWindow_get_WindowStyle,
5067 VideoWindow_put_WindowStyleEx,
5068 VideoWindow_get_WindowStyleEx,
5069 VideoWindow_put_AutoShow,
5070 VideoWindow_get_AutoShow,
5071 VideoWindow_put_WindowState,
5072 VideoWindow_get_WindowState,
5073 VideoWindow_put_BackgroundPalette,
5074 VideoWindow_get_BackgroundPalette,
5075 VideoWindow_put_Visible,
5076 VideoWindow_get_Visible,
5077 VideoWindow_put_Left,
5078 VideoWindow_get_Left,
5079 VideoWindow_put_Width,
5080 VideoWindow_get_Width,
5081 VideoWindow_put_Top,
5082 VideoWindow_get_Top,
5083 VideoWindow_put_Height,
5084 VideoWindow_get_Height,
5085 VideoWindow_put_Owner,
5086 VideoWindow_get_Owner,
5087 VideoWindow_put_MessageDrain,
5088 VideoWindow_get_MessageDrain,
5089 VideoWindow_get_BorderColor,
5090 VideoWindow_put_BorderColor,
5091 VideoWindow_get_FullScreenMode,
5092 VideoWindow_put_FullScreenMode,
5093 VideoWindow_SetWindowForeground,
5094 VideoWindow_NotifyOwnerMessage,
5095 VideoWindow_SetWindowPosition,
5096 VideoWindow_GetWindowPosition,
5097 VideoWindow_GetMinIdealImageSize,
5098 VideoWindow_GetMaxIdealImageSize,
5099 VideoWindow_GetRestorePosition,
5100 VideoWindow_HideCursor,
5101 VideoWindow_IsCursorHidden
5104 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
5106 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
5109 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
5111 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5113 TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj);
5115 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
5118 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
5120 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5122 TRACE("(%p/%p)->()\n", This, iface);
5124 return IUnknown_AddRef(This->outer_unk);
5127 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
5129 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5131 TRACE("(%p/%p)->()\n", This, iface);
5133 return IUnknown_Release(This->outer_unk);
5136 /*** IDispatch methods ***/
5137 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
5139 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5141 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
5143 return S_OK;
5146 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
5147 ITypeInfo **ppTInfo)
5149 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5151 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
5153 return S_OK;
5156 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
5157 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
5159 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5161 TRACE("(%p/%p)->(%s, %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), rgszNames,
5162 cNames, lcid, rgDispId);
5164 return S_OK;
5167 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
5168 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
5169 UINT *puArgErr)
5171 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5173 TRACE("(%p/%p)->(%d, %s, %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember,
5174 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
5176 return S_OK;
5179 /*** IMediaEvent methods ***/
5180 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
5182 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5184 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5186 *hEvent = (OAEVENT)This->evqueue.msg_event;
5188 return S_OK;
5191 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5192 LONG_PTR *lParam2, LONG msTimeout)
5194 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5195 Event evt;
5197 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5199 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5201 *lEventCode = evt.lEventCode;
5202 *lParam1 = evt.lParam1;
5203 *lParam2 = evt.lParam2;
5204 return S_OK;
5207 *lEventCode = 0;
5208 return E_ABORT;
5211 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5212 LONG *pEvCode)
5214 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5216 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5218 if (This->state != State_Running)
5219 return VFW_E_WRONG_STATE;
5221 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5223 *pEvCode = This->CompletionStatus;
5224 return S_OK;
5227 *pEvCode = 0;
5228 return E_ABORT;
5231 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5233 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5235 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5237 if (lEvCode == EC_COMPLETE)
5238 This->HandleEcComplete = FALSE;
5239 else if (lEvCode == EC_REPAINT)
5240 This->HandleEcRepaint = FALSE;
5241 else if (lEvCode == EC_CLOCK_CHANGED)
5242 This->HandleEcClockChanged = FALSE;
5243 else
5244 return S_FALSE;
5246 return S_OK;
5249 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5251 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5253 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5255 if (lEvCode == EC_COMPLETE)
5256 This->HandleEcComplete = TRUE;
5257 else if (lEvCode == EC_REPAINT)
5258 This->HandleEcRepaint = TRUE;
5259 else if (lEvCode == EC_CLOCK_CHANGED)
5260 This->HandleEcClockChanged = TRUE;
5261 else
5262 return S_FALSE;
5264 return S_OK;
5267 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5268 LONG_PTR lParam1, LONG_PTR lParam2)
5270 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5272 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5274 return S_OK;
5277 /*** IMediaEventEx methods ***/
5278 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5279 LONG_PTR lInstanceData)
5281 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5283 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5285 This->notif.hWnd = (HWND)hwnd;
5286 This->notif.msg = lMsg;
5287 This->notif.instance = lInstanceData;
5289 return S_OK;
5292 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5294 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5296 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5298 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5299 return E_INVALIDARG;
5301 This->notif.disabled = lNoNotifyFlags;
5303 return S_OK;
5306 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5308 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5310 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5312 if (!lplNoNotifyFlags)
5313 return E_POINTER;
5315 *lplNoNotifyFlags = This->notif.disabled;
5317 return S_OK;
5321 static const IMediaEventExVtbl IMediaEventEx_VTable =
5323 MediaEvent_QueryInterface,
5324 MediaEvent_AddRef,
5325 MediaEvent_Release,
5326 MediaEvent_GetTypeInfoCount,
5327 MediaEvent_GetTypeInfo,
5328 MediaEvent_GetIDsOfNames,
5329 MediaEvent_Invoke,
5330 MediaEvent_GetEventHandle,
5331 MediaEvent_GetEvent,
5332 MediaEvent_WaitForCompletion,
5333 MediaEvent_CancelDefaultHandling,
5334 MediaEvent_RestoreDefaultHandling,
5335 MediaEvent_FreeEventParams,
5336 MediaEvent_SetNotifyWindow,
5337 MediaEvent_SetNotifyFlags,
5338 MediaEvent_GetNotifyFlags
5342 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5344 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5347 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5349 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5351 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5354 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5356 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5358 return IUnknown_AddRef(This->outer_unk);
5361 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5363 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5365 return IUnknown_Release(This->outer_unk);
5368 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5370 FIXME("(%p): stub\n", pClassID);
5372 return E_NOTIMPL;
5375 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5377 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5379 TRACE("graph %p.\n", graph);
5381 EnterCriticalSection(&graph->cs);
5383 if (graph->state == State_Stopped)
5385 LeaveCriticalSection(&graph->cs);
5386 return S_OK;
5389 if (graph->state == State_Running)
5390 SendFilterMessage(graph, SendPause, 0);
5391 SendFilterMessage(graph, SendStop, 0);
5392 graph->state = State_Stopped;
5394 LeaveCriticalSection(&graph->cs);
5395 return S_OK;
5398 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5400 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5402 TRACE("graph %p.\n", graph);
5404 EnterCriticalSection(&graph->cs);
5406 if (graph->state == State_Paused)
5408 LeaveCriticalSection(&graph->cs);
5409 return S_OK;
5412 if (graph->defaultclock && !graph->refClock)
5413 IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
5415 if (graph->state == State_Running && graph->refClock && graph->start_time >= 0)
5416 IReferenceClock_GetTime(graph->refClock, &graph->pause_time);
5417 else
5418 graph->pause_time = -1;
5420 SendFilterMessage(graph, SendPause, 0);
5421 graph->state = State_Paused;
5423 LeaveCriticalSection(&graph->cs);
5424 return S_FALSE;
5427 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME start)
5429 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5431 TRACE("graph %p, start %s.\n", graph, wine_dbgstr_longlong(start));
5433 EnterCriticalSection(&graph->cs);
5435 if (graph->state == State_Running)
5437 LeaveCriticalSection(&graph->cs);
5438 return S_OK;
5440 graph->EcCompleteCount = 0;
5442 if (graph->defaultclock && !graph->refClock)
5443 IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
5445 if (!start && graph->refClock)
5447 REFERENCE_TIME now;
5448 IReferenceClock_GetTime(graph->refClock, &now);
5449 if (graph->state == State_Stopped)
5450 graph->start_time = now + 500000;
5451 else if (graph->pause_time >= 0)
5452 graph->start_time += now - graph->pause_time;
5453 else
5454 graph->start_time = now;
5456 else
5457 graph->start_time = start;
5459 SendFilterMessage(graph, SendRun, (DWORD_PTR)&graph->start_time);
5460 graph->state = State_Running;
5462 LeaveCriticalSection(&graph->cs);
5463 return S_FALSE;
5466 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD timeout, FILTER_STATE *state)
5468 IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
5469 DWORD end;
5471 TRACE("graph %p, timeout %u, state %p.\n", graph, timeout, state);
5473 if (!state)
5474 return E_POINTER;
5476 EnterCriticalSection(&graph->cs);
5478 *state = graph->state;
5479 if (timeout > 0)
5480 end = GetTickCount() + timeout;
5481 else if (timeout == INFINITE)
5482 end = INFINITE;
5483 else
5484 end = 0;
5485 if (end)
5486 SendFilterMessage(graph, SendGetState, end);
5488 LeaveCriticalSection(&graph->cs);
5489 return S_OK;
5492 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5494 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5495 struct filter *filter;
5496 HRESULT hr = S_OK;
5498 TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
5500 EnterCriticalSection(&This->cs);
5502 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
5504 hr = IBaseFilter_SetSyncSource(filter->filter, pClock);
5505 if (FAILED(hr))
5506 break;
5509 if (FAILED(hr))
5511 LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
5512 IBaseFilter_SetSyncSource(filter->filter, This->refClock);
5514 else
5516 if (This->refClock)
5517 IReferenceClock_Release(This->refClock);
5518 This->refClock = pClock;
5519 if (This->refClock)
5520 IReferenceClock_AddRef(This->refClock);
5521 This->defaultclock = FALSE;
5523 if (This->HandleEcClockChanged)
5525 IMediaEventSink *pEventSink;
5526 HRESULT eshr;
5528 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (void **)&pEventSink);
5529 if (SUCCEEDED(eshr))
5531 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5532 IMediaEventSink_Release(pEventSink);
5537 LeaveCriticalSection(&This->cs);
5539 return hr;
5542 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5544 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5546 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
5548 if (!ppClock)
5549 return E_POINTER;
5551 EnterCriticalSection(&This->cs);
5553 *ppClock = This->refClock;
5554 if (*ppClock)
5555 IReferenceClock_AddRef(*ppClock);
5557 LeaveCriticalSection(&This->cs);
5559 return S_OK;
5562 static const IMediaFilterVtbl IMediaFilter_VTable =
5564 MediaFilter_QueryInterface,
5565 MediaFilter_AddRef,
5566 MediaFilter_Release,
5567 MediaFilter_GetClassID,
5568 MediaFilter_Stop,
5569 MediaFilter_Pause,
5570 MediaFilter_Run,
5571 MediaFilter_GetState,
5572 MediaFilter_SetSyncSource,
5573 MediaFilter_GetSyncSource
5576 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5578 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5581 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5583 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5585 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5588 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5590 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5592 return IUnknown_AddRef(This->outer_unk);
5595 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5597 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5599 return IUnknown_Release(This->outer_unk);
5602 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5603 LONG_PTR EventParam1, LONG_PTR EventParam2)
5605 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5606 Event evt;
5608 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5610 /* We need thread safety here, let's use the events queue's one */
5611 EnterCriticalSection(&This->evqueue.msg_crst);
5613 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5615 TRACE("Process EC_COMPLETE notification\n");
5616 if (++This->EcCompleteCount == This->nRenderers)
5618 evt.lEventCode = EC_COMPLETE;
5619 evt.lParam1 = S_OK;
5620 evt.lParam2 = 0;
5621 TRACE("Send EC_COMPLETE to app\n");
5622 EventsQueue_PutEvent(&This->evqueue, &evt);
5623 if (!This->notif.disabled && This->notif.hWnd)
5625 TRACE("Send Window message\n");
5626 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5628 This->CompletionStatus = EC_COMPLETE;
5629 SetEvent(This->hEventCompletion);
5632 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5634 /* FIXME: Not handled yet */
5636 else
5638 evt.lEventCode = EventCode;
5639 evt.lParam1 = EventParam1;
5640 evt.lParam2 = EventParam2;
5641 EventsQueue_PutEvent(&This->evqueue, &evt);
5642 if (!This->notif.disabled && This->notif.hWnd)
5643 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5646 LeaveCriticalSection(&This->evqueue.msg_crst);
5647 return S_OK;
5650 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5652 MediaEventSink_QueryInterface,
5653 MediaEventSink_AddRef,
5654 MediaEventSink_Release,
5655 MediaEventSink_Notify
5658 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5660 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5663 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5665 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5667 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5670 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5672 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5674 return IUnknown_AddRef(This->outer_unk);
5677 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5679 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5681 return IUnknown_Release(This->outer_unk);
5684 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5685 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5686 DWORD dwFlags)
5688 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5690 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5692 return E_NOTIMPL;
5695 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5696 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5698 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5699 HRESULT hr;
5701 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5703 if (hAbortEvent)
5704 FIXME("The parameter hAbortEvent is not handled!\n");
5706 EnterCriticalSection(&This->cs);
5708 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5710 LeaveCriticalSection(&This->cs);
5712 return hr;
5715 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5717 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5719 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5721 return E_NOTIMPL;
5724 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5726 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5728 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5730 return E_NOTIMPL;
5733 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5735 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5737 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5739 return E_NOTIMPL;
5742 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5744 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5746 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5748 return E_NOTIMPL;
5751 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5752 IPinConnection *pConnection, HANDLE hEventAbort)
5754 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5756 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5758 return E_NOTIMPL;
5761 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5762 DWORD dwFlags)
5764 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5766 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5768 return E_NOTIMPL;
5771 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5772 DWORD *dwFlags)
5774 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5776 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5778 return E_NOTIMPL;
5781 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5782 DWORD dwFlags)
5784 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5786 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5788 return E_NOTIMPL;
5791 static const IGraphConfigVtbl IGraphConfig_VTable =
5793 GraphConfig_QueryInterface,
5794 GraphConfig_AddRef,
5795 GraphConfig_Release,
5796 GraphConfig_Reconnect,
5797 GraphConfig_Reconfigure,
5798 GraphConfig_AddFilterToCache,
5799 GraphConfig_EnumCacheFilter,
5800 GraphConfig_RemoveFilterFromCache,
5801 GraphConfig_GetStartTime,
5802 GraphConfig_PushThroughData,
5803 GraphConfig_SetFilterFlags,
5804 GraphConfig_GetFilterFlags,
5805 GraphConfig_RemoveFilterEx
5808 static inline IFilterGraphImpl *impl_from_IGraphVersion(IGraphVersion *iface)
5810 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphVersion_iface);
5813 static HRESULT WINAPI GraphVersion_QueryInterface(IGraphVersion *iface, REFIID riid, void **ppv)
5815 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5817 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5820 static ULONG WINAPI GraphVersion_AddRef(IGraphVersion *iface)
5822 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5824 return IUnknown_AddRef(This->outer_unk);
5827 static ULONG WINAPI GraphVersion_Release(IGraphVersion *iface)
5829 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5831 return IUnknown_Release(This->outer_unk);
5834 static HRESULT WINAPI GraphVersion_QueryVersion(IGraphVersion *iface, LONG *pVersion)
5836 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5838 if(!pVersion)
5839 return E_POINTER;
5841 TRACE("(%p)->(%p): current version %i\n", This, pVersion, This->version);
5843 *pVersion = This->version;
5844 return S_OK;
5847 static const IGraphVersionVtbl IGraphVersion_VTable =
5849 GraphVersion_QueryInterface,
5850 GraphVersion_AddRef,
5851 GraphVersion_Release,
5852 GraphVersion_QueryVersion,
5855 static const IUnknownVtbl IInner_VTable =
5857 FilterGraphInner_QueryInterface,
5858 FilterGraphInner_AddRef,
5859 FilterGraphInner_Release
5862 /* This is the only function that actually creates a FilterGraph class... */
5863 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5865 IFilterGraphImpl *fimpl;
5866 HRESULT hr;
5868 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5870 *ppObj = NULL;
5872 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5873 fimpl->defaultclock = TRUE;
5874 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5875 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5876 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5877 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5878 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5879 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5880 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5881 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5882 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5883 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5884 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5885 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5886 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5887 fimpl->IGraphVersion_iface.lpVtbl = &IGraphVersion_VTable;
5888 fimpl->ref = 1;
5889 list_init(&fimpl->filters);
5890 fimpl->nameIndex = 1;
5891 fimpl->refClock = NULL;
5892 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5893 fimpl->HandleEcComplete = TRUE;
5894 fimpl->HandleEcRepaint = TRUE;
5895 fimpl->HandleEcClockChanged = TRUE;
5896 fimpl->notif.hWnd = 0;
5897 fimpl->notif.disabled = FALSE;
5898 fimpl->nRenderers = 0;
5899 fimpl->EcCompleteCount = 0;
5900 fimpl->refClockProvider = NULL;
5901 fimpl->state = State_Stopped;
5902 fimpl->pSite = NULL;
5903 EventsQueue_Init(&fimpl->evqueue);
5904 InitializeCriticalSection(&fimpl->cs);
5905 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5906 fimpl->nItfCacheEntries = 0;
5907 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5908 fimpl->start_time = fimpl->pause_time = 0;
5909 fimpl->stop_position = -1;
5910 fimpl->punkFilterMapper2 = NULL;
5911 fimpl->recursioncount = 0;
5912 fimpl->version = 0;
5914 if (pUnkOuter)
5915 fimpl->outer_unk = pUnkOuter;
5916 else
5917 fimpl->outer_unk = &fimpl->IUnknown_inner;
5919 /* create Filtermapper aggregated. */
5920 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5921 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5923 if (FAILED(hr)) {
5924 ERR("Unable to create filter mapper (%x)\n", hr);
5925 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5926 CloseHandle(fimpl->hEventCompletion);
5927 EventsQueue_Destroy(&fimpl->evqueue);
5928 fimpl->cs.DebugInfo->Spare[0] = 0;
5929 DeleteCriticalSection(&fimpl->cs);
5930 CoTaskMemFree(fimpl);
5931 return hr;
5934 *ppObj = &fimpl->IUnknown_inner;
5935 return S_OK;
5938 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5940 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5941 return FilterGraph_create(pUnkOuter, ppObj);