[AMSTREAM][QUARTZ][STRMBASE]
[reactos.git] / reactos / dll / directx / wine / quartz / filtergraph.c
1 /* DirectShow FilterGraph object (QUARTZ.DLL)
2 *
3 * Copyright 2002 Lionel Ulmer
4 * Copyright 2004 Christian Costa
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "quartz_private.h"
22
23 typedef struct {
24 HWND hWnd; /* Target window */
25 UINT msg; /* User window message */
26 LONG_PTR instance; /* User data */
27 int disabled; /* Disabled messages posting */
28 } WndNotify;
29
30 typedef struct {
31 LONG lEventCode; /* Event code */
32 LONG_PTR lParam1; /* Param1 */
33 LONG_PTR lParam2; /* Param2 */
34 } Event;
35
36 /* messages ring implementation for queuing events (taken from winmm) */
37 #define EVENTS_RING_BUFFER_INCREMENT 64
38 typedef struct {
39 Event* messages;
40 int ring_buffer_size;
41 int msg_tosave;
42 int msg_toget;
43 CRITICAL_SECTION msg_crst;
44 HANDLE msg_event; /* Signaled for no empty queue */
45 } EventsQueue;
46
47 static int EventsQueue_Init(EventsQueue* omr)
48 {
49 omr->msg_toget = 0;
50 omr->msg_tosave = 0;
51 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
52 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
53 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
54 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
55
56 InitializeCriticalSection(&omr->msg_crst);
57 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
58 return TRUE;
59 }
60
61 static int EventsQueue_Destroy(EventsQueue* omr)
62 {
63 CloseHandle(omr->msg_event);
64 CoTaskMemFree(omr->messages);
65 omr->msg_crst.DebugInfo->Spare[0] = 0;
66 DeleteCriticalSection(&omr->msg_crst);
67 return TRUE;
68 }
69
70 static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
71 {
72 EnterCriticalSection(&omr->msg_crst);
73 if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))
74 {
75 int old_ring_buffer_size = omr->ring_buffer_size;
76 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
77 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
78 omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event));
79 /* Now we need to rearrange the ring buffer so that the new
80 buffers just allocated are in between omr->msg_tosave and
81 omr->msg_toget.
82 */
83 if (omr->msg_tosave < omr->msg_toget)
84 {
85 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
86 &(omr->messages[omr->msg_toget]),
87 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
88 );
89 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
90 }
91 }
92 omr->messages[omr->msg_tosave] = *evt;
93 SetEvent(omr->msg_event);
94 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
95 LeaveCriticalSection(&omr->msg_crst);
96 return TRUE;
97 }
98
99 static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut)
100 {
101 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
102 return FALSE;
103
104 EnterCriticalSection(&omr->msg_crst);
105
106 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
107 {
108 LeaveCriticalSection(&omr->msg_crst);
109 return FALSE;
110 }
111
112 *evt = omr->messages[omr->msg_toget];
113 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
114
115 /* Mark the buffer as empty if needed */
116 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
117 ResetEvent(omr->msg_event);
118
119 LeaveCriticalSection(&omr->msg_crst);
120 return TRUE;
121 }
122
123 #define MAX_ITF_CACHE_ENTRIES 3
124 typedef struct _ITF_CACHE_ENTRY {
125 const IID* riid;
126 IBaseFilter* filter;
127 IUnknown* iface;
128 } ITF_CACHE_ENTRY;
129
130 typedef struct _IFilterGraphImpl {
131 IUnknown IUnknown_inner;
132 IFilterGraph2 IFilterGraph2_iface;
133 IMediaControl IMediaControl_iface;
134 IMediaSeeking IMediaSeeking_iface;
135 IBasicAudio IBasicAudio_iface;
136 IBasicVideo2 IBasicVideo2_iface;
137 IVideoWindow IVideoWindow_iface;
138 IMediaEventEx IMediaEventEx_iface;
139 IMediaFilter IMediaFilter_iface;
140 IMediaEventSink IMediaEventSink_iface;
141 IGraphConfig IGraphConfig_iface;
142 IMediaPosition IMediaPosition_iface;
143 IObjectWithSite IObjectWithSite_iface;
144 IGraphVersion IGraphVersion_iface;
145 /* IAMGraphStreams */
146 /* IAMStats */
147 /* IFilterChain */
148 /* IFilterMapper2 */
149 /* IQueueCommand */
150 /* IRegisterServiceProvider */
151 /* IResourceMananger */
152 /* IServiceProvider */
153 /* IVideoFrameStep */
154
155 IUnknown *outer_unk;
156 LONG ref;
157 IUnknown *punkFilterMapper2;
158 IFilterMapper2 * pFilterMapper2;
159 IBaseFilter ** ppFiltersInGraph;
160 LPWSTR * pFilterNames;
161 ULONG nFilters;
162 int filterCapacity;
163 LONG nameIndex;
164 IReferenceClock *refClock;
165 IBaseFilter *refClockProvider;
166 EventsQueue evqueue;
167 HANDLE hEventCompletion;
168 int CompletionStatus;
169 WndNotify notif;
170 int nRenderers;
171 int EcCompleteCount;
172 int HandleEcComplete;
173 int HandleEcRepaint;
174 int HandleEcClockChanged;
175 OAFilterState state;
176 CRITICAL_SECTION cs;
177 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
178 int nItfCacheEntries;
179 BOOL defaultclock;
180 GUID timeformatseek;
181 REFERENCE_TIME start_time;
182 REFERENCE_TIME pause_time;
183 LONGLONG stop_position;
184 LONG recursioncount;
185 IUnknown *pSite;
186 LONG version;
187 } IFilterGraphImpl;
188
189 static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface)
190 {
191 return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner);
192 }
193
194 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObj)
195 {
196 IFilterGraphImpl *This = impl_from_IUnknown(iface);
197 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
198
199 if (IsEqualGUID(&IID_IUnknown, riid)) {
200 *ppvObj = &This->IUnknown_inner;
201 TRACE(" returning IUnknown interface (%p)\n", *ppvObj);
202 } else if (IsEqualGUID(&IID_IFilterGraph, riid) ||
203 IsEqualGUID(&IID_IFilterGraph2, riid) ||
204 IsEqualGUID(&IID_IGraphBuilder, riid)) {
205 *ppvObj = &This->IFilterGraph2_iface;
206 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj);
207 } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
208 *ppvObj = &This->IMediaControl_iface;
209 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj);
210 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
211 *ppvObj = &This->IMediaSeeking_iface;
212 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj);
213 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
214 *ppvObj = &This->IBasicAudio_iface;
215 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj);
216 } else if (IsEqualGUID(&IID_IBasicVideo, riid) ||
217 IsEqualGUID(&IID_IBasicVideo2, riid)) {
218 *ppvObj = &This->IBasicVideo2_iface;
219 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj);
220 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
221 *ppvObj = &This->IVideoWindow_iface;
222 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj);
223 } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
224 IsEqualGUID(&IID_IMediaEventEx, riid)) {
225 *ppvObj = &This->IMediaEventEx_iface;
226 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
227 } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
228 IsEqualGUID(&IID_IPersist, riid)) {
229 *ppvObj = &This->IMediaFilter_iface;
230 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj);
231 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
232 *ppvObj = &This->IMediaEventSink_iface;
233 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj);
234 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
235 *ppvObj = &This->IGraphConfig_iface;
236 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
237 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
238 *ppvObj = &This->IMediaPosition_iface;
239 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
240 } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) {
241 *ppvObj = &This->IObjectWithSite_iface;
242 TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj);
243 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
244 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
245 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
246 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
247 *ppvObj = This->pFilterMapper2;
248 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
249 } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) {
250 *ppvObj = This->pFilterMapper2;
251 TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj);
252 } else if (IsEqualGUID(&IID_IGraphVersion, riid)) {
253 *ppvObj = &This->IGraphConfig_iface;
254 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj);
255 } else {
256 *ppvObj = NULL;
257 FIXME("unknown interface %s\n", debugstr_guid(riid));
258 return E_NOINTERFACE;
259 }
260
261 IUnknown_AddRef((IUnknown *)*ppvObj);
262 return S_OK;
263 }
264
265 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown *iface)
266 {
267 IFilterGraphImpl *This = impl_from_IUnknown(iface);
268 ULONG ref = InterlockedIncrement(&This->ref);
269
270 TRACE("(%p)->(): new ref = %d\n", This, ref);
271
272 return ref;
273 }
274
275 static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
276 {
277 IFilterGraphImpl *This = impl_from_IUnknown(iface);
278 ULONG ref = InterlockedDecrement(&This->ref);
279
280 TRACE("(%p)->(): new ref = %d\n", This, ref);
281
282 if (ref == 0) {
283 int i;
284
285 This->ref = 1; /* guard against reentrancy (aggregation). */
286
287 IMediaControl_Stop(&This->IMediaControl_iface);
288
289 while (This->nFilters)
290 IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, This->ppFiltersInGraph[0]);
291
292 if (This->refClock)
293 IReferenceClock_Release(This->refClock);
294
295 for (i = 0; i < This->nItfCacheEntries; i++)
296 {
297 if (This->ItfCacheEntries[i].iface)
298 IUnknown_Release(This->ItfCacheEntries[i].iface);
299 }
300
301 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 */
302 IUnknown_AddRef(This->outer_unk);
303 IFilterMapper2_Release(This->pFilterMapper2);
304 IUnknown_Release(This->punkFilterMapper2);
305
306 if (This->pSite) IUnknown_Release(This->pSite);
307
308 CloseHandle(This->hEventCompletion);
309 EventsQueue_Destroy(&This->evqueue);
310 This->cs.DebugInfo->Spare[0] = 0;
311 DeleteCriticalSection(&This->cs);
312 CoTaskMemFree(This->ppFiltersInGraph);
313 CoTaskMemFree(This->pFilterNames);
314 CoTaskMemFree(This);
315 }
316 return ref;
317 }
318
319 static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface)
320 {
321 return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface);
322 }
323
324 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj)
325 {
326 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
327
328 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
329
330 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
331 }
332
333 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface)
334 {
335 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
336
337 TRACE("(%p/%p)->()\n", This, iface);
338
339 return IUnknown_AddRef(This->outer_unk);
340 }
341
342 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
343 {
344 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
345
346 TRACE("(%p/%p)->()\n", This, iface);
347
348 return IUnknown_Release(This->outer_unk);
349 }
350
351 /*** IFilterGraph methods ***/
352 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
353 LPCWSTR pName)
354 {
355 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
356 HRESULT hr;
357 int i,j;
358 WCHAR* wszFilterName = NULL;
359 BOOL duplicate_name = FALSE;
360
361 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
362
363 if (!pFilter)
364 return E_POINTER;
365
366 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
367
368 if (pName)
369 {
370 /* Check if name already exists */
371 for(i = 0; i < This->nFilters; i++)
372 if (!strcmpW(This->pFilterNames[i], pName))
373 {
374 duplicate_name = TRUE;
375 break;
376 }
377 }
378
379 /* If no name given or name already existing, generate one */
380 if (!pName || duplicate_name)
381 {
382 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
383 static const WCHAR wszFmt2[] = {'%','0','4','d',0};
384
385 for (j = 0; j < 10000 ; j++)
386 {
387 /* Create name */
388 if (pName)
389 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
390 else
391 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
392 TRACE("Generated name %s\n", debugstr_w(wszFilterName));
393
394 /* Check if the generated name already exists */
395 for(i = 0; i < This->nFilters; i++)
396 if (!strcmpW(This->pFilterNames[i], wszFilterName))
397 break;
398
399 /* Compute next index and exit if generated name is suitable */
400 if (This->nameIndex++ == 10000)
401 This->nameIndex = 1;
402 if (i == This->nFilters)
403 break;
404 }
405 /* Unable to find a suitable name */
406 if (j == 10000)
407 {
408 CoTaskMemFree(wszFilterName);
409 return VFW_E_DUPLICATE_NAME;
410 }
411 }
412 else
413 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
414
415 if (This->nFilters + 1 > This->filterCapacity)
416 {
417 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
418 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
419 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
420 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
421 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
422 if (This->filterCapacity)
423 {
424 CoTaskMemFree(This->ppFiltersInGraph);
425 CoTaskMemFree(This->pFilterNames);
426 }
427 This->ppFiltersInGraph = ppNewFilters;
428 This->pFilterNames = pNewNames;
429 This->filterCapacity = newCapacity;
430 }
431
432 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)&This->IFilterGraph2_iface, wszFilterName);
433
434 if (SUCCEEDED(hr))
435 {
436 IBaseFilter_AddRef(pFilter);
437 This->ppFiltersInGraph[This->nFilters] = pFilter;
438 This->pFilterNames[This->nFilters] = wszFilterName;
439 This->nFilters++;
440 This->version++;
441 IBaseFilter_SetSyncSource(pFilter, This->refClock);
442 }
443 else
444 CoTaskMemFree(wszFilterName);
445
446 if (SUCCEEDED(hr) && duplicate_name)
447 return VFW_S_DUPLICATE_NAME;
448
449 return hr;
450 }
451
452 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
453 {
454 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
455 int i;
456 HRESULT hr = E_FAIL;
457
458 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
459
460 /* FIXME: check graph is stopped */
461
462 for (i = 0; i < This->nFilters; i++)
463 {
464 if (This->ppFiltersInGraph[i] == pFilter)
465 {
466 IEnumPins *penumpins = NULL;
467 FILTER_STATE state;
468
469 if (This->defaultclock && This->refClockProvider == pFilter)
470 {
471 IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL);
472 This->defaultclock = TRUE;
473 }
474
475 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
476 IBaseFilter_GetState(pFilter, 0, &state);
477 if (state == State_Running)
478 IBaseFilter_Pause(pFilter);
479 if (state != State_Stopped)
480 IBaseFilter_Stop(pFilter);
481
482 hr = IBaseFilter_EnumPins(pFilter, &penumpins);
483 if (SUCCEEDED(hr)) {
484 IPin *ppin;
485 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK)
486 {
487 IPin *victim = NULL;
488 HRESULT h;
489 IPin_ConnectedTo(ppin, &victim);
490 if (victim)
491 {
492 h = IPin_Disconnect(victim);
493 TRACE("Disconnect other side: %08x\n", h);
494 if (h == VFW_E_NOT_STOPPED)
495 {
496 PIN_INFO pinfo;
497 IPin_QueryPinInfo(victim, &pinfo);
498
499 IBaseFilter_GetState(pinfo.pFilter, 0, &state);
500 if (state == State_Running)
501 IBaseFilter_Pause(pinfo.pFilter);
502 IBaseFilter_Stop(pinfo.pFilter);
503 IBaseFilter_Release(pinfo.pFilter);
504 h = IPin_Disconnect(victim);
505 TRACE("Disconnect retry: %08x\n", h);
506 }
507 IPin_Release(victim);
508 }
509 h = IPin_Disconnect(ppin);
510 TRACE("Disconnect 2: %08x\n", h);
511
512 IPin_Release(ppin);
513 }
514 IEnumPins_Release(penumpins);
515 }
516
517 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
518 if (SUCCEEDED(hr))
519 {
520 IBaseFilter_SetSyncSource(pFilter, NULL);
521 IBaseFilter_Release(pFilter);
522 CoTaskMemFree(This->pFilterNames[i]);
523 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
524 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
525 This->nFilters--;
526 This->version++;
527 /* Invalidate interfaces in the cache */
528 for (i = 0; i < This->nItfCacheEntries; i++)
529 if (pFilter == This->ItfCacheEntries[i].filter)
530 {
531 IUnknown_Release(This->ItfCacheEntries[i].iface);
532 This->ItfCacheEntries[i].iface = NULL;
533 This->ItfCacheEntries[i].filter = NULL;
534 }
535 return S_OK;
536 }
537 break;
538 }
539 }
540
541 return hr; /* FIXME: check this error code */
542 }
543
544 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum)
545 {
546 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
547
548 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
549
550 return IEnumFiltersImpl_Construct(&This->IGraphVersion_iface, &This->ppFiltersInGraph, &This->nFilters, ppEnum);
551 }
552
553 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName,
554 IBaseFilter **ppFilter)
555 {
556 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
557 int i;
558
559 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
560
561 if (!ppFilter)
562 return E_POINTER;
563
564 for (i = 0; i < This->nFilters; i++)
565 {
566 if (!strcmpW(pName, This->pFilterNames[i]))
567 {
568 *ppFilter = This->ppFiltersInGraph[i];
569 IBaseFilter_AddRef(*ppFilter);
570 return S_OK;
571 }
572 }
573
574 *ppFilter = NULL;
575 return VFW_E_NOT_FOUND;
576 }
577
578 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case.
579 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached
580 */
581 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in)
582 {
583 #if 1
584 HRESULT hr;
585 PIN_INFO info_out, info_in;
586
587 hr = IPin_QueryPinInfo(out, &info_out);
588 if (FAILED(hr))
589 return hr;
590 if (info_out.dir != PINDIR_OUTPUT)
591 {
592 IBaseFilter_Release(info_out.pFilter);
593 return E_UNEXPECTED;
594 }
595
596 hr = IPin_QueryPinInfo(in, &info_in);
597 if (SUCCEEDED(hr))
598 IBaseFilter_Release(info_in.pFilter);
599 if (FAILED(hr))
600 goto out;
601 if (info_in.dir != PINDIR_INPUT)
602 {
603 hr = E_UNEXPECTED;
604 goto out;
605 }
606
607 if (info_out.pFilter == info_in.pFilter)
608 hr = VFW_E_CIRCULAR_GRAPH;
609 else
610 {
611 IEnumPins *enumpins;
612 IPin *test;
613
614 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins);
615 if (FAILED(hr))
616 goto out;
617
618 IEnumPins_Reset(enumpins);
619 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK)
620 {
621 PIN_DIRECTION dir = PINDIR_OUTPUT;
622 IPin_QueryDirection(test, &dir);
623 if (dir == PINDIR_INPUT)
624 {
625 IPin *victim = NULL;
626 IPin_ConnectedTo(test, &victim);
627 if (victim)
628 {
629 hr = CheckCircularConnection(This, victim, in);
630 IPin_Release(victim);
631 if (FAILED(hr))
632 {
633 IPin_Release(test);
634 break;
635 }
636 }
637 }
638 IPin_Release(test);
639 }
640 IEnumPins_Release(enumpins);
641 }
642
643 out:
644 IBaseFilter_Release(info_out.pFilter);
645 if (FAILED(hr))
646 ERR("Checking filtergraph returned %08x, something's not right!\n", hr);
647 return hr;
648 #else
649 /* Debugging filtergraphs not enabled */
650 return S_OK;
651 #endif
652 }
653
654
655 /* NOTE: despite the implication, it doesn't matter which
656 * way round you put in the input and output pins */
657 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut,
658 const AM_MEDIA_TYPE *pmt)
659 {
660 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
661 PIN_DIRECTION dir;
662 HRESULT hr;
663
664 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
665
666 /* FIXME: check pins are in graph */
667
668 if (TRACE_ON(quartz))
669 {
670 PIN_INFO PinInfo;
671
672 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
673 if (FAILED(hr))
674 return hr;
675
676 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
677 IBaseFilter_Release(PinInfo.pFilter);
678
679 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
680 if (FAILED(hr))
681 return hr;
682
683 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
684 IBaseFilter_Release(PinInfo.pFilter);
685 }
686
687 hr = IPin_QueryDirection(ppinIn, &dir);
688 if (SUCCEEDED(hr))
689 {
690 if (dir == PINDIR_INPUT)
691 {
692 hr = CheckCircularConnection(This, ppinOut, ppinIn);
693 if (SUCCEEDED(hr))
694 hr = IPin_Connect(ppinOut, ppinIn, pmt);
695 }
696 else
697 {
698 hr = CheckCircularConnection(This, ppinIn, ppinOut);
699 if (SUCCEEDED(hr))
700 hr = IPin_Connect(ppinIn, ppinOut, pmt);
701 }
702 }
703
704 return hr;
705 }
706
707 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin)
708 {
709 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
710 IPin *pConnectedTo = NULL;
711 HRESULT hr;
712 PIN_DIRECTION pindir;
713
714 IPin_QueryDirection(ppin, &pindir);
715 hr = IPin_ConnectedTo(ppin, &pConnectedTo);
716 if (FAILED(hr)) {
717 TRACE("Querying connected to failed: %x\n", hr);
718 return hr;
719 }
720 IPin_Disconnect(ppin);
721 IPin_Disconnect(pConnectedTo);
722 if (pindir == PINDIR_INPUT)
723 hr = IPin_Connect(pConnectedTo, ppin, NULL);
724 else
725 hr = IPin_Connect(ppin, pConnectedTo, NULL);
726 IPin_Release(pConnectedTo);
727 if (FAILED(hr))
728 WARN("Reconnecting pins failed, pins are not connected now..\n");
729 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
730 return hr;
731 }
732
733 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin)
734 {
735 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
736
737 TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
738
739 if (!ppin)
740 return E_POINTER;
741
742 return IPin_Disconnect(ppin);
743 }
744
745 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
746 {
747 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
748 IReferenceClock *pClock = NULL;
749 HRESULT hr = S_OK;
750 int i;
751
752 TRACE("(%p/%p)->() live sources not handled properly!\n", iface, This);
753
754 EnterCriticalSection(&This->cs);
755
756 for (i = 0; i < This->nFilters; ++i)
757 {
758 DWORD miscflags;
759 IAMFilterMiscFlags *flags = NULL;
760 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags);
761 if (!flags)
762 continue;
763 miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
764 IAMFilterMiscFlags_Release(flags);
765 if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
766 IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock);
767 if (pClock)
768 break;
769 }
770
771 if (!pClock)
772 {
773 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
774 This->refClockProvider = NULL;
775 }
776 else
777 This->refClockProvider = This->ppFiltersInGraph[i];
778
779 if (SUCCEEDED(hr))
780 {
781 hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock);
782 This->defaultclock = TRUE;
783 IReferenceClock_Release(pClock);
784 }
785 LeaveCriticalSection(&This->cs);
786
787 return hr;
788 }
789
790 static HRESULT GetFilterInfo(IMoniker* pMoniker, VARIANT* pvar)
791 {
792 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
793 IPropertyBag * pPropBagCat = NULL;
794 HRESULT hr;
795
796 VariantInit(pvar);
797
798 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
799
800 if (SUCCEEDED(hr))
801 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
802
803 if (SUCCEEDED(hr))
804 TRACE("Moniker = %s\n", debugstr_w(V_UNION(pvar, bstrVal)));
805
806 if (pPropBagCat)
807 IPropertyBag_Release(pPropBagCat);
808
809 return hr;
810 }
811
812 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
813 {
814 HRESULT hr;
815 ULONG nb = 0;
816
817 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
818 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
819 if (hr == S_OK) {
820 /* Rendered input */
821 } else if (hr == S_FALSE) {
822 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
823 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
824 if (hr != S_OK) {
825 WARN("Error (%x)\n", hr);
826 }
827 } else if (hr == E_NOTIMPL) {
828 /* Input connected to all outputs */
829 IEnumPins* penumpins;
830 IPin* ppin;
831 int i = 0;
832 TRACE("E_NOTIMPL\n");
833 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
834 if (FAILED(hr)) {
835 WARN("filter Enumpins failed (%x)\n", hr);
836 return hr;
837 }
838 i = 0;
839 /* Count output pins */
840 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
841 PIN_DIRECTION pindir;
842 IPin_QueryDirection(ppin, &pindir);
843 if (pindir == PINDIR_OUTPUT)
844 i++;
845 IPin_Release(ppin);
846 }
847 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
848 /* Retrieve output pins */
849 IEnumPins_Reset(penumpins);
850 i = 0;
851 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
852 PIN_DIRECTION pindir;
853 IPin_QueryDirection(ppin, &pindir);
854 if (pindir == PINDIR_OUTPUT)
855 (*pppins)[i++] = ppin;
856 else
857 IPin_Release(ppin);
858 }
859 IEnumPins_Release(penumpins);
860 nb = i;
861 if (FAILED(hr)) {
862 WARN("Next failed (%x)\n", hr);
863 return hr;
864 }
865 } else if (FAILED(hr)) {
866 WARN("Cannot get internal connection (%x)\n", hr);
867 return hr;
868 }
869
870 *pnb = nb;
871 return S_OK;
872 }
873
874 /*** IGraphBuilder methods ***/
875 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn)
876 {
877 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
878 HRESULT hr;
879 AM_MEDIA_TYPE* mt = NULL;
880 IEnumMediaTypes* penummt = NULL;
881 ULONG nbmt;
882 IEnumPins* penumpins;
883 IEnumMoniker* pEnumMoniker;
884 GUID tab[2];
885 ULONG nb = 0;
886 IMoniker* pMoniker;
887 ULONG pin;
888 PIN_INFO PinInfo;
889 CLSID FilterCLSID;
890 PIN_DIRECTION dir;
891 unsigned int i = 0;
892
893 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
894
895 if (TRACE_ON(quartz))
896 {
897 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
898 if (FAILED(hr))
899 return hr;
900
901 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
902 IBaseFilter_Release(PinInfo.pFilter);
903
904 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
905 if (FAILED(hr))
906 return hr;
907
908 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
909 IBaseFilter_Release(PinInfo.pFilter);
910 }
911
912 EnterCriticalSection(&This->cs);
913 ++This->recursioncount;
914 if (This->recursioncount >= 5)
915 {
916 WARN("Recursion count has reached %d\n", This->recursioncount);
917 hr = VFW_E_CANNOT_CONNECT;
918 goto out;
919 }
920
921 hr = IPin_QueryDirection(ppinOut, &dir);
922 if (FAILED(hr))
923 goto out;
924
925 if (dir == PINDIR_INPUT)
926 {
927 IPin *temp;
928
929 temp = ppinIn;
930 ppinIn = ppinOut;
931 ppinOut = temp;
932 }
933
934 hr = CheckCircularConnection(This, ppinOut, ppinIn);
935 if (FAILED(hr))
936 goto out;
937
938 /* Try direct connection first */
939 hr = IPin_Connect(ppinOut, ppinIn, NULL);
940 if (SUCCEEDED(hr))
941 goto out;
942
943 TRACE("Direct connection failed, trying to render using extra filters\n");
944
945 hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
946 if (FAILED(hr))
947 goto out;
948
949 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
950 IBaseFilter_Release(PinInfo.pFilter);
951 if (FAILED(hr))
952 goto out;
953
954 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream
955 * filter to the minor mediatype of input pin of the renderer */
956 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
957 if (FAILED(hr))
958 {
959 WARN("EnumMediaTypes (%x)\n", hr);
960 goto out;
961 }
962
963 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
964 if (FAILED(hr)) {
965 WARN("IEnumMediaTypes_Next (%x)\n", hr);
966 goto out;
967 }
968
969 if (!nbmt)
970 {
971 WARN("No media type found!\n");
972 hr = VFW_E_INVALIDMEDIATYPE;
973 goto out;
974 }
975 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
976 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
977
978 /* Try to find a suitable filter that can connect to the pin to render */
979 tab[0] = mt->majortype;
980 tab[1] = mt->subtype;
981 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
982 if (FAILED(hr)) {
983 WARN("Unable to enum filters (%x)\n", hr);
984 goto out;
985 }
986
987 hr = VFW_E_CANNOT_RENDER;
988 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
989 {
990 VARIANT var;
991 GUID clsid;
992 IPin** ppins = NULL;
993 IPin* ppinfilter = NULL;
994 IBaseFilter* pfilter = NULL;
995 IAMGraphBuilderCallback *callback = NULL;
996
997 hr = GetFilterInfo(pMoniker, &var);
998 if (FAILED(hr)) {
999 WARN("Unable to retrieve filter info (%x)\n", hr);
1000 goto error;
1001 }
1002
1003 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1004 IMoniker_Release(pMoniker);
1005 if (FAILED(hr)) {
1006 WARN("Unable to create filter (%x), trying next one\n", hr);
1007 goto error;
1008 }
1009
1010 hr = IBaseFilter_GetClassID(pfilter, &clsid);
1011 if (FAILED(hr))
1012 {
1013 IBaseFilter_Release(pfilter);
1014 goto error;
1015 }
1016
1017 if (IsEqualGUID(&clsid, &FilterCLSID)) {
1018 /* Skip filter (same as the one the output pin belongs to) */
1019 IBaseFilter_Release(pfilter);
1020 goto error;
1021 }
1022
1023 if (This->pSite)
1024 {
1025 IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback);
1026 if (callback)
1027 {
1028 HRESULT rc;
1029 rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker);
1030 if (FAILED(rc))
1031 {
1032 TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n");
1033 IAMGraphBuilderCallback_Release(callback);
1034 goto error;
1035 }
1036 }
1037 }
1038
1039 if (callback)
1040 {
1041 HRESULT rc;
1042 rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter);
1043 IAMGraphBuilderCallback_Release(callback);
1044 if (FAILED(rc))
1045 {
1046 IBaseFilter_Release(pfilter);
1047 pfilter = NULL;
1048 TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n");
1049 goto error;
1050 }
1051 }
1052
1053 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1054 if (FAILED(hr)) {
1055 WARN("Unable to add filter (%x)\n", hr);
1056 IBaseFilter_Release(pfilter);
1057 pfilter = NULL;
1058 goto error;
1059 }
1060
1061 VariantClear(&var);
1062
1063 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1064 if (FAILED(hr)) {
1065 WARN("Enumpins (%x)\n", hr);
1066 goto error;
1067 }
1068
1069 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
1070 IEnumPins_Release(penumpins);
1071
1072 if (FAILED(hr)) {
1073 WARN("Obtaining next pin: (%x)\n", hr);
1074 goto error;
1075 }
1076 if (pin == 0) {
1077 WARN("Cannot use this filter: no pins\n");
1078 goto error;
1079 }
1080
1081 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1082 if (FAILED(hr)) {
1083 TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1084 goto error;
1085 }
1086 TRACE("Successfully connected to filter, follow chain...\n");
1087
1088 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */
1089 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
1090
1091 if (SUCCEEDED(hr)) {
1092 if (nb == 0) {
1093 IPin_Disconnect(ppinfilter);
1094 IPin_Disconnect(ppinOut);
1095 goto error;
1096 }
1097 TRACE("pins to consider: %d\n", nb);
1098 for(i = 0; i < nb; i++)
1099 {
1100 LPWSTR pinname = NULL;
1101
1102 TRACE("Processing pin %u\n", i);
1103
1104 hr = IPin_QueryId(ppins[i], &pinname);
1105 if (SUCCEEDED(hr))
1106 {
1107 if (pinname[0] == '~')
1108 {
1109 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname));
1110 hr = E_FAIL;
1111 }
1112 else
1113 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn);
1114 CoTaskMemFree(pinname);
1115 }
1116
1117 if (FAILED(hr)) {
1118 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr);
1119 }
1120 IPin_Release(ppins[i]);
1121 if (SUCCEEDED(hr)) break;
1122 }
1123 while (++i < nb) IPin_Release(ppins[i]);
1124 CoTaskMemFree(ppins);
1125 IPin_Release(ppinfilter);
1126 IBaseFilter_Release(pfilter);
1127 if (FAILED(hr))
1128 {
1129 IPin_Disconnect(ppinfilter);
1130 IPin_Disconnect(ppinOut);
1131 IFilterGraph2_RemoveFilter(iface, pfilter);
1132 continue;
1133 }
1134 break;
1135 }
1136
1137 error:
1138 VariantClear(&var);
1139 if (ppinfilter) IPin_Release(ppinfilter);
1140 if (pfilter) {
1141 IFilterGraph2_RemoveFilter(iface, pfilter);
1142 IBaseFilter_Release(pfilter);
1143 }
1144 while (++i < nb) IPin_Release(ppins[i]);
1145 CoTaskMemFree(ppins);
1146 }
1147
1148 out:
1149 if (penummt)
1150 IEnumMediaTypes_Release(penummt);
1151 if (mt)
1152 DeleteMediaType(mt);
1153 --This->recursioncount;
1154 LeaveCriticalSection(&This->cs);
1155 TRACE("--> %08x\n", hr);
1156 return SUCCEEDED(hr) ? S_OK : hr;
1157 }
1158
1159 static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut)
1160 {
1161 /* This pin has been connected now, try to call render on all pins that aren't connected */
1162 IPin *to = NULL;
1163 PIN_INFO info;
1164 IEnumPins *enumpins = NULL;
1165 BOOL renderany = FALSE;
1166 BOOL renderall = TRUE;
1167
1168 IPin_QueryPinInfo(ppinOut, &info);
1169
1170 IBaseFilter_EnumPins(info.pFilter, &enumpins);
1171 /* Don't need to hold a reference, IEnumPins does */
1172 IBaseFilter_Release(info.pFilter);
1173
1174 IEnumPins_Reset(enumpins);
1175 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK)
1176 {
1177 PIN_DIRECTION dir = PINDIR_INPUT;
1178
1179 IPin_QueryDirection(to, &dir);
1180
1181 if (dir == PINDIR_OUTPUT)
1182 {
1183 IPin *out = NULL;
1184
1185 IPin_ConnectedTo(to, &out);
1186 if (!out)
1187 {
1188 HRESULT hr;
1189 hr = IFilterGraph2_Render(&This->IFilterGraph2_iface, to);
1190 if (SUCCEEDED(hr))
1191 renderany = TRUE;
1192 else
1193 renderall = FALSE;
1194 }
1195 else
1196 IPin_Release(out);
1197 }
1198
1199 IPin_Release(to);
1200 }
1201
1202 IEnumPins_Release(enumpins);
1203
1204 if (renderall)
1205 return S_OK;
1206
1207 if (renderany)
1208 return VFW_S_PARTIAL_RENDER;
1209
1210 return VFW_E_CANNOT_RENDER;
1211 }
1212
1213 /* Ogg hates me if I create a direct rendering method
1214 *
1215 * It can only connect to a pin properly once, so use a recursive method that does
1216 *
1217 * +----+ --- (PIN 1) (Render is called on this pin)
1218 * | |
1219 * +----+ --- (PIN 2)
1220 *
1221 * Enumerate possible renderers that EXACTLY match the requested type
1222 *
1223 * If none is available, try to add intermediate filters that can connect to the input pin
1224 * then call Render on that intermediate pin's output pins
1225 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed,
1226 * and another filter that can connect to the input pin is tried
1227 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER
1228 * It's recursive, but fun!
1229 */
1230
1231 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
1232 {
1233 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1234 IEnumMediaTypes* penummt;
1235 AM_MEDIA_TYPE* mt;
1236 ULONG nbmt;
1237 HRESULT hr;
1238
1239 IEnumMoniker* pEnumMoniker;
1240 GUID tab[4];
1241 ULONG nb;
1242 IMoniker* pMoniker;
1243 INT x;
1244
1245 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
1246
1247 if (TRACE_ON(quartz))
1248 {
1249 PIN_INFO PinInfo;
1250
1251 hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
1252 if (FAILED(hr))
1253 return hr;
1254
1255 TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
1256 IBaseFilter_Release(PinInfo.pFilter);
1257 }
1258
1259 /* Try to find out if there is a renderer for the specified subtype already, and use that
1260 */
1261 EnterCriticalSection(&This->cs);
1262 for (x = 0; x < This->nFilters; ++x)
1263 {
1264 IEnumPins *enumpins = NULL;
1265 IPin *pin = NULL;
1266
1267 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
1268
1269 if (FAILED(hr) || !enumpins)
1270 continue;
1271
1272 IEnumPins_Reset(enumpins);
1273 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
1274 {
1275 IPin *to = NULL;
1276 PIN_DIRECTION dir = PINDIR_OUTPUT;
1277
1278 IPin_QueryDirection(pin, &dir);
1279 if (dir != PINDIR_INPUT)
1280 {
1281 IPin_Release(pin);
1282 continue;
1283 }
1284 IPin_ConnectedTo(pin, &to);
1285
1286 if (to == NULL)
1287 {
1288 hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL);
1289 if (SUCCEEDED(hr))
1290 {
1291 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr);
1292 IPin_Release(pin);
1293
1294 hr = FilterGraph2_RenderRecurse(This, pin);
1295 if (FAILED(hr))
1296 {
1297 IPin_Disconnect(ppinOut);
1298 IPin_Disconnect(pin);
1299 continue;
1300 }
1301 IEnumPins_Release(enumpins);
1302 LeaveCriticalSection(&This->cs);
1303 return hr;
1304 }
1305 WARN("Could not connect!\n");
1306 }
1307 else
1308 IPin_Release(to);
1309
1310 IPin_Release(pin);
1311 }
1312 IEnumPins_Release(enumpins);
1313 }
1314
1315 LeaveCriticalSection(&This->cs);
1316
1317 hr = IPin_EnumMediaTypes(ppinOut, &penummt);
1318 if (FAILED(hr)) {
1319 WARN("EnumMediaTypes (%x)\n", hr);
1320 return hr;
1321 }
1322
1323 IEnumMediaTypes_Reset(penummt);
1324
1325 /* Looks like no existing renderer of the kind exists
1326 * Try adding new ones
1327 */
1328 tab[0] = tab[1] = GUID_NULL;
1329 while (SUCCEEDED(hr))
1330 {
1331 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
1332 if (FAILED(hr)) {
1333 WARN("IEnumMediaTypes_Next (%x)\n", hr);
1334 break;
1335 }
1336 if (!nbmt)
1337 {
1338 hr = VFW_E_CANNOT_RENDER;
1339 break;
1340 }
1341 else
1342 {
1343 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
1344 TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
1345
1346 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */
1347 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype))
1348 {
1349 DeleteMediaType(mt);
1350 continue;
1351 }
1352
1353 /* Try to find a suitable renderer with the same media type */
1354 tab[0] = mt->majortype;
1355 tab[1] = mt->subtype;
1356 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1357 if (FAILED(hr))
1358 {
1359 WARN("Unable to enum filters (%x)\n", hr);
1360 break;
1361 }
1362 }
1363 hr = E_FAIL;
1364
1365 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1366 {
1367 VARIANT var;
1368 IPin* ppinfilter;
1369 IBaseFilter* pfilter = NULL;
1370 IEnumPins* penumpins = NULL;
1371 ULONG pin;
1372
1373 hr = GetFilterInfo(pMoniker, &var);
1374 if (FAILED(hr)) {
1375 WARN("Unable to retrieve filter info (%x)\n", hr);
1376 goto error;
1377 }
1378
1379 hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter);
1380 IMoniker_Release(pMoniker);
1381 if (FAILED(hr))
1382 {
1383 WARN("Unable to create filter (%x), trying next one\n", hr);
1384 goto error;
1385 }
1386
1387 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
1388 if (FAILED(hr)) {
1389 WARN("Unable to add filter (%x)\n", hr);
1390 IBaseFilter_Release(pfilter);
1391 pfilter = NULL;
1392 goto error;
1393 }
1394
1395 hr = IBaseFilter_EnumPins(pfilter, &penumpins);
1396 if (FAILED(hr)) {
1397 WARN("Splitter Enumpins (%x)\n", hr);
1398 goto error;
1399 }
1400
1401 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK)
1402 {
1403 PIN_DIRECTION dir;
1404
1405 if (pin == 0) {
1406 WARN("No Pin\n");
1407 hr = E_FAIL;
1408 goto error;
1409 }
1410
1411 hr = IPin_QueryDirection(ppinfilter, &dir);
1412 if (FAILED(hr)) {
1413 IPin_Release(ppinfilter);
1414 WARN("QueryDirection failed (%x)\n", hr);
1415 goto error;
1416 }
1417 if (dir != PINDIR_INPUT) {
1418 IPin_Release(ppinfilter);
1419 continue; /* Wrong direction */
1420 }
1421
1422 /* Connect the pin to the "Renderer" */
1423 hr = IPin_Connect(ppinOut, ppinfilter, NULL);
1424 IPin_Release(ppinfilter);
1425
1426 if (FAILED(hr)) {
1427 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr);
1428 goto error;
1429 }
1430 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal)));
1431
1432 VariantClear(&var);
1433
1434 hr = FilterGraph2_RenderRecurse(This, ppinfilter);
1435 if (FAILED(hr)) {
1436 WARN("Unable to connect recursively (%x)\n", hr);
1437 goto error;
1438 }
1439 IBaseFilter_Release(pfilter);
1440 break;
1441 }
1442 if (SUCCEEDED(hr)) {
1443 IEnumPins_Release(penumpins);
1444 break; /* out of IEnumMoniker_Next loop */
1445 }
1446
1447 /* IEnumPins_Next failed, all other failure case caught by goto error */
1448 WARN("IEnumPins_Next (%x)\n", hr);
1449 /* goto error */
1450
1451 error:
1452 VariantClear(&var);
1453 if (penumpins)
1454 IEnumPins_Release(penumpins);
1455 if (pfilter) {
1456 IFilterGraph2_RemoveFilter(iface, pfilter);
1457 IBaseFilter_Release(pfilter);
1458 }
1459 if (SUCCEEDED(hr)) DebugBreak();
1460 }
1461
1462 IEnumMoniker_Release(pEnumMoniker);
1463 if (nbmt)
1464 DeleteMediaType(mt);
1465 if (SUCCEEDED(hr))
1466 break;
1467 hr = S_OK;
1468 }
1469
1470 IEnumMediaTypes_Release(penummt);
1471 return hr;
1472 }
1473
1474 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile,
1475 LPCWSTR lpcwstrPlayList)
1476 {
1477 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1478 static const WCHAR string[] = {'R','e','a','d','e','r',0};
1479 IBaseFilter* preader = NULL;
1480 IPin* ppinreader = NULL;
1481 IEnumPins* penumpins = NULL;
1482 HRESULT hr;
1483 BOOL partial = FALSE;
1484 BOOL any = FALSE;
1485
1486 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1487
1488 if (lpcwstrPlayList != NULL)
1489 return E_INVALIDARG;
1490
1491 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1492 if (FAILED(hr))
1493 return hr;
1494
1495 if (SUCCEEDED(hr))
1496 hr = IBaseFilter_EnumPins(preader, &penumpins);
1497 if (SUCCEEDED(hr))
1498 {
1499 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK)
1500 {
1501 PIN_DIRECTION dir;
1502
1503 IPin_QueryDirection(ppinreader, &dir);
1504 if (dir == PINDIR_OUTPUT)
1505 {
1506 INT i;
1507
1508 hr = IFilterGraph2_Render(iface, ppinreader);
1509 TRACE("Render %08x\n", hr);
1510
1511 for (i = 0; i < This->nFilters; ++i)
1512 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
1513
1514 if (SUCCEEDED(hr))
1515 any = TRUE;
1516 if (hr != S_OK)
1517 partial = TRUE;
1518 }
1519 IPin_Release(ppinreader);
1520 }
1521 IEnumPins_Release(penumpins);
1522
1523 if (!any)
1524 hr = VFW_E_CANNOT_RENDER;
1525 else if (partial)
1526 hr = VFW_S_PARTIAL_RENDER;
1527 else
1528 hr = S_OK;
1529 }
1530 IBaseFilter_Release(preader);
1531
1532 TRACE("--> %08x\n", hr);
1533 return hr;
1534 }
1535
1536 static HRESULT CreateFilterInstanceAndLoadFile(GUID* clsid, LPCOLESTR pszFileName, IBaseFilter **filter)
1537 {
1538 IFileSourceFilter *source = NULL;
1539 HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1540 TRACE("CLSID: %s\n", debugstr_guid(clsid));
1541 if (FAILED(hr))
1542 return hr;
1543
1544 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source);
1545 if (FAILED(hr))
1546 {
1547 IBaseFilter_Release(*filter);
1548 return hr;
1549 }
1550
1551 /* Load the file in the file source filter */
1552 hr = IFileSourceFilter_Load(source, pszFileName, NULL);
1553 IFileSourceFilter_Release(source);
1554 if (FAILED(hr)) {
1555 WARN("Load (%x)\n", hr);
1556 IBaseFilter_Release(*filter);
1557 return hr;
1558 }
1559
1560 return hr;
1561 }
1562
1563 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
1564 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter)
1565 {
1566 HRESULT hr;
1567 GUID clsid;
1568 IAsyncReader * pReader = NULL;
1569 IFileSourceFilter* pSource = NULL;
1570 IPin * pOutputPin = NULL;
1571 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
1572
1573 /* Try to find a match without reading the file first */
1574 hr = GetClassMediaFile(NULL, pszFileName, NULL, NULL, &clsid);
1575
1576 if (!hr)
1577 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1578
1579 /* Now create a AyncReader instance, to check for signature bytes in the file */
1580 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter);
1581 if (FAILED(hr))
1582 return hr;
1583
1584 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID *)&pSource);
1585 if (FAILED(hr))
1586 {
1587 IBaseFilter_Release(*filter);
1588 return hr;
1589 }
1590
1591 hr = IFileSourceFilter_Load(pSource, pszFileName, NULL);
1592 IFileSourceFilter_Release(pSource);
1593 if (FAILED(hr))
1594 {
1595 IBaseFilter_Release(*filter);
1596 return hr;
1597 }
1598
1599 hr = IBaseFilter_FindPin(*filter, wszOutputPinName, &pOutputPin);
1600 if (FAILED(hr))
1601 {
1602 IBaseFilter_Release(*filter);
1603 return hr;
1604 }
1605
1606 hr = IPin_QueryInterface(pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
1607 IPin_Release(pOutputPin);
1608 if (FAILED(hr))
1609 {
1610 IBaseFilter_Release(*filter);
1611 return hr;
1612 }
1613
1614 /* Try again find a match */
1615 hr = GetClassMediaFile(pReader, pszFileName, NULL, NULL, &clsid);
1616 IAsyncReader_Release(pReader);
1617
1618 if (!hr)
1619 {
1620 /* Release the AsyncReader filter and create the matching one */
1621 IBaseFilter_Release(*filter);
1622 return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
1623 }
1624
1625 /* Return the AsyncReader filter */
1626 return S_OK;
1627 }
1628
1629 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName,
1630 LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1631 {
1632 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1633 HRESULT hr;
1634 IBaseFilter* preader;
1635 IFileSourceFilter* pfile = NULL;
1636 AM_MEDIA_TYPE mt;
1637 WCHAR* filename;
1638
1639 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1640
1641 /* Try from file name first, then fall back to default asynchronous reader */
1642 hr = GetFileSourceFilter(lpcwstrFileName, &preader);
1643 if (FAILED(hr)) {
1644 WARN("Unable to create file source filter (%x)\n", hr);
1645 return hr;
1646 }
1647
1648 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName);
1649 if (FAILED(hr)) {
1650 WARN("Unable add filter (%x)\n", hr);
1651 IBaseFilter_Release(preader);
1652 return hr;
1653 }
1654
1655 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1656 if (FAILED(hr)) {
1657 WARN("Unable to get IFileSourceInterface (%x)\n", hr);
1658 goto error;
1659 }
1660
1661 /* The file has been already loaded */
1662 hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1663 if (FAILED(hr)) {
1664 WARN("GetCurFile (%x)\n", hr);
1665 goto error;
1666 }
1667
1668 TRACE("File %s\n", debugstr_w(filename));
1669 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1670 TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1671
1672 if (ppFilter)
1673 *ppFilter = preader;
1674 IFileSourceFilter_Release(pfile);
1675
1676 return S_OK;
1677
1678 error:
1679 if (pfile)
1680 IFileSourceFilter_Release(pfile);
1681 IFilterGraph2_RemoveFilter(iface, preader);
1682 IBaseFilter_Release(preader);
1683
1684 return hr;
1685 }
1686
1687 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile)
1688 {
1689 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1690
1691 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1692
1693 return S_OK;
1694 }
1695
1696 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface)
1697 {
1698 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1699
1700 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1701
1702 return S_OK;
1703 }
1704
1705 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface)
1706 {
1707 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1708
1709 TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1710
1711 return S_OK;
1712 }
1713
1714 /*** IFilterGraph2 methods ***/
1715 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface,
1716 IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter)
1717 {
1718 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1719
1720 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter);
1721
1722 return S_OK;
1723 }
1724
1725 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin,
1726 const AM_MEDIA_TYPE *pmt)
1727 {
1728 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1729
1730 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt);
1731
1732 return S_OK;
1733 }
1734
1735 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
1736 DWORD *pvContext)
1737 {
1738 IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
1739
1740 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
1741
1742 return S_OK;
1743 }
1744
1745
1746 static const IFilterGraph2Vtbl IFilterGraph2_VTable =
1747 {
1748 FilterGraph2_QueryInterface,
1749 FilterGraph2_AddRef,
1750 FilterGraph2_Release,
1751 FilterGraph2_AddFilter,
1752 FilterGraph2_RemoveFilter,
1753 FilterGraph2_EnumFilters,
1754 FilterGraph2_FindFilterByName,
1755 FilterGraph2_ConnectDirect,
1756 FilterGraph2_Reconnect,
1757 FilterGraph2_Disconnect,
1758 FilterGraph2_SetDefaultSyncSource,
1759 FilterGraph2_Connect,
1760 FilterGraph2_Render,
1761 FilterGraph2_RenderFile,
1762 FilterGraph2_AddSourceFilter,
1763 FilterGraph2_SetLogFile,
1764 FilterGraph2_Abort,
1765 FilterGraph2_ShouldOperationContinue,
1766 FilterGraph2_AddSourceFilterForMoniker,
1767 FilterGraph2_ReconnectEx,
1768 FilterGraph2_RenderEx
1769 };
1770
1771 static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface)
1772 {
1773 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface);
1774 }
1775
1776 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj)
1777 {
1778 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1779
1780 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1781
1782 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1783 }
1784
1785 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface)
1786 {
1787 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1788
1789 TRACE("(%p/%p)->()\n", This, iface);
1790
1791 return IUnknown_AddRef(This->outer_unk);
1792 }
1793
1794 static ULONG WINAPI MediaControl_Release(IMediaControl *iface)
1795 {
1796 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1797
1798 TRACE("(%p/%p)->()\n", This, iface);
1799
1800 return IUnknown_Release(This->outer_unk);
1801
1802 }
1803
1804 /*** IDispatch methods ***/
1805 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo)
1806 {
1807 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1808
1809 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1810
1811 return S_OK;
1812 }
1813
1814 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid,
1815 ITypeInfo **ppTInfo)
1816 {
1817 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1818
1819 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1820
1821 return S_OK;
1822 }
1823
1824 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid,
1825 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1826 {
1827 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1828
1829 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1830
1831 return S_OK;
1832 }
1833
1834 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid,
1835 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
1836 UINT *puArgErr)
1837 {
1838 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1839
1840 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1841
1842 return S_OK;
1843 }
1844
1845 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
1846
1847 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
1848 {
1849 HRESULT hr;
1850 IPin* pInputPin;
1851 IPin** ppPins;
1852 ULONG nb;
1853 ULONG i;
1854 PIN_INFO PinInfo;
1855
1856 TRACE("%p %p\n", pGraph, pOutputPin);
1857 PinInfo.pFilter = NULL;
1858
1859 hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1860
1861 if (SUCCEEDED(hr))
1862 {
1863 hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1864 if (SUCCEEDED(hr))
1865 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1866 IPin_Release(pInputPin);
1867 }
1868
1869 if (SUCCEEDED(hr))
1870 {
1871 if (nb == 0)
1872 {
1873 TRACE("Reached a renderer\n");
1874 /* Count renderers for end of stream notification */
1875 pGraph->nRenderers++;
1876 }
1877 else
1878 {
1879 for(i = 0; i < nb; i++)
1880 {
1881 /* Explore the graph downstream from this pin
1882 * FIXME: We should prevent exploring from a pin more than once. This can happens when
1883 * several input pins are connected to the same output (a MUX for instance). */
1884 ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
1885 IPin_Release(ppPins[i]);
1886 }
1887
1888 CoTaskMemFree(ppPins);
1889 }
1890 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1891
1892 FoundFilter(PinInfo.pFilter, data);
1893 }
1894
1895 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1896 return hr;
1897 }
1898
1899 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
1900 {
1901 REFERENCE_TIME time = *(REFERENCE_TIME*)data;
1902 return IBaseFilter_Run(pFilter, time);
1903 }
1904
1905 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
1906 {
1907 return IBaseFilter_Pause(pFilter);
1908 }
1909
1910 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
1911 {
1912 return IBaseFilter_Stop(pFilter);
1913 }
1914
1915 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
1916 {
1917 FILTER_STATE state;
1918 DWORD time_end = data;
1919 DWORD time_now = GetTickCount();
1920 LONG wait;
1921
1922 if (time_end == INFINITE)
1923 {
1924 wait = INFINITE;
1925 }
1926 else if (time_end > time_now)
1927 {
1928 wait = time_end - time_now;
1929 }
1930 else
1931 wait = 0;
1932
1933 return IBaseFilter_GetState(pFilter, wait, &state);
1934 }
1935
1936
1937 static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
1938 {
1939 int i;
1940 IBaseFilter* pfilter;
1941 IEnumPins* pEnum;
1942 HRESULT hr;
1943 IPin* pPin;
1944 DWORD dummy;
1945 PIN_DIRECTION dir;
1946
1947 TRACE("(%p)->()\n", This);
1948
1949 /* Explorer the graph from source filters to renderers, determine renderers
1950 * number and run filters from renderers to source filters */
1951 This->nRenderers = 0;
1952 ResetEvent(This->hEventCompletion);
1953
1954 for(i = 0; i < This->nFilters; i++)
1955 {
1956 BOOL source = TRUE;
1957 pfilter = This->ppFiltersInGraph[i];
1958 hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1959 if (hr != S_OK)
1960 {
1961 WARN("Enum pins failed %x\n", hr);
1962 continue;
1963 }
1964 /* Check if it is a source filter */
1965 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1966 {
1967 IPin_QueryDirection(pPin, &dir);
1968 IPin_Release(pPin);
1969 if (dir == PINDIR_INPUT)
1970 {
1971 source = FALSE;
1972 break;
1973 }
1974 }
1975 if (source)
1976 {
1977 TRACE("Found a source filter %p\n", pfilter);
1978 IEnumPins_Reset(pEnum);
1979 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1980 {
1981 /* Explore the graph downstream from this pin */
1982 ExploreGraph(This, pPin, FoundFilter, data);
1983 IPin_Release(pPin);
1984 }
1985 FoundFilter(pfilter, data);
1986 }
1987 IEnumPins_Release(pEnum);
1988 }
1989
1990 return S_FALSE;
1991 }
1992
1993 /*** IMediaControl methods ***/
1994 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
1995 {
1996 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
1997
1998 TRACE("(%p/%p)->()\n", This, iface);
1999
2000 EnterCriticalSection(&This->cs);
2001 if (This->state == State_Running)
2002 goto out;
2003 This->EcCompleteCount = 0;
2004
2005 if (This->defaultclock && !This->refClock)
2006 IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
2007
2008 if (This->refClock)
2009 {
2010 REFERENCE_TIME now;
2011 IReferenceClock_GetTime(This->refClock, &now);
2012 if (This->state == State_Stopped)
2013 This->start_time = now + 500000;
2014 else if (This->pause_time >= 0)
2015 This->start_time += now - This->pause_time;
2016 else
2017 This->start_time = now;
2018 }
2019 else This->start_time = 0;
2020
2021 SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time);
2022 This->state = State_Running;
2023 out:
2024 LeaveCriticalSection(&This->cs);
2025 return S_FALSE;
2026 }
2027
2028 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
2029 {
2030 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2031
2032 TRACE("(%p/%p)->()\n", This, iface);
2033
2034 EnterCriticalSection(&This->cs);
2035 if (This->state == State_Paused)
2036 goto out;
2037
2038 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2039 IReferenceClock_GetTime(This->refClock, &This->pause_time);
2040 else
2041 This->pause_time = -1;
2042
2043 SendFilterMessage(This, SendPause, 0);
2044 This->state = State_Paused;
2045 out:
2046 LeaveCriticalSection(&This->cs);
2047 return S_FALSE;
2048 }
2049
2050 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
2051 {
2052 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2053
2054 TRACE("(%p/%p)->()\n", This, iface);
2055
2056 if (This->state == State_Stopped) return S_OK;
2057
2058 EnterCriticalSection(&This->cs);
2059 if (This->state == State_Running) SendFilterMessage(This, SendPause, 0);
2060 SendFilterMessage(This, SendStop, 0);
2061 This->state = State_Stopped;
2062 LeaveCriticalSection(&This->cs);
2063 return S_OK;
2064 }
2065
2066 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout,
2067 OAFilterState *pfs)
2068 {
2069 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2070 DWORD end;
2071
2072 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
2073
2074 if (!pfs)
2075 return E_POINTER;
2076
2077 EnterCriticalSection(&This->cs);
2078
2079 *pfs = This->state;
2080 if (msTimeout > 0)
2081 {
2082 end = GetTickCount() + msTimeout;
2083 }
2084 else if (msTimeout < 0)
2085 {
2086 end = INFINITE;
2087 }
2088 else
2089 {
2090 end = 0;
2091 }
2092 if (end)
2093 SendFilterMessage(This, SendGetState, end);
2094
2095 LeaveCriticalSection(&This->cs);
2096
2097 return S_OK;
2098 }
2099
2100 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
2101 {
2102 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2103
2104 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename);
2105
2106 return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL);
2107 }
2108
2109 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename,
2110 IDispatch **ppUnk)
2111 {
2112 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2113
2114 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
2115
2116 return S_OK;
2117 }
2118
2119 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2120 {
2121 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2122
2123 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2124
2125 return S_OK;
2126 }
2127
2128 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk)
2129 {
2130 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2131
2132 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
2133
2134 return S_OK;
2135 }
2136
2137 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface)
2138 {
2139 IFilterGraphImpl *This = impl_from_IMediaControl(iface);
2140
2141 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
2142
2143 return S_OK;
2144 }
2145
2146
2147 static const IMediaControlVtbl IMediaControl_VTable =
2148 {
2149 MediaControl_QueryInterface,
2150 MediaControl_AddRef,
2151 MediaControl_Release,
2152 MediaControl_GetTypeInfoCount,
2153 MediaControl_GetTypeInfo,
2154 MediaControl_GetIDsOfNames,
2155 MediaControl_Invoke,
2156 MediaControl_Run,
2157 MediaControl_Pause,
2158 MediaControl_Stop,
2159 MediaControl_GetState,
2160 MediaControl_RenderFile,
2161 MediaControl_AddSourceFilter,
2162 MediaControl_get_FilterCollection,
2163 MediaControl_get_RegFilterCollection,
2164 MediaControl_StopWhenReady
2165 };
2166
2167 static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface)
2168 {
2169 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface);
2170 }
2171
2172 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj)
2173 {
2174 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2175
2176 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2177
2178 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2179 }
2180
2181 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface)
2182 {
2183 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2184
2185 TRACE("(%p/%p)->()\n", This, iface);
2186
2187 return IUnknown_AddRef(This->outer_unk);
2188 }
2189
2190 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface)
2191 {
2192 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2193
2194 TRACE("(%p/%p)->()\n", This, iface);
2195
2196 return IUnknown_Release(This->outer_unk);
2197 }
2198
2199 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg);
2200
2201 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
2202 BOOL allnotimpl = TRUE;
2203 int i;
2204 HRESULT hr, hr_return = S_OK;
2205
2206 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
2207 /* Send a message to all renderers, they are responsible for broadcasting it further */
2208
2209 for(i = 0; i < This->nFilters; i++)
2210 {
2211 IMediaSeeking *seek = NULL;
2212 IBaseFilter* pfilter = This->ppFiltersInGraph[i];
2213 IAMFilterMiscFlags *flags = NULL;
2214 ULONG filterflags;
2215 IBaseFilter_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags);
2216 if (!flags)
2217 continue;
2218 filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
2219 IAMFilterMiscFlags_Release(flags);
2220 if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
2221 continue;
2222
2223 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
2224 if (!seek)
2225 continue;
2226 hr = FoundSeek(This, seek, arg);
2227 IMediaSeeking_Release(seek);
2228 if (hr_return != E_NOTIMPL)
2229 allnotimpl = FALSE;
2230 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return)))
2231 hr_return = hr;
2232 }
2233
2234 if (allnotimpl)
2235 return E_NOTIMPL;
2236 return hr_return;
2237 }
2238
2239 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps)
2240 {
2241 HRESULT hr;
2242 DWORD caps = 0;
2243
2244 hr = IMediaSeeking_GetCapabilities(seek, &caps);
2245 if (FAILED(hr))
2246 return hr;
2247
2248 /* Only add common capabilities everything supports */
2249 *(DWORD*)pcaps &= caps;
2250
2251 return hr;
2252 }
2253
2254 /*** IMediaSeeking methods ***/
2255 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2256 {
2257 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2258 HRESULT hr;
2259
2260 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2261
2262 if (!pCapabilities)
2263 return E_POINTER;
2264
2265 EnterCriticalSection(&This->cs);
2266 *pCapabilities = 0xffffffff;
2267
2268 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2269 LeaveCriticalSection(&This->cs);
2270
2271 return hr;
2272 }
2273
2274 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities)
2275 {
2276 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2277 DWORD originalcaps;
2278 HRESULT hr;
2279
2280 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities);
2281
2282 if (!pCapabilities)
2283 return E_POINTER;
2284
2285 EnterCriticalSection(&This->cs);
2286 originalcaps = *pCapabilities;
2287 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities);
2288 LeaveCriticalSection(&This->cs);
2289
2290 if (FAILED(hr))
2291 return hr;
2292
2293 if (!*pCapabilities)
2294 return E_FAIL;
2295 if (*pCapabilities != originalcaps)
2296 return S_FALSE;
2297 return S_OK;
2298 }
2299
2300 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat)
2301 {
2302 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2303
2304 if (!pFormat)
2305 return E_POINTER;
2306
2307 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2308
2309 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2310 {
2311 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2312 return S_FALSE;
2313 }
2314
2315 return S_OK;
2316 }
2317
2318 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat)
2319 {
2320 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2321
2322 if (!pFormat)
2323 return E_POINTER;
2324
2325 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat);
2326 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
2327
2328 return S_OK;
2329 }
2330
2331 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat)
2332 {
2333 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2334
2335 if (!pFormat)
2336 return E_POINTER;
2337
2338 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2339 memcpy(pFormat, &This->timeformatseek, sizeof(GUID));
2340
2341 return S_OK;
2342 }
2343
2344 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2345 {
2346 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2347
2348 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat);
2349 if (!pFormat)
2350 return E_POINTER;
2351
2352 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID)))
2353 return S_FALSE;
2354
2355 return S_OK;
2356 }
2357
2358 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat)
2359 {
2360 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2361
2362 if (!pFormat)
2363 return E_POINTER;
2364
2365 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat));
2366
2367 if (This->state != State_Stopped)
2368 return VFW_E_WRONG_STATE;
2369
2370 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat))
2371 {
2372 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat));
2373 return E_INVALIDARG;
2374 }
2375
2376 return S_OK;
2377 }
2378
2379 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration)
2380 {
2381 HRESULT hr;
2382 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration;
2383
2384 hr = IMediaSeeking_GetDuration(seek, &duration);
2385 if (FAILED(hr))
2386 return hr;
2387
2388 if (*pdur < duration)
2389 *pdur = duration;
2390 return hr;
2391 }
2392
2393 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration)
2394 {
2395 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2396 HRESULT hr;
2397
2398 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration);
2399
2400 if (!pDuration)
2401 return E_POINTER;
2402
2403 EnterCriticalSection(&This->cs);
2404 *pDuration = 0;
2405 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
2406 LeaveCriticalSection(&This->cs);
2407
2408 TRACE("--->%08x\n", hr);
2409 return hr;
2410 }
2411
2412 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop)
2413 {
2414 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2415 HRESULT hr = S_OK;
2416
2417 TRACE("(%p/%p)->(%p)\n", This, iface, pStop);
2418
2419 if (!pStop)
2420 return E_POINTER;
2421
2422 EnterCriticalSection(&This->cs);
2423 if (This->stop_position < 0)
2424 /* Stop position not set, use duration instead */
2425 hr = IMediaSeeking_GetDuration(iface, pStop);
2426 else
2427 *pStop = This->stop_position;
2428 LeaveCriticalSection(&This->cs);
2429
2430 return hr;
2431 }
2432
2433 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent)
2434 {
2435 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2436 LONGLONG time = 0;
2437
2438 if (!pCurrent)
2439 return E_POINTER;
2440
2441 EnterCriticalSection(&This->cs);
2442 if (This->state == State_Running && This->refClock && This->start_time >= 0)
2443 {
2444 IReferenceClock_GetTime(This->refClock, &time);
2445 if (time)
2446 time -= This->start_time;
2447 }
2448 if (This->pause_time > 0)
2449 time += This->pause_time;
2450 *pCurrent = time;
2451 LeaveCriticalSection(&This->cs);
2452
2453 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000));
2454
2455 return S_OK;
2456 }
2457
2458 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget,
2459 const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat)
2460 {
2461 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2462
2463 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
2464 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
2465
2466 return S_OK;
2467 }
2468
2469 struct pos_args {
2470 LONGLONG* current, *stop;
2471 DWORD curflags, stopflags;
2472 };
2473
2474 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs)
2475 {
2476 struct pos_args *args = (void*)pargs;
2477
2478 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags);
2479 }
2480
2481 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2482 DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags)
2483 {
2484 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2485 HRESULT hr = S_OK;
2486 FILTER_STATE state;
2487 struct pos_args args;
2488
2489 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
2490
2491 EnterCriticalSection(&This->cs);
2492 state = This->state;
2493 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN")));
2494
2495 if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning &&
2496 (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2497 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7);
2498
2499 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning)
2500 This->stop_position = *pStop;
2501 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning)
2502 FIXME("Stop position not handled yet!\n");
2503
2504 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2505 IMediaControl_Pause(&This->IMediaControl_iface);
2506 args.current = pCurrent;
2507 args.stop = pStop;
2508 args.curflags = dwCurrentFlags;
2509 args.stopflags = dwStopFlags;
2510 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args);
2511
2512 if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)
2513 This->pause_time = This->start_time = -1;
2514 if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush))
2515 IMediaControl_Run(&This->IMediaControl_iface);
2516 LeaveCriticalSection(&This->cs);
2517
2518 return hr;
2519 }
2520
2521 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent,
2522 LONGLONG *pStop)
2523 {
2524 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2525 HRESULT hr;
2526
2527 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop);
2528 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent);
2529 if (SUCCEEDED(hr))
2530 hr = IMediaSeeking_GetStopPosition(iface, pStop);
2531
2532 return hr;
2533 }
2534
2535 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest,
2536 LONGLONG *pLatest)
2537 {
2538 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2539
2540 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2541
2542 return S_OK;
2543 }
2544
2545 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate)
2546 {
2547 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2548
2549 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2550
2551 return S_OK;
2552 }
2553
2554 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate)
2555 {
2556 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2557
2558 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2559
2560 return S_OK;
2561 }
2562
2563 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll)
2564 {
2565 IFilterGraphImpl *This = impl_from_IMediaSeeking(iface);
2566
2567 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2568
2569 return S_OK;
2570 }
2571
2572
2573 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2574 {
2575 MediaSeeking_QueryInterface,
2576 MediaSeeking_AddRef,
2577 MediaSeeking_Release,
2578 MediaSeeking_GetCapabilities,
2579 MediaSeeking_CheckCapabilities,
2580 MediaSeeking_IsFormatSupported,
2581 MediaSeeking_QueryPreferredFormat,
2582 MediaSeeking_GetTimeFormat,
2583 MediaSeeking_IsUsingTimeFormat,
2584 MediaSeeking_SetTimeFormat,
2585 MediaSeeking_GetDuration,
2586 MediaSeeking_GetStopPosition,
2587 MediaSeeking_GetCurrentPosition,
2588 MediaSeeking_ConvertTimeFormat,
2589 MediaSeeking_SetPositions,
2590 MediaSeeking_GetPositions,
2591 MediaSeeking_GetAvailable,
2592 MediaSeeking_SetRate,
2593 MediaSeeking_GetRate,
2594 MediaSeeking_GetPreroll
2595 };
2596
2597 static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface)
2598 {
2599 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface);
2600 }
2601
2602 /*** IUnknown methods ***/
2603 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj)
2604 {
2605 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2606
2607 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2608
2609 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2610 }
2611
2612 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface)
2613 {
2614 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2615
2616 TRACE("(%p/%p)->()\n", This, iface);
2617
2618 return IUnknown_AddRef(This->outer_unk);
2619 }
2620
2621 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface)
2622 {
2623 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2624
2625 TRACE("(%p/%p)->()\n", This, iface);
2626
2627 return IUnknown_Release(This->outer_unk);
2628 }
2629
2630 /*** IDispatch methods ***/
2631 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo)
2632 {
2633 FIXME("(%p) stub!\n", iface);
2634 return E_NOTIMPL;
2635 }
2636
2637 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2638 {
2639 FIXME("(%p) stub!\n", iface);
2640 return E_NOTIMPL;
2641 }
2642
2643 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
2644 {
2645 FIXME("(%p) stub!\n", iface);
2646 return E_NOTIMPL;
2647 }
2648
2649 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
2650 {
2651 FIXME("(%p) stub!\n", iface);
2652 return E_NOTIMPL;
2653 }
2654
2655 static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out)
2656 {
2657 GUID time_format;
2658 HRESULT hr;
2659
2660 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2661 if (FAILED(hr))
2662 return hr;
2663 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2664 {
2665 FIXME("Unsupported time format.\n");
2666 return E_NOTIMPL;
2667 }
2668
2669 *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */
2670 return S_OK;
2671 }
2672
2673 static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out)
2674 {
2675 GUID time_format;
2676 HRESULT hr;
2677
2678 hr = MediaSeeking_GetTimeFormat(seek, &time_format);
2679 if (FAILED(hr))
2680 return hr;
2681 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format))
2682 {
2683 FIXME("Unsupported time format.\n");
2684 return E_NOTIMPL;
2685 }
2686
2687 *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */
2688 return S_OK;
2689 }
2690
2691 /*** IMediaPosition methods ***/
2692 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength)
2693 {
2694 LONGLONG duration;
2695 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2696 HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration);
2697 if (FAILED(hr))
2698 return hr;
2699 return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength);
2700 }
2701
2702 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime)
2703 {
2704 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2705 LONGLONG reftime;
2706 HRESULT hr;
2707
2708 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2709 if (FAILED(hr))
2710 return hr;
2711 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime,
2712 AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
2713 }
2714
2715 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime)
2716 {
2717 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2718 LONGLONG pos;
2719 HRESULT hr;
2720
2721 hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos);
2722 if (FAILED(hr))
2723 return hr;
2724 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2725 }
2726
2727 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime)
2728 {
2729 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2730 LONGLONG pos;
2731 HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos);
2732 if (FAILED(hr))
2733 return hr;
2734 return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime);
2735 }
2736
2737 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime)
2738 {
2739 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2740 LONGLONG reftime;
2741 HRESULT hr;
2742
2743 hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime);
2744 if (FAILED(hr))
2745 return hr;
2746 return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning,
2747 &reftime, AM_SEEKING_AbsolutePositioning);
2748 }
2749
2750 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime)
2751 {
2752 FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2753 return E_NOTIMPL;
2754 }
2755
2756 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime)
2757 {
2758 FIXME("(%p)->(%f) stub!\n", iface, llTime);
2759 return E_NOTIMPL;
2760 }
2761
2762 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate)
2763 {
2764 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2765 return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate);
2766 }
2767
2768 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate)
2769 {
2770 IFilterGraphImpl *This = impl_from_IMediaPosition( iface );
2771 return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate);
2772 }
2773
2774 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward)
2775 {
2776 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2777 return E_NOTIMPL;
2778 }
2779
2780 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward)
2781 {
2782 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2783 return E_NOTIMPL;
2784 }
2785
2786
2787 static const IMediaPositionVtbl IMediaPosition_VTable =
2788 {
2789 MediaPosition_QueryInterface,
2790 MediaPosition_AddRef,
2791 MediaPosition_Release,
2792 MediaPosition_GetTypeInfoCount,
2793 MediaPosition_GetTypeInfo,
2794 MediaPosition_GetIDsOfNames,
2795 MediaPosition_Invoke,
2796 MediaPosition_get_Duration,
2797 MediaPosition_put_CurrentPosition,
2798 MediaPosition_get_CurrentPosition,
2799 MediaPosition_get_StopTime,
2800 MediaPosition_put_StopTime,
2801 MediaPosition_get_PrerollTime,
2802 MediaPosition_put_PrerollTime,
2803 MediaPosition_put_Rate,
2804 MediaPosition_get_Rate,
2805 MediaPosition_CanSeekForward,
2806 MediaPosition_CanSeekBackward
2807 };
2808
2809 static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
2810 {
2811 return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface);
2812 }
2813
2814 /*** IUnknown methods ***/
2815 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj)
2816 {
2817 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2818
2819 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2820
2821 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2822 }
2823
2824 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
2825 {
2826 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2827
2828 TRACE("(%p/%p)->()\n", This, iface);
2829
2830 return IUnknown_AddRef(This->outer_unk);
2831 }
2832
2833 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
2834 {
2835 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2836
2837 TRACE("(%p/%p)->()\n", This, iface);
2838
2839 return IUnknown_Release(This->outer_unk);
2840 }
2841
2842 /*** IObjectWithSite methods ***/
2843
2844 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite)
2845 {
2846 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2847
2848 TRACE("(%p/%p)->()\n", This, iface);
2849 if (This->pSite) IUnknown_Release(This->pSite);
2850 This->pSite = pUnkSite;
2851 IUnknown_AddRef(This->pSite);
2852 return S_OK;
2853 }
2854
2855 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite)
2856 {
2857 IFilterGraphImpl *This = impl_from_IObjectWithSite( iface );
2858
2859 TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid));
2860
2861 *ppvSite = NULL;
2862 if (!This->pSite)
2863 return E_FAIL;
2864 else
2865 return IUnknown_QueryInterface(This->pSite, riid, ppvSite);
2866 }
2867
2868 static const IObjectWithSiteVtbl IObjectWithSite_VTable =
2869 {
2870 ObjectWithSite_QueryInterface,
2871 ObjectWithSite_AddRef,
2872 ObjectWithSite_Release,
2873 ObjectWithSite_SetSite,
2874 ObjectWithSite_GetSite,
2875 };
2876
2877 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2878 {
2879 HRESULT hr = E_NOINTERFACE;
2880 int i;
2881 int entry;
2882
2883 /* Check if the interface type is already registered */
2884 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2885 if (riid == pGraph->ItfCacheEntries[entry].riid)
2886 {
2887 if (pGraph->ItfCacheEntries[entry].iface)
2888 {
2889 /* Return the interface if available */
2890 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2891 return S_OK;
2892 }
2893 break;
2894 }
2895
2896 if (entry >= MAX_ITF_CACHE_ENTRIES)
2897 {
2898 FIXME("Not enough space to store interface in the cache\n");
2899 return E_OUTOFMEMORY;
2900 }
2901
2902 /* Find a filter supporting the requested interface */
2903 for (i = 0; i < pGraph->nFilters; i++)
2904 {
2905 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2906 if (hr == S_OK)
2907 {
2908 pGraph->ItfCacheEntries[entry].riid = riid;
2909 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2910 pGraph->ItfCacheEntries[entry].iface = *ppvObj;
2911 if (entry >= pGraph->nItfCacheEntries)
2912 pGraph->nItfCacheEntries++;
2913 return S_OK;
2914 }
2915 if (hr != E_NOINTERFACE)
2916 return hr;
2917 }
2918
2919 return hr;
2920 }
2921
2922 static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface)
2923 {
2924 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface);
2925 }
2926
2927 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj)
2928 {
2929 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2930
2931 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2932
2933 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
2934 }
2935
2936 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface)
2937 {
2938 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2939
2940 TRACE("(%p/%p)->()\n", This, iface);
2941
2942 return IUnknown_AddRef(This->outer_unk);
2943 }
2944
2945 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface)
2946 {
2947 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2948
2949 TRACE("(%p/%p)->()\n", This, iface);
2950
2951 return IUnknown_Release(This->outer_unk);
2952 }
2953
2954 /*** IDispatch methods ***/
2955 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo)
2956 {
2957 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2958 IBasicAudio* pBasicAudio;
2959 HRESULT hr;
2960
2961 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2962
2963 EnterCriticalSection(&This->cs);
2964
2965 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2966
2967 if (hr == S_OK)
2968 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2969
2970 LeaveCriticalSection(&This->cs);
2971
2972 return hr;
2973 }
2974
2975 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid,
2976 ITypeInfo **ppTInfo)
2977 {
2978 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
2979 IBasicAudio* pBasicAudio;
2980 HRESULT hr;
2981
2982 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2983
2984 EnterCriticalSection(&This->cs);
2985
2986 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2987
2988 if (hr == S_OK)
2989 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2990
2991 LeaveCriticalSection(&This->cs);
2992
2993 return hr;
2994 }
2995
2996 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames,
2997 UINT cNames, LCID lcid, DISPID *rgDispId)
2998 {
2999 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3000 IBasicAudio* pBasicAudio;
3001 HRESULT hr;
3002
3003 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3004
3005 EnterCriticalSection(&This->cs);
3006
3007 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3008
3009 if (hr == S_OK)
3010 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
3011
3012 LeaveCriticalSection(&This->cs);
3013
3014 return hr;
3015 }
3016
3017 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid,
3018 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3019 UINT *puArgErr)
3020 {
3021 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3022 IBasicAudio* pBasicAudio;
3023 HRESULT hr;
3024
3025 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3026
3027 EnterCriticalSection(&This->cs);
3028
3029 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3030
3031 if (hr == S_OK)
3032 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3033
3034 LeaveCriticalSection(&This->cs);
3035
3036 return hr;
3037 }
3038
3039 /*** IBasicAudio methods ***/
3040 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume)
3041 {
3042 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3043 IBasicAudio* pBasicAudio;
3044 HRESULT hr;
3045
3046 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume);
3047
3048 EnterCriticalSection(&This->cs);
3049
3050 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3051
3052 if (hr == S_OK)
3053 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
3054
3055 LeaveCriticalSection(&This->cs);
3056
3057 return hr;
3058 }
3059
3060 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume)
3061 {
3062 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3063 IBasicAudio* pBasicAudio;
3064 HRESULT hr;
3065
3066 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
3067
3068 EnterCriticalSection(&This->cs);
3069
3070 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3071
3072 if (hr == S_OK)
3073 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
3074
3075 LeaveCriticalSection(&This->cs);
3076
3077 return hr;
3078 }
3079
3080 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance)
3081 {
3082 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3083 IBasicAudio* pBasicAudio;
3084 HRESULT hr;
3085
3086 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance);
3087
3088 EnterCriticalSection(&This->cs);
3089
3090 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3091
3092 if (hr == S_OK)
3093 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
3094
3095 LeaveCriticalSection(&This->cs);
3096
3097 return hr;
3098 }
3099
3100 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance)
3101 {
3102 IFilterGraphImpl *This = impl_from_IBasicAudio(iface);
3103 IBasicAudio* pBasicAudio;
3104 HRESULT hr;
3105
3106 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
3107
3108 EnterCriticalSection(&This->cs);
3109
3110 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
3111
3112 if (hr == S_OK)
3113 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
3114
3115 LeaveCriticalSection(&This->cs);
3116
3117 return hr;
3118 }
3119
3120 static const IBasicAudioVtbl IBasicAudio_VTable =
3121 {
3122 BasicAudio_QueryInterface,
3123 BasicAudio_AddRef,
3124 BasicAudio_Release,
3125 BasicAudio_GetTypeInfoCount,
3126 BasicAudio_GetTypeInfo,
3127 BasicAudio_GetIDsOfNames,
3128 BasicAudio_Invoke,
3129 BasicAudio_put_Volume,
3130 BasicAudio_get_Volume,
3131 BasicAudio_put_Balance,
3132 BasicAudio_get_Balance
3133 };
3134
3135 static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface)
3136 {
3137 return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface);
3138 }
3139
3140 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj)
3141 {
3142 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3143
3144 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3145
3146 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3147 }
3148
3149 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface)
3150 {
3151 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3152
3153 TRACE("(%p/%p)->()\n", This, iface);
3154
3155 return IUnknown_AddRef(This->outer_unk);
3156 }
3157
3158 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface)
3159 {
3160 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3161
3162 TRACE("(%p/%p)->()\n", This, iface);
3163
3164 return IUnknown_Release(This->outer_unk);
3165 }
3166
3167 /*** IDispatch methods ***/
3168 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo)
3169 {
3170 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3171 IBasicVideo *pBasicVideo;
3172 HRESULT hr;
3173
3174 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3175
3176 EnterCriticalSection(&This->cs);
3177
3178 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3179
3180 if (hr == S_OK)
3181 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
3182
3183 LeaveCriticalSection(&This->cs);
3184
3185 return hr;
3186 }
3187
3188 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid,
3189 ITypeInfo **ppTInfo)
3190 {
3191 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3192 IBasicVideo *pBasicVideo;
3193 HRESULT hr;
3194
3195 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3196
3197 EnterCriticalSection(&This->cs);
3198
3199 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3200
3201 if (hr == S_OK)
3202 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
3203
3204 LeaveCriticalSection(&This->cs);
3205
3206 return hr;
3207 }
3208
3209 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid,
3210 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3211 {
3212 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3213 IBasicVideo *pBasicVideo;
3214 HRESULT hr;
3215
3216 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3217
3218 EnterCriticalSection(&This->cs);
3219
3220 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3221
3222 if (hr == S_OK)
3223 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
3224
3225 LeaveCriticalSection(&This->cs);
3226
3227 return hr;
3228 }
3229
3230 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid,
3231 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
3232 UINT *puArgErr)
3233 {
3234 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3235 IBasicVideo *pBasicVideo;
3236 HRESULT hr;
3237
3238 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3239
3240 EnterCriticalSection(&This->cs);
3241
3242 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3243
3244 if (hr == S_OK)
3245 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3246
3247 LeaveCriticalSection(&This->cs);
3248
3249 return hr;
3250 }
3251
3252 /*** IBasicVideo methods ***/
3253 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame)
3254 {
3255 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3256 IBasicVideo *pBasicVideo;
3257 HRESULT hr;
3258
3259 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
3260
3261 EnterCriticalSection(&This->cs);
3262
3263 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3264
3265 if (hr == S_OK)
3266 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
3267
3268 LeaveCriticalSection(&This->cs);
3269
3270 return hr;
3271 }
3272
3273 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate)
3274 {
3275 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3276 IBasicVideo *pBasicVideo;
3277 HRESULT hr;
3278
3279 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
3280
3281 EnterCriticalSection(&This->cs);
3282
3283 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3284
3285 if (hr == S_OK)
3286 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
3287
3288 LeaveCriticalSection(&This->cs);
3289
3290 return hr;
3291 }
3292
3293 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate)
3294 {
3295 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3296 IBasicVideo *pBasicVideo;
3297 HRESULT hr;
3298
3299 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
3300
3301 EnterCriticalSection(&This->cs);
3302
3303 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3304
3305 if (hr == S_OK)
3306 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
3307
3308 LeaveCriticalSection(&This->cs);
3309
3310 return hr;
3311 }
3312
3313 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth)
3314 {
3315 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3316 IBasicVideo *pBasicVideo;
3317 HRESULT hr;
3318
3319 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
3320
3321 EnterCriticalSection(&This->cs);
3322
3323 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3324
3325 if (hr == S_OK)
3326 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
3327
3328 LeaveCriticalSection(&This->cs);
3329
3330 return hr;
3331 }
3332
3333 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight)
3334 {
3335 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3336 IBasicVideo *pBasicVideo;
3337 HRESULT hr;
3338
3339 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
3340
3341 EnterCriticalSection(&This->cs);
3342
3343 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3344
3345 if (hr == S_OK)
3346 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
3347
3348 LeaveCriticalSection(&This->cs);
3349
3350 return hr;
3351 }
3352
3353 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft)
3354 {
3355 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3356 IBasicVideo *pBasicVideo;
3357 HRESULT hr;
3358
3359 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
3360
3361 EnterCriticalSection(&This->cs);
3362
3363 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3364
3365 if (hr == S_OK)
3366 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
3367
3368 LeaveCriticalSection(&This->cs);
3369
3370 return hr;
3371 }
3372
3373 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft)
3374 {
3375 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3376 IBasicVideo *pBasicVideo;
3377 HRESULT hr;
3378
3379 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
3380
3381 EnterCriticalSection(&This->cs);
3382
3383 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3384
3385 if (hr == S_OK)
3386 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
3387
3388 LeaveCriticalSection(&This->cs);
3389
3390 return hr;
3391 }
3392
3393 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth)
3394 {
3395 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3396 IBasicVideo *pBasicVideo;
3397 HRESULT hr;
3398
3399 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
3400
3401 EnterCriticalSection(&This->cs);
3402
3403 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3404
3405 if (hr == S_OK)
3406 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
3407
3408 LeaveCriticalSection(&This->cs);
3409
3410 return hr;
3411 }
3412
3413 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth)
3414 {
3415 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3416 IBasicVideo *pBasicVideo;
3417 HRESULT hr;
3418
3419 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
3420
3421 EnterCriticalSection(&This->cs);
3422
3423 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3424
3425 if (hr == S_OK)
3426 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
3427
3428 LeaveCriticalSection(&This->cs);
3429
3430 return hr;
3431 }
3432
3433 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop)
3434 {
3435 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3436 IBasicVideo *pBasicVideo;
3437 HRESULT hr;
3438
3439 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
3440
3441 EnterCriticalSection(&This->cs);
3442
3443 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3444
3445 if (hr == S_OK)
3446 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
3447
3448 LeaveCriticalSection(&This->cs);
3449
3450 return hr;
3451 }
3452
3453 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop)
3454 {
3455 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3456 IBasicVideo *pBasicVideo;
3457 HRESULT hr;
3458
3459 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
3460
3461 EnterCriticalSection(&This->cs);
3462
3463 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3464
3465 if (hr == S_OK)
3466 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
3467
3468 LeaveCriticalSection(&This->cs);
3469
3470 return hr;
3471 }
3472
3473 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight)
3474 {
3475 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3476 IBasicVideo *pBasicVideo;
3477 HRESULT hr;
3478
3479 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
3480
3481 EnterCriticalSection(&This->cs);
3482
3483 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3484
3485 if (hr == S_OK)
3486 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
3487
3488 LeaveCriticalSection(&This->cs);
3489
3490 return hr;
3491 }
3492
3493 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight)
3494 {
3495 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3496 IBasicVideo *pBasicVideo;
3497 HRESULT hr;
3498
3499 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
3500
3501 EnterCriticalSection(&This->cs);
3502
3503 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3504
3505 if (hr == S_OK)
3506 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
3507
3508 LeaveCriticalSection(&This->cs);
3509
3510 return hr;
3511 }
3512
3513 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft)
3514 {
3515 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3516 IBasicVideo *pBasicVideo;
3517 HRESULT hr;
3518
3519 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
3520
3521 EnterCriticalSection(&This->cs);
3522
3523 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3524
3525 if (hr == S_OK)
3526 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
3527
3528 LeaveCriticalSection(&This->cs);
3529
3530 return hr;
3531 }
3532
3533 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft)
3534 {
3535 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3536 IBasicVideo *pBasicVideo;
3537 HRESULT hr;
3538
3539 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
3540
3541 EnterCriticalSection(&This->cs);
3542
3543 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3544
3545 if (hr == S_OK)
3546 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
3547
3548 LeaveCriticalSection(&This->cs);
3549
3550 return hr;
3551 }
3552
3553 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth)
3554 {
3555 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3556 IBasicVideo *pBasicVideo;
3557 HRESULT hr;
3558
3559 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
3560
3561 EnterCriticalSection(&This->cs);
3562
3563 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3564
3565 if (hr == S_OK)
3566 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
3567
3568 LeaveCriticalSection(&This->cs);
3569
3570 return hr;
3571 }
3572
3573 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth)
3574 {
3575 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3576 IBasicVideo *pBasicVideo;
3577 HRESULT hr;
3578
3579 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
3580
3581 EnterCriticalSection(&This->cs);
3582
3583 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3584
3585 if (hr == S_OK)
3586 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
3587
3588 LeaveCriticalSection(&This->cs);
3589
3590 return hr;
3591 }
3592
3593 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop)
3594 {
3595 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3596 IBasicVideo *pBasicVideo;
3597 HRESULT hr;
3598
3599 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
3600
3601 EnterCriticalSection(&This->cs);
3602
3603 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3604
3605 if (hr == S_OK)
3606 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
3607
3608 LeaveCriticalSection(&This->cs);
3609
3610 return hr;
3611 }
3612
3613 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop)
3614 {
3615 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3616 IBasicVideo *pBasicVideo;
3617 HRESULT hr;
3618
3619 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
3620
3621 EnterCriticalSection(&This->cs);
3622
3623 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3624
3625 if (hr == S_OK)
3626 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
3627
3628 LeaveCriticalSection(&This->cs);
3629
3630 return hr;
3631 }
3632
3633 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight)
3634 {
3635 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3636 IBasicVideo *pBasicVideo;
3637 HRESULT hr;
3638
3639 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
3640
3641 EnterCriticalSection(&This->cs);
3642
3643 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3644
3645 if (hr == S_OK)
3646 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
3647
3648 LeaveCriticalSection(&This->cs);
3649
3650 return hr;
3651 }
3652
3653 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface,
3654 LONG *pDestinationHeight)
3655 {
3656 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3657 IBasicVideo *pBasicVideo;
3658 HRESULT hr;
3659
3660 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
3661
3662 EnterCriticalSection(&This->cs);
3663
3664 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3665
3666 if (hr == S_OK)
3667 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
3668
3669 LeaveCriticalSection(&This->cs);
3670
3671 return hr;
3672 }
3673
3674 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3675 LONG Width, LONG Height)
3676 {
3677 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3678 IBasicVideo *pBasicVideo;
3679 HRESULT hr;
3680
3681 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3682
3683 EnterCriticalSection(&This->cs);
3684
3685 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3686
3687 if (hr == S_OK)
3688 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3689
3690 LeaveCriticalSection(&This->cs);
3691
3692 return hr;
3693 }
3694
3695 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop,
3696 LONG *pWidth, LONG *pHeight)
3697 {
3698 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3699 IBasicVideo *pBasicVideo;
3700 HRESULT hr;
3701
3702 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3703
3704 EnterCriticalSection(&This->cs);
3705
3706 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3707
3708 if (hr == S_OK)
3709 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3710
3711 LeaveCriticalSection(&This->cs);
3712
3713 return hr;
3714 }
3715
3716 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface)
3717 {
3718 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3719 IBasicVideo *pBasicVideo;
3720 HRESULT hr;
3721
3722 TRACE("(%p/%p)->()\n", This, iface);
3723
3724 EnterCriticalSection(&This->cs);
3725
3726 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3727
3728 if (hr == S_OK)
3729 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3730
3731 LeaveCriticalSection(&This->cs);
3732
3733 return hr;
3734 }
3735
3736 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top,
3737 LONG Width, LONG Height)
3738 {
3739 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3740 IBasicVideo *pBasicVideo;
3741 HRESULT hr;
3742
3743 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
3744
3745 EnterCriticalSection(&This->cs);
3746
3747 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3748
3749 if (hr == S_OK)
3750 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3751
3752 LeaveCriticalSection(&This->cs);
3753
3754 return hr;
3755 }
3756
3757 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft,
3758 LONG *pTop, LONG *pWidth, LONG *pHeight)
3759 {
3760 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3761 IBasicVideo *pBasicVideo;
3762 HRESULT hr;
3763
3764 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3765
3766 EnterCriticalSection(&This->cs);
3767
3768 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3769
3770 if (hr == S_OK)
3771 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3772
3773 LeaveCriticalSection(&This->cs);
3774
3775 return hr;
3776 }
3777
3778 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface)
3779 {
3780 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3781 IBasicVideo *pBasicVideo;
3782 HRESULT hr;
3783
3784 TRACE("(%p/%p)->()\n", This, iface);
3785
3786 EnterCriticalSection(&This->cs);
3787
3788 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3789
3790 if (hr == S_OK)
3791 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3792
3793 LeaveCriticalSection(&This->cs);
3794
3795 return hr;
3796 }
3797
3798 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight)
3799 {
3800 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3801 IBasicVideo *pBasicVideo;
3802 HRESULT hr;
3803
3804 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3805
3806 EnterCriticalSection(&This->cs);
3807
3808 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3809
3810 if (hr == S_OK)
3811 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3812
3813 LeaveCriticalSection(&This->cs);
3814
3815 return hr;
3816 }
3817
3818 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex,
3819 LONG Entries, LONG *pRetrieved, LONG *pPalette)
3820 {
3821 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3822 IBasicVideo *pBasicVideo;
3823 HRESULT hr;
3824
3825 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3826
3827 EnterCriticalSection(&This->cs);
3828
3829 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3830
3831 if (hr == S_OK)
3832 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3833
3834 LeaveCriticalSection(&This->cs);
3835
3836 return hr;
3837 }
3838
3839 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize,
3840 LONG *pDIBImage)
3841 {
3842 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3843 IBasicVideo *pBasicVideo;
3844 HRESULT hr;
3845
3846 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3847
3848 EnterCriticalSection(&This->cs);
3849
3850 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3851
3852 if (hr == S_OK)
3853 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3854
3855 LeaveCriticalSection(&This->cs);
3856
3857 return hr;
3858 }
3859
3860 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface)
3861 {
3862 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3863 IBasicVideo *pBasicVideo;
3864 HRESULT hr;
3865
3866 TRACE("(%p/%p)->()\n", This, iface);
3867
3868 EnterCriticalSection(&This->cs);
3869
3870 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3871
3872 if (hr == S_OK)
3873 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3874
3875 LeaveCriticalSection(&This->cs);
3876
3877 return hr;
3878 }
3879
3880 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface)
3881 {
3882 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3883 IBasicVideo *pBasicVideo;
3884 HRESULT hr;
3885
3886 TRACE("(%p/%p)->()\n", This, iface);
3887
3888 EnterCriticalSection(&This->cs);
3889
3890 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3891
3892 if (hr == S_OK)
3893 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3894
3895 LeaveCriticalSection(&This->cs);
3896
3897 return hr;
3898 }
3899
3900 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX,
3901 LONG *plAspectY)
3902 {
3903 IFilterGraphImpl *This = impl_from_IBasicVideo2(iface);
3904 IBasicVideo2 *pBasicVideo2;
3905 HRESULT hr;
3906
3907 TRACE("(%p/%p)->()\n", This, iface);
3908
3909 EnterCriticalSection(&This->cs);
3910
3911 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2);
3912
3913 if (hr == S_OK)
3914 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY);
3915
3916 LeaveCriticalSection(&This->cs);
3917
3918 return hr;
3919 }
3920
3921 static const IBasicVideo2Vtbl IBasicVideo_VTable =
3922 {
3923 BasicVideo_QueryInterface,
3924 BasicVideo_AddRef,
3925 BasicVideo_Release,
3926 BasicVideo_GetTypeInfoCount,
3927 BasicVideo_GetTypeInfo,
3928 BasicVideo_GetIDsOfNames,
3929 BasicVideo_Invoke,
3930 BasicVideo_get_AvgTimePerFrame,
3931 BasicVideo_get_BitRate,
3932 BasicVideo_get_BitErrorRate,
3933 BasicVideo_get_VideoWidth,
3934 BasicVideo_get_VideoHeight,
3935 BasicVideo_put_SourceLeft,
3936 BasicVideo_get_SourceLeft,
3937 BasicVideo_put_SourceWidth,
3938 BasicVideo_get_SourceWidth,
3939 BasicVideo_put_SourceTop,
3940 BasicVideo_get_SourceTop,
3941 BasicVideo_put_SourceHeight,
3942 BasicVideo_get_SourceHeight,
3943 BasicVideo_put_DestinationLeft,
3944 BasicVideo_get_DestinationLeft,
3945 BasicVideo_put_DestinationWidth,
3946 BasicVideo_get_DestinationWidth,
3947 BasicVideo_put_DestinationTop,
3948 BasicVideo_get_DestinationTop,
3949 BasicVideo_put_DestinationHeight,
3950 BasicVideo_get_DestinationHeight,
3951 BasicVideo_SetSourcePosition,
3952 BasicVideo_GetSourcePosition,
3953 BasicVideo_SetDefaultSourcePosition,
3954 BasicVideo_SetDestinationPosition,
3955 BasicVideo_GetDestinationPosition,
3956 BasicVideo_SetDefaultDestinationPosition,
3957 BasicVideo_GetVideoSize,
3958 BasicVideo_GetVideoPaletteEntries,
3959 BasicVideo_GetCurrentImage,
3960 BasicVideo_IsUsingDefaultSource,
3961 BasicVideo_IsUsingDefaultDestination,
3962 BasicVideo2_GetPreferredAspectRatio
3963 };
3964
3965 static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface)
3966 {
3967 return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface);
3968 }
3969
3970 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj)
3971 {
3972 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3973
3974 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3975
3976 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
3977 }
3978
3979 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface)
3980 {
3981 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3982
3983 TRACE("(%p/%p)->()\n", This, iface);
3984
3985 return IUnknown_AddRef(This->outer_unk);
3986 }
3987
3988 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface)
3989 {
3990 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
3991
3992 TRACE("(%p/%p)->()\n", This, iface);
3993
3994 return IUnknown_Release(This->outer_unk);
3995 }
3996
3997 /*** IDispatch methods ***/
3998 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo)
3999 {
4000 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4001 IVideoWindow *pVideoWindow;
4002 HRESULT hr;
4003
4004 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
4005
4006 EnterCriticalSection(&This->cs);
4007
4008 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4009
4010 if (hr == S_OK)
4011 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
4012
4013 LeaveCriticalSection(&This->cs);
4014
4015 return hr;
4016 }
4017
4018 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid,
4019 ITypeInfo **ppTInfo)
4020 {
4021 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4022 IVideoWindow *pVideoWindow;
4023 HRESULT hr;
4024
4025 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
4026
4027 EnterCriticalSection(&This->cs);
4028
4029 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4030
4031 if (hr == S_OK)
4032 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
4033
4034 LeaveCriticalSection(&This->cs);
4035
4036 return hr;
4037 }
4038
4039 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid,
4040 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4041 {
4042 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4043 IVideoWindow *pVideoWindow;
4044 HRESULT hr;
4045
4046 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4047
4048 EnterCriticalSection(&This->cs);
4049
4050 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4051
4052 if (hr == S_OK)
4053 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
4054
4055 LeaveCriticalSection(&This->cs);
4056
4057 return hr;
4058 }
4059
4060 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid,
4061 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4062 UINT*puArgErr)
4063 {
4064 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4065 IVideoWindow *pVideoWindow;
4066 HRESULT hr;
4067
4068 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4069
4070 EnterCriticalSection(&This->cs);
4071
4072 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4073
4074 if (hr == S_OK)
4075 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4076
4077 LeaveCriticalSection(&This->cs);
4078
4079 return hr;
4080 }
4081
4082
4083 /*** IVideoWindow methods ***/
4084 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption)
4085 {
4086 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4087 IVideoWindow *pVideoWindow;
4088 HRESULT hr;
4089
4090 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
4091
4092 EnterCriticalSection(&This->cs);
4093
4094 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4095
4096 if (hr == S_OK)
4097 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
4098
4099 LeaveCriticalSection(&This->cs);
4100
4101 return hr;
4102 }
4103
4104 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption)
4105 {
4106 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4107 IVideoWindow *pVideoWindow;
4108 HRESULT hr;
4109
4110 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
4111
4112 EnterCriticalSection(&This->cs);
4113
4114 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4115
4116 if (hr == S_OK)
4117 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
4118
4119 LeaveCriticalSection(&This->cs);
4120
4121 return hr;
4122 }
4123
4124 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle)
4125 {
4126 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4127 IVideoWindow *pVideoWindow;
4128 HRESULT hr;
4129
4130 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle);
4131
4132 EnterCriticalSection(&This->cs);
4133
4134 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4135
4136 if (hr == S_OK)
4137 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
4138
4139 LeaveCriticalSection(&This->cs);
4140
4141 return hr;
4142 }
4143
4144 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle)
4145 {
4146 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4147 IVideoWindow *pVideoWindow;
4148 HRESULT hr;
4149
4150 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
4151
4152 EnterCriticalSection(&This->cs);
4153
4154 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4155
4156 if (hr == S_OK)
4157 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
4158
4159 LeaveCriticalSection(&This->cs);
4160
4161 return hr;
4162 }
4163
4164 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx)
4165 {
4166 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4167 IVideoWindow *pVideoWindow;
4168 HRESULT hr;
4169
4170 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
4171
4172 EnterCriticalSection(&This->cs);
4173
4174 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4175
4176 if (hr == S_OK)
4177 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
4178
4179 LeaveCriticalSection(&This->cs);
4180
4181 return hr;
4182 }
4183
4184 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx)
4185 {
4186 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4187 IVideoWindow *pVideoWindow;
4188 HRESULT hr;
4189
4190 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
4191
4192 EnterCriticalSection(&This->cs);
4193
4194 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4195
4196 if (hr == S_OK)
4197 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
4198
4199 LeaveCriticalSection(&This->cs);
4200
4201 return hr;
4202 }
4203
4204 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
4205 {
4206 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4207 IVideoWindow *pVideoWindow;
4208 HRESULT hr;
4209
4210 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
4211
4212 EnterCriticalSection(&This->cs);
4213
4214 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4215
4216 if (hr == S_OK)
4217 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
4218
4219 LeaveCriticalSection(&This->cs);
4220
4221 return hr;
4222 }
4223
4224 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
4225 {
4226 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4227 IVideoWindow *pVideoWindow;
4228 HRESULT hr;
4229
4230 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
4231
4232 EnterCriticalSection(&This->cs);
4233
4234 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4235
4236 if (hr == S_OK)
4237 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
4238
4239 LeaveCriticalSection(&This->cs);
4240
4241 return hr;
4242 }
4243
4244 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState)
4245 {
4246 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4247 IVideoWindow *pVideoWindow;
4248 HRESULT hr;
4249
4250 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
4251
4252 EnterCriticalSection(&This->cs);
4253
4254 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4255
4256 if (hr == S_OK)
4257 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
4258
4259 LeaveCriticalSection(&This->cs);
4260
4261 return hr;
4262 }
4263
4264 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState)
4265 {
4266 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4267 IVideoWindow *pVideoWindow;
4268 HRESULT hr;
4269
4270 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
4271
4272 EnterCriticalSection(&This->cs);
4273
4274 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4275
4276 if (hr == S_OK)
4277 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
4278
4279 LeaveCriticalSection(&This->cs);
4280
4281 return hr;
4282 }
4283
4284 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
4285 {
4286 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4287 IVideoWindow *pVideoWindow;
4288 HRESULT hr;
4289
4290 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette);
4291
4292 EnterCriticalSection(&This->cs);
4293
4294 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4295
4296 if (hr == S_OK)
4297 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
4298
4299 LeaveCriticalSection(&This->cs);
4300
4301 return hr;
4302 }
4303
4304 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
4305 LONG *pBackgroundPalette)
4306 {
4307 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4308 IVideoWindow *pVideoWindow;
4309 HRESULT hr;
4310
4311 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
4312
4313 EnterCriticalSection(&This->cs);
4314
4315 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4316
4317 if (hr == S_OK)
4318 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
4319
4320 LeaveCriticalSection(&This->cs);
4321
4322 return hr;
4323 }
4324
4325 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible)
4326 {
4327 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4328 IVideoWindow *pVideoWindow;
4329 HRESULT hr;
4330
4331 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
4332
4333 EnterCriticalSection(&This->cs);
4334
4335 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4336
4337 if (hr == S_OK)
4338 hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
4339
4340 LeaveCriticalSection(&This->cs);
4341
4342 return hr;
4343 }
4344
4345 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible)
4346 {
4347 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4348 IVideoWindow *pVideoWindow;
4349 HRESULT hr;
4350
4351 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
4352
4353 EnterCriticalSection(&This->cs);
4354
4355 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4356
4357 if (hr == S_OK)
4358 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
4359
4360 LeaveCriticalSection(&This->cs);
4361
4362 return hr;
4363 }
4364
4365 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left)
4366 {
4367 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4368 IVideoWindow *pVideoWindow;
4369 HRESULT hr;
4370
4371 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
4372
4373 EnterCriticalSection(&This->cs);
4374
4375 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4376
4377 if (hr == S_OK)
4378 hr = IVideoWindow_put_Left(pVideoWindow, Left);
4379
4380 LeaveCriticalSection(&This->cs);
4381
4382 return hr;
4383 }
4384
4385 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft)
4386 {
4387 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4388 IVideoWindow *pVideoWindow;
4389 HRESULT hr;
4390
4391 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
4392
4393 EnterCriticalSection(&This->cs);
4394
4395 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4396
4397 if (hr == S_OK)
4398 hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
4399
4400 LeaveCriticalSection(&This->cs);
4401
4402 return hr;
4403 }
4404
4405 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width)
4406 {
4407 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4408 IVideoWindow *pVideoWindow;
4409 HRESULT hr;
4410
4411 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
4412
4413 EnterCriticalSection(&This->cs);
4414
4415 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4416
4417 if (hr == S_OK)
4418 hr = IVideoWindow_put_Width(pVideoWindow, Width);
4419
4420 LeaveCriticalSection(&This->cs);
4421
4422 return hr;
4423 }
4424
4425 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth)
4426 {
4427 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4428 IVideoWindow *pVideoWindow;
4429 HRESULT hr;
4430
4431 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
4432
4433 EnterCriticalSection(&This->cs);
4434
4435 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4436
4437 if (hr == S_OK)
4438 hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
4439
4440 LeaveCriticalSection(&This->cs);
4441
4442 return hr;
4443 }
4444
4445 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top)
4446 {
4447 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4448 IVideoWindow *pVideoWindow;
4449 HRESULT hr;
4450
4451 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
4452
4453 EnterCriticalSection(&This->cs);
4454
4455 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4456
4457 if (hr == S_OK)
4458 hr = IVideoWindow_put_Top(pVideoWindow, Top);
4459
4460 LeaveCriticalSection(&This->cs);
4461
4462 return hr;
4463 }
4464
4465 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop)
4466 {
4467 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4468 IVideoWindow *pVideoWindow;
4469 HRESULT hr;
4470
4471 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
4472
4473 EnterCriticalSection(&This->cs);
4474
4475 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4476
4477 if (hr == S_OK)
4478 hr = IVideoWindow_get_Top(pVideoWindow, pTop);
4479
4480 LeaveCriticalSection(&This->cs);
4481
4482 return hr;
4483 }
4484
4485 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height)
4486 {
4487 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4488 IVideoWindow *pVideoWindow;
4489 HRESULT hr;
4490
4491 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
4492
4493 EnterCriticalSection(&This->cs);
4494
4495 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4496
4497 if (hr == S_OK)
4498 hr = IVideoWindow_put_Height(pVideoWindow, Height);
4499
4500 LeaveCriticalSection(&This->cs);
4501
4502 return hr;
4503 }
4504
4505 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight)
4506 {
4507 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4508 IVideoWindow *pVideoWindow;
4509 HRESULT hr;
4510
4511 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
4512
4513 EnterCriticalSection(&This->cs);
4514
4515 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4516
4517 if (hr == S_OK)
4518 hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
4519
4520 LeaveCriticalSection(&This->cs);
4521
4522 return hr;
4523 }
4524
4525 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner)
4526 {
4527 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4528 IVideoWindow *pVideoWindow;
4529 HRESULT hr;
4530
4531 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
4532
4533 EnterCriticalSection(&This->cs);
4534
4535 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4536
4537 if (hr == S_OK)
4538 hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
4539
4540 LeaveCriticalSection(&This->cs);
4541
4542 return hr;
4543 }
4544
4545 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner)
4546 {
4547 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4548 IVideoWindow *pVideoWindow;
4549 HRESULT hr;
4550
4551 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
4552
4553 EnterCriticalSection(&This->cs);
4554
4555 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4556
4557 if (hr == S_OK)
4558 hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
4559
4560 LeaveCriticalSection(&This->cs);
4561
4562 return hr;
4563 }
4564
4565 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
4566 {
4567 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4568 IVideoWindow *pVideoWindow;
4569 HRESULT hr;
4570
4571 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
4572
4573 EnterCriticalSection(&This->cs);
4574
4575 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4576
4577 if (hr == S_OK)
4578 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
4579
4580 LeaveCriticalSection(&This->cs);
4581
4582 return hr;
4583 }
4584
4585 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
4586 {
4587 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4588 IVideoWindow *pVideoWindow;
4589 HRESULT hr;
4590
4591 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
4592
4593 EnterCriticalSection(&This->cs);
4594
4595 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4596
4597 if (hr == S_OK)
4598 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
4599
4600 LeaveCriticalSection(&This->cs);
4601
4602 return hr;
4603 }
4604
4605 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color)
4606 {
4607 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4608 IVideoWindow *pVideoWindow;
4609 HRESULT hr;
4610
4611 TRACE("(%p/%p)->(%p)\n", This, iface, Color);
4612
4613 EnterCriticalSection(&This->cs);
4614
4615 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4616
4617 if (hr == S_OK)
4618 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
4619
4620 LeaveCriticalSection(&This->cs);
4621
4622 return hr;
4623 }
4624
4625 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color)
4626 {
4627 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4628 IVideoWindow *pVideoWindow;
4629 HRESULT hr;
4630
4631 TRACE("(%p/%p)->(%d)\n", This, iface, Color);
4632
4633 EnterCriticalSection(&This->cs);
4634
4635 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4636
4637 if (hr == S_OK)
4638 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
4639
4640 LeaveCriticalSection(&This->cs);
4641
4642 return hr;
4643 }
4644
4645 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
4646 {
4647 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4648 IVideoWindow *pVideoWindow;
4649 HRESULT hr;
4650
4651 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
4652
4653 EnterCriticalSection(&This->cs);
4654
4655 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4656
4657 if (hr == S_OK)
4658 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
4659
4660 LeaveCriticalSection(&This->cs);
4661
4662 return hr;
4663 }
4664
4665 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode)
4666 {
4667 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4668 IVideoWindow *pVideoWindow;
4669 HRESULT hr;
4670
4671 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode);
4672
4673 EnterCriticalSection(&This->cs);
4674
4675 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4676
4677 if (hr == S_OK)
4678 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
4679
4680 LeaveCriticalSection(&This->cs);
4681
4682 return hr;
4683 }
4684
4685 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus)
4686 {
4687 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4688 IVideoWindow *pVideoWindow;
4689 HRESULT hr;
4690
4691 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
4692
4693 EnterCriticalSection(&This->cs);
4694
4695 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4696
4697 if (hr == S_OK)
4698 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4699
4700 LeaveCriticalSection(&This->cs);
4701
4702 return hr;
4703 }
4704
4705 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg,
4706 LONG_PTR wParam, LONG_PTR lParam)
4707 {
4708 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4709 IVideoWindow *pVideoWindow;
4710 HRESULT hr;
4711
4712 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
4713
4714 EnterCriticalSection(&This->cs);
4715
4716 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4717
4718 if (hr == S_OK)
4719 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4720
4721 LeaveCriticalSection(&This->cs);
4722
4723 return hr;
4724 }
4725
4726 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top,
4727 LONG Width, LONG Height)
4728 {
4729 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4730 IVideoWindow *pVideoWindow;
4731 HRESULT hr;
4732
4733 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
4734
4735 EnterCriticalSection(&This->cs);
4736
4737 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4738
4739 if (hr == S_OK)
4740 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4741
4742 LeaveCriticalSection(&This->cs);
4743
4744 return hr;
4745 }
4746
4747 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4748 LONG *pWidth, LONG *pHeight)
4749 {
4750 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4751 IVideoWindow *pVideoWindow;
4752 HRESULT hr;
4753
4754 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4755
4756 EnterCriticalSection(&This->cs);
4757
4758 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4759
4760 if (hr == S_OK)
4761 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4762
4763 LeaveCriticalSection(&This->cs);
4764
4765 return hr;
4766 }
4767
4768 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4769 LONG *pHeight)
4770 {
4771 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4772 IVideoWindow *pVideoWindow;
4773 HRESULT hr;
4774
4775 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4776
4777 EnterCriticalSection(&This->cs);
4778
4779 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4780
4781 if (hr == S_OK)
4782 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4783
4784 LeaveCriticalSection(&This->cs);
4785
4786 return hr;
4787 }
4788
4789 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth,
4790 LONG *pHeight)
4791 {
4792 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4793 IVideoWindow *pVideoWindow;
4794 HRESULT hr;
4795
4796 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4797
4798 EnterCriticalSection(&This->cs);
4799
4800 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4801
4802 if (hr == S_OK)
4803 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4804
4805 LeaveCriticalSection(&This->cs);
4806
4807 return hr;
4808 }
4809
4810 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop,
4811 LONG *pWidth, LONG *pHeight)
4812 {
4813 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4814 IVideoWindow *pVideoWindow;
4815 HRESULT hr;
4816
4817 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4818
4819 EnterCriticalSection(&This->cs);
4820
4821 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4822
4823 if (hr == S_OK)
4824 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4825
4826 LeaveCriticalSection(&This->cs);
4827
4828 return hr;
4829 }
4830
4831 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor)
4832 {
4833 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4834 IVideoWindow *pVideoWindow;
4835 HRESULT hr;
4836
4837 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor);
4838
4839 EnterCriticalSection(&This->cs);
4840
4841 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4842
4843 if (hr == S_OK)
4844 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4845
4846 LeaveCriticalSection(&This->cs);
4847
4848 return hr;
4849 }
4850
4851 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
4852 {
4853 IFilterGraphImpl *This = impl_from_IVideoWindow(iface);
4854 IVideoWindow *pVideoWindow;
4855 HRESULT hr;
4856
4857 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4858
4859 EnterCriticalSection(&This->cs);
4860
4861 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4862
4863 if (hr == S_OK)
4864 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4865
4866 LeaveCriticalSection(&This->cs);
4867
4868 return hr;
4869 }
4870
4871
4872 static const IVideoWindowVtbl IVideoWindow_VTable =
4873 {
4874 VideoWindow_QueryInterface,
4875 VideoWindow_AddRef,
4876 VideoWindow_Release,
4877 VideoWindow_GetTypeInfoCount,
4878 VideoWindow_GetTypeInfo,
4879 VideoWindow_GetIDsOfNames,
4880 VideoWindow_Invoke,
4881 VideoWindow_put_Caption,
4882 VideoWindow_get_Caption,
4883 VideoWindow_put_WindowStyle,
4884 VideoWindow_get_WindowStyle,
4885 VideoWindow_put_WindowStyleEx,
4886 VideoWindow_get_WindowStyleEx,
4887 VideoWindow_put_AutoShow,
4888 VideoWindow_get_AutoShow,
4889 VideoWindow_put_WindowState,
4890 VideoWindow_get_WindowState,
4891 VideoWindow_put_BackgroundPalette,
4892 VideoWindow_get_BackgroundPalette,
4893 VideoWindow_put_Visible,
4894 VideoWindow_get_Visible,
4895 VideoWindow_put_Left,
4896 VideoWindow_get_Left,
4897 VideoWindow_put_Width,
4898 VideoWindow_get_Width,
4899 VideoWindow_put_Top,
4900 VideoWindow_get_Top,
4901 VideoWindow_put_Height,
4902 VideoWindow_get_Height,
4903 VideoWindow_put_Owner,
4904 VideoWindow_get_Owner,
4905 VideoWindow_put_MessageDrain,
4906 VideoWindow_get_MessageDrain,
4907 VideoWindow_get_BorderColor,
4908 VideoWindow_put_BorderColor,
4909 VideoWindow_get_FullScreenMode,
4910 VideoWindow_put_FullScreenMode,
4911 VideoWindow_SetWindowForeground,
4912 VideoWindow_NotifyOwnerMessage,
4913 VideoWindow_SetWindowPosition,
4914 VideoWindow_GetWindowPosition,
4915 VideoWindow_GetMinIdealImageSize,
4916 VideoWindow_GetMaxIdealImageSize,
4917 VideoWindow_GetRestorePosition,
4918 VideoWindow_HideCursor,
4919 VideoWindow_IsCursorHidden
4920 };
4921
4922 static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface)
4923 {
4924 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface);
4925 }
4926
4927 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj)
4928 {
4929 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4930
4931 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4932
4933 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
4934 }
4935
4936 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface)
4937 {
4938 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4939
4940 TRACE("(%p/%p)->()\n", This, iface);
4941
4942 return IUnknown_AddRef(This->outer_unk);
4943 }
4944
4945 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface)
4946 {
4947 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4948
4949 TRACE("(%p/%p)->()\n", This, iface);
4950
4951 return IUnknown_Release(This->outer_unk);
4952 }
4953
4954 /*** IDispatch methods ***/
4955 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo)
4956 {
4957 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4958
4959 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4960
4961 return S_OK;
4962 }
4963
4964 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid,
4965 ITypeInfo **ppTInfo)
4966 {
4967 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4968
4969 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4970
4971 return S_OK;
4972 }
4973
4974 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid,
4975 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4976 {
4977 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4978
4979 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4980
4981 return S_OK;
4982 }
4983
4984 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid,
4985 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo,
4986 UINT *puArgErr)
4987 {
4988 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4989
4990 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4991
4992 return S_OK;
4993 }
4994
4995 /*** IMediaEvent methods ***/
4996 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent)
4997 {
4998 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
4999
5000 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
5001
5002 *hEvent = (OAEVENT)This->evqueue.msg_event;
5003
5004 return S_OK;
5005 }
5006
5007 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1,
5008 LONG_PTR *lParam2, LONG msTimeout)
5009 {
5010 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5011 Event evt;
5012
5013 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
5014
5015 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
5016 {
5017 *lEventCode = evt.lEventCode;
5018 *lParam1 = evt.lParam1;
5019 *lParam2 = evt.lParam2;
5020 return S_OK;
5021 }
5022
5023 *lEventCode = 0;
5024 return E_ABORT;
5025 }
5026
5027 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout,
5028 LONG *pEvCode)
5029 {
5030 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5031
5032 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode);
5033
5034 if (This->state != State_Running)
5035 return VFW_E_WRONG_STATE;
5036
5037 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
5038 {
5039 *pEvCode = This->CompletionStatus;
5040 return S_OK;
5041 }
5042
5043 *pEvCode = 0;
5044 return E_ABORT;
5045 }
5046
5047 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5048 {
5049 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5050
5051 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5052
5053 if (lEvCode == EC_COMPLETE)
5054 This->HandleEcComplete = FALSE;
5055 else if (lEvCode == EC_REPAINT)
5056 This->HandleEcRepaint = FALSE;
5057 else if (lEvCode == EC_CLOCK_CHANGED)
5058 This->HandleEcClockChanged = FALSE;
5059 else
5060 return S_FALSE;
5061
5062 return S_OK;
5063 }
5064
5065 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode)
5066 {
5067 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5068
5069 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode);
5070
5071 if (lEvCode == EC_COMPLETE)
5072 This->HandleEcComplete = TRUE;
5073 else if (lEvCode == EC_REPAINT)
5074 This->HandleEcRepaint = TRUE;
5075 else if (lEvCode == EC_CLOCK_CHANGED)
5076 This->HandleEcClockChanged = TRUE;
5077 else
5078 return S_FALSE;
5079
5080 return S_OK;
5081 }
5082
5083 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode,
5084 LONG_PTR lParam1, LONG_PTR lParam2)
5085 {
5086 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5087
5088 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
5089
5090 return S_OK;
5091 }
5092
5093 /*** IMediaEventEx methods ***/
5094 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg,
5095 LONG_PTR lInstanceData)
5096 {
5097 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5098
5099 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData);
5100
5101 This->notif.hWnd = (HWND)hwnd;
5102 This->notif.msg = lMsg;
5103 This->notif.instance = lInstanceData;
5104
5105 return S_OK;
5106 }
5107
5108 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags)
5109 {
5110 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5111
5112 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags);
5113
5114 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
5115 return E_INVALIDARG;
5116
5117 This->notif.disabled = lNoNotifyFlags;
5118
5119 return S_OK;
5120 }
5121
5122 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags)
5123 {
5124 IFilterGraphImpl *This = impl_from_IMediaEventEx(iface);
5125
5126 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
5127
5128 if (!lplNoNotifyFlags)
5129 return E_POINTER;
5130
5131 *lplNoNotifyFlags = This->notif.disabled;
5132
5133 return S_OK;
5134 }
5135
5136
5137 static const IMediaEventExVtbl IMediaEventEx_VTable =
5138 {
5139 MediaEvent_QueryInterface,
5140 MediaEvent_AddRef,
5141 MediaEvent_Release,
5142 MediaEvent_GetTypeInfoCount,
5143 MediaEvent_GetTypeInfo,
5144 MediaEvent_GetIDsOfNames,
5145 MediaEvent_Invoke,
5146 MediaEvent_GetEventHandle,
5147 MediaEvent_GetEvent,
5148 MediaEvent_WaitForCompletion,
5149 MediaEvent_CancelDefaultHandling,
5150 MediaEvent_RestoreDefaultHandling,
5151 MediaEvent_FreeEventParams,
5152 MediaEvent_SetNotifyWindow,
5153 MediaEvent_SetNotifyFlags,
5154 MediaEvent_GetNotifyFlags
5155 };
5156
5157
5158 static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface)
5159 {
5160 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface);
5161 }
5162
5163 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
5164 {
5165 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5166
5167 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5168 }
5169
5170 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
5171 {
5172 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5173
5174 return IUnknown_AddRef(This->outer_unk);
5175 }
5176
5177 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
5178 {
5179 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5180
5181 return IUnknown_Release(This->outer_unk);
5182 }
5183
5184 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
5185 {
5186 FIXME("(%p): stub\n", pClassID);
5187
5188 return E_NOTIMPL;
5189 }
5190
5191 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
5192 {
5193 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5194
5195 return MediaControl_Stop(&This->IMediaControl_iface);
5196 }
5197
5198 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
5199 {
5200 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5201
5202 return MediaControl_Pause(&This->IMediaControl_iface);
5203 }
5204
5205 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
5206 {
5207 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5208
5209 if (tStart)
5210 FIXME("Run called with non-null tStart: %x%08x\n",
5211 (int)(tStart>>32), (int)tStart);
5212
5213 return MediaControl_Run(&This->IMediaControl_iface);
5214 }
5215
5216 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
5217 FILTER_STATE *pState)
5218 {
5219 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5220
5221 return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
5222 }
5223
5224 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
5225 {
5226 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5227 HRESULT hr = S_OK;
5228 int i;
5229
5230 TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
5231
5232 EnterCriticalSection(&This->cs);
5233 {
5234 for (i = 0;i < This->nFilters;i++)
5235 {
5236 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
5237 if (FAILED(hr))
5238 break;
5239 }
5240
5241 if (FAILED(hr))
5242 {
5243 for(;i >= 0;i--)
5244 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
5245 }
5246 else
5247 {
5248 if (This->refClock)
5249 IReferenceClock_Release(This->refClock);
5250 This->refClock = pClock;
5251 if (This->refClock)
5252 IReferenceClock_AddRef(This->refClock);
5253 This->defaultclock = FALSE;
5254
5255 if (This->HandleEcClockChanged)
5256 {
5257 IMediaEventSink *pEventSink;
5258 HRESULT eshr;
5259
5260 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (void **)&pEventSink);
5261 if (SUCCEEDED(eshr))
5262 {
5263 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
5264 IMediaEventSink_Release(pEventSink);
5265 }
5266 }
5267 }
5268 }
5269 LeaveCriticalSection(&This->cs);
5270
5271 return hr;
5272 }
5273
5274 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
5275 {
5276 IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
5277
5278 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
5279
5280 if (!ppClock)
5281 return E_POINTER;
5282
5283 EnterCriticalSection(&This->cs);
5284 {
5285 *ppClock = This->refClock;
5286 if (*ppClock)
5287 IReferenceClock_AddRef(*ppClock);
5288 }
5289 LeaveCriticalSection(&This->cs);
5290
5291 return S_OK;
5292 }
5293
5294 static const IMediaFilterVtbl IMediaFilter_VTable =
5295 {
5296 MediaFilter_QueryInterface,
5297 MediaFilter_AddRef,
5298 MediaFilter_Release,
5299 MediaFilter_GetClassID,
5300 MediaFilter_Stop,
5301 MediaFilter_Pause,
5302 MediaFilter_Run,
5303 MediaFilter_GetState,
5304 MediaFilter_SetSyncSource,
5305 MediaFilter_GetSyncSource
5306 };
5307
5308 static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface)
5309 {
5310 return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface);
5311 }
5312
5313 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
5314 {
5315 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5316
5317 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5318 }
5319
5320 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
5321 {
5322 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5323
5324 return IUnknown_AddRef(This->outer_unk);
5325 }
5326
5327 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
5328 {
5329 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5330
5331 return IUnknown_Release(This->outer_unk);
5332 }
5333
5334 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode,
5335 LONG_PTR EventParam1, LONG_PTR EventParam2)
5336 {
5337 IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
5338 Event evt;
5339
5340 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
5341
5342 /* We need thread safety here, let's use the events queue's one */
5343 EnterCriticalSection(&This->evqueue.msg_crst);
5344
5345 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
5346 {
5347 TRACE("Process EC_COMPLETE notification\n");
5348 if (++This->EcCompleteCount == This->nRenderers)
5349 {
5350 evt.lEventCode = EC_COMPLETE;
5351 evt.lParam1 = S_OK;
5352 evt.lParam2 = 0;
5353 TRACE("Send EC_COMPLETE to app\n");
5354 EventsQueue_PutEvent(&This->evqueue, &evt);
5355 if (!This->notif.disabled && This->notif.hWnd)
5356 {
5357 TRACE("Send Window message\n");
5358 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5359 }
5360 This->CompletionStatus = EC_COMPLETE;
5361 SetEvent(This->hEventCompletion);
5362 }
5363 }
5364 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
5365 {
5366 /* FIXME: Not handled yet */
5367 }
5368 else
5369 {
5370 evt.lEventCode = EventCode;
5371 evt.lParam1 = EventParam1;
5372 evt.lParam2 = EventParam2;
5373 EventsQueue_PutEvent(&This->evqueue, &evt);
5374 if (!This->notif.disabled && This->notif.hWnd)
5375 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
5376 }
5377
5378 LeaveCriticalSection(&This->evqueue.msg_crst);
5379 return S_OK;
5380 }
5381
5382 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
5383 {
5384 MediaEventSink_QueryInterface,
5385 MediaEventSink_AddRef,
5386 MediaEventSink_Release,
5387 MediaEventSink_Notify
5388 };
5389
5390 static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
5391 {
5392 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
5393 }
5394
5395 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
5396 {
5397 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5398
5399 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5400 }
5401
5402 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
5403 {
5404 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5405
5406 return IUnknown_AddRef(This->outer_unk);
5407 }
5408
5409 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
5410 {
5411 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5412
5413 return IUnknown_Release(This->outer_unk);
5414 }
5415
5416 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin,
5417 const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent,
5418 DWORD dwFlags)
5419 {
5420 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5421
5422 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
5423
5424 return E_NOTIMPL;
5425 }
5426
5427 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback,
5428 void *pvContext, DWORD dwFlags, HANDLE hAbortEvent)
5429 {
5430 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5431 HRESULT hr;
5432
5433 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
5434
5435 if (hAbortEvent)
5436 FIXME("The parameter hAbortEvent is not handled!\n");
5437
5438 EnterCriticalSection(&This->cs);
5439
5440 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags);
5441
5442 LeaveCriticalSection(&This->cs);
5443
5444 return hr;
5445 }
5446
5447 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter)
5448 {
5449 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5450
5451 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5452
5453 return E_NOTIMPL;
5454 }
5455
5456 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum)
5457 {
5458 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5459
5460 FIXME("(%p)->(%p): stub!\n", This, pEnum);
5461
5462 return E_NOTIMPL;
5463 }
5464
5465 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter)
5466 {
5467 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5468
5469 FIXME("(%p)->(%p): stub!\n", This, pFilter);
5470
5471 return E_NOTIMPL;
5472 }
5473
5474 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart)
5475 {
5476 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5477
5478 FIXME("(%p)->(%p): stub!\n", This, prtStart);
5479
5480 return E_NOTIMPL;
5481 }
5482
5483 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin,
5484 IPinConnection *pConnection, HANDLE hEventAbort)
5485 {
5486 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5487
5488 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
5489
5490 return E_NOTIMPL;
5491 }
5492
5493 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5494 DWORD dwFlags)
5495 {
5496 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5497
5498 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5499
5500 return E_NOTIMPL;
5501 }
5502
5503 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter,
5504 DWORD *dwFlags)
5505 {
5506 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5507
5508 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
5509
5510 return E_NOTIMPL;
5511 }
5512
5513 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter,
5514 DWORD dwFlags)
5515 {
5516 IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
5517
5518 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
5519
5520 return E_NOTIMPL;
5521 }
5522
5523 static const IGraphConfigVtbl IGraphConfig_VTable =
5524 {
5525 GraphConfig_QueryInterface,
5526 GraphConfig_AddRef,
5527 GraphConfig_Release,
5528 GraphConfig_Reconnect,
5529 GraphConfig_Reconfigure,
5530 GraphConfig_AddFilterToCache,
5531 GraphConfig_EnumCacheFilter,
5532 GraphConfig_RemoveFilterFromCache,
5533 GraphConfig_GetStartTime,
5534 GraphConfig_PushThroughData,
5535 GraphConfig_SetFilterFlags,
5536 GraphConfig_GetFilterFlags,
5537 GraphConfig_RemoveFilterEx
5538 };
5539
5540 static inline IFilterGraphImpl *impl_from_IGraphVersion(IGraphVersion *iface)
5541 {
5542 return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphVersion_iface);
5543 }
5544
5545 static HRESULT WINAPI GraphVersion_QueryInterface(IGraphVersion *iface, REFIID riid, void **ppv)
5546 {
5547 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5548
5549 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
5550 }
5551
5552 static ULONG WINAPI GraphVersion_AddRef(IGraphVersion *iface)
5553 {
5554 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5555
5556 return IUnknown_AddRef(This->outer_unk);
5557 }
5558
5559 static ULONG WINAPI GraphVersion_Release(IGraphVersion *iface)
5560 {
5561 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5562
5563 return IUnknown_Release(This->outer_unk);
5564 }
5565
5566 static HRESULT WINAPI GraphVersion_QueryVersion(IGraphVersion *iface, LONG *pVersion)
5567 {
5568 IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
5569
5570 if(!pVersion)
5571 return E_POINTER;
5572
5573 TRACE("(%p)->(%p): current version %i\n", This, pVersion, This->version);
5574
5575 *pVersion = This->version;
5576 return S_OK;
5577 }
5578
5579 static const IGraphVersionVtbl IGraphVersion_VTable =
5580 {
5581 GraphVersion_QueryInterface,
5582 GraphVersion_AddRef,
5583 GraphVersion_Release,
5584 GraphVersion_QueryVersion,
5585 };
5586
5587 static const IUnknownVtbl IInner_VTable =
5588 {
5589 FilterGraphInner_QueryInterface,
5590 FilterGraphInner_AddRef,
5591 FilterGraphInner_Release
5592 };
5593
5594 /* This is the only function that actually creates a FilterGraph class... */
5595 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5596 {
5597 IFilterGraphImpl *fimpl;
5598 HRESULT hr;
5599
5600 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
5601
5602 *ppObj = NULL;
5603
5604 fimpl = CoTaskMemAlloc(sizeof(*fimpl));
5605 fimpl->defaultclock = TRUE;
5606 fimpl->IUnknown_inner.lpVtbl = &IInner_VTable;
5607 fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable;
5608 fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable;
5609 fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable;
5610 fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable;
5611 fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable;
5612 fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable;
5613 fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable;
5614 fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable;
5615 fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable;
5616 fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable;
5617 fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable;
5618 fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
5619 fimpl->IGraphVersion_iface.lpVtbl = &IGraphVersion_VTable;
5620 fimpl->ref = 1;
5621 fimpl->ppFiltersInGraph = NULL;
5622 fimpl->pFilterNames = NULL;
5623 fimpl->nFilters = 0;
5624 fimpl->filterCapacity = 0;
5625 fimpl->nameIndex = 1;
5626 fimpl->refClock = NULL;
5627 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
5628 fimpl->HandleEcComplete = TRUE;
5629 fimpl->HandleEcRepaint = TRUE;
5630 fimpl->HandleEcClockChanged = TRUE;
5631 fimpl->notif.hWnd = 0;
5632 fimpl->notif.disabled = FALSE;
5633 fimpl->nRenderers = 0;
5634 fimpl->EcCompleteCount = 0;
5635 fimpl->refClockProvider = NULL;
5636 fimpl->state = State_Stopped;
5637 fimpl->pSite = NULL;
5638 EventsQueue_Init(&fimpl->evqueue);
5639 InitializeCriticalSection(&fimpl->cs);
5640 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
5641 fimpl->nItfCacheEntries = 0;
5642 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
5643 fimpl->start_time = fimpl->pause_time = 0;
5644 fimpl->stop_position = -1;
5645 fimpl->punkFilterMapper2 = NULL;
5646 fimpl->recursioncount = 0;
5647 fimpl->version = 0;
5648
5649 if (pUnkOuter)
5650 fimpl->outer_unk = pUnkOuter;
5651 else
5652 fimpl->outer_unk = &fimpl->IUnknown_inner;
5653
5654 /* create Filtermapper aggregated. */
5655 hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER,
5656 &IID_IUnknown, (void**)&fimpl->punkFilterMapper2);
5657
5658 if (SUCCEEDED(hr))
5659 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2,
5660 (void**)&fimpl->pFilterMapper2);
5661
5662 if (SUCCEEDED(hr))
5663 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
5664 IUnknown_Release(fimpl->outer_unk);
5665
5666 if (FAILED(hr)) {
5667 ERR("Unable to create filter mapper (%x)\n", hr);
5668 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
5669 CloseHandle(fimpl->hEventCompletion);
5670 EventsQueue_Destroy(&fimpl->evqueue);
5671 fimpl->cs.DebugInfo->Spare[0] = 0;
5672 DeleteCriticalSection(&fimpl->cs);
5673 CoTaskMemFree(fimpl);
5674 return hr;
5675 }
5676
5677 *ppObj = &fimpl->IUnknown_inner;
5678 return S_OK;
5679 }
5680
5681 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
5682 {
5683 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
5684 return FilterGraph_create(pUnkOuter, ppObj);
5685 }