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