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