quartz: Add VideoRendererDefault.
[wine] / dlls / quartz / videorenderer.c
1 /*
2  * Video Renderer (Fullscreen and Windowed using Direct Draw)
3  *
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 "config.h"
22
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
26 #include "control_private.h"
27 #include "pin.h"
28
29 #include "uuids.h"
30 #include "vfwmsgs.h"
31 #include "amvideo.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "dshow.h"
35 #include "evcode.h"
36 #include "strmif.h"
37 #include "ddraw.h"
38
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43
44 static BOOL wnd_class_registered = FALSE;
45
46 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
47
48 static const IBaseFilterVtbl VideoRenderer_Vtbl;
49 static const IUnknownVtbl IInner_VTable;
50 static const IBasicVideoVtbl IBasicVideo_VTable;
51 static const IVideoWindowVtbl IVideoWindow_VTable;
52 static const IPinVtbl VideoRenderer_InputPin_Vtbl;
53
54 typedef struct VideoRendererImpl
55 {
56     const IBaseFilterVtbl * lpVtbl;
57     const IBasicVideoVtbl * IBasicVideo_vtbl;
58     const IVideoWindowVtbl * IVideoWindow_vtbl;
59     const IUnknownVtbl * IInner_vtbl;
60
61     LONG refCount;
62     CRITICAL_SECTION csFilter;
63     FILTER_STATE state;
64     REFERENCE_TIME rtStreamStart;
65     IReferenceClock * pClock;
66     FILTER_INFO filterInfo;
67
68     InputPin * pInputPin;
69     IPin ** ppPins;
70
71     BOOL init;
72     HANDLE hThread;
73     DWORD ThreadID;
74     HANDLE hEvent;
75     BOOL ThreadResult;
76     HWND hWnd;
77     HWND hWndMsgDrain;
78     BOOL AutoShow;
79     RECT SourceRect;
80     RECT DestRect;
81     RECT WindowPos;
82     long VideoWidth;
83     long VideoHeight;
84     IUnknown * pUnkOuter;
85     BOOL bUnkOuterValid;
86     BOOL bAggregatable;
87 } VideoRendererImpl;
88
89 static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
90 {
91     VideoRendererImpl* pVideoRenderer = (VideoRendererImpl*)GetWindowLongA(hwnd, 0);
92     LPRECT lprect = (LPRECT)lParam;
93
94     if (pVideoRenderer && pVideoRenderer->hWndMsgDrain)
95     {
96         switch(uMsg)
97         {
98             case WM_KEYDOWN:
99             case WM_KEYUP:
100             case WM_LBUTTONDBLCLK:
101             case WM_LBUTTONDOWN:
102             case WM_LBUTTONUP:
103             case WM_MBUTTONDBLCLK:
104             case WM_MBUTTONDOWN:
105             case WM_MBUTTONUP:
106             case WM_MOUSEACTIVATE:
107             case WM_MOUSEMOVE:
108             case WM_NCLBUTTONDBLCLK:
109             case WM_NCLBUTTONDOWN:
110             case WM_NCLBUTTONUP:
111             case WM_NCMBUTTONDBLCLK:
112             case WM_NCMBUTTONDOWN:
113             case WM_NCMBUTTONUP:
114             case WM_NCMOUSEMOVE:
115             case WM_NCRBUTTONDBLCLK:
116             case WM_NCRBUTTONDOWN:
117             case WM_NCRBUTTONUP:
118             case WM_RBUTTONDBLCLK:
119             case WM_RBUTTONDOWN:
120             case WM_RBUTTONUP:
121                 PostMessageA(pVideoRenderer->hWndMsgDrain, uMsg, wParam, lParam);
122                 break;
123             default:
124                 break;
125         }
126     }
127
128     switch(uMsg)
129     {
130         case WM_SIZING:
131             /* TRACE("WM_SIZING %d %d %d %d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); */
132             SetWindowPos(hwnd, NULL, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top, SWP_NOZORDER);
133             GetClientRect(hwnd, &pVideoRenderer->DestRect);
134             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
135                 pVideoRenderer->DestRect.left,
136                 pVideoRenderer->DestRect.top,
137                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
138                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
139             return TRUE;
140         case WM_SIZE:
141             TRACE("WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
142             GetClientRect(hwnd, &pVideoRenderer->DestRect);
143             TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
144                 pVideoRenderer->DestRect.left,
145                 pVideoRenderer->DestRect.top,
146                 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
147                 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
148             return TRUE;
149         default:
150             return DefWindowProcA(hwnd, uMsg, wParam, lParam);
151     }
152     return 0;
153 }
154
155 static BOOL CreateRenderingWindow(VideoRendererImpl* This)
156 {
157     WNDCLASSA winclass;
158
159     TRACE("(%p)->()\n", This);
160     
161     winclass.style = 0;
162     winclass.lpfnWndProc = VideoWndProcA;
163     winclass.cbClsExtra = 0;
164     winclass.cbWndExtra = sizeof(VideoRendererImpl*);
165     winclass.hInstance = NULL;
166     winclass.hIcon = NULL;
167     winclass.hCursor = NULL;
168     winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
169     winclass.lpszMenuName = NULL;
170     winclass.lpszClassName = "Wine ActiveMovie Class";
171
172     if (!wnd_class_registered)
173     {
174         if (!RegisterClassA(&winclass))
175         {
176             ERR("Unable to register window %u\n", GetLastError());
177             return FALSE;
178         }
179         wnd_class_registered = TRUE;
180     }
181
182     This->hWnd = CreateWindowExA(0, "Wine ActiveMovie Class", "Wine ActiveMovie Window", WS_SIZEBOX,
183                                  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
184                                  NULL, NULL, NULL);
185
186     if (!This->hWnd)
187     {
188         ERR("Unable to create window\n");
189         return FALSE;
190     }
191
192     SetWindowLongA(This->hWnd, 0, (LONG)This);
193
194     return TRUE;
195 }
196
197 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
198 {
199     VideoRendererImpl* This = (VideoRendererImpl*) lpParameter;
200     MSG msg; 
201     BOOL fGotMessage;
202
203     TRACE("Starting message loop\n");
204
205     if (!CreateRenderingWindow(This))
206     {
207         This->ThreadResult = FALSE;
208         SetEvent(This->hEvent);
209         return 0;
210     }
211
212     This->ThreadResult = TRUE;
213     SetEvent(This->hEvent);
214
215     while ((fGotMessage = GetMessageA(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) 
216     {
217         TranslateMessage(&msg); 
218         DispatchMessageA(&msg); 
219     }
220
221     TRACE("End of message loop\n");
222
223     return msg.wParam;
224 }
225
226 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
227 {
228     This->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
229     if (!This->hEvent)
230         return FALSE;
231
232     This->hThread = CreateThread(NULL, 0, MessageLoop, (LPVOID)This, 0, &This->ThreadID);
233     if (!This->hThread)
234     {
235         CloseHandle(This->hEvent);
236         return FALSE;
237     }
238
239     WaitForSingleObject(This->hEvent, INFINITE);
240     CloseHandle(This->hEvent);
241
242     if (!This->ThreadResult)
243     {
244         CloseHandle(This->hThread);
245         return FALSE;
246     }
247
248     return TRUE;
249 }
250
251 static const IMemInputPinVtbl MemInputPin_Vtbl = 
252 {
253     MemInputPin_QueryInterface,
254     MemInputPin_AddRef,
255     MemInputPin_Release,
256     MemInputPin_GetAllocator,
257     MemInputPin_NotifyAllocator,
258     MemInputPin_GetAllocatorRequirements,
259     MemInputPin_Receive,
260     MemInputPin_ReceiveMultiple,
261     MemInputPin_ReceiveCanBlock
262 };
263
264 static HRESULT VideoRenderer_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
265 {
266     InputPin * pPinImpl;
267
268     *ppPin = NULL;
269
270     if (pPinInfo->dir != PINDIR_INPUT)
271     {
272         ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
273         return E_INVALIDARG;
274     }
275
276     pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
277
278     if (!pPinImpl)
279         return E_OUTOFMEMORY;
280
281     if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl)))
282     {
283         pPinImpl->pin.lpVtbl = &VideoRenderer_InputPin_Vtbl;
284         pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
285
286         *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
287         return S_OK;
288     }
289
290     CoTaskMemFree(pPinImpl);
291     return E_FAIL;
292 }
293
294 static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
295 {
296     VIDEOINFOHEADER* format;
297     AM_MEDIA_TYPE amt;
298     HRESULT hr = S_OK;
299     DDSURFACEDESC sdesc;
300     int width;
301     int height;
302     LPBYTE palette = NULL;
303     HDC hDC;
304
305     TRACE("%p %p %d\n", This, data, size);
306
307     sdesc.dwSize = sizeof(sdesc);
308     hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
309     if (FAILED(hr)) {
310         ERR("Unable to retrieve media type\n");
311         return hr;
312     }
313     format = (VIDEOINFOHEADER*)amt.pbFormat;
314
315     TRACE("biSize = %d\n", format->bmiHeader.biSize);
316     TRACE("biWidth = %d\n", format->bmiHeader.biWidth);
317     TRACE("biHeight = %d\n", format->bmiHeader.biHeight);
318     TRACE("biPlanes = %d\n", format->bmiHeader.biPlanes);
319     TRACE("biBitCount = %d\n", format->bmiHeader.biBitCount);
320     TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(format->bmiHeader.biCompression), 4));
321     TRACE("biSizeImage = %d\n", format->bmiHeader.biSizeImage);
322
323     width = format->bmiHeader.biWidth;
324     height = format->bmiHeader.biHeight;
325     palette = ((LPBYTE)&format->bmiHeader) + format->bmiHeader.biSize;
326  
327     if (!This->init)
328     {
329         /* Honor previously set WindowPos */
330         TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom);
331         SetWindowPos(This->hWnd, NULL,
332             This->WindowPos.left,
333             This->WindowPos.top,
334             This->WindowPos.right - This->WindowPos.left,
335             This->WindowPos.bottom - This->WindowPos.top,
336             SWP_NOZORDER|SWP_NOMOVE);
337         GetClientRect(This->hWnd, &This->DestRect);
338         This->init  = TRUE;
339     }
340
341     hDC = GetDC(This->hWnd);
342
343     if (!hDC) {
344         ERR("Cannot get DC from window!\n");
345         return E_FAIL;
346     }
347
348     TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
349     TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
350
351     StretchDIBits(hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
352                   This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
353                   This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
354                   data, (BITMAPINFO*)&format->bmiHeader, DIB_RGB_COLORS, SRCCOPY);
355
356     ReleaseDC(This->hWnd, hDC);
357     
358     if (This->AutoShow)
359         ShowWindow(This->hWnd, SW_SHOW);
360
361     return S_OK;
362 }
363
364 static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
365 {
366     VideoRendererImpl *This = (VideoRendererImpl *)iface;
367     LPBYTE pbSrcStream = NULL;
368     long cbSrcStream = 0;
369     REFERENCE_TIME tStart, tStop;
370     HRESULT hr;
371
372     TRACE("%p %p\n", iface, pSample);
373     
374     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
375     if (FAILED(hr))
376     {
377         ERR("Cannot get pointer to sample data (%x)\n", hr);
378         return hr;
379     }
380
381     hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
382     if (FAILED(hr))
383         ERR("Cannot get sample time (%x)\n", hr);
384
385     cbSrcStream = IMediaSample_GetActualDataLength(pSample);
386
387     TRACE("val %p %ld\n", pbSrcStream, cbSrcStream);
388
389 #if 0 /* For debugging purpose */
390     {
391         int i;
392         for(i = 0; i < cbSrcStream; i++)
393         {
394             if ((i!=0) && !(i%16))
395                 TRACE("\n");
396                 TRACE("%02x ", pbSrcStream[i]);
397         }
398         TRACE("\n");
399     }
400 #endif
401     
402     VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
403
404     return S_OK;
405 }
406
407 static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
408 {
409     if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
410         return S_FALSE;
411
412     if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
413         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
414         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
415         IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
416     {
417         VideoRendererImpl* This = (VideoRendererImpl*) iface;
418         VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat;
419
420         if (!IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
421         {
422             WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
423             return S_FALSE;
424         }
425         This->SourceRect.left = 0;
426         This->SourceRect.top = 0;
427         This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
428         This->SourceRect.bottom = This->VideoHeight = format->bmiHeader.biHeight;
429         return S_OK;
430     }
431     return S_FALSE;
432 }
433
434 HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
435 {
436     HRESULT hr;
437     PIN_INFO piInput;
438     VideoRendererImpl * pVideoRenderer;
439
440     TRACE("(%p, %p)\n", pUnkOuter, ppv);
441
442     *ppv = NULL;
443
444     pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
445     pVideoRenderer->pUnkOuter = pUnkOuter;
446     pVideoRenderer->bUnkOuterValid = FALSE;
447     pVideoRenderer->bAggregatable = FALSE;
448     pVideoRenderer->IInner_vtbl = &IInner_VTable;
449
450     pVideoRenderer->lpVtbl = &VideoRenderer_Vtbl;
451     pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable;
452     pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable;
453     
454     pVideoRenderer->refCount = 1;
455     InitializeCriticalSection(&pVideoRenderer->csFilter);
456     pVideoRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter");
457     pVideoRenderer->state = State_Stopped;
458     pVideoRenderer->pClock = NULL;
459     pVideoRenderer->init = 0;
460     pVideoRenderer->AutoShow = 1;
461     ZeroMemory(&pVideoRenderer->filterInfo, sizeof(FILTER_INFO));
462
463     pVideoRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
464
465     /* construct input pin */
466     piInput.dir = PINDIR_INPUT;
467     piInput.pFilter = (IBaseFilter *)pVideoRenderer;
468     lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
469
470     hr = VideoRenderer_InputPin_Construct(&piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, &pVideoRenderer->csFilter, (IPin **)&pVideoRenderer->pInputPin);
471
472     if (SUCCEEDED(hr))
473     {
474         pVideoRenderer->ppPins[0] = (IPin *)pVideoRenderer->pInputPin;
475         *ppv = (LPVOID)pVideoRenderer;
476     }
477     else
478     {
479         CoTaskMemFree(pVideoRenderer->ppPins);
480         pVideoRenderer->csFilter.DebugInfo->Spare[0] = 0;
481         DeleteCriticalSection(&pVideoRenderer->csFilter);
482         CoTaskMemFree(pVideoRenderer);
483     }
484
485     if (!CreateRenderingSubsystem(pVideoRenderer))
486         return E_FAIL;
487     
488     return hr;
489 }
490
491 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
492 {
493     /* TODO: Attenmpt to use the VMR-7 renderer instead when possible */
494     return VideoRenderer_create(pUnkOuter, ppv);
495 }
496
497 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
498 {
499     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
500     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
501
502     if (This->bAggregatable)
503         This->bUnkOuterValid = TRUE;
504
505     *ppv = NULL;
506
507     if (IsEqualIID(riid, &IID_IUnknown))
508         *ppv = (LPVOID)&(This->IInner_vtbl);
509     else if (IsEqualIID(riid, &IID_IPersist))
510         *ppv = (LPVOID)This;
511     else if (IsEqualIID(riid, &IID_IMediaFilter))
512         *ppv = (LPVOID)This;
513     else if (IsEqualIID(riid, &IID_IBaseFilter))
514         *ppv = (LPVOID)This;
515     else if (IsEqualIID(riid, &IID_IBasicVideo))
516         *ppv = (LPVOID)&(This->IBasicVideo_vtbl);
517     else if (IsEqualIID(riid, &IID_IVideoWindow))
518         *ppv = (LPVOID)&(This->IVideoWindow_vtbl);
519
520     if (*ppv)
521     {
522         IUnknown_AddRef((IUnknown *)(*ppv));
523         return S_OK;
524     }
525
526     FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
527
528     return E_NOINTERFACE;
529 }
530
531 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface)
532 {
533     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
534     ULONG refCount = InterlockedIncrement(&This->refCount);
535
536     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
537
538     return refCount;
539 }
540
541 static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
542 {
543     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
544     ULONG refCount = InterlockedDecrement(&This->refCount);
545
546     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
547
548     if (!refCount)
549     {
550         IPin *pConnectedTo;
551
552         DestroyWindow(This->hWnd);
553         PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
554         WaitForSingleObject(This->hThread, INFINITE);
555         CloseHandle(This->hThread);
556
557         if (This->pClock)
558             IReferenceClock_Release(This->pClock);
559         
560         if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
561         {
562             IPin_Disconnect(pConnectedTo);
563             IPin_Release(pConnectedTo);
564         }
565         IPin_Disconnect(This->ppPins[0]);
566
567         IPin_Release(This->ppPins[0]);
568         
569         CoTaskMemFree(This->ppPins);
570         This->lpVtbl = NULL;
571         
572         This->csFilter.DebugInfo->Spare[0] = 0;
573         DeleteCriticalSection(&This->csFilter);
574
575         TRACE("Destroying Video Renderer\n");
576         CoTaskMemFree(This);
577         
578         return 0;
579     }
580     else
581         return refCount;
582 }
583
584 static const IUnknownVtbl IInner_VTable =
585 {
586     VideoRendererInner_QueryInterface,
587     VideoRendererInner_AddRef,
588     VideoRendererInner_Release
589 };
590
591 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
592 {
593     VideoRendererImpl *This = (VideoRendererImpl *)iface;
594
595     if (This->bAggregatable)
596         This->bUnkOuterValid = TRUE;
597
598     if (This->pUnkOuter)
599     {
600         if (This->bAggregatable)
601             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
602
603         if (IsEqualIID(riid, &IID_IUnknown))
604         {
605             HRESULT hr;
606
607             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
608             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
609             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
610             This->bAggregatable = TRUE;
611             return hr;
612         }
613
614         *ppv = NULL;
615         return E_NOINTERFACE;
616     }
617
618     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
619 }
620
621 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
622 {
623     VideoRendererImpl *This = (VideoRendererImpl *)iface;
624
625     if (This->pUnkOuter && This->bUnkOuterValid)
626         return IUnknown_AddRef(This->pUnkOuter);
627     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
628 }
629
630 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
631 {
632     VideoRendererImpl *This = (VideoRendererImpl *)iface;
633
634     if (This->pUnkOuter && This->bUnkOuterValid)
635         return IUnknown_Release(This->pUnkOuter);
636     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
637 }
638
639 /** IPersist methods **/
640
641 static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
642 {
643     VideoRendererImpl *This = (VideoRendererImpl *)iface;
644
645     TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
646
647     *pClsid = CLSID_VideoRenderer;
648
649     return S_OK;
650 }
651
652 /** IMediaFilter methods **/
653
654 static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
655 {
656     VideoRendererImpl *This = (VideoRendererImpl *)iface;
657
658     TRACE("(%p/%p)->()\n", This, iface);
659
660     EnterCriticalSection(&This->csFilter);
661     {
662         This->state = State_Stopped;
663     }
664     LeaveCriticalSection(&This->csFilter);
665     
666     return S_OK;
667 }
668
669 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
670 {
671     VideoRendererImpl *This = (VideoRendererImpl *)iface;
672     
673     TRACE("(%p/%p)->()\n", This, iface);
674
675     EnterCriticalSection(&This->csFilter);
676     {
677         This->state = State_Paused;
678     }
679     LeaveCriticalSection(&This->csFilter);
680
681     return S_OK;
682 }
683
684 static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
685 {
686     VideoRendererImpl *This = (VideoRendererImpl *)iface;
687
688     TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
689
690     EnterCriticalSection(&This->csFilter);
691     {
692         This->rtStreamStart = tStart;
693         This->state = State_Running;
694     }
695     LeaveCriticalSection(&This->csFilter);
696
697     return S_OK;
698 }
699
700 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
701 {
702     VideoRendererImpl *This = (VideoRendererImpl *)iface;
703
704     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
705
706     EnterCriticalSection(&This->csFilter);
707     {
708         *pState = This->state;
709     }
710     LeaveCriticalSection(&This->csFilter);
711
712     return S_OK;
713 }
714
715 static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
716 {
717     VideoRendererImpl *This = (VideoRendererImpl *)iface;
718
719     TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
720
721     EnterCriticalSection(&This->csFilter);
722     {
723         if (This->pClock)
724             IReferenceClock_Release(This->pClock);
725         This->pClock = pClock;
726         if (This->pClock)
727             IReferenceClock_AddRef(This->pClock);
728     }
729     LeaveCriticalSection(&This->csFilter);
730
731     return S_OK;
732 }
733
734 static HRESULT WINAPI VideoRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
735 {
736     VideoRendererImpl *This = (VideoRendererImpl *)iface;
737
738     TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
739
740     EnterCriticalSection(&This->csFilter);
741     {
742         *ppClock = This->pClock;
743         IReferenceClock_AddRef(This->pClock);
744     }
745     LeaveCriticalSection(&This->csFilter);
746     
747     return S_OK;
748 }
749
750 /** IBaseFilter implementation **/
751
752 static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
753 {
754     ENUMPINDETAILS epd;
755     VideoRendererImpl *This = (VideoRendererImpl *)iface;
756
757     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
758
759     epd.cPins = 1; /* input pin */
760     epd.ppPins = This->ppPins;
761     return IEnumPinsImpl_Construct(&epd, ppEnum);
762 }
763
764 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
765 {
766     VideoRendererImpl *This = (VideoRendererImpl *)iface;
767
768     TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
769
770     FIXME("VideoRenderer::FindPin(...)\n");
771
772     /* FIXME: critical section */
773
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI VideoRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
778 {
779     VideoRendererImpl *This = (VideoRendererImpl *)iface;
780
781     TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
782
783     strcpyW(pInfo->achName, This->filterInfo.achName);
784     pInfo->pGraph = This->filterInfo.pGraph;
785
786     if (pInfo->pGraph)
787         IFilterGraph_AddRef(pInfo->pGraph);
788     
789     return S_OK;
790 }
791
792 static HRESULT WINAPI VideoRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
793 {
794     VideoRendererImpl *This = (VideoRendererImpl *)iface;
795
796     TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
797
798     EnterCriticalSection(&This->csFilter);
799     {
800         if (pName)
801             strcpyW(This->filterInfo.achName, pName);
802         else
803             *This->filterInfo.achName = '\0';
804         This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
805     }
806     LeaveCriticalSection(&This->csFilter);
807
808     return S_OK;
809 }
810
811 static HRESULT WINAPI VideoRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
812 {
813     VideoRendererImpl *This = (VideoRendererImpl *)iface;
814     TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
815     return E_NOTIMPL;
816 }
817
818 static const IBaseFilterVtbl VideoRenderer_Vtbl =
819 {
820     VideoRenderer_QueryInterface,
821     VideoRenderer_AddRef,
822     VideoRenderer_Release,
823     VideoRenderer_GetClassID,
824     VideoRenderer_Stop,
825     VideoRenderer_Pause,
826     VideoRenderer_Run,
827     VideoRenderer_GetState,
828     VideoRenderer_SetSyncSource,
829     VideoRenderer_GetSyncSource,
830     VideoRenderer_EnumPins,
831     VideoRenderer_FindPin,
832     VideoRenderer_QueryFilterInfo,
833     VideoRenderer_JoinFilterGraph,
834     VideoRenderer_QueryVendorInfo
835 };
836
837 static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
838 {
839     InputPin* This = (InputPin*)iface;
840     IMediaEventSink* pEventSink;
841     HRESULT hr;
842
843     TRACE("(%p/%p)->()\n", This, iface);
844
845     hr = IFilterGraph_QueryInterface(((VideoRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
846     if (SUCCEEDED(hr))
847     {
848         hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
849         IMediaEventSink_Release(pEventSink);
850     }
851
852     return hr;
853 }
854
855 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
856 {
857     InputPin_QueryInterface,
858     IPinImpl_AddRef,
859     InputPin_Release,
860     InputPin_Connect,
861     InputPin_ReceiveConnection,
862     IPinImpl_Disconnect,
863     IPinImpl_ConnectedTo,
864     IPinImpl_ConnectionMediaType,
865     IPinImpl_QueryPinInfo,
866     IPinImpl_QueryDirection,
867     IPinImpl_QueryId,
868     IPinImpl_QueryAccept,
869     IPinImpl_EnumMediaTypes,
870     IPinImpl_QueryInternalConnections,
871     VideoRenderer_InputPin_EndOfStream,
872     InputPin_BeginFlush,
873     InputPin_EndFlush,
874     InputPin_NewSegment
875 };
876
877 /*** IUnknown methods ***/
878 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
879                                                 REFIID riid,
880                                                 LPVOID*ppvObj) {
881     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
882
883     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
884
885     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
886 }
887
888 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
889     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
890
891     TRACE("(%p/%p)->()\n", This, iface);
892
893     return VideoRenderer_AddRef((IBaseFilter*)This);
894 }
895
896 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
897     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
898
899     TRACE("(%p/%p)->()\n", This, iface);
900
901     return VideoRenderer_Release((IBaseFilter*)This);
902 }
903
904 /*** IDispatch methods ***/
905 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
906                                                   UINT*pctinfo) {
907     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
908
909     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
910
911     return S_OK;
912 }
913
914 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
915                                              UINT iTInfo,
916                                              LCID lcid,
917                                              ITypeInfo**ppTInfo) {
918     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
919
920     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
921
922     return S_OK;
923 }
924
925 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
926                                                REFIID riid,
927                                                LPOLESTR*rgszNames,
928                                                UINT cNames,
929                                                LCID lcid,
930                                                DISPID*rgDispId) {
931     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
932
933     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
934
935     return S_OK;
936 }
937
938 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
939                                         DISPID dispIdMember,
940                                         REFIID riid,
941                                         LCID lcid,
942                                         WORD wFlags,
943                                         DISPPARAMS*pDispParams,
944                                         VARIANT*pVarResult,
945                                         EXCEPINFO*pExepInfo,
946                                         UINT*puArgErr) {
947     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
948
949     FIXME("(%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);
950
951     return S_OK;
952 }
953
954 /*** IBasicVideo methods ***/
955 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
956                                                      REFTIME *pAvgTimePerFrame) {
957     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
958
959     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
960
961     return S_OK;
962 }
963
964 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
965                                              long *pBitRate) {
966     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
967
968     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
969
970     return S_OK;
971 }
972
973 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
974                                                   long *pBitErrorRate) {
975     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
976
977     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
978
979     return S_OK;
980 }
981
982 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
983                                                 long *pVideoWidth) {
984     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
985
986     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
987
988     *pVideoWidth = This->VideoWidth;
989
990     return S_OK;
991 }
992
993 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
994                                                  long *pVideoHeight) {
995     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
996
997     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
998
999     *pVideoHeight = This->VideoHeight;
1000
1001     return S_OK;
1002 }
1003
1004 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1005                                                 long SourceLeft) {
1006     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1007
1008     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
1009
1010     This->SourceRect.left = SourceLeft;
1011
1012     return S_OK;
1013 }
1014
1015 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1016                                                 long *pSourceLeft) {
1017     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1018
1019     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
1020
1021     *pSourceLeft = This->SourceRect.left;
1022
1023     return S_OK;
1024 }
1025
1026 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1027                                                  long SourceWidth) {
1028     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1029
1030     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
1031
1032     This->SourceRect.right = This->SourceRect.left + SourceWidth;
1033
1034     return S_OK;
1035 }
1036
1037 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1038                                                  long *pSourceWidth) {
1039     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1040
1041     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
1042
1043     *pSourceWidth = This->SourceRect.right - This->SourceRect.left;
1044     
1045     return S_OK;
1046 }
1047
1048 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1049                                                long SourceTop) {
1050     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1051
1052     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
1053
1054     This->SourceRect.top = SourceTop;
1055
1056     return S_OK;
1057 }
1058
1059 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1060                                                long *pSourceTop) {
1061     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1062
1063     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
1064
1065     *pSourceTop = This->SourceRect.top;
1066
1067     return S_OK;
1068 }
1069
1070 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1071                                                   long SourceHeight) {
1072     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1073
1074     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
1075
1076     This->SourceRect.bottom = This->SourceRect.top + SourceHeight;
1077
1078     return S_OK;
1079 }
1080
1081 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1082                                                   long *pSourceHeight) {
1083     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1084
1085     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
1086
1087     *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top;
1088
1089     return S_OK;
1090 }
1091
1092 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1093                                                      long DestinationLeft) {
1094     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1095
1096     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
1097
1098     This->DestRect.left = DestinationLeft;
1099
1100     return S_OK;
1101 }
1102
1103 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1104                                                      long *pDestinationLeft) {
1105     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1106
1107     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
1108
1109     *pDestinationLeft = This->DestRect.left;
1110
1111     return S_OK;
1112 }
1113
1114 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1115                                                       long DestinationWidth) {
1116     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1117
1118     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
1119
1120     This->DestRect.right = This->DestRect.left + DestinationWidth;
1121
1122     return S_OK;
1123 }
1124
1125 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1126                                                       long *pDestinationWidth) {
1127     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1128
1129     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
1130
1131     *pDestinationWidth = This->DestRect.right - This->DestRect.left;
1132
1133     return S_OK;
1134 }
1135
1136 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1137                                                     long DestinationTop) {
1138     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1139
1140     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
1141
1142     This->DestRect.top = DestinationTop;
1143     
1144     return S_OK;
1145 }
1146
1147 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1148                                                     long *pDestinationTop) {
1149     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1150
1151     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
1152
1153     *pDestinationTop = This->DestRect.top;
1154
1155     return S_OK;
1156 }
1157
1158 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1159                                                        long DestinationHeight) {
1160     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1161
1162     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
1163
1164     This->DestRect.right = This->DestRect.left + DestinationHeight;
1165
1166     return S_OK;
1167 }
1168
1169 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1170                                                        long *pDestinationHeight) {
1171     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1172
1173     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
1174
1175     *pDestinationHeight = This->DestRect.right - This->DestRect.left;
1176
1177     return S_OK;
1178 }
1179
1180 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1181                                                    long Left,
1182                                                    long Top,
1183                                                    long Width,
1184                                                    long Height) {
1185     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1186
1187     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1188
1189     This->SourceRect.left = Left;
1190     This->SourceRect.top = Top;
1191     This->SourceRect.right = Left + Width;
1192     This->SourceRect.bottom = Top + Height;
1193     
1194     return S_OK;
1195 }
1196
1197 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
1198                                                    long *pLeft,
1199                                                    long *pTop,
1200                                                    long *pWidth,
1201                                                    long *pHeight) {
1202     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1203
1204     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1205
1206     *pLeft = This->SourceRect.left;
1207     *pTop = This->SourceRect.top;
1208     *pWidth = This->SourceRect.right - This->SourceRect.left;
1209     *pHeight = This->SourceRect.bottom - This->SourceRect.top;
1210     
1211     return S_OK;
1212 }
1213
1214 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
1215     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1216
1217     TRACE("(%p/%p)->()\n", This, iface);
1218
1219     This->SourceRect.left = 0;
1220     This->SourceRect.top = 0;
1221     This->SourceRect.right = This->VideoWidth;
1222     This->SourceRect.bottom = This->VideoHeight;
1223
1224     return S_OK;
1225 }
1226
1227 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
1228                                                         long Left,
1229                                                         long Top,
1230                                                         long Width,
1231                                                         long Height) {
1232     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1233
1234     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1235
1236     This->DestRect.left = Left;
1237     This->DestRect.top = Top;
1238     This->DestRect.right = Left + Width;
1239     This->DestRect.bottom = Top + Height;
1240
1241     return S_OK;
1242 }
1243
1244 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
1245                                                         long *pLeft,
1246                                                         long *pTop,
1247                                                         long *pWidth,
1248                                                         long *pHeight) {
1249     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1250
1251     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1252
1253     *pLeft = This->DestRect.left;
1254     *pTop = This->DestRect.top;
1255     *pWidth = This->DestRect.right - This->DestRect.left;
1256     *pHeight = This->DestRect.bottom - This->DestRect.top;
1257
1258     return S_OK;
1259 }
1260
1261 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
1262     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1263     RECT rect;
1264
1265     TRACE("(%p/%p)->()\n", This, iface);
1266
1267     if (!GetClientRect(This->hWnd, &rect))
1268         return E_FAIL;
1269     
1270     This->SourceRect.left = 0;
1271     This->SourceRect.top = 0;
1272     This->SourceRect.right = rect.right;
1273     This->SourceRect.bottom = rect.bottom;
1274     
1275     return S_OK;
1276 }
1277
1278 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
1279                                               long *pWidth,
1280                                               long *pHeight) {
1281     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1282
1283     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
1284
1285     *pWidth = This->VideoWidth;
1286     *pHeight = This->VideoHeight;
1287     
1288     return S_OK;
1289 }
1290
1291 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
1292                                                         long StartIndex,
1293                                                         long Entries,
1294                                                         long *pRetrieved,
1295                                                         long *pPalette) {
1296     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1297
1298     FIXME("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
1299
1300     return S_OK;
1301 }
1302
1303 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
1304                                                  long *pBufferSize,
1305                                                  long *pDIBImage) {
1306     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1307
1308     FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
1309
1310     return S_OK;
1311 }
1312
1313 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
1314     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1315
1316     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1317
1318     return S_OK;
1319 }
1320
1321 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
1322     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1323
1324     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1325
1326     return S_OK;
1327 }
1328
1329
1330 static const IBasicVideoVtbl IBasicVideo_VTable =
1331 {
1332     Basicvideo_QueryInterface,
1333     Basicvideo_AddRef,
1334     Basicvideo_Release,
1335     Basicvideo_GetTypeInfoCount,
1336     Basicvideo_GetTypeInfo,
1337     Basicvideo_GetIDsOfNames,
1338     Basicvideo_Invoke,
1339     Basicvideo_get_AvgTimePerFrame,
1340     Basicvideo_get_BitRate,
1341     Basicvideo_get_BitErrorRate,
1342     Basicvideo_get_VideoWidth,
1343     Basicvideo_get_VideoHeight,
1344     Basicvideo_put_SourceLeft,
1345     Basicvideo_get_SourceLeft,
1346     Basicvideo_put_SourceWidth,
1347     Basicvideo_get_SourceWidth,
1348     Basicvideo_put_SourceTop,
1349     Basicvideo_get_SourceTop,
1350     Basicvideo_put_SourceHeight,
1351     Basicvideo_get_SourceHeight,
1352     Basicvideo_put_DestinationLeft,
1353     Basicvideo_get_DestinationLeft,
1354     Basicvideo_put_DestinationWidth,
1355     Basicvideo_get_DestinationWidth,
1356     Basicvideo_put_DestinationTop,
1357     Basicvideo_get_DestinationTop,
1358     Basicvideo_put_DestinationHeight,
1359     Basicvideo_get_DestinationHeight,
1360     Basicvideo_SetSourcePosition,
1361     Basicvideo_GetSourcePosition,
1362     Basicvideo_SetDefaultSourcePosition,
1363     Basicvideo_SetDestinationPosition,
1364     Basicvideo_GetDestinationPosition,
1365     Basicvideo_SetDefaultDestinationPosition,
1366     Basicvideo_GetVideoSize,
1367     Basicvideo_GetVideoPaletteEntries,
1368     Basicvideo_GetCurrentImage,
1369     Basicvideo_IsUsingDefaultSource,
1370     Basicvideo_IsUsingDefaultDestination
1371 };
1372
1373
1374 /*** IUnknown methods ***/
1375 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
1376                                                  REFIID riid,
1377                                                  LPVOID*ppvObj) {
1378     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1379
1380     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1381
1382     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1383 }
1384
1385 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
1386     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1387
1388     TRACE("(%p/%p)->()\n", This, iface);
1389
1390     return VideoRenderer_AddRef((IBaseFilter*)This);
1391 }
1392
1393 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
1394     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1395
1396     TRACE("(%p/%p)->()\n", This, iface);
1397
1398     return VideoRenderer_Release((IBaseFilter*)This);
1399 }
1400
1401 /*** IDispatch methods ***/
1402 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
1403                                                    UINT*pctinfo) {
1404     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1405
1406     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1407
1408     return S_OK;
1409 }
1410
1411 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
1412                                               UINT iTInfo,
1413                                               LCID lcid,
1414                                               ITypeInfo**ppTInfo) {
1415     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1416
1417     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1418
1419     return S_OK;
1420 }
1421
1422 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
1423                                                 REFIID riid,
1424                                                 LPOLESTR*rgszNames,
1425                                                 UINT cNames,
1426                                                 LCID lcid,
1427                                                 DISPID*rgDispId) {
1428     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1429
1430     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1431
1432     return S_OK;
1433 }
1434
1435 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
1436                                          DISPID dispIdMember,
1437                                          REFIID riid,
1438                                          LCID lcid,
1439                                          WORD wFlags,
1440                                          DISPPARAMS*pDispParams,
1441                                          VARIANT*pVarResult,
1442                                          EXCEPINFO*pExepInfo,
1443                                          UINT*puArgErr) {
1444     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1445
1446     FIXME("(%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);
1447
1448     return S_OK;
1449 }
1450
1451 /*** IVideoWindow methods ***/
1452 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
1453                                               BSTR strCaption) {
1454     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1455
1456     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
1457
1458     if (!SetWindowTextW(This->hWnd, strCaption))
1459         return E_FAIL;
1460
1461     return S_OK;
1462 }
1463
1464 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
1465                                               BSTR *strCaption) {
1466     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1467
1468     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
1469
1470     GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100);
1471
1472     return S_OK;
1473 }
1474
1475 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
1476                                                   long WindowStyle) {
1477     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1478     LONG old;
1479
1480     old = GetWindowLongA(This->hWnd, GWL_STYLE);
1481     
1482     TRACE("(%p/%p)->(%x -> %lx)\n", This, iface, old, WindowStyle);
1483
1484     if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1485         return E_INVALIDARG;
1486     
1487     SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle);
1488
1489     return S_OK;
1490 }
1491
1492 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
1493                                                   long *WindowStyle) {
1494     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1495
1496     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
1497
1498     *WindowStyle = GetWindowLongA(This->hWnd, GWL_STYLE);
1499
1500     return S_OK;
1501 }
1502
1503 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
1504                                                     long WindowStyleEx) {
1505     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1506
1507     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
1508
1509     if (WindowStyleEx & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1510         return E_INVALIDARG;
1511
1512     if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx))
1513         return E_FAIL;
1514
1515     return S_OK;
1516 }
1517
1518 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
1519                                                     long *WindowStyleEx) {
1520     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1521
1522     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
1523
1524     *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE);
1525
1526     return S_OK;
1527 }
1528
1529 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
1530                                                long AutoShow) {
1531     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1532
1533     TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
1534
1535     This->AutoShow = 1; /* FXIME: Should be AutoShow */;
1536
1537     return S_OK;
1538 }
1539
1540 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
1541                                                long *AutoShow) {
1542     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1543
1544     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
1545
1546     *AutoShow = This->AutoShow;
1547
1548     return S_OK;
1549 }
1550
1551 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
1552                                                   long WindowState) {
1553     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1554
1555     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
1556
1557     return S_OK;
1558 }
1559
1560 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
1561                                                   long *WindowState) {
1562     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1563
1564     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
1565
1566     return S_OK;
1567 }
1568
1569 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
1570                                                         long BackgroundPalette) {
1571     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1572
1573     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
1574
1575     return S_OK;
1576 }
1577
1578 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
1579                                                         long *pBackgroundPalette) {
1580     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1581
1582     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
1583
1584     return S_OK;
1585 }
1586
1587 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
1588                                               long Visible) {
1589     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1590
1591     TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
1592
1593     ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE);
1594
1595     return S_OK;
1596 }
1597
1598 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
1599                                               long *pVisible) {
1600     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1601
1602     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
1603
1604     *pVisible = IsWindowVisible(This->hWnd);
1605
1606     return S_OK;
1607 }
1608
1609 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
1610                                            long Left) {
1611     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1612
1613     TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
1614
1615     if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1616         return E_FAIL;
1617
1618     This->WindowPos.left = Left;
1619
1620     return S_OK;
1621 }
1622
1623 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
1624                                            long *pLeft) {
1625     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1626
1627     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
1628
1629     *pLeft = This->WindowPos.left;
1630
1631     return S_OK;
1632 }
1633
1634 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
1635                                             long Width) {
1636     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1637
1638     TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
1639
1640     if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE))
1641         return E_FAIL;
1642
1643     This->WindowPos.right = This->WindowPos.left + Width;
1644
1645     return S_OK;
1646 }
1647
1648 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
1649                                             long *pWidth) {
1650     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1651
1652     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
1653
1654     *pWidth = This->WindowPos.right - This->WindowPos.left;
1655
1656     return S_OK;
1657 }
1658
1659 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
1660                                           long Top) {
1661     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1662
1663     TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
1664
1665     if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1666         return E_FAIL;
1667
1668     This->WindowPos.top = Top;
1669
1670     return S_OK;
1671 }
1672
1673 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
1674                                           long *pTop) {
1675     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1676
1677     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
1678
1679     *pTop = This->WindowPos.top;
1680
1681     return S_OK;
1682 }
1683
1684 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
1685                                              long Height) {
1686     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1687
1688     TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
1689
1690     if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE))
1691         return E_FAIL;
1692
1693     This->WindowPos.bottom = This->WindowPos.top + Height;
1694
1695     return S_OK;
1696 }
1697
1698 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
1699                                              long *pHeight) {
1700     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1701
1702     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
1703
1704     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1705
1706     return S_OK;
1707 }
1708
1709 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
1710                                             OAHWND Owner) {
1711     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1712
1713     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1714
1715     SetParent(This->hWnd, (HWND)Owner);
1716
1717     return S_OK;
1718 }
1719
1720 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
1721                                             OAHWND *Owner) {
1722     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1723
1724     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1725
1726     *(HWND*)Owner = GetParent(This->hWnd);
1727
1728     return S_OK;
1729 }
1730
1731 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
1732                                                    OAHWND Drain) {
1733     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1734
1735     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
1736
1737     This->hWndMsgDrain = (HWND)Drain;
1738
1739     return S_OK;
1740 }
1741
1742 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
1743                                                    OAHWND *Drain) {
1744     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1745
1746     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
1747
1748     *Drain = (OAHWND)This->hWndMsgDrain;
1749
1750     return S_OK;
1751 }
1752
1753 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
1754                                                   long *Color) {
1755     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1756
1757     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
1758
1759     return S_OK;
1760 }
1761
1762 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
1763                                                   long Color) {
1764     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1765
1766     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
1767
1768     return S_OK;
1769 }
1770
1771 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
1772                                                      long *FullScreenMode) {
1773     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1774
1775     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
1776
1777     return S_OK;
1778 }
1779
1780 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
1781                                                      long FullScreenMode) {
1782     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1783
1784     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
1785
1786     return S_OK;
1787 }
1788
1789 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
1790                                                       long Focus) {
1791     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1792     BOOL ret;
1793     IPin* pPin;
1794     HRESULT hr;
1795
1796     TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
1797
1798     if ((Focus != FALSE) && (Focus != TRUE))
1799         return E_INVALIDARG;
1800
1801     hr = IPin_ConnectedTo(This->ppPins[0], &pPin);
1802     if ((hr != S_OK) || !pPin)
1803         return VFW_E_NOT_CONNECTED;
1804
1805     if (Focus)
1806         ret = SetForegroundWindow(This->hWnd);
1807     else
1808         ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1809
1810     if (!ret)
1811         return E_FAIL;
1812
1813     return S_OK;
1814 }
1815
1816 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
1817                                                      OAHWND hwnd,
1818                                                      long uMsg,
1819                                                      LONG_PTR wParam,
1820                                                      LONG_PTR lParam) {
1821     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1822
1823     TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
1824
1825     if (!PostMessageA(This->hWnd, uMsg, wParam, lParam))
1826         return E_FAIL;
1827     
1828     return S_OK;
1829 }
1830
1831 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
1832                                                     long Left,
1833                                                     long Top,
1834                                                     long Width,
1835                                                     long Height) {
1836     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1837     
1838     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1839
1840     if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER))
1841         return E_FAIL;
1842
1843     This->WindowPos.left = Left;
1844     This->WindowPos.top = Top;
1845     This->WindowPos.right = Left + Width;
1846     This->WindowPos.bottom = Top + Height;
1847     
1848     return S_OK;
1849 }
1850
1851 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
1852                                                     long *pLeft,
1853                                                     long *pTop,
1854                                                     long *pWidth,
1855                                                     long *pHeight) {
1856     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1857
1858     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1859
1860     *pLeft = This->WindowPos.left;
1861     *pTop = This->WindowPos.top;
1862     *pWidth = This->WindowPos.right - This->WindowPos.left;
1863     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1864
1865     return S_OK;
1866 }
1867
1868 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
1869                                                        long *pWidth,
1870                                                        long *pHeight) {
1871     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1872
1873     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1874
1875     *pWidth = This->VideoWidth;
1876     *pHeight = This->VideoHeight;
1877
1878     return S_OK;
1879 }
1880
1881 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
1882                                                        long *pWidth,
1883                                                        long *pHeight) {
1884     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1885
1886     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1887
1888     *pWidth = This->VideoWidth;
1889     *pHeight = This->VideoHeight;
1890
1891     return S_OK;
1892 }
1893
1894 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
1895                                                      long *pLeft,
1896                                                      long *pTop,
1897                                                      long *pWidth,
1898                                                      long *pHeight) {
1899     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1900
1901     FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
1902
1903     return S_OK;
1904 }
1905
1906 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
1907                                              long HideCursor) {
1908     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1909
1910     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
1911
1912     return S_OK;
1913 }
1914
1915 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
1916                                                  long *CursorHidden) {
1917     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1918
1919     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
1920
1921     return S_OK;
1922 }
1923
1924 static const IVideoWindowVtbl IVideoWindow_VTable =
1925 {
1926     Videowindow_QueryInterface,
1927     Videowindow_AddRef,
1928     Videowindow_Release,
1929     Videowindow_GetTypeInfoCount,
1930     Videowindow_GetTypeInfo,
1931     Videowindow_GetIDsOfNames,
1932     Videowindow_Invoke,
1933     Videowindow_put_Caption,
1934     Videowindow_get_Caption,
1935     Videowindow_put_WindowStyle,
1936     Videowindow_get_WindowStyle,
1937     Videowindow_put_WindowStyleEx,
1938     Videowindow_get_WindowStyleEx,
1939     Videowindow_put_AutoShow,
1940     Videowindow_get_AutoShow,
1941     Videowindow_put_WindowState,
1942     Videowindow_get_WindowState,
1943     Videowindow_put_BackgroundPalette,
1944     Videowindow_get_BackgroundPalette,
1945     Videowindow_put_Visible,
1946     Videowindow_get_Visible,
1947     Videowindow_put_Left,
1948     Videowindow_get_Left,
1949     Videowindow_put_Width,
1950     Videowindow_get_Width,
1951     Videowindow_put_Top,
1952     Videowindow_get_Top,
1953     Videowindow_put_Height,
1954     Videowindow_get_Height,
1955     Videowindow_put_Owner,
1956     Videowindow_get_Owner,
1957     Videowindow_put_MessageDrain,
1958     Videowindow_get_MessageDrain,
1959     Videowindow_get_BorderColor,
1960     Videowindow_put_BorderColor,
1961     Videowindow_get_FullScreenMode,
1962     Videowindow_put_FullScreenMode,
1963     Videowindow_SetWindowForeground,
1964     Videowindow_NotifyOwnerMessage,
1965     Videowindow_SetWindowPosition,
1966     Videowindow_GetWindowPosition,
1967     Videowindow_GetMinIdealImageSize,
1968     Videowindow_GetMaxIdealImageSize,
1969     Videowindow_GetRestorePosition,
1970     Videowindow_HideCursor,
1971     Videowindow_IsCursorHidden
1972 };