msvcrt: Implement _strlwr_s.
[wine.git] / dlls / quartz / videorenderer.c
blob7975e4d0b1950ddcc9537ccbdfee2c55e34456d9
1 /*
2 * Video Renderer (Fullscreen and Windowed using Direct Draw)
4 * Copyright 2004 Christian Costa
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.
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.
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
21 #include "config.h"
23 #define NONAMELESSSTRUCT
24 #define NONAMELESSUNION
25 #include "quartz_private.h"
26 #include "control_private.h"
27 #include "pin.h"
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"
40 #include <assert.h>
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
46 static BOOL wnd_class_registered = FALSE;
48 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
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;
56 typedef struct VideoRendererImpl
58 BaseFilter filter;
59 const IBasicVideoVtbl * IBasicVideo_vtbl;
60 const IVideoWindowVtbl * IVideoWindow_vtbl;
61 const IUnknownVtbl * IInner_vtbl;
62 IUnknown *seekthru_unk;
64 BaseInputPin *pInputPin;
66 BOOL init;
67 HANDLE hThread;
68 HANDLE blocked;
70 DWORD ThreadID;
71 HANDLE hEvent;
72 BOOL ThreadResult;
73 HWND hWnd;
74 HWND hWndMsgDrain;
75 BOOL AutoShow;
76 RECT SourceRect;
77 RECT DestRect;
78 RECT WindowPos;
79 LONG VideoWidth;
80 LONG VideoHeight;
81 IUnknown * pUnkOuter;
82 BOOL bUnkOuterValid;
83 BOOL bAggregatable;
84 REFERENCE_TIME rtLastStop;
85 MediaSeekingImpl mediaSeeking;
86 LONG WindowStyle;
88 /* During pause we can hold a single sample, for use in GetCurrentImage */
89 IMediaSample *sample_held;
90 } VideoRendererImpl;
92 static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
94 VideoRendererImpl* pVideoRenderer = (VideoRendererImpl*)GetWindowLongPtrW(hwnd, 0);
95 LPRECT lprect = (LPRECT)lParam;
97 if (pVideoRenderer && pVideoRenderer->hWndMsgDrain)
99 switch(uMsg)
101 case WM_KEYDOWN:
102 case WM_KEYUP:
103 case WM_LBUTTONDBLCLK:
104 case WM_LBUTTONDOWN:
105 case WM_LBUTTONUP:
106 case WM_MBUTTONDBLCLK:
107 case WM_MBUTTONDOWN:
108 case WM_MBUTTONUP:
109 case WM_MOUSEACTIVATE:
110 case WM_MOUSEMOVE:
111 case WM_NCLBUTTONDBLCLK:
112 case WM_NCLBUTTONDOWN:
113 case WM_NCLBUTTONUP:
114 case WM_NCMBUTTONDBLCLK:
115 case WM_NCMBUTTONDOWN:
116 case WM_NCMBUTTONUP:
117 case WM_NCMOUSEMOVE:
118 case WM_NCRBUTTONDBLCLK:
119 case WM_NCRBUTTONDOWN:
120 case WM_NCRBUTTONUP:
121 case WM_RBUTTONDBLCLK:
122 case WM_RBUTTONDOWN:
123 case WM_RBUTTONUP:
124 PostMessageA(pVideoRenderer->hWndMsgDrain, uMsg, wParam, lParam);
125 break;
126 default:
127 break;
131 switch(uMsg)
133 case WM_SIZING:
134 /* TRACE("WM_SIZING %d %d %d %d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); */
135 SetWindowPos(hwnd, NULL, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top, SWP_NOZORDER);
136 GetClientRect(hwnd, &pVideoRenderer->DestRect);
137 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
138 pVideoRenderer->DestRect.left,
139 pVideoRenderer->DestRect.top,
140 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
141 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
142 return TRUE;
143 case WM_SIZE:
144 TRACE("WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
145 GetClientRect(hwnd, &pVideoRenderer->DestRect);
146 TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n",
147 pVideoRenderer->DestRect.left,
148 pVideoRenderer->DestRect.top,
149 pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left,
150 pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top);
151 return TRUE;
152 default:
153 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
155 return 0;
158 static BOOL CreateRenderingWindow(VideoRendererImpl* This)
160 WNDCLASSA winclass;
162 TRACE("(%p)->()\n", This);
164 winclass.style = 0;
165 winclass.lpfnWndProc = VideoWndProcA;
166 winclass.cbClsExtra = 0;
167 winclass.cbWndExtra = sizeof(VideoRendererImpl*);
168 winclass.hInstance = NULL;
169 winclass.hIcon = NULL;
170 winclass.hCursor = NULL;
171 winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
172 winclass.lpszMenuName = NULL;
173 winclass.lpszClassName = "Wine ActiveMovie Class";
175 if (!wnd_class_registered)
177 if (!RegisterClassA(&winclass))
179 ERR("Unable to register window %u\n", GetLastError());
180 return FALSE;
182 wnd_class_registered = TRUE;
185 This->hWnd = CreateWindowExA(0, "Wine ActiveMovie Class", "Wine ActiveMovie Window", WS_SIZEBOX,
186 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
187 NULL, NULL, NULL);
189 if (!This->hWnd)
191 ERR("Unable to create window\n");
192 return FALSE;
195 SetWindowLongPtrW(This->hWnd, 0, (LONG_PTR)This);
197 return TRUE;
200 static DWORD WINAPI MessageLoop(LPVOID lpParameter)
202 VideoRendererImpl* This = lpParameter;
203 MSG msg;
204 BOOL fGotMessage;
206 TRACE("Starting message loop\n");
208 if (!CreateRenderingWindow(This))
210 This->ThreadResult = FALSE;
211 SetEvent(This->hEvent);
212 return 0;
215 This->ThreadResult = TRUE;
216 SetEvent(This->hEvent);
218 while ((fGotMessage = GetMessageA(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1)
220 TranslateMessage(&msg);
221 DispatchMessageA(&msg);
224 TRACE("End of message loop\n");
226 return msg.wParam;
229 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
231 This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
232 if (!This->hEvent)
233 return FALSE;
235 This->hThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->ThreadID);
236 if (!This->hThread)
238 CloseHandle(This->hEvent);
239 return FALSE;
242 WaitForSingleObject(This->hEvent, INFINITE);
244 if (!This->ThreadResult)
246 CloseHandle(This->hEvent);
247 CloseHandle(This->hThread);
248 return FALSE;
251 return TRUE;
254 static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size)
256 AM_MEDIA_TYPE amt;
257 HRESULT hr = S_OK;
258 DDSURFACEDESC sdesc;
259 HDC hDC;
260 BITMAPINFOHEADER *bmiHeader;
262 TRACE("(%p)->(%p, %d)\n", This, data, size);
264 sdesc.dwSize = sizeof(sdesc);
265 hr = IPin_ConnectionMediaType((IPin *)This->pInputPin, &amt);
266 if (FAILED(hr)) {
267 ERR("Unable to retrieve media type\n");
268 return hr;
271 if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo))
273 bmiHeader = &((VIDEOINFOHEADER *)amt.pbFormat)->bmiHeader;
275 else if (IsEqualIID(&amt.formattype, &FORMAT_VideoInfo2))
277 bmiHeader = &((VIDEOINFOHEADER2 *)amt.pbFormat)->bmiHeader;
279 else
281 FIXME("Unknown type %s\n", debugstr_guid(&amt.subtype));
282 return VFW_E_RUNTIME_ERROR;
285 TRACE("biSize = %d\n", bmiHeader->biSize);
286 TRACE("biWidth = %d\n", bmiHeader->biWidth);
287 TRACE("biHeight = %d\n", bmiHeader->biHeight);
288 TRACE("biPlanes = %d\n", bmiHeader->biPlanes);
289 TRACE("biBitCount = %d\n", bmiHeader->biBitCount);
290 TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
291 TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
293 if (!This->init)
295 if (!This->WindowPos.right || !This->WindowPos.top)
297 DWORD style = GetWindowLongW(This->hWnd, GWL_STYLE);
298 DWORD style_ex = GetWindowLongW(This->hWnd, GWL_EXSTYLE);
300 if (!This->WindowPos.right)
302 This->WindowPos.left = This->SourceRect.left;
303 This->WindowPos.right = This->SourceRect.right;
305 if (!This->WindowPos.bottom)
307 This->WindowPos.top = This->SourceRect.top;
308 This->WindowPos.bottom = This->SourceRect.bottom;
311 AdjustWindowRectEx(&This->WindowPos, style, TRUE, style_ex);
313 TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom);
314 SetWindowPos(This->hWnd, NULL,
315 This->WindowPos.left,
316 This->WindowPos.top,
317 This->WindowPos.right - This->WindowPos.left,
318 This->WindowPos.bottom - This->WindowPos.top,
319 SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE);
321 GetClientRect(This->hWnd, &This->DestRect);
323 else
324 This->DestRect = This->WindowPos;
325 This->init = TRUE;
328 hDC = GetDC(This->hWnd);
330 if (!hDC) {
331 ERR("Cannot get DC from window!\n");
332 return E_FAIL;
335 TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom);
336 TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom);
338 StretchDIBits(hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left,
339 This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top,
340 This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top,
341 data, (BITMAPINFO *)bmiHeader, DIB_RGB_COLORS, SRCCOPY);
343 ReleaseDC(This->hWnd, hDC);
344 if (This->AutoShow)
345 ShowWindow(This->hWnd, SW_SHOW);
347 return S_OK;
350 static HRESULT WINAPI VideoRenderer_Receive(IPin* iface, IMediaSample * pSample)
352 BaseInputPin* pin = (BaseInputPin*)iface;
353 VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
354 LPBYTE pbSrcStream = NULL;
355 LONG cbSrcStream = 0;
356 REFERENCE_TIME tStart, tStop;
357 HRESULT hr;
359 TRACE("(%p)->(%p)\n", iface, pSample);
361 EnterCriticalSection(&This->filter.csFilter);
363 if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
365 LeaveCriticalSection(&This->filter.csFilter);
366 return S_FALSE;
369 if (This->filter.state == State_Stopped)
371 LeaveCriticalSection(&This->filter.csFilter);
372 return VFW_E_WRONG_STATE;
375 hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
376 if (FAILED(hr))
377 ERR("Cannot get sample time (%x)\n", hr);
378 else
379 MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, tStart);
381 if (This->rtLastStop != tStart && This->filter.state == State_Running)
383 LONG64 delta;
384 delta = tStart - This->rtLastStop;
385 if ((delta < -100000 || delta > 100000) &&
386 IMediaSample_IsDiscontinuity(pSample) == S_FALSE)
387 ERR("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n",
388 (DWORD)(This->rtLastStop / 10000000),
389 (DWORD)((This->rtLastStop / 10000)%1000),
390 (DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000));
391 This->rtLastStop = tStart;
394 /* Preroll means the sample isn't shown, this is used for key frames and things like that */
395 if (IMediaSample_IsPreroll(pSample) == S_OK)
397 This->rtLastStop = tStop;
398 LeaveCriticalSection(&This->filter.csFilter);
399 return S_OK;
402 hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
403 if (FAILED(hr))
405 ERR("Cannot get pointer to sample data (%x)\n", hr);
406 LeaveCriticalSection(&This->filter.csFilter);
407 return hr;
410 cbSrcStream = IMediaSample_GetActualDataLength(pSample);
412 TRACE("val %p %d\n", pbSrcStream, cbSrcStream);
414 #if 0 /* For debugging purpose */
416 int i;
417 for(i = 0; i < cbSrcStream; i++)
419 if ((i!=0) && !(i%16))
420 TRACE("\n");
421 TRACE("%02x ", pbSrcStream[i]);
423 TRACE("\n");
425 #endif
427 SetEvent(This->hEvent);
428 if (This->filter.state == State_Paused)
430 This->sample_held = pSample;
431 LeaveCriticalSection(&This->filter.csFilter);
432 WaitForSingleObject(This->blocked, INFINITE);
433 EnterCriticalSection(&This->filter.csFilter);
434 This->sample_held = NULL;
435 if (This->filter.state == State_Paused)
437 /* Flushing */
438 LeaveCriticalSection(&This->filter.csFilter);
439 return S_OK;
441 if (This->filter.state == State_Stopped)
443 LeaveCriticalSection(&This->filter.csFilter);
444 return VFW_E_WRONG_STATE;
448 if (This->filter.pClock && This->filter.state == State_Running)
450 REFERENCE_TIME time, trefstart, trefstop;
451 LONG delta;
453 /* Perhaps I <SHOULD> use the reference clock AdviseTime function here
454 * I'm not going to! When I tried, it seemed to generate lag and
455 * it caused instability.
457 IReferenceClock_GetTime(This->filter.pClock, &time);
459 trefstart = This->filter.rtStreamStart;
460 trefstop = (REFERENCE_TIME)((double)(tStop - tStart) / This->pInputPin->dRate) + This->filter.rtStreamStart;
461 delta = (LONG)((trefstart-time)/10000);
462 This->filter.rtStreamStart = trefstop;
463 This->rtLastStop = tStop;
465 if (delta > 0)
467 TRACE("Sleeping for %u ms\n", delta);
468 Sleep(delta);
470 else if (time > trefstop)
472 TRACE("Dropping sample: Time: %u.%03u ms trefstop: %u.%03u ms!\n",
473 (DWORD)(time / 10000000), (DWORD)((time / 10000)%1000),
474 (DWORD)(trefstop / 10000000), (DWORD)((trefstop / 10000)%1000) );
475 This->rtLastStop = tStop;
476 LeaveCriticalSection(&This->filter.csFilter);
477 return S_OK;
480 This->rtLastStop = tStop;
482 VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
484 LeaveCriticalSection(&This->filter.csFilter);
485 return S_OK;
488 static HRESULT WINAPI VideoRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
490 BaseInputPin* pin = (BaseInputPin*)iface;
491 VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
493 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
494 return S_FALSE;
496 if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB32) ||
497 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB24) ||
498 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
499 IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
501 LONG height;
503 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
505 VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat;
506 This->SourceRect.left = 0;
507 This->SourceRect.top = 0;
508 This->SourceRect.right = This->VideoWidth = format->bmiHeader.biWidth;
509 height = format->bmiHeader.biHeight;
510 if (height < 0)
511 This->SourceRect.bottom = This->VideoHeight = -height;
512 else
513 This->SourceRect.bottom = This->VideoHeight = height;
515 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2))
517 VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat;
519 This->SourceRect.left = 0;
520 This->SourceRect.top = 0;
521 This->SourceRect.right = This->VideoWidth = format2->bmiHeader.biWidth;
522 height = format2->bmiHeader.biHeight;
523 if (height < 0)
524 This->SourceRect.bottom = This->VideoHeight = -height;
525 else
526 This->SourceRect.bottom = This->VideoHeight = height;
528 else
530 WARN("Format type %s not supported\n", debugstr_guid(&pmt->formattype));
531 return S_FALSE;
533 return S_OK;
535 return S_FALSE;
538 static IPin* WINAPI VideoRenderer_GetPin(IBaseFilter *iface, int pos)
540 VideoRendererImpl *This = (VideoRendererImpl *)iface;
542 if (pos >= 1 || pos < 0)
543 return NULL;
545 IPin_AddRef((IPin *)This->pInputPin);
546 return (IPin *)This->pInputPin;
549 static LONG WINAPI VideoRenderer_GetPinCount(IBaseFilter *iface)
551 return 1;
554 HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
556 HRESULT hr;
557 PIN_INFO piInput;
558 VideoRendererImpl * pVideoRenderer;
559 ISeekingPassThru *passthru;
561 TRACE("(%p, %p)\n", pUnkOuter, ppv);
563 *ppv = NULL;
565 pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
566 pVideoRenderer->pUnkOuter = pUnkOuter;
567 pVideoRenderer->bUnkOuterValid = FALSE;
568 pVideoRenderer->bAggregatable = FALSE;
569 pVideoRenderer->IInner_vtbl = &IInner_VTable;
571 BaseFilter_Init(&pVideoRenderer->filter, &VideoRenderer_Vtbl, &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"), VideoRenderer_GetPin, VideoRenderer_GetPinCount);
573 pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable;
574 pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable;
576 pVideoRenderer->init = 0;
577 pVideoRenderer->AutoShow = 1;
578 pVideoRenderer->rtLastStop = -1;
579 ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
580 ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
581 ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
582 pVideoRenderer->hWndMsgDrain = NULL;
583 pVideoRenderer->WindowStyle = WS_OVERLAPPED;
585 /* construct input pin */
586 piInput.dir = PINDIR_INPUT;
587 piInput.pFilter = (IBaseFilter *)pVideoRenderer;
588 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
590 hr = BaseInputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_CheckMediaType, VideoRenderer_Receive, &pVideoRenderer->filter.csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin);
592 if (SUCCEEDED(hr))
594 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pVideoRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pVideoRenderer->seekthru_unk);
595 if (FAILED(hr)) {
596 IPin_Release((IPin*)pVideoRenderer->pInputPin);
597 goto fail;
599 IUnknown_QueryInterface(pVideoRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
600 ISeekingPassThru_Init(passthru, TRUE, (IPin*)pVideoRenderer->pInputPin);
601 ISeekingPassThru_Release(passthru);
602 pVideoRenderer->sample_held = NULL;
603 *ppv = pVideoRenderer;
605 if (FAILED(hr))
606 goto fail;
608 if (!CreateRenderingSubsystem(pVideoRenderer))
609 return E_FAIL;
611 pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
612 if (!pVideoRenderer->blocked)
614 hr = HRESULT_FROM_WIN32(GetLastError());
615 IUnknown_Release((IUnknown *)pVideoRenderer);
618 return hr;
619 fail:
620 BaseFilterImpl_Release((IBaseFilter*)pVideoRenderer);
621 CoTaskMemFree(pVideoRenderer);
622 return hr;
625 HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
627 /* TODO: Attempt to use the VMR-7 renderer instead when possible */
628 return VideoRenderer_create(pUnkOuter, ppv);
631 static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
633 ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
634 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
636 if (This->bAggregatable)
637 This->bUnkOuterValid = TRUE;
639 *ppv = NULL;
641 if (IsEqualIID(riid, &IID_IUnknown))
642 *ppv = &This->IInner_vtbl;
643 else if (IsEqualIID(riid, &IID_IPersist))
644 *ppv = This;
645 else if (IsEqualIID(riid, &IID_IMediaFilter))
646 *ppv = This;
647 else if (IsEqualIID(riid, &IID_IBaseFilter))
648 *ppv = This;
649 else if (IsEqualIID(riid, &IID_IBasicVideo))
650 *ppv = &This->IBasicVideo_vtbl;
651 else if (IsEqualIID(riid, &IID_IVideoWindow))
652 *ppv = &This->IVideoWindow_vtbl;
653 else if (IsEqualIID(riid, &IID_IMediaSeeking))
654 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
656 if (*ppv)
658 IUnknown_AddRef((IUnknown *)(*ppv));
659 return S_OK;
662 if (!IsEqualIID(riid, &IID_IPin))
663 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
665 return E_NOINTERFACE;
668 static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface)
670 ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
671 ULONG refCount = InterlockedIncrement(&This->filter.refCount);
673 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
675 return refCount;
678 static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
680 ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
681 ULONG refCount = InterlockedDecrement(&This->filter.refCount);
683 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
685 if (!refCount)
687 IPin *pConnectedTo;
689 DestroyWindow(This->hWnd);
690 PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
691 WaitForSingleObject(This->hThread, INFINITE);
692 CloseHandle(This->hThread);
693 CloseHandle(This->hEvent);
695 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
697 IPin_Disconnect(pConnectedTo);
698 IPin_Release(pConnectedTo);
700 IPin_Disconnect((IPin *)This->pInputPin);
702 IPin_Release((IPin *)This->pInputPin);
704 This->filter.lpVtbl = NULL;
705 IUnknown_Release(This->seekthru_unk);
706 This->filter.csFilter.DebugInfo->Spare[0] = 0;
707 DeleteCriticalSection(&This->filter.csFilter);
709 TRACE("Destroying Video Renderer\n");
710 CoTaskMemFree(This);
712 return 0;
714 else
715 return refCount;
718 static const IUnknownVtbl IInner_VTable =
720 VideoRendererInner_QueryInterface,
721 VideoRendererInner_AddRef,
722 VideoRendererInner_Release
725 static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
727 VideoRendererImpl *This = (VideoRendererImpl *)iface;
729 if (This->bAggregatable)
730 This->bUnkOuterValid = TRUE;
732 if (This->pUnkOuter)
734 if (This->bAggregatable)
735 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
737 if (IsEqualIID(riid, &IID_IUnknown))
739 HRESULT hr;
741 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
742 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
743 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
744 This->bAggregatable = TRUE;
745 return hr;
748 *ppv = NULL;
749 return E_NOINTERFACE;
752 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
755 static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface)
757 VideoRendererImpl *This = (VideoRendererImpl *)iface;
759 if (This->pUnkOuter && This->bUnkOuterValid)
760 return IUnknown_AddRef(This->pUnkOuter);
761 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
764 static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface)
766 VideoRendererImpl *This = (VideoRendererImpl *)iface;
768 if (This->pUnkOuter && This->bUnkOuterValid)
769 return IUnknown_Release(This->pUnkOuter);
770 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
773 /** IMediaFilter methods **/
775 static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
777 VideoRendererImpl *This = (VideoRendererImpl *)iface;
779 TRACE("(%p/%p)->()\n", This, iface);
781 EnterCriticalSection(&This->filter.csFilter);
783 This->filter.state = State_Stopped;
784 SetEvent(This->hEvent);
785 SetEvent(This->blocked);
786 MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk);
788 LeaveCriticalSection(&This->filter.csFilter);
790 return S_OK;
793 static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
795 VideoRendererImpl *This = (VideoRendererImpl *)iface;
797 TRACE("(%p/%p)->()\n", This, iface);
799 EnterCriticalSection(&This->filter.csFilter);
800 if (This->filter.state != State_Paused)
802 if (This->filter.state == State_Stopped)
804 This->pInputPin->end_of_stream = 0;
805 ResetEvent(This->hEvent);
808 This->filter.state = State_Paused;
809 ResetEvent(This->blocked);
811 LeaveCriticalSection(&This->filter.csFilter);
813 return S_OK;
816 static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
818 VideoRendererImpl *This = (VideoRendererImpl *)iface;
820 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
822 EnterCriticalSection(&This->filter.csFilter);
823 if (This->filter.state != State_Running)
825 if (This->filter.state == State_Stopped)
827 This->pInputPin->end_of_stream = 0;
828 ResetEvent(This->hEvent);
830 SetEvent(This->blocked);
832 This->filter.rtStreamStart = tStart;
833 This->filter.state = State_Running;
835 LeaveCriticalSection(&This->filter.csFilter);
837 return S_OK;
840 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
842 VideoRendererImpl *This = (VideoRendererImpl *)iface;
843 HRESULT hr;
845 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
847 if (WaitForSingleObject(This->hEvent, dwMilliSecsTimeout) == WAIT_TIMEOUT)
848 hr = VFW_S_STATE_INTERMEDIATE;
849 else
850 hr = S_OK;
852 BaseFilterImpl_GetState(iface, dwMilliSecsTimeout, pState);
854 return hr;
857 /** IBaseFilter implementation **/
859 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
861 VideoRendererImpl *This = (VideoRendererImpl *)iface;
863 FIXME("(%p/%p)->(%p,%p): stub !!!\n", This, iface, debugstr_w(Id), ppPin);
865 /* FIXME: critical section */
867 return E_NOTIMPL;
870 static const IBaseFilterVtbl VideoRenderer_Vtbl =
872 VideoRenderer_QueryInterface,
873 VideoRenderer_AddRef,
874 VideoRenderer_Release,
875 BaseFilterImpl_GetClassID,
876 VideoRenderer_Stop,
877 VideoRenderer_Pause,
878 VideoRenderer_Run,
879 VideoRenderer_GetState,
880 BaseFilterImpl_SetSyncSource,
881 BaseFilterImpl_GetSyncSource,
882 BaseFilterImpl_EnumPins,
883 VideoRenderer_FindPin,
884 BaseFilterImpl_QueryFilterInfo,
885 BaseFilterImpl_JoinFilterGraph,
886 BaseFilterImpl_QueryVendorInfo
889 static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
891 BaseInputPin* This = (BaseInputPin*)iface;
892 VideoRendererImpl *pFilter;
893 IMediaEventSink* pEventSink;
894 HRESULT hr;
896 TRACE("(%p/%p)->()\n", This, iface);
898 pFilter = (VideoRendererImpl*)This->pin.pinInfo.pFilter;
899 hr = IFilterGraph_QueryInterface(pFilter->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
900 if (SUCCEEDED(hr))
902 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
903 IMediaEventSink_Release(pEventSink);
905 MediaSeekingPassThru_EOS(pFilter->seekthru_unk);
907 return hr;
910 static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
912 BaseInputPin* This = (BaseInputPin*)iface;
913 VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
914 HRESULT hr;
916 TRACE("(%p/%p)->()\n", This, iface);
918 EnterCriticalSection(This->pin.pCritSec);
919 if (pVideoRenderer->filter.state == State_Paused)
920 SetEvent(pVideoRenderer->blocked);
922 hr = BaseInputPinImpl_BeginFlush(iface);
923 LeaveCriticalSection(This->pin.pCritSec);
925 return hr;
928 static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
930 BaseInputPin* This = (BaseInputPin*)iface;
931 VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
932 HRESULT hr;
934 TRACE("(%p/%p)->()\n", This, iface);
936 EnterCriticalSection(This->pin.pCritSec);
937 if (pVideoRenderer->filter.state == State_Paused)
938 ResetEvent(pVideoRenderer->blocked);
940 hr = BaseInputPinImpl_EndFlush(iface);
941 LeaveCriticalSection(This->pin.pCritSec);
942 MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
944 return hr;
947 static const IPinVtbl VideoRenderer_InputPin_Vtbl =
949 BaseInputPinImpl_QueryInterface,
950 BasePinImpl_AddRef,
951 BaseInputPinImpl_Release,
952 BaseInputPinImpl_Connect,
953 BaseInputPinImpl_ReceiveConnection,
954 BasePinImpl_Disconnect,
955 BasePinImpl_ConnectedTo,
956 BasePinImpl_ConnectionMediaType,
957 BasePinImpl_QueryPinInfo,
958 BasePinImpl_QueryDirection,
959 BasePinImpl_QueryId,
960 BaseInputPinImpl_QueryAccept,
961 BasePinImpl_EnumMediaTypes,
962 BasePinImpl_QueryInternalConnections,
963 VideoRenderer_InputPin_EndOfStream,
964 VideoRenderer_InputPin_BeginFlush,
965 VideoRenderer_InputPin_EndFlush,
966 BaseInputPinImpl_NewSegment
969 /*** IUnknown methods ***/
970 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
971 REFIID riid,
972 LPVOID*ppvObj) {
973 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
975 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
977 return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
980 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
981 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
983 TRACE("(%p/%p)->()\n", This, iface);
985 return VideoRenderer_AddRef((IBaseFilter*)This);
988 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
989 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
991 TRACE("(%p/%p)->()\n", This, iface);
993 return VideoRenderer_Release((IBaseFilter*)This);
996 /*** IDispatch methods ***/
997 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
998 UINT*pctinfo) {
999 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1001 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1003 return S_OK;
1006 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
1007 UINT iTInfo,
1008 LCID lcid,
1009 ITypeInfo**ppTInfo) {
1010 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1012 FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1014 return S_OK;
1017 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
1018 REFIID riid,
1019 LPOLESTR*rgszNames,
1020 UINT cNames,
1021 LCID lcid,
1022 DISPID*rgDispId) {
1023 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1025 FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1027 return S_OK;
1030 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
1031 DISPID dispIdMember,
1032 REFIID riid,
1033 LCID lcid,
1034 WORD wFlags,
1035 DISPPARAMS*pDispParams,
1036 VARIANT*pVarResult,
1037 EXCEPINFO*pExepInfo,
1038 UINT*puArgErr) {
1039 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1041 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);
1043 return S_OK;
1046 /*** IBasicVideo methods ***/
1047 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
1048 REFTIME *pAvgTimePerFrame) {
1049 AM_MEDIA_TYPE *pmt;
1050 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1052 if (!This->pInputPin->pin.pConnectedTo)
1053 return VFW_E_NOT_CONNECTED;
1055 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
1057 pmt = &This->pInputPin->pin.mtCurrent;
1058 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) {
1059 VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)pmt->pbFormat;
1060 *pAvgTimePerFrame = vih->AvgTimePerFrame;
1061 } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) {
1062 VIDEOINFOHEADER2 *vih = (VIDEOINFOHEADER2*)pmt->pbFormat;
1063 *pAvgTimePerFrame = vih->AvgTimePerFrame;
1064 } else {
1065 ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
1066 *pAvgTimePerFrame = 0;
1068 return S_OK;
1071 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
1072 LONG *pBitRate) {
1073 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1075 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
1077 return S_OK;
1080 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
1081 LONG *pBitErrorRate) {
1082 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1084 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
1086 return S_OK;
1089 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
1090 LONG *pVideoWidth) {
1091 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1093 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
1095 *pVideoWidth = This->VideoWidth;
1097 return S_OK;
1100 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
1101 LONG *pVideoHeight) {
1102 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1104 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
1106 *pVideoHeight = This->VideoHeight;
1108 return S_OK;
1111 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1112 LONG SourceLeft) {
1113 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1115 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft);
1117 This->SourceRect.left = SourceLeft;
1119 return S_OK;
1122 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1123 LONG *pSourceLeft) {
1124 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1126 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
1128 *pSourceLeft = This->SourceRect.left;
1130 return S_OK;
1133 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1134 LONG SourceWidth) {
1135 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1137 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth);
1139 This->SourceRect.right = This->SourceRect.left + SourceWidth;
1141 return S_OK;
1144 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1145 LONG *pSourceWidth) {
1146 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1148 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
1150 *pSourceWidth = This->SourceRect.right - This->SourceRect.left;
1152 return S_OK;
1155 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1156 LONG SourceTop) {
1157 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1159 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop);
1161 This->SourceRect.top = SourceTop;
1163 return S_OK;
1166 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1167 LONG *pSourceTop) {
1168 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1170 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
1172 *pSourceTop = This->SourceRect.top;
1174 return S_OK;
1177 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1178 LONG SourceHeight) {
1179 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1181 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight);
1183 This->SourceRect.bottom = This->SourceRect.top + SourceHeight;
1185 return S_OK;
1188 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1189 LONG *pSourceHeight) {
1190 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1192 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
1194 *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top;
1196 return S_OK;
1199 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1200 LONG DestinationLeft) {
1201 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1203 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft);
1205 This->DestRect.left = DestinationLeft;
1207 return S_OK;
1210 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1211 LONG *pDestinationLeft) {
1212 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1214 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
1216 *pDestinationLeft = This->DestRect.left;
1218 return S_OK;
1221 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1222 LONG DestinationWidth) {
1223 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1225 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
1227 This->DestRect.right = This->DestRect.left + DestinationWidth;
1229 return S_OK;
1232 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1233 LONG *pDestinationWidth) {
1234 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1236 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
1238 *pDestinationWidth = This->DestRect.right - This->DestRect.left;
1240 return S_OK;
1243 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1244 LONG DestinationTop) {
1245 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1247 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
1249 This->DestRect.top = DestinationTop;
1251 return S_OK;
1254 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1255 LONG *pDestinationTop) {
1256 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1258 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
1260 *pDestinationTop = This->DestRect.top;
1262 return S_OK;
1265 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1266 LONG DestinationHeight) {
1267 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1269 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight);
1271 This->DestRect.right = This->DestRect.left + DestinationHeight;
1273 return S_OK;
1276 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1277 LONG *pDestinationHeight) {
1278 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1280 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
1282 *pDestinationHeight = This->DestRect.right - This->DestRect.left;
1284 return S_OK;
1287 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1288 LONG Left,
1289 LONG Top,
1290 LONG Width,
1291 LONG Height) {
1292 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1294 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
1296 This->SourceRect.left = Left;
1297 This->SourceRect.top = Top;
1298 This->SourceRect.right = Left + Width;
1299 This->SourceRect.bottom = Top + Height;
1301 return S_OK;
1304 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
1305 LONG *pLeft,
1306 LONG *pTop,
1307 LONG *pWidth,
1308 LONG *pHeight) {
1309 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1311 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1313 *pLeft = This->SourceRect.left;
1314 *pTop = This->SourceRect.top;
1315 *pWidth = This->SourceRect.right - This->SourceRect.left;
1316 *pHeight = This->SourceRect.bottom - This->SourceRect.top;
1318 return S_OK;
1321 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
1322 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1324 TRACE("(%p/%p)->()\n", This, iface);
1326 This->SourceRect.left = 0;
1327 This->SourceRect.top = 0;
1328 This->SourceRect.right = This->VideoWidth;
1329 This->SourceRect.bottom = This->VideoHeight;
1331 return S_OK;
1334 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
1335 LONG Left,
1336 LONG Top,
1337 LONG Width,
1338 LONG Height) {
1339 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1341 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
1343 This->DestRect.left = Left;
1344 This->DestRect.top = Top;
1345 This->DestRect.right = Left + Width;
1346 This->DestRect.bottom = Top + Height;
1348 return S_OK;
1351 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
1352 LONG *pLeft,
1353 LONG *pTop,
1354 LONG *pWidth,
1355 LONG *pHeight) {
1356 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1358 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
1360 *pLeft = This->DestRect.left;
1361 *pTop = This->DestRect.top;
1362 *pWidth = This->DestRect.right - This->DestRect.left;
1363 *pHeight = This->DestRect.bottom - This->DestRect.top;
1365 return S_OK;
1368 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
1369 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1370 RECT rect;
1372 TRACE("(%p/%p)->()\n", This, iface);
1374 if (!GetClientRect(This->hWnd, &rect))
1375 return E_FAIL;
1377 This->SourceRect.left = 0;
1378 This->SourceRect.top = 0;
1379 This->SourceRect.right = rect.right;
1380 This->SourceRect.bottom = rect.bottom;
1382 return S_OK;
1385 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
1386 LONG *pWidth,
1387 LONG *pHeight) {
1388 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1390 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
1392 *pWidth = This->VideoWidth;
1393 *pHeight = This->VideoHeight;
1395 return S_OK;
1398 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
1399 LONG StartIndex,
1400 LONG Entries,
1401 LONG *pRetrieved,
1402 LONG *pPalette) {
1403 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1405 FIXME("(%p/%p)->(%d, %d, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
1407 return S_OK;
1410 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
1411 LONG *pBufferSize,
1412 LONG *pDIBImage) {
1413 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1414 BITMAPINFOHEADER *bmiHeader;
1415 LONG needed_size;
1416 AM_MEDIA_TYPE *amt = &This->pInputPin->pin.mtCurrent;
1417 char *ptr;
1419 FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage);
1421 EnterCriticalSection(&This->filter.csFilter);
1423 if (!This->sample_held)
1425 LeaveCriticalSection(&This->filter.csFilter);
1426 return (This->filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED);
1429 if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo))
1431 bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader;
1433 else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2))
1435 bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader;
1437 else
1439 FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype));
1440 LeaveCriticalSection(&This->filter.csFilter);
1441 return VFW_E_RUNTIME_ERROR;
1444 needed_size = bmiHeader->biSize;
1445 needed_size += IMediaSample_GetActualDataLength(This->sample_held);
1447 if (!pDIBImage)
1449 *pBufferSize = needed_size;
1450 LeaveCriticalSection(&This->filter.csFilter);
1451 return S_OK;
1454 if (needed_size < *pBufferSize)
1456 ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize);
1457 LeaveCriticalSection(&This->filter.csFilter);
1458 return E_FAIL;
1460 *pBufferSize = needed_size;
1462 memcpy(pDIBImage, bmiHeader, bmiHeader->biSize);
1463 IMediaSample_GetPointer(This->sample_held, (BYTE **)&ptr);
1464 memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->sample_held));
1466 LeaveCriticalSection(&This->filter.csFilter);
1468 return S_OK;
1471 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
1472 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1474 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1476 return S_OK;
1479 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
1480 ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
1482 FIXME("(%p/%p)->(): stub !!!\n", This, iface);
1484 return S_OK;
1488 static const IBasicVideoVtbl IBasicVideo_VTable =
1490 Basicvideo_QueryInterface,
1491 Basicvideo_AddRef,
1492 Basicvideo_Release,
1493 Basicvideo_GetTypeInfoCount,
1494 Basicvideo_GetTypeInfo,
1495 Basicvideo_GetIDsOfNames,
1496 Basicvideo_Invoke,
1497 Basicvideo_get_AvgTimePerFrame,
1498 Basicvideo_get_BitRate,
1499 Basicvideo_get_BitErrorRate,
1500 Basicvideo_get_VideoWidth,
1501 Basicvideo_get_VideoHeight,
1502 Basicvideo_put_SourceLeft,
1503 Basicvideo_get_SourceLeft,
1504 Basicvideo_put_SourceWidth,
1505 Basicvideo_get_SourceWidth,
1506 Basicvideo_put_SourceTop,
1507 Basicvideo_get_SourceTop,
1508 Basicvideo_put_SourceHeight,
1509 Basicvideo_get_SourceHeight,
1510 Basicvideo_put_DestinationLeft,
1511 Basicvideo_get_DestinationLeft,
1512 Basicvideo_put_DestinationWidth,
1513 Basicvideo_get_DestinationWidth,
1514 Basicvideo_put_DestinationTop,
1515 Basicvideo_get_DestinationTop,
1516 Basicvideo_put_DestinationHeight,
1517 Basicvideo_get_DestinationHeight,
1518 Basicvideo_SetSourcePosition,
1519 Basicvideo_GetSourcePosition,
1520 Basicvideo_SetDefaultSourcePosition,
1521 Basicvideo_SetDestinationPosition,
1522 Basicvideo_GetDestinationPosition,
1523 Basicvideo_SetDefaultDestinationPosition,
1524 Basicvideo_GetVideoSize,
1525 Basicvideo_GetVideoPaletteEntries,
1526 Basicvideo_GetCurrentImage,
1527 Basicvideo_IsUsingDefaultSource,
1528 Basicvideo_IsUsingDefaultDestination
1532 /*** IUnknown methods ***/
1533 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
1534 REFIID riid,
1535 LPVOID*ppvObj) {
1536 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1538 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1540 return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
1543 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
1544 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1546 TRACE("(%p/%p)->()\n", This, iface);
1548 return VideoRenderer_AddRef((IBaseFilter*)This);
1551 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
1552 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1554 TRACE("(%p/%p)->()\n", This, iface);
1556 return VideoRenderer_Release((IBaseFilter*)This);
1559 /*** IDispatch methods ***/
1560 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
1561 UINT*pctinfo) {
1562 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1564 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1566 return S_OK;
1569 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
1570 UINT iTInfo,
1571 LCID lcid,
1572 ITypeInfo**ppTInfo) {
1573 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1575 FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1577 return S_OK;
1580 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
1581 REFIID riid,
1582 LPOLESTR*rgszNames,
1583 UINT cNames,
1584 LCID lcid,
1585 DISPID*rgDispId) {
1586 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1588 FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1590 return S_OK;
1593 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
1594 DISPID dispIdMember,
1595 REFIID riid,
1596 LCID lcid,
1597 WORD wFlags,
1598 DISPPARAMS*pDispParams,
1599 VARIANT*pVarResult,
1600 EXCEPINFO*pExepInfo,
1601 UINT*puArgErr) {
1602 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1604 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);
1606 return S_OK;
1609 /*** IVideoWindow methods ***/
1610 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
1611 BSTR strCaption) {
1612 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1614 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
1616 if (!SetWindowTextW(This->hWnd, strCaption))
1617 return E_FAIL;
1619 return S_OK;
1622 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
1623 BSTR *strCaption) {
1624 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1626 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
1628 GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100);
1630 return S_OK;
1633 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
1634 LONG WindowStyle) {
1635 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1636 LONG old;
1638 old = GetWindowLongA(This->hWnd, GWL_STYLE);
1640 TRACE("(%p/%p)->(%x -> %x)\n", This, iface, old, WindowStyle);
1642 if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
1643 return E_INVALIDARG;
1645 SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle);
1646 SetWindowPos(This->hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER);
1647 This->WindowStyle = WindowStyle;
1649 return S_OK;
1652 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
1653 LONG *WindowStyle) {
1654 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1656 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
1658 *WindowStyle = This->WindowStyle;
1660 return S_OK;
1663 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
1664 LONG WindowStyleEx) {
1665 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1667 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx);
1669 if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx))
1670 return E_FAIL;
1672 return S_OK;
1675 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
1676 LONG *WindowStyleEx) {
1677 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1679 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
1681 *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE);
1683 return S_OK;
1686 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
1687 LONG AutoShow) {
1688 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1690 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow);
1692 This->AutoShow = AutoShow;
1694 return S_OK;
1697 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
1698 LONG *AutoShow) {
1699 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1701 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
1703 *AutoShow = This->AutoShow;
1705 return S_OK;
1708 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
1709 LONG WindowState) {
1710 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1712 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState);
1713 ShowWindow(This->hWnd, WindowState);
1714 return S_OK;
1717 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
1718 LONG *WindowState) {
1719 WINDOWPLACEMENT place;
1720 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1722 place.length = sizeof(place);
1723 GetWindowPlacement(This->hWnd, &place);
1724 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
1725 *WindowState = place.showCmd;
1727 return S_OK;
1730 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
1731 LONG BackgroundPalette) {
1732 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1734 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, BackgroundPalette);
1736 return S_OK;
1739 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
1740 LONG *pBackgroundPalette) {
1741 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1743 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
1745 return S_OK;
1748 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
1749 LONG Visible) {
1750 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1752 TRACE("(%p/%p)->(%d)\n", This, iface, Visible);
1754 ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE);
1756 return S_OK;
1759 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
1760 LONG *pVisible) {
1761 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1763 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
1765 *pVisible = IsWindowVisible(This->hWnd);
1767 return S_OK;
1770 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
1771 LONG Left) {
1772 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1774 TRACE("(%p/%p)->(%d)\n", This, iface, Left);
1776 if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1777 return E_FAIL;
1779 This->WindowPos.left = Left;
1781 return S_OK;
1784 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
1785 LONG *pLeft) {
1786 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1788 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
1790 *pLeft = This->WindowPos.left;
1792 return S_OK;
1795 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
1796 LONG Width) {
1797 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1799 TRACE("(%p/%p)->(%d)\n", This, iface, Width);
1801 if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE))
1802 return E_FAIL;
1804 This->WindowPos.right = This->WindowPos.left + Width;
1806 return S_OK;
1809 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
1810 LONG *pWidth) {
1811 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1813 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
1815 *pWidth = This->WindowPos.right - This->WindowPos.left;
1817 return S_OK;
1820 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
1821 LONG Top) {
1822 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1824 TRACE("(%p/%p)->(%d)\n", This, iface, Top);
1826 if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE))
1827 return E_FAIL;
1829 This->WindowPos.top = Top;
1831 return S_OK;
1834 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
1835 LONG *pTop) {
1836 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1838 TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
1840 *pTop = This->WindowPos.top;
1842 return S_OK;
1845 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
1846 LONG Height) {
1847 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1849 TRACE("(%p/%p)->(%d)\n", This, iface, Height);
1851 if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE))
1852 return E_FAIL;
1854 This->WindowPos.bottom = This->WindowPos.top + Height;
1856 return S_OK;
1859 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
1860 LONG *pHeight) {
1861 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1863 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
1865 *pHeight = This->WindowPos.bottom - This->WindowPos.top;
1867 return S_OK;
1870 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
1871 OAHWND Owner) {
1872 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1874 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
1876 SetParent(This->hWnd, (HWND)Owner);
1877 if (This->WindowStyle & WS_CHILD)
1879 LONG old = GetWindowLongA(This->hWnd, GWL_STYLE);
1880 if (old != This->WindowStyle)
1882 SetWindowLongA(This->hWnd, GWL_STYLE, This->WindowStyle);
1883 SetWindowPos(This->hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER);
1887 return S_OK;
1890 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
1891 OAHWND *Owner) {
1892 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1894 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
1896 *(HWND*)Owner = GetParent(This->hWnd);
1898 return S_OK;
1901 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
1902 OAHWND Drain) {
1903 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1905 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
1907 This->hWndMsgDrain = (HWND)Drain;
1909 return S_OK;
1912 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
1913 OAHWND *Drain) {
1914 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1916 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
1918 *Drain = (OAHWND)This->hWndMsgDrain;
1920 return S_OK;
1923 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
1924 LONG *Color) {
1925 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1927 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
1929 return S_OK;
1932 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
1933 LONG Color) {
1934 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1936 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, Color);
1938 return S_OK;
1941 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
1942 LONG *FullScreenMode) {
1943 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1945 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
1947 return S_OK;
1950 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
1951 LONG FullScreenMode) {
1952 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1954 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode);
1956 return S_OK;
1959 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
1960 LONG Focus) {
1961 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1962 BOOL ret;
1963 IPin* pPin;
1964 HRESULT hr;
1966 TRACE("(%p/%p)->(%d)\n", This, iface, Focus);
1968 if ((Focus != FALSE) && (Focus != TRUE))
1969 return E_INVALIDARG;
1971 hr = IPin_ConnectedTo((IPin *)This->pInputPin, &pPin);
1972 if ((hr != S_OK) || !pPin)
1973 return VFW_E_NOT_CONNECTED;
1975 if (Focus)
1976 ret = SetForegroundWindow(This->hWnd);
1977 else
1978 ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
1980 if (!ret)
1981 return E_FAIL;
1983 return S_OK;
1986 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
1987 OAHWND hwnd,
1988 LONG uMsg,
1989 LONG_PTR wParam,
1990 LONG_PTR lParam) {
1991 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
1993 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam);
1995 if (!PostMessageA(This->hWnd, uMsg, wParam, lParam))
1996 return E_FAIL;
1998 return S_OK;
2001 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
2002 LONG Left,
2003 LONG Top,
2004 LONG Width,
2005 LONG Height) {
2006 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2008 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height);
2010 if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER))
2011 return E_FAIL;
2013 This->WindowPos.left = Left;
2014 This->WindowPos.top = Top;
2015 This->WindowPos.right = Left + Width;
2016 This->WindowPos.bottom = Top + Height;
2018 return S_OK;
2021 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
2022 LONG *pLeft,
2023 LONG *pTop,
2024 LONG *pWidth,
2025 LONG *pHeight) {
2026 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2028 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
2030 *pLeft = This->WindowPos.left;
2031 *pTop = This->WindowPos.top;
2032 *pWidth = This->WindowPos.right - This->WindowPos.left;
2033 *pHeight = This->WindowPos.bottom - This->WindowPos.top;
2035 return S_OK;
2038 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
2039 LONG *pWidth,
2040 LONG *pHeight) {
2041 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2043 FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
2045 *pWidth = This->VideoWidth;
2046 *pHeight = This->VideoHeight;
2048 return S_OK;
2051 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
2052 LONG *pWidth,
2053 LONG *pHeight) {
2054 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2056 FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight);
2058 *pWidth = This->VideoWidth;
2059 *pHeight = This->VideoHeight;
2061 return S_OK;
2064 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
2065 LONG *pLeft,
2066 LONG *pTop,
2067 LONG *pWidth,
2068 LONG *pHeight) {
2069 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2071 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2073 return S_OK;
2076 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
2077 LONG HideCursor) {
2078 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2080 FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, HideCursor);
2082 return S_OK;
2085 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
2086 LONG *CursorHidden) {
2087 ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
2089 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
2091 return S_OK;
2094 static const IVideoWindowVtbl IVideoWindow_VTable =
2096 Videowindow_QueryInterface,
2097 Videowindow_AddRef,
2098 Videowindow_Release,
2099 Videowindow_GetTypeInfoCount,
2100 Videowindow_GetTypeInfo,
2101 Videowindow_GetIDsOfNames,
2102 Videowindow_Invoke,
2103 Videowindow_put_Caption,
2104 Videowindow_get_Caption,
2105 Videowindow_put_WindowStyle,
2106 Videowindow_get_WindowStyle,
2107 Videowindow_put_WindowStyleEx,
2108 Videowindow_get_WindowStyleEx,
2109 Videowindow_put_AutoShow,
2110 Videowindow_get_AutoShow,
2111 Videowindow_put_WindowState,
2112 Videowindow_get_WindowState,
2113 Videowindow_put_BackgroundPalette,
2114 Videowindow_get_BackgroundPalette,
2115 Videowindow_put_Visible,
2116 Videowindow_get_Visible,
2117 Videowindow_put_Left,
2118 Videowindow_get_Left,
2119 Videowindow_put_Width,
2120 Videowindow_get_Width,
2121 Videowindow_put_Top,
2122 Videowindow_get_Top,
2123 Videowindow_put_Height,
2124 Videowindow_get_Height,
2125 Videowindow_put_Owner,
2126 Videowindow_get_Owner,
2127 Videowindow_put_MessageDrain,
2128 Videowindow_get_MessageDrain,
2129 Videowindow_get_BorderColor,
2130 Videowindow_put_BorderColor,
2131 Videowindow_get_FullScreenMode,
2132 Videowindow_put_FullScreenMode,
2133 Videowindow_SetWindowForeground,
2134 Videowindow_NotifyOwnerMessage,
2135 Videowindow_SetWindowPosition,
2136 Videowindow_GetWindowPosition,
2137 Videowindow_GetMinIdealImageSize,
2138 Videowindow_GetMaxIdealImageSize,
2139 Videowindow_GetRestorePosition,
2140 Videowindow_HideCursor,
2141 Videowindow_IsCursorHidden