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