quartz: Clean up pullpin code.
[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
515     /* construct input pin */
516     piInput.dir = PINDIR_INPUT;
517     piInput.pFilter = (IBaseFilter *)pVideoRenderer;
518     lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
519
520     hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, (IPin **)&pVideoRenderer->pInputPin);
521
522     if (SUCCEEDED(hr))
523     {
524         *ppv = (LPVOID)pVideoRenderer;
525     }
526     else
527     {
528         pVideoRenderer->csFilter.DebugInfo->Spare[0] = 0;
529         DeleteCriticalSection(&pVideoRenderer->csFilter);
530         CoTaskMemFree(pVideoRenderer);
531     }
532
533     if (!CreateRenderingSubsystem(pVideoRenderer))
534         return E_FAIL;
535     
536     return hr;
537 }
538
539 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
540 {
541     /* TODO: Attempt to use the VMR-7 renderer instead when possible */
542     return VideoRenderer_create(pUnkOuter, ppv);
543 }
544
545 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
546 {
547     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
548     TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
549
550     if (This->bAggregatable)
551         This->bUnkOuterValid = TRUE;
552
553     *ppv = NULL;
554
555     if (IsEqualIID(riid, &IID_IUnknown))
556         *ppv = (LPVOID)&(This->IInner_vtbl);
557     else if (IsEqualIID(riid, &IID_IPersist))
558         *ppv = (LPVOID)This;
559     else if (IsEqualIID(riid, &IID_IMediaFilter))
560         *ppv = (LPVOID)This;
561     else if (IsEqualIID(riid, &IID_IBaseFilter))
562         *ppv = (LPVOID)This;
563     else if (IsEqualIID(riid, &IID_IBasicVideo))
564         *ppv = (LPVOID)&(This->IBasicVideo_vtbl);
565     else if (IsEqualIID(riid, &IID_IVideoWindow))
566         *ppv = (LPVOID)&(This->IVideoWindow_vtbl);
567
568     if (*ppv)
569     {
570         IUnknown_AddRef((IUnknown *)(*ppv));
571         return S_OK;
572     }
573
574     if (!IsEqualIID(riid, &IID_IPin))
575         FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
576
577     return E_NOINTERFACE;
578 }
579
580 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface)
581 {
582     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
583     ULONG refCount = InterlockedIncrement(&This->refCount);
584
585     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
586
587     return refCount;
588 }
589
590 static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
591 {
592     ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
593     ULONG refCount = InterlockedDecrement(&This->refCount);
594
595     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
596
597     if (!refCount)
598     {
599         IPin *pConnectedTo;
600
601         DestroyWindow(This->hWnd);
602         PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
603         WaitForSingleObject(This->hThread, INFINITE);
604         CloseHandle(This->hThread);
605
606         if (This->pClock)
607             IReferenceClock_Release(This->pClock);
608         
609         if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
610         {
611             IPin_Disconnect(pConnectedTo);
612             IPin_Release(pConnectedTo);
613         }
614         IPin_Disconnect((IPin *)This->pInputPin);
615
616         IPin_Release((IPin *)This->pInputPin);
617
618         This->lpVtbl = NULL;
619         
620         This->csFilter.DebugInfo->Spare[0] = 0;
621         DeleteCriticalSection(&This->csFilter);
622
623         TRACE("Destroying Video Renderer\n");
624         CoTaskMemFree(This);
625         
626         return 0;
627     }
628     else
629         return refCount;
630 }
631
632 static const IUnknownVtbl IInner_VTable =
633 {
634     VideoRendererInner_QueryInterface,
635     VideoRendererInner_AddRef,
636     VideoRendererInner_Release
637 };
638
639 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
640 {
641     VideoRendererImpl *This = (VideoRendererImpl *)iface;
642
643     if (This->bAggregatable)
644         This->bUnkOuterValid = TRUE;
645
646     if (This->pUnkOuter)
647     {
648         if (This->bAggregatable)
649             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
650
651         if (IsEqualIID(riid, &IID_IUnknown))
652         {
653             HRESULT hr;
654
655             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
656             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
657             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
658             This->bAggregatable = TRUE;
659             return hr;
660         }
661
662         *ppv = NULL;
663         return E_NOINTERFACE;
664     }
665
666     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
667 }
668
669 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
670 {
671     VideoRendererImpl *This = (VideoRendererImpl *)iface;
672
673     if (This->pUnkOuter && This->bUnkOuterValid)
674         return IUnknown_AddRef(This->pUnkOuter);
675     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
676 }
677
678 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
679 {
680     VideoRendererImpl *This = (VideoRendererImpl *)iface;
681
682     if (This->pUnkOuter && This->bUnkOuterValid)
683         return IUnknown_Release(This->pUnkOuter);
684     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
685 }
686
687 /** IPersist methods **/
688
689 static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
690 {
691     VideoRendererImpl *This = (VideoRendererImpl *)iface;
692
693     TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
694
695     *pClsid = CLSID_VideoRenderer;
696
697     return S_OK;
698 }
699
700 /** IMediaFilter methods **/
701
702 static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
703 {
704     VideoRendererImpl *This = (VideoRendererImpl *)iface;
705
706     TRACE("(%p/%p)->()\n", This, iface);
707
708     EnterCriticalSection(&This->csFilter);
709     {
710         This->state = State_Stopped;
711     }
712     LeaveCriticalSection(&This->csFilter);
713     
714     return S_OK;
715 }
716
717 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
718 {
719     VideoRendererImpl *This = (VideoRendererImpl *)iface;
720     
721     TRACE("(%p/%p)->()\n", This, iface);
722
723     EnterCriticalSection(&This->csFilter);
724     {
725         if (This->state == State_Stopped)
726             This->pInputPin->end_of_stream = 0;
727
728         This->state = State_Paused;
729     }
730     LeaveCriticalSection(&This->csFilter);
731
732     return S_OK;
733 }
734
735 static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
736 {
737     VideoRendererImpl *This = (VideoRendererImpl *)iface;
738
739     TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
740
741     EnterCriticalSection(&This->csFilter);
742     if (This->state != State_Running)
743     {
744         if (This->state == State_Stopped)
745             This->pInputPin->end_of_stream = 0;
746
747         This->rtStreamStart = tStart;
748         This->state = State_Running;
749     }
750     LeaveCriticalSection(&This->csFilter);
751
752     return S_OK;
753 }
754
755 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
756 {
757     VideoRendererImpl *This = (VideoRendererImpl *)iface;
758
759     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
760
761     EnterCriticalSection(&This->csFilter);
762     {
763         *pState = This->state;
764     }
765     LeaveCriticalSection(&This->csFilter);
766
767     return S_OK;
768 }
769
770 static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
771 {
772     VideoRendererImpl *This = (VideoRendererImpl *)iface;
773
774     TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
775
776     EnterCriticalSection(&This->csFilter);
777     {
778         if (This->pClock)
779             IReferenceClock_Release(This->pClock);
780         This->pClock = pClock;
781         if (This->pClock)
782             IReferenceClock_AddRef(This->pClock);
783     }
784     LeaveCriticalSection(&This->csFilter);
785
786     return S_OK;
787 }
788
789 static HRESULT WINAPI VideoRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
790 {
791     VideoRendererImpl *This = (VideoRendererImpl *)iface;
792
793     TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
794
795     EnterCriticalSection(&This->csFilter);
796     {
797         *ppClock = This->pClock;
798         if (This->pClock)
799             IReferenceClock_AddRef(This->pClock);
800     }
801     LeaveCriticalSection(&This->csFilter);
802     
803     return S_OK;
804 }
805
806 /** IBaseFilter implementation **/
807
808 static HRESULT VideoRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
809 {
810     VideoRendererImpl *This = (VideoRendererImpl *)iface;
811
812     /* Our pins are static, not changing so setting static tick count is ok */
813     *lastsynctick = 0;
814
815     if (pos >= 1)
816         return S_FALSE;
817
818     *pin = (IPin *)This->pInputPin;
819     IPin_AddRef(*pin);
820     return S_OK;
821 }
822
823 static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
824 {
825     VideoRendererImpl *This = (VideoRendererImpl *)iface;
826
827     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
828
829     return IEnumPinsImpl_Construct(ppEnum, VideoRenderer_GetPin, iface);
830 }
831
832 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
833 {
834     VideoRendererImpl *This = (VideoRendererImpl *)iface;
835
836     TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
837
838     FIXME("VideoRenderer::FindPin(...)\n");
839
840     /* FIXME: critical section */
841
842     return E_NOTIMPL;
843 }
844
845 static HRESULT WINAPI VideoRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
846 {
847     VideoRendererImpl *This = (VideoRendererImpl *)iface;
848
849     TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
850
851     strcpyW(pInfo->achName, This->filterInfo.achName);
852     pInfo->pGraph = This->filterInfo.pGraph;
853
854     if (pInfo->pGraph)
855         IFilterGraph_AddRef(pInfo->pGraph);
856     
857     return S_OK;
858 }
859
860 static HRESULT WINAPI VideoRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
861 {
862     VideoRendererImpl *This = (VideoRendererImpl *)iface;
863
864     TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
865
866     EnterCriticalSection(&This->csFilter);
867     {
868         if (pName)
869             strcpyW(This->filterInfo.achName, pName);
870         else
871             *This->filterInfo.achName = '\0';
872         This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
873     }
874     LeaveCriticalSection(&This->csFilter);
875
876     return S_OK;
877 }
878
879 static HRESULT WINAPI VideoRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
880 {
881     VideoRendererImpl *This = (VideoRendererImpl *)iface;
882     TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
883     return E_NOTIMPL;
884 }
885
886 static const IBaseFilterVtbl VideoRenderer_Vtbl =
887 {
888     VideoRenderer_QueryInterface,
889     VideoRenderer_AddRef,
890     VideoRenderer_Release,
891     VideoRenderer_GetClassID,
892     VideoRenderer_Stop,
893     VideoRenderer_Pause,
894     VideoRenderer_Run,
895     VideoRenderer_GetState,
896     VideoRenderer_SetSyncSource,
897     VideoRenderer_GetSyncSource,
898     VideoRenderer_EnumPins,
899     VideoRenderer_FindPin,
900     VideoRenderer_QueryFilterInfo,
901     VideoRenderer_JoinFilterGraph,
902     VideoRenderer_QueryVendorInfo
903 };
904
905 static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
906 {
907     InputPin* This = (InputPin*)iface;
908     IMediaEventSink* pEventSink;
909     HRESULT hr;
910
911     TRACE("(%p/%p)->()\n", This, iface);
912
913     hr = IFilterGraph_QueryInterface(((VideoRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
914     if (SUCCEEDED(hr))
915     {
916         hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
917         IMediaEventSink_Release(pEventSink);
918     }
919
920     return hr;
921 }
922
923 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
924 {
925     InputPin_QueryInterface,
926     IPinImpl_AddRef,
927     InputPin_Release,
928     InputPin_Connect,
929     InputPin_ReceiveConnection,
930     IPinImpl_Disconnect,
931     IPinImpl_ConnectedTo,
932     IPinImpl_ConnectionMediaType,
933     IPinImpl_QueryPinInfo,
934     IPinImpl_QueryDirection,
935     IPinImpl_QueryId,
936     IPinImpl_QueryAccept,
937     IPinImpl_EnumMediaTypes,
938     IPinImpl_QueryInternalConnections,
939     VideoRenderer_InputPin_EndOfStream,
940     InputPin_BeginFlush,
941     InputPin_EndFlush,
942     InputPin_NewSegment
943 };
944
945 /*** IUnknown methods ***/
946 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
947                                                 REFIID riid,
948                                                 LPVOID*ppvObj) {
949     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
950
951     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
952
953     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
954 }
955
956 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
957     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
958
959     TRACE("(%p/%p)->()\n", This, iface);
960
961     return VideoRenderer_AddRef((IBaseFilter*)This);
962 }
963
964 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
965     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
966
967     TRACE("(%p/%p)->()\n", This, iface);
968
969     return VideoRenderer_Release((IBaseFilter*)This);
970 }
971
972 /*** IDispatch methods ***/
973 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
974                                                   UINT*pctinfo) {
975     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
976
977     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
978
979     return S_OK;
980 }
981
982 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
983                                              UINT iTInfo,
984                                              LCID lcid,
985                                              ITypeInfo**ppTInfo) {
986     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
987
988     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
989
990     return S_OK;
991 }
992
993 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
994                                                REFIID riid,
995                                                LPOLESTR*rgszNames,
996                                                UINT cNames,
997                                                LCID lcid,
998                                                DISPID*rgDispId) {
999     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1000
1001     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1002
1003     return S_OK;
1004 }
1005
1006 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
1007                                         DISPID dispIdMember,
1008                                         REFIID riid,
1009                                         LCID lcid,
1010                                         WORD wFlags,
1011                                         DISPPARAMS*pDispParams,
1012                                         VARIANT*pVarResult,
1013                                         EXCEPINFO*pExepInfo,
1014                                         UINT*puArgErr) {
1015     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1016
1017     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);
1018
1019     return S_OK;
1020 }
1021
1022 /*** IBasicVideo methods ***/
1023 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
1024                                                      REFTIME *pAvgTimePerFrame) {
1025     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1026
1027     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
1028
1029     return S_OK;
1030 }
1031
1032 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
1033                                              long *pBitRate) {
1034     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1035
1036     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
1037
1038     return S_OK;
1039 }
1040
1041 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
1042                                                   long *pBitErrorRate) {
1043     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1044
1045     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
1046
1047     return S_OK;
1048 }
1049
1050 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
1051                                                 long *pVideoWidth) {
1052     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1053
1054     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
1055
1056     *pVideoWidth = This->VideoWidth;
1057
1058     return S_OK;
1059 }
1060
1061 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
1062                                                  long *pVideoHeight) {
1063     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1064
1065     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
1066
1067     *pVideoHeight = This->VideoHeight;
1068
1069     return S_OK;
1070 }
1071
1072 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1073                                                 long SourceLeft) {
1074     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1075
1076     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
1077
1078     This->SourceRect.left = SourceLeft;
1079
1080     return S_OK;
1081 }
1082
1083 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1084                                                 long *pSourceLeft) {
1085     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1086
1087     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
1088
1089     *pSourceLeft = This->SourceRect.left;
1090
1091     return S_OK;
1092 }
1093
1094 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1095                                                  long SourceWidth) {
1096     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1097
1098     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
1099
1100     This->SourceRect.right = This->SourceRect.left + SourceWidth;
1101
1102     return S_OK;
1103 }
1104
1105 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1106                                                  long *pSourceWidth) {
1107     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1108
1109     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
1110
1111     *pSourceWidth = This->SourceRect.right - This->SourceRect.left;
1112     
1113     return S_OK;
1114 }
1115
1116 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1117                                                long SourceTop) {
1118     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1119
1120     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
1121
1122     This->SourceRect.top = SourceTop;
1123
1124     return S_OK;
1125 }
1126
1127 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1128                                                long *pSourceTop) {
1129     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1130
1131     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
1132
1133     *pSourceTop = This->SourceRect.top;
1134
1135     return S_OK;
1136 }
1137
1138 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1139                                                   long SourceHeight) {
1140     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1141
1142     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
1143
1144     This->SourceRect.bottom = This->SourceRect.top + SourceHeight;
1145
1146     return S_OK;
1147 }
1148
1149 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1150                                                   long *pSourceHeight) {
1151     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1152
1153     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
1154
1155     *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top;
1156
1157     return S_OK;
1158 }
1159
1160 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1161                                                      long DestinationLeft) {
1162     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1163
1164     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
1165
1166     This->DestRect.left = DestinationLeft;
1167
1168     return S_OK;
1169 }
1170
1171 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1172                                                      long *pDestinationLeft) {
1173     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1174
1175     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
1176
1177     *pDestinationLeft = This->DestRect.left;
1178
1179     return S_OK;
1180 }
1181
1182 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1183                                                       long DestinationWidth) {
1184     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1185
1186     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
1187
1188     This->DestRect.right = This->DestRect.left + DestinationWidth;
1189
1190     return S_OK;
1191 }
1192
1193 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1194                                                       long *pDestinationWidth) {
1195     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1196
1197     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
1198
1199     *pDestinationWidth = This->DestRect.right - This->DestRect.left;
1200
1201     return S_OK;
1202 }
1203
1204 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1205                                                     long DestinationTop) {
1206     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1207
1208     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
1209
1210     This->DestRect.top = DestinationTop;
1211     
1212     return S_OK;
1213 }
1214
1215 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1216                                                     long *pDestinationTop) {
1217     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1218
1219     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
1220
1221     *pDestinationTop = This->DestRect.top;
1222
1223     return S_OK;
1224 }
1225
1226 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1227                                                        long DestinationHeight) {
1228     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1229
1230     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
1231
1232     This->DestRect.right = This->DestRect.left + DestinationHeight;
1233
1234     return S_OK;
1235 }
1236
1237 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1238                                                        long *pDestinationHeight) {
1239     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1240
1241     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
1242
1243     *pDestinationHeight = This->DestRect.right - This->DestRect.left;
1244
1245     return S_OK;
1246 }
1247
1248 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1249                                                    long Left,
1250                                                    long Top,
1251                                                    long Width,
1252                                                    long Height) {
1253     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1254
1255     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1256
1257     This->SourceRect.left = Left;
1258     This->SourceRect.top = Top;
1259     This->SourceRect.right = Left + Width;
1260     This->SourceRect.bottom = Top + Height;
1261     
1262     return S_OK;
1263 }
1264
1265 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
1266                                                    long *pLeft,
1267                                                    long *pTop,
1268                                                    long *pWidth,
1269                                                    long *pHeight) {
1270     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1271
1272     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1273
1274     *pLeft = This->SourceRect.left;
1275     *pTop = This->SourceRect.top;
1276     *pWidth = This->SourceRect.right - This->SourceRect.left;
1277     *pHeight = This->SourceRect.bottom - This->SourceRect.top;
1278     
1279     return S_OK;
1280 }
1281
1282 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
1283     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1284
1285     TRACE("(%p/%p)->()\n", This, iface);
1286
1287     This->SourceRect.left = 0;
1288     This->SourceRect.top = 0;
1289     This->SourceRect.right = This->VideoWidth;
1290     This->SourceRect.bottom = This->VideoHeight;
1291
1292     return S_OK;
1293 }
1294
1295 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
1296                                                         long Left,
1297                                                         long Top,
1298                                                         long Width,
1299                                                         long Height) {
1300     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1301
1302     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1303
1304     This->DestRect.left = Left;
1305     This->DestRect.top = Top;
1306     This->DestRect.right = Left + Width;
1307     This->DestRect.bottom = Top + Height;
1308
1309     return S_OK;
1310 }
1311
1312 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
1313                                                         long *pLeft,
1314                                                         long *pTop,
1315                                                         long *pWidth,
1316                                                         long *pHeight) {
1317     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1318
1319     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1320
1321     *pLeft = This->DestRect.left;
1322     *pTop = This->DestRect.top;
1323     *pWidth = This->DestRect.right - This->DestRect.left;
1324     *pHeight = This->DestRect.bottom - This->DestRect.top;
1325
1326     return S_OK;
1327 }
1328
1329 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
1330     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1331     RECT rect;
1332
1333     TRACE("(%p/%p)->()\n", This, iface);
1334
1335     if (!GetClientRect(This->hWnd, &rect))
1336         return E_FAIL;
1337     
1338     This->SourceRect.left = 0;
1339     This->SourceRect.top = 0;
1340     This->SourceRect.right = rect.right;
1341     This->SourceRect.bottom = rect.bottom;
1342     
1343     return S_OK;
1344 }
1345
1346 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
1347                                               long *pWidth,
1348                                               long *pHeight) {
1349     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1350
1351     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
1352
1353     *pWidth = This->VideoWidth;
1354     *pHeight = This->VideoHeight;
1355     
1356     return S_OK;
1357 }
1358
1359 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
1360                                                         long StartIndex,
1361                                                         long Entries,
1362                                                         long *pRetrieved,
1363                                                         long *pPalette) {
1364     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1365
1366     FIXME("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
1367
1368     return S_OK;
1369 }
1370
1371 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
1372                                                  long *pBufferSize,
1373                                                  long *pDIBImage) {
1374     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1375
1376     FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
1377
1378     return S_OK;
1379 }
1380
1381 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
1382     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1383
1384     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1385
1386     return S_OK;
1387 }
1388
1389 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
1390     ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1391
1392     FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1393
1394     return S_OK;
1395 }
1396
1397
1398 static const IBasicVideoVtbl IBasicVideo_VTable =
1399 {
1400     Basicvideo_QueryInterface,
1401     Basicvideo_AddRef,
1402     Basicvideo_Release,
1403     Basicvideo_GetTypeInfoCount,
1404     Basicvideo_GetTypeInfo,
1405     Basicvideo_GetIDsOfNames,
1406     Basicvideo_Invoke,
1407     Basicvideo_get_AvgTimePerFrame,
1408     Basicvideo_get_BitRate,
1409     Basicvideo_get_BitErrorRate,
1410     Basicvideo_get_VideoWidth,
1411     Basicvideo_get_VideoHeight,
1412     Basicvideo_put_SourceLeft,
1413     Basicvideo_get_SourceLeft,
1414     Basicvideo_put_SourceWidth,
1415     Basicvideo_get_SourceWidth,
1416     Basicvideo_put_SourceTop,
1417     Basicvideo_get_SourceTop,
1418     Basicvideo_put_SourceHeight,
1419     Basicvideo_get_SourceHeight,
1420     Basicvideo_put_DestinationLeft,
1421     Basicvideo_get_DestinationLeft,
1422     Basicvideo_put_DestinationWidth,
1423     Basicvideo_get_DestinationWidth,
1424     Basicvideo_put_DestinationTop,
1425     Basicvideo_get_DestinationTop,
1426     Basicvideo_put_DestinationHeight,
1427     Basicvideo_get_DestinationHeight,
1428     Basicvideo_SetSourcePosition,
1429     Basicvideo_GetSourcePosition,
1430     Basicvideo_SetDefaultSourcePosition,
1431     Basicvideo_SetDestinationPosition,
1432     Basicvideo_GetDestinationPosition,
1433     Basicvideo_SetDefaultDestinationPosition,
1434     Basicvideo_GetVideoSize,
1435     Basicvideo_GetVideoPaletteEntries,
1436     Basicvideo_GetCurrentImage,
1437     Basicvideo_IsUsingDefaultSource,
1438     Basicvideo_IsUsingDefaultDestination
1439 };
1440
1441
1442 /*** IUnknown methods ***/
1443 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
1444                                                  REFIID riid,
1445                                                  LPVOID*ppvObj) {
1446     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1447
1448     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1449
1450     return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1451 }
1452
1453 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
1454     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1455
1456     TRACE("(%p/%p)->()\n", This, iface);
1457
1458     return VideoRenderer_AddRef((IBaseFilter*)This);
1459 }
1460
1461 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
1462     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1463
1464     TRACE("(%p/%p)->()\n", This, iface);
1465
1466     return VideoRenderer_Release((IBaseFilter*)This);
1467 }
1468
1469 /*** IDispatch methods ***/
1470 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
1471                                                    UINT*pctinfo) {
1472     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1473
1474     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1475
1476     return S_OK;
1477 }
1478
1479 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
1480                                               UINT iTInfo,
1481                                               LCID lcid,
1482                                               ITypeInfo**ppTInfo) {
1483     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1484
1485     FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1486
1487     return S_OK;
1488 }
1489
1490 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
1491                                                 REFIID riid,
1492                                                 LPOLESTR*rgszNames,
1493                                                 UINT cNames,
1494                                                 LCID lcid,
1495                                                 DISPID*rgDispId) {
1496     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1497
1498     FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1499
1500     return S_OK;
1501 }
1502
1503 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
1504                                          DISPID dispIdMember,
1505                                          REFIID riid,
1506                                          LCID lcid,
1507                                          WORD wFlags,
1508                                          DISPPARAMS*pDispParams,
1509                                          VARIANT*pVarResult,
1510                                          EXCEPINFO*pExepInfo,
1511                                          UINT*puArgErr) {
1512     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1513
1514     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);
1515
1516     return S_OK;
1517 }
1518
1519 /*** IVideoWindow methods ***/
1520 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
1521                                               BSTR strCaption) {
1522     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1523
1524     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
1525
1526     if (!SetWindowTextW(This->hWnd, strCaption))
1527         return E_FAIL;
1528
1529     return S_OK;
1530 }
1531
1532 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
1533                                               BSTR *strCaption) {
1534     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1535
1536     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
1537
1538     GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100);
1539
1540     return S_OK;
1541 }
1542
1543 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
1544                                                   long WindowStyle) {
1545     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1546     LONG old;
1547
1548     old = GetWindowLongA(This->hWnd, GWL_STYLE);
1549     
1550     TRACE("(%p/%p)->(%x -> %lx)\n", This, iface, old, WindowStyle);
1551
1552     if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1553         return E_INVALIDARG;
1554     
1555     SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle);
1556
1557     return S_OK;
1558 }
1559
1560 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
1561                                                   long *WindowStyle) {
1562     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1563
1564     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
1565
1566     *WindowStyle = GetWindowLongA(This->hWnd, GWL_STYLE);
1567
1568     return S_OK;
1569 }
1570
1571 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
1572                                                     long WindowStyleEx) {
1573     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1574
1575     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
1576
1577     if (WindowStyleEx & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1578         return E_INVALIDARG;
1579
1580     if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx))
1581         return E_FAIL;
1582
1583     return S_OK;
1584 }
1585
1586 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
1587                                                     long *WindowStyleEx) {
1588     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1589
1590     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
1591
1592     *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE);
1593
1594     return S_OK;
1595 }
1596
1597 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
1598                                                long AutoShow) {
1599     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1600
1601     TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
1602
1603     This->AutoShow = 1; /* FXIME: Should be AutoShow */;
1604
1605     return S_OK;
1606 }
1607
1608 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
1609                                                long *AutoShow) {
1610     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1611
1612     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
1613
1614     *AutoShow = This->AutoShow;
1615
1616     return S_OK;
1617 }
1618
1619 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
1620                                                   long WindowState) {
1621     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1622
1623     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
1624
1625     return S_OK;
1626 }
1627
1628 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
1629                                                   long *WindowState) {
1630     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1631
1632     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
1633
1634     return S_OK;
1635 }
1636
1637 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
1638                                                         long BackgroundPalette) {
1639     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1640
1641     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
1642
1643     return S_OK;
1644 }
1645
1646 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
1647                                                         long *pBackgroundPalette) {
1648     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1649
1650     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
1651
1652     return S_OK;
1653 }
1654
1655 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
1656                                               long Visible) {
1657     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1658
1659     TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
1660
1661     ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE);
1662
1663     return S_OK;
1664 }
1665
1666 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
1667                                               long *pVisible) {
1668     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1669
1670     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
1671
1672     *pVisible = IsWindowVisible(This->hWnd);
1673
1674     return S_OK;
1675 }
1676
1677 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
1678                                            long Left) {
1679     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1680
1681     TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
1682
1683     if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1684         return E_FAIL;
1685
1686     This->WindowPos.left = Left;
1687
1688     return S_OK;
1689 }
1690
1691 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
1692                                            long *pLeft) {
1693     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1694
1695     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
1696
1697     *pLeft = This->WindowPos.left;
1698
1699     return S_OK;
1700 }
1701
1702 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
1703                                             long Width) {
1704     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1705
1706     TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
1707
1708     if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE))
1709         return E_FAIL;
1710
1711     This->WindowPos.right = This->WindowPos.left + Width;
1712
1713     return S_OK;
1714 }
1715
1716 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
1717                                             long *pWidth) {
1718     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1719
1720     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
1721
1722     *pWidth = This->WindowPos.right - This->WindowPos.left;
1723
1724     return S_OK;
1725 }
1726
1727 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
1728                                           long Top) {
1729     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1730
1731     TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
1732
1733     if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1734         return E_FAIL;
1735
1736     This->WindowPos.top = Top;
1737
1738     return S_OK;
1739 }
1740
1741 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
1742                                           long *pTop) {
1743     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1744
1745     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
1746
1747     *pTop = This->WindowPos.top;
1748
1749     return S_OK;
1750 }
1751
1752 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
1753                                              long Height) {
1754     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1755
1756     TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
1757
1758     if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE))
1759         return E_FAIL;
1760
1761     This->WindowPos.bottom = This->WindowPos.top + Height;
1762
1763     return S_OK;
1764 }
1765
1766 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
1767                                              long *pHeight) {
1768     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1769
1770     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
1771
1772     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1773
1774     return S_OK;
1775 }
1776
1777 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
1778                                             OAHWND Owner) {
1779     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1780
1781     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1782
1783     SetParent(This->hWnd, (HWND)Owner);
1784
1785     return S_OK;
1786 }
1787
1788 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
1789                                             OAHWND *Owner) {
1790     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1791
1792     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1793
1794     *(HWND*)Owner = GetParent(This->hWnd);
1795
1796     return S_OK;
1797 }
1798
1799 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
1800                                                    OAHWND Drain) {
1801     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1802
1803     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
1804
1805     This->hWndMsgDrain = (HWND)Drain;
1806
1807     return S_OK;
1808 }
1809
1810 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
1811                                                    OAHWND *Drain) {
1812     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1813
1814     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
1815
1816     *Drain = (OAHWND)This->hWndMsgDrain;
1817
1818     return S_OK;
1819 }
1820
1821 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
1822                                                   long *Color) {
1823     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1824
1825     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
1826
1827     return S_OK;
1828 }
1829
1830 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
1831                                                   long Color) {
1832     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1833
1834     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
1835
1836     return S_OK;
1837 }
1838
1839 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
1840                                                      long *FullScreenMode) {
1841     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1842
1843     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
1844
1845     return S_OK;
1846 }
1847
1848 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
1849                                                      long FullScreenMode) {
1850     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1851
1852     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
1853
1854     return S_OK;
1855 }
1856
1857 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
1858                                                       long Focus) {
1859     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1860     BOOL ret;
1861     IPin* pPin;
1862     HRESULT hr;
1863
1864     TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
1865
1866     if ((Focus != FALSE) && (Focus != TRUE))
1867         return E_INVALIDARG;
1868
1869     hr = IPin_ConnectedTo((IPin *)This->pInputPin, &pPin);
1870     if ((hr != S_OK) || !pPin)
1871         return VFW_E_NOT_CONNECTED;
1872
1873     if (Focus)
1874         ret = SetForegroundWindow(This->hWnd);
1875     else
1876         ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1877
1878     if (!ret)
1879         return E_FAIL;
1880
1881     return S_OK;
1882 }
1883
1884 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
1885                                                      OAHWND hwnd,
1886                                                      long uMsg,
1887                                                      LONG_PTR wParam,
1888                                                      LONG_PTR lParam) {
1889     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1890
1891     TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
1892
1893     if (!PostMessageA(This->hWnd, uMsg, wParam, lParam))
1894         return E_FAIL;
1895     
1896     return S_OK;
1897 }
1898
1899 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
1900                                                     long Left,
1901                                                     long Top,
1902                                                     long Width,
1903                                                     long Height) {
1904     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1905     
1906     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
1907
1908     if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER))
1909         return E_FAIL;
1910
1911     This->WindowPos.left = Left;
1912     This->WindowPos.top = Top;
1913     This->WindowPos.right = Left + Width;
1914     This->WindowPos.bottom = Top + Height;
1915     
1916     return S_OK;
1917 }
1918
1919 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
1920                                                     long *pLeft,
1921                                                     long *pTop,
1922                                                     long *pWidth,
1923                                                     long *pHeight) {
1924     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1925
1926     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1927
1928     *pLeft = This->WindowPos.left;
1929     *pTop = This->WindowPos.top;
1930     *pWidth = This->WindowPos.right - This->WindowPos.left;
1931     *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1932
1933     return S_OK;
1934 }
1935
1936 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
1937                                                        long *pWidth,
1938                                                        long *pHeight) {
1939     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1940
1941     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1942
1943     *pWidth = This->VideoWidth;
1944     *pHeight = This->VideoHeight;
1945
1946     return S_OK;
1947 }
1948
1949 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
1950                                                        long *pWidth,
1951                                                        long *pHeight) {
1952     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1953
1954     FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
1955
1956     *pWidth = This->VideoWidth;
1957     *pHeight = This->VideoHeight;
1958
1959     return S_OK;
1960 }
1961
1962 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
1963                                                      long *pLeft,
1964                                                      long *pTop,
1965                                                      long *pWidth,
1966                                                      long *pHeight) {
1967     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1968
1969     FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
1970
1971     return S_OK;
1972 }
1973
1974 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
1975                                              long HideCursor) {
1976     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1977
1978     FIXME("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
1979
1980     return S_OK;
1981 }
1982
1983 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
1984                                                  long *CursorHidden) {
1985     ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1986
1987     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
1988
1989     return S_OK;
1990 }
1991
1992 static const IVideoWindowVtbl IVideoWindow_VTable =
1993 {
1994     Videowindow_QueryInterface,
1995     Videowindow_AddRef,
1996     Videowindow_Release,
1997     Videowindow_GetTypeInfoCount,
1998     Videowindow_GetTypeInfo,
1999     Videowindow_GetIDsOfNames,
2000     Videowindow_Invoke,
2001     Videowindow_put_Caption,
2002     Videowindow_get_Caption,
2003     Videowindow_put_WindowStyle,
2004     Videowindow_get_WindowStyle,
2005     Videowindow_put_WindowStyleEx,
2006     Videowindow_get_WindowStyleEx,
2007     Videowindow_put_AutoShow,
2008     Videowindow_get_AutoShow,
2009     Videowindow_put_WindowState,
2010     Videowindow_get_WindowState,
2011     Videowindow_put_BackgroundPalette,
2012     Videowindow_get_BackgroundPalette,
2013     Videowindow_put_Visible,
2014     Videowindow_get_Visible,
2015     Videowindow_put_Left,
2016     Videowindow_get_Left,
2017     Videowindow_put_Width,
2018     Videowindow_get_Width,
2019     Videowindow_put_Top,
2020     Videowindow_get_Top,
2021     Videowindow_put_Height,
2022     Videowindow_get_Height,
2023     Videowindow_put_Owner,
2024     Videowindow_get_Owner,
2025     Videowindow_put_MessageDrain,
2026     Videowindow_get_MessageDrain,
2027     Videowindow_get_BorderColor,
2028     Videowindow_put_BorderColor,
2029     Videowindow_get_FullScreenMode,
2030     Videowindow_put_FullScreenMode,
2031     Videowindow_SetWindowForeground,
2032     Videowindow_NotifyOwnerMessage,
2033     Videowindow_SetWindowPosition,
2034     Videowindow_GetWindowPosition,
2035     Videowindow_GetMinIdealImageSize,
2036     Videowindow_GetMaxIdealImageSize,
2037     Videowindow_GetRestorePosition,
2038     Videowindow_HideCursor,
2039     Videowindow_IsCursorHidden
2040 };