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