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