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