2 * Common implementation of IVideoWindow
4 * Copyright 2012 Aric Stewart, CodeWeavers
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 "quartz_private.h"
23 #define WM_QUARTZ_DESTROY (WM_USER + WM_DESTROY)
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
27 static const WCHAR class_name
[] = L
"wine_quartz_window";
29 static inline struct video_window
*impl_from_IVideoWindow(IVideoWindow
*iface
)
31 return CONTAINING_RECORD(iface
, struct video_window
, IVideoWindow_iface
);
34 static LRESULT CALLBACK
WndProcW(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
36 struct video_window
*window
= (struct video_window
*)GetWindowLongPtrW(hwnd
, 0);
39 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
45 case WM_LBUTTONDBLCLK
:
48 case WM_MBUTTONDBLCLK
:
51 case WM_MOUSEACTIVATE
:
53 case WM_NCLBUTTONDBLCLK
:
54 case WM_NCLBUTTONDOWN
:
56 case WM_NCMBUTTONDBLCLK
:
57 case WM_NCMBUTTONDOWN
:
60 case WM_NCRBUTTONDBLCLK
:
61 case WM_NCRBUTTONDOWN
:
63 case WM_RBUTTONDBLCLK
:
66 if (window
->hwndDrain
)
68 PostMessageW(window
->hwndDrain
, message
, wparam
, lparam
);
73 if (window
->default_dst
)
74 GetClientRect(window
->hwnd
, &window
->dst
);
76 case WM_QUARTZ_DESTROY
:
81 IFilterGraph
*graph
= window
->pFilter
->graph
;
82 IMediaEventSink
*event_sink
;
83 IVideoWindow_put_Visible(&window
->IVideoWindow_iface
, OAFALSE
);
84 if (graph
&& SUCCEEDED(IFilterGraph_QueryInterface(graph
,
86 (void **)&event_sink
)))
88 IMediaEventSink_Notify(event_sink
, EC_USERABORT
, 0, 0);
89 IMediaEventSink_Release(event_sink
);
95 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
98 HRESULT
video_window_create_window(struct video_window
*window
)
100 WNDCLASSW winclass
= {0};
102 winclass
.lpfnWndProc
= WndProcW
;
103 winclass
.cbWndExtra
= sizeof(window
);
104 winclass
.lpszClassName
= class_name
;
105 if (!RegisterClassW(&winclass
) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS
)
107 ERR("Failed to register class, error %lu.\n", GetLastError());
111 if (!(window
->hwnd
= CreateWindowExW(0, class_name
, L
"ActiveMovie Window",
112 WS_OVERLAPPEDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
113 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
114 NULL
, NULL
, NULL
, NULL
)))
116 ERR("Unable to create window\n");
120 SetWindowLongPtrW(window
->hwnd
, 0, (LONG_PTR
)window
);
125 HRESULT WINAPI
BaseControlWindowImpl_QueryInterface(IVideoWindow
*iface
, REFIID iid
, void **out
)
127 struct video_window
*window
= impl_from_IVideoWindow(iface
);
128 return IUnknown_QueryInterface(window
->pFilter
->outer_unk
, iid
, out
);
131 ULONG WINAPI
BaseControlWindowImpl_AddRef(IVideoWindow
*iface
)
133 struct video_window
*window
= impl_from_IVideoWindow(iface
);
134 return IUnknown_AddRef(window
->pFilter
->outer_unk
);
137 ULONG WINAPI
BaseControlWindowImpl_Release(IVideoWindow
*iface
)
139 struct video_window
*window
= impl_from_IVideoWindow(iface
);
140 return IUnknown_Release(window
->pFilter
->outer_unk
);
143 HRESULT WINAPI
BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow
*iface
, UINT
*count
)
145 TRACE("iface %p, count %p.\n", iface
, count
);
150 HRESULT WINAPI
BaseControlWindowImpl_GetTypeInfo(IVideoWindow
*iface
, UINT index
,
151 LCID lcid
, ITypeInfo
**typeinfo
)
153 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface
, index
, lcid
, typeinfo
);
154 return strmbase_get_typeinfo(IVideoWindow_tid
, typeinfo
);
157 HRESULT WINAPI
BaseControlWindowImpl_GetIDsOfNames(IVideoWindow
*iface
, REFIID iid
,
158 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
163 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
164 iface
, debugstr_guid(iid
), names
, count
, lcid
, ids
);
166 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IVideoWindow_tid
, &typeinfo
)))
168 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, ids
);
169 ITypeInfo_Release(typeinfo
);
174 HRESULT WINAPI
BaseControlWindowImpl_Invoke(IVideoWindow
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
175 WORD flags
, DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*error_arg
)
180 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
181 iface
, id
, debugstr_guid(iid
), lcid
, flags
, params
, result
, excepinfo
, error_arg
);
183 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IVideoWindow_tid
, &typeinfo
)))
185 hr
= ITypeInfo_Invoke(typeinfo
, iface
, id
, flags
, params
, result
, excepinfo
, error_arg
);
186 ITypeInfo_Release(typeinfo
);
191 HRESULT WINAPI
BaseControlWindowImpl_put_Caption(IVideoWindow
*iface
, BSTR caption
)
193 struct video_window
*window
= impl_from_IVideoWindow(iface
);
195 TRACE("window %p, caption %s.\n", window
, debugstr_w(caption
));
197 if (!SetWindowTextW(window
->hwnd
, caption
))
203 HRESULT WINAPI
BaseControlWindowImpl_get_Caption(IVideoWindow
*iface
, BSTR
*caption
)
205 struct video_window
*window
= impl_from_IVideoWindow(iface
);
209 TRACE("window %p, caption %p.\n", window
, caption
);
213 len
= GetWindowTextLengthW(window
->hwnd
) + 1;
214 if (!(str
= heap_alloc(len
* sizeof(WCHAR
))))
215 return E_OUTOFMEMORY
;
217 GetWindowTextW(window
->hwnd
, str
, len
);
218 *caption
= SysAllocString(str
);
220 return *caption
? S_OK
: E_OUTOFMEMORY
;
223 HRESULT WINAPI
BaseControlWindowImpl_put_WindowStyle(IVideoWindow
*iface
, LONG style
)
225 struct video_window
*window
= impl_from_IVideoWindow(iface
);
227 TRACE("window %p, style %#lx.\n", window
, style
);
229 if (style
& (WS_DISABLED
|WS_HSCROLL
|WS_MAXIMIZE
|WS_MINIMIZE
|WS_VSCROLL
))
232 SetWindowLongW(window
->hwnd
, GWL_STYLE
, style
);
233 SetWindowPos(window
->hwnd
, 0, 0, 0, 0, 0,
234 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
238 HRESULT WINAPI
BaseControlWindowImpl_get_WindowStyle(IVideoWindow
*iface
, LONG
*style
)
240 struct video_window
*window
= impl_from_IVideoWindow(iface
);
242 TRACE("window %p, style %p.\n", window
, style
);
244 *style
= GetWindowLongW(window
->hwnd
, GWL_STYLE
);
248 HRESULT WINAPI
BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow
*iface
, LONG style
)
250 struct video_window
*window
= impl_from_IVideoWindow(iface
);
252 TRACE("window %p, style %#lx.\n", window
, style
);
254 if (!SetWindowLongW(window
->hwnd
, GWL_EXSTYLE
, style
))
259 HRESULT WINAPI
BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow
*iface
, LONG
*style
)
261 struct video_window
*window
= impl_from_IVideoWindow(iface
);
263 TRACE("window %p, style %p.\n", window
, style
);
265 *style
= GetWindowLongW(window
->hwnd
, GWL_EXSTYLE
);
269 HRESULT WINAPI
BaseControlWindowImpl_put_AutoShow(IVideoWindow
*iface
, LONG AutoShow
)
271 struct video_window
*This
= impl_from_IVideoWindow(iface
);
273 TRACE("window %p, AutoShow %ld.\n", This
, AutoShow
);
275 This
->AutoShow
= AutoShow
;
280 HRESULT WINAPI
BaseControlWindowImpl_get_AutoShow(IVideoWindow
*iface
, LONG
*AutoShow
)
282 struct video_window
*This
= impl_from_IVideoWindow(iface
);
284 TRACE("(%p/%p)->(%p)\n", This
, iface
, AutoShow
);
286 *AutoShow
= This
->AutoShow
;
291 HRESULT WINAPI
BaseControlWindowImpl_put_WindowState(IVideoWindow
*iface
, LONG state
)
293 struct video_window
*window
= impl_from_IVideoWindow(iface
);
295 TRACE("window %p, state %ld.\n", window
, state
);
297 ShowWindow(window
->hwnd
, state
);
301 HRESULT WINAPI
BaseControlWindowImpl_get_WindowState(IVideoWindow
*iface
, LONG
*state
)
303 struct video_window
*window
= impl_from_IVideoWindow(iface
);
306 TRACE("window %p, state %p.\n", window
, state
);
308 style
= GetWindowLongPtrW(window
->hwnd
, GWL_STYLE
);
309 if (!(style
& WS_VISIBLE
))
311 else if (style
& WS_MINIMIZE
)
312 *state
= SW_MINIMIZE
;
313 else if (style
& WS_MAXIMIZE
)
314 *state
= SW_MAXIMIZE
;
321 HRESULT WINAPI
BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow
*iface
, LONG BackgroundPalette
)
323 struct video_window
*This
= impl_from_IVideoWindow(iface
);
325 FIXME("window %p, palette %ld, stub!\n", This
, BackgroundPalette
);
330 HRESULT WINAPI
BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow
*iface
, LONG
*pBackgroundPalette
)
332 struct video_window
*This
= impl_from_IVideoWindow(iface
);
334 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, pBackgroundPalette
);
339 HRESULT WINAPI
BaseControlWindowImpl_put_Visible(IVideoWindow
*iface
, LONG visible
)
341 struct video_window
*window
= impl_from_IVideoWindow(iface
);
343 TRACE("window %p, visible %ld.\n", window
, visible
);
345 ShowWindow(window
->hwnd
, visible
? SW_SHOW
: SW_HIDE
);
349 HRESULT WINAPI
BaseControlWindowImpl_get_Visible(IVideoWindow
*iface
, LONG
*visible
)
351 struct video_window
*window
= impl_from_IVideoWindow(iface
);
353 TRACE("window %p, visible %p.\n", window
, visible
);
358 *visible
= IsWindowVisible(window
->hwnd
) ? OATRUE
: OAFALSE
;
362 HRESULT WINAPI
BaseControlWindowImpl_put_Left(IVideoWindow
*iface
, LONG left
)
364 struct video_window
*window
= impl_from_IVideoWindow(iface
);
367 TRACE("window %p, left %ld.\n", window
, left
);
369 GetWindowRect(window
->hwnd
, &rect
);
370 if (!SetWindowPos(window
->hwnd
, NULL
, left
, rect
.top
, 0, 0,
371 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
))
377 HRESULT WINAPI
BaseControlWindowImpl_get_Left(IVideoWindow
*iface
, LONG
*left
)
379 struct video_window
*window
= impl_from_IVideoWindow(iface
);
382 TRACE("window %p, left %p.\n", window
, left
);
384 GetWindowRect(window
->hwnd
, &rect
);
389 HRESULT WINAPI
BaseControlWindowImpl_put_Width(IVideoWindow
*iface
, LONG width
)
391 struct video_window
*window
= impl_from_IVideoWindow(iface
);
394 TRACE("window %p, width %ld.\n", window
, width
);
396 GetWindowRect(window
->hwnd
, &rect
);
397 if (!SetWindowPos(window
->hwnd
, NULL
, 0, 0, width
, rect
.bottom
- rect
.top
,
398 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOMOVE
))
404 HRESULT WINAPI
BaseControlWindowImpl_get_Width(IVideoWindow
*iface
, LONG
*width
)
406 struct video_window
*window
= impl_from_IVideoWindow(iface
);
409 TRACE("window %p, width %p.\n", window
, width
);
411 GetWindowRect(window
->hwnd
, &rect
);
412 *width
= rect
.right
- rect
.left
;
416 HRESULT WINAPI
BaseControlWindowImpl_put_Top(IVideoWindow
*iface
, LONG top
)
418 struct video_window
*window
= impl_from_IVideoWindow(iface
);
421 TRACE("window %p, top %ld.\n", window
, top
);
423 GetWindowRect(window
->hwnd
, &rect
);
424 if (!SetWindowPos(window
->hwnd
, NULL
, rect
.left
, top
, 0, 0,
425 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
))
431 HRESULT WINAPI
BaseControlWindowImpl_get_Top(IVideoWindow
*iface
, LONG
*top
)
433 struct video_window
*window
= impl_from_IVideoWindow(iface
);
436 TRACE("window %p, top %p.\n", window
, top
);
438 GetWindowRect(window
->hwnd
, &rect
);
443 HRESULT WINAPI
BaseControlWindowImpl_put_Height(IVideoWindow
*iface
, LONG height
)
445 struct video_window
*window
= impl_from_IVideoWindow(iface
);
448 TRACE("window %p, height %ld.\n", window
, height
);
450 GetWindowRect(window
->hwnd
, &rect
);
451 if (!SetWindowPos(window
->hwnd
, NULL
, 0, 0, rect
.right
- rect
.left
,
452 height
, SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOMOVE
))
458 HRESULT WINAPI
BaseControlWindowImpl_get_Height(IVideoWindow
*iface
, LONG
*height
)
460 struct video_window
*window
= impl_from_IVideoWindow(iface
);
463 TRACE("window %p, height %p.\n", window
, height
);
465 GetWindowRect(window
->hwnd
, &rect
);
466 *height
= rect
.bottom
- rect
.top
;
470 HRESULT WINAPI
BaseControlWindowImpl_put_Owner(IVideoWindow
*iface
, OAHWND owner
)
472 struct video_window
*window
= impl_from_IVideoWindow(iface
);
473 HWND hwnd
= window
->hwnd
;
475 TRACE("window %p, owner %#Ix.\n", window
, owner
);
477 /* Make sure we are marked as WS_CHILD before reparenting ourselves, so that
478 * we do not steal focus. LEGO Island depends on this. */
480 window
->hwndOwner
= (HWND
)owner
;
482 SetWindowLongPtrW(hwnd
, GWL_STYLE
, GetWindowLongPtrW(hwnd
, GWL_STYLE
) | WS_CHILD
);
484 SetWindowLongPtrW(hwnd
, GWL_STYLE
, GetWindowLongPtrW(hwnd
, GWL_STYLE
) & ~WS_CHILD
);
485 SetParent(hwnd
, (HWND
)owner
);
490 HRESULT WINAPI
BaseControlWindowImpl_get_Owner(IVideoWindow
*iface
, OAHWND
*Owner
)
492 struct video_window
*This
= impl_from_IVideoWindow(iface
);
494 TRACE("(%p/%p)->(%p)\n", This
, iface
, Owner
);
496 *(HWND
*)Owner
= This
->hwndOwner
;
501 HRESULT WINAPI
BaseControlWindowImpl_put_MessageDrain(IVideoWindow
*iface
, OAHWND Drain
)
503 struct video_window
*This
= impl_from_IVideoWindow(iface
);
505 TRACE("window %p, drain %#Ix.\n", This
, Drain
);
507 This
->hwndDrain
= (HWND
)Drain
;
512 HRESULT WINAPI
BaseControlWindowImpl_get_MessageDrain(IVideoWindow
*iface
, OAHWND
*Drain
)
514 struct video_window
*This
= impl_from_IVideoWindow(iface
);
516 TRACE("(%p/%p)->(%p)\n", This
, iface
, Drain
);
518 *Drain
= (OAHWND
)This
->hwndDrain
;
523 HRESULT WINAPI
BaseControlWindowImpl_get_BorderColor(IVideoWindow
*iface
, LONG
*Color
)
525 struct video_window
*This
= impl_from_IVideoWindow(iface
);
527 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, Color
);
532 HRESULT WINAPI
BaseControlWindowImpl_put_BorderColor(IVideoWindow
*iface
, LONG Color
)
534 struct video_window
*This
= impl_from_IVideoWindow(iface
);
536 TRACE("window %p, colour %#lx.\n", This
, Color
);
541 HRESULT WINAPI
BaseControlWindowImpl_get_FullScreenMode(IVideoWindow
*iface
, LONG
*FullScreenMode
)
543 TRACE("(%p)->(%p)\n", iface
, FullScreenMode
);
548 HRESULT WINAPI
BaseControlWindowImpl_put_FullScreenMode(IVideoWindow
*iface
, LONG fullscreen
)
550 struct video_window
*window
= impl_from_IVideoWindow(iface
);
552 TRACE("window %p, fullscreen %ld.\n", window
, fullscreen
);
557 HRESULT WINAPI
BaseControlWindowImpl_SetWindowForeground(IVideoWindow
*iface
, LONG focus
)
559 struct video_window
*window
= impl_from_IVideoWindow(iface
);
560 UINT flags
= SWP_NOMOVE
| SWP_NOSIZE
;
562 TRACE("window %p, focus %ld.\n", window
, focus
);
564 if (focus
!= OAFALSE
&& focus
!= OATRUE
)
567 if (!window
->pPin
->peer
)
568 return VFW_E_NOT_CONNECTED
;
571 flags
|= SWP_NOACTIVATE
;
572 SetWindowPos(window
->hwnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
577 HRESULT WINAPI
BaseControlWindowImpl_SetWindowPosition(IVideoWindow
*iface
,
578 LONG left
, LONG top
, LONG width
, LONG height
)
580 struct video_window
*window
= impl_from_IVideoWindow(iface
);
582 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
584 if (!SetWindowPos(window
->hwnd
, NULL
, left
, top
, width
, height
, SWP_NOACTIVATE
| SWP_NOZORDER
))
589 HRESULT WINAPI
BaseControlWindowImpl_GetWindowPosition(IVideoWindow
*iface
,
590 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
592 struct video_window
*window
= impl_from_IVideoWindow(iface
);
595 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
597 GetWindowRect(window
->hwnd
, &rect
);
600 *width
= rect
.right
- rect
.left
;
601 *height
= rect
.bottom
- rect
.top
;
605 HRESULT WINAPI
BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow
*iface
,
606 OAHWND hwnd
, LONG message
, LONG_PTR wparam
, LONG_PTR lparam
)
608 struct video_window
*window
= impl_from_IVideoWindow(iface
);
610 TRACE("window %p, hwnd %#Ix, message %#lx, wparam %#Ix, lparam %#Ix.\n",
611 window
, hwnd
, message
, wparam
, lparam
);
613 /* That these messages are forwarded, and no others, is stated by the
614 * DirectX documentation, and supported by manual testing. */
618 case WM_DEVMODECHANGE
:
619 case WM_DISPLAYCHANGE
:
620 case WM_PALETTECHANGED
:
621 case WM_PALETTEISCHANGING
:
622 case WM_QUERYNEWPALETTE
:
623 case WM_SYSCOLORCHANGE
:
624 SendMessageW(window
->hwnd
, message
, wparam
, lparam
);
631 HRESULT WINAPI
BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow
*iface
, LONG
*width
, LONG
*height
)
633 struct video_window
*window
= impl_from_IVideoWindow(iface
);
636 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
638 rect
= window
->ops
->get_default_rect(window
);
639 *width
= rect
.right
- rect
.left
;
640 *height
= rect
.bottom
- rect
.top
;
644 HRESULT WINAPI
BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow
*iface
, LONG
*width
, LONG
*height
)
646 struct video_window
*window
= impl_from_IVideoWindow(iface
);
649 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
651 rect
= window
->ops
->get_default_rect(window
);
652 *width
= rect
.right
- rect
.left
;
653 *height
= rect
.bottom
- rect
.top
;
657 HRESULT WINAPI
BaseControlWindowImpl_GetRestorePosition(IVideoWindow
*iface
, LONG
*pLeft
, LONG
*pTop
, LONG
*pWidth
, LONG
*pHeight
)
659 struct video_window
*This
= impl_from_IVideoWindow(iface
);
661 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This
, iface
, pLeft
, pTop
, pWidth
, pHeight
);
666 HRESULT WINAPI
BaseControlWindowImpl_HideCursor(IVideoWindow
*iface
, LONG hide
)
668 struct video_window
*window
= impl_from_IVideoWindow(iface
);
670 FIXME("window %p, hide %ld, stub!\n", window
, hide
);
675 HRESULT WINAPI
BaseControlWindowImpl_IsCursorHidden(IVideoWindow
*iface
, LONG
*CursorHidden
)
677 struct video_window
*This
= impl_from_IVideoWindow(iface
);
679 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, CursorHidden
);
684 static inline struct video_window
*impl_from_IBasicVideo(IBasicVideo
*iface
)
686 return CONTAINING_RECORD(iface
, struct video_window
, IBasicVideo_iface
);
689 static HRESULT WINAPI
basic_video_QueryInterface(IBasicVideo
*iface
, REFIID iid
, void **out
)
691 struct video_window
*window
= impl_from_IBasicVideo(iface
);
692 return IUnknown_QueryInterface(window
->pFilter
->outer_unk
, iid
, out
);
695 static ULONG WINAPI
basic_video_AddRef(IBasicVideo
*iface
)
697 struct video_window
*window
= impl_from_IBasicVideo(iface
);
698 return IUnknown_AddRef(window
->pFilter
->outer_unk
);
701 static ULONG WINAPI
basic_video_Release(IBasicVideo
*iface
)
703 struct video_window
*window
= impl_from_IBasicVideo(iface
);
704 return IUnknown_Release(window
->pFilter
->outer_unk
);
707 static HRESULT WINAPI
basic_video_GetTypeInfoCount(IBasicVideo
*iface
, UINT
*count
)
709 TRACE("iface %p, count %p.\n", iface
, count
);
714 static HRESULT WINAPI
basic_video_GetTypeInfo(IBasicVideo
*iface
, UINT index
,
715 LCID lcid
, ITypeInfo
**typeinfo
)
717 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface
, index
, lcid
, typeinfo
);
718 return strmbase_get_typeinfo(IBasicVideo_tid
, typeinfo
);
721 static HRESULT WINAPI
basic_video_GetIDsOfNames(IBasicVideo
*iface
, REFIID iid
,
722 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
727 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
728 iface
, debugstr_guid(iid
), names
, count
, lcid
, ids
);
730 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IBasicVideo_tid
, &typeinfo
)))
732 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, ids
);
733 ITypeInfo_Release(typeinfo
);
738 static HRESULT WINAPI
basic_video_Invoke(IBasicVideo
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
739 WORD flags
, DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*error_arg
)
744 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
745 iface
, id
, debugstr_guid(iid
), lcid
, flags
, params
, result
, excepinfo
, error_arg
);
747 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IBasicVideo_tid
, &typeinfo
)))
749 hr
= ITypeInfo_Invoke(typeinfo
, iface
, id
, flags
, params
, result
, excepinfo
, error_arg
);
750 ITypeInfo_Release(typeinfo
);
755 static const VIDEOINFOHEADER
*get_video_format(struct video_window
*window
)
757 /* Members of VIDEOINFOHEADER up to bmiHeader are identical to those of
758 * VIDEOINFOHEADER2. */
759 return (const VIDEOINFOHEADER
*)window
->pPin
->mt
.pbFormat
;
762 static const BITMAPINFOHEADER
*get_bitmap_header(struct video_window
*window
)
764 const AM_MEDIA_TYPE
*mt
= &window
->pPin
->mt
;
765 if (IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
766 return &((VIDEOINFOHEADER
*)mt
->pbFormat
)->bmiHeader
;
768 return &((VIDEOINFOHEADER2
*)mt
->pbFormat
)->bmiHeader
;
771 static HRESULT WINAPI
basic_video_get_AvgTimePerFrame(IBasicVideo
*iface
, REFTIME
*reftime
)
773 struct video_window
*window
= impl_from_IBasicVideo(iface
);
777 if (!window
->pPin
->peer
)
778 return VFW_E_NOT_CONNECTED
;
780 TRACE("window %p, reftime %p.\n", window
, reftime
);
782 *reftime
= (double)get_video_format(window
)->AvgTimePerFrame
/ 1e7
;
786 static HRESULT WINAPI
basic_video_get_BitRate(IBasicVideo
*iface
, LONG
*rate
)
788 struct video_window
*window
= impl_from_IBasicVideo(iface
);
790 TRACE("window %p, rate %p.\n", window
, rate
);
794 if (!window
->pPin
->peer
)
795 return VFW_E_NOT_CONNECTED
;
797 *rate
= get_video_format(window
)->dwBitRate
;
801 static HRESULT WINAPI
basic_video_get_BitErrorRate(IBasicVideo
*iface
, LONG
*rate
)
803 struct video_window
*window
= impl_from_IBasicVideo(iface
);
805 TRACE("window %p, rate %p.\n", window
, rate
);
809 if (!window
->pPin
->peer
)
810 return VFW_E_NOT_CONNECTED
;
812 *rate
= get_video_format(window
)->dwBitErrorRate
;
816 static HRESULT WINAPI
basic_video_get_VideoWidth(IBasicVideo
*iface
, LONG
*width
)
818 struct video_window
*window
= impl_from_IBasicVideo(iface
);
820 TRACE("window %p, width %p.\n", window
, width
);
825 *width
= get_bitmap_header(window
)->biWidth
;
830 static HRESULT WINAPI
basic_video_get_VideoHeight(IBasicVideo
*iface
, LONG
*height
)
832 struct video_window
*window
= impl_from_IBasicVideo(iface
);
834 TRACE("window %p, height %p.\n", window
, height
);
839 *height
= abs(get_bitmap_header(window
)->biHeight
);
844 static HRESULT WINAPI
basic_video_put_SourceLeft(IBasicVideo
*iface
, LONG left
)
846 struct video_window
*window
= impl_from_IBasicVideo(iface
);
848 TRACE("window %p, left %ld.\n", window
, left
);
850 if (left
< 0 || window
->src
.right
+ left
- window
->src
.left
> get_bitmap_header(window
)->biWidth
)
853 OffsetRect(&window
->src
, left
- window
->src
.left
, 0);
857 static HRESULT WINAPI
basic_video_get_SourceLeft(IBasicVideo
*iface
, LONG
*left
)
859 struct video_window
*window
= impl_from_IBasicVideo(iface
);
861 TRACE("window %p, left %p.\n", window
, left
);
866 *left
= window
->src
.left
;
870 static HRESULT WINAPI
basic_video_put_SourceWidth(IBasicVideo
*iface
, LONG width
)
872 struct video_window
*window
= impl_from_IBasicVideo(iface
);
874 TRACE("window %p, width %ld.\n", window
, width
);
876 if (width
<= 0 || window
->src
.left
+ width
> get_bitmap_header(window
)->biWidth
)
879 window
->src
.right
= window
->src
.left
+ width
;
883 static HRESULT WINAPI
basic_video_get_SourceWidth(IBasicVideo
*iface
, LONG
*width
)
885 struct video_window
*window
= impl_from_IBasicVideo(iface
);
887 TRACE("window %p, width %p.\n", window
, width
);
892 *width
= window
->src
.right
- window
->src
.left
;
896 static HRESULT WINAPI
basic_video_put_SourceTop(IBasicVideo
*iface
, LONG top
)
898 struct video_window
*window
= impl_from_IBasicVideo(iface
);
900 TRACE("window %p, top %ld.\n", window
, top
);
902 if (top
< 0 || window
->src
.bottom
+ top
- window
->src
.top
> get_bitmap_header(window
)->biHeight
)
905 OffsetRect(&window
->src
, 0, top
- window
->src
.top
);
909 static HRESULT WINAPI
basic_video_get_SourceTop(IBasicVideo
*iface
, LONG
*top
)
911 struct video_window
*window
= impl_from_IBasicVideo(iface
);
913 TRACE("window %p, top %p.\n", window
, top
);
918 *top
= window
->src
.top
;
922 static HRESULT WINAPI
basic_video_put_SourceHeight(IBasicVideo
*iface
, LONG height
)
924 struct video_window
*window
= impl_from_IBasicVideo(iface
);
926 TRACE("window %p, height %ld.\n", window
, height
);
928 if (height
<= 0 || window
->src
.top
+ height
> get_bitmap_header(window
)->biHeight
)
931 window
->src
.bottom
= window
->src
.top
+ height
;
935 static HRESULT WINAPI
basic_video_get_SourceHeight(IBasicVideo
*iface
, LONG
*height
)
937 struct video_window
*window
= impl_from_IBasicVideo(iface
);
939 TRACE("window %p, height %p\n", window
, height
);
944 *height
= window
->src
.bottom
- window
->src
.top
;
948 static HRESULT WINAPI
basic_video_put_DestinationLeft(IBasicVideo
*iface
, LONG left
)
950 struct video_window
*window
= impl_from_IBasicVideo(iface
);
952 TRACE("window %p, left %ld.\n", window
, left
);
954 window
->default_dst
= FALSE
;
955 OffsetRect(&window
->dst
, left
- window
->dst
.left
, 0);
959 static HRESULT WINAPI
basic_video_get_DestinationLeft(IBasicVideo
*iface
, LONG
*left
)
961 struct video_window
*window
= impl_from_IBasicVideo(iface
);
963 TRACE("window %p, left %p.\n", window
, left
);
968 *left
= window
->dst
.left
;
972 static HRESULT WINAPI
basic_video_put_DestinationWidth(IBasicVideo
*iface
, LONG width
)
974 struct video_window
*window
= impl_from_IBasicVideo(iface
);
976 TRACE("window %p, width %ld.\n", window
, width
);
981 window
->default_dst
= FALSE
;
982 window
->dst
.right
= window
->dst
.left
+ width
;
986 static HRESULT WINAPI
basic_video_get_DestinationWidth(IBasicVideo
*iface
, LONG
*width
)
988 struct video_window
*window
= impl_from_IBasicVideo(iface
);
990 TRACE("window %p, width %p.\n", window
, width
);
995 *width
= window
->dst
.right
- window
->dst
.left
;
999 static HRESULT WINAPI
basic_video_put_DestinationTop(IBasicVideo
*iface
, LONG top
)
1001 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1003 TRACE("window %p, top %ld.\n", window
, top
);
1005 window
->default_dst
= FALSE
;
1006 OffsetRect(&window
->dst
, 0, top
- window
->dst
.top
);
1010 static HRESULT WINAPI
basic_video_get_DestinationTop(IBasicVideo
*iface
, LONG
*top
)
1012 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1014 TRACE("window %p, top %p.\n", window
, top
);
1019 *top
= window
->dst
.top
;
1023 static HRESULT WINAPI
basic_video_put_DestinationHeight(IBasicVideo
*iface
, LONG height
)
1025 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1027 TRACE("window %p, height %ld.\n", window
, height
);
1030 return E_INVALIDARG
;
1032 window
->default_dst
= FALSE
;
1033 window
->dst
.bottom
= window
->dst
.top
+ height
;
1037 static HRESULT WINAPI
basic_video_get_DestinationHeight(IBasicVideo
*iface
, LONG
*height
)
1039 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1041 TRACE("window %p, height %p.\n", window
, height
);
1046 *height
= window
->dst
.bottom
- window
->dst
.top
;
1050 static HRESULT WINAPI
basic_video_SetSourcePosition(IBasicVideo
*iface
,
1051 LONG left
, LONG top
, LONG width
, LONG height
)
1053 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1054 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1056 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
1058 if (left
< 0 || left
+ width
> bitmap_header
->biWidth
|| width
<= 0)
1059 return E_INVALIDARG
;
1060 if (top
< 0 || top
+ height
> bitmap_header
->biHeight
|| height
<= 0)
1061 return E_INVALIDARG
;
1063 SetRect(&window
->src
, left
, top
, left
+ width
, top
+ height
);
1067 static HRESULT WINAPI
basic_video_GetSourcePosition(IBasicVideo
*iface
,
1068 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
1070 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1072 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
1074 if (!left
|| !top
|| !width
|| !height
)
1077 *left
= window
->src
.left
;
1078 *top
= window
->src
.top
;
1079 *width
= window
->src
.right
- window
->src
.left
;
1080 *height
= window
->src
.bottom
- window
->src
.top
;
1084 static HRESULT WINAPI
basic_video_SetDefaultSourcePosition(IBasicVideo
*iface
)
1086 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1087 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1089 TRACE("window %p.\n", window
);
1091 SetRect(&window
->src
, 0, 0, bitmap_header
->biWidth
, bitmap_header
->biHeight
);
1095 static HRESULT WINAPI
basic_video_SetDestinationPosition(IBasicVideo
*iface
,
1096 LONG left
, LONG top
, LONG width
, LONG height
)
1098 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1100 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
1102 if (width
<= 0 || height
<= 0)
1103 return E_INVALIDARG
;
1105 window
->default_dst
= FALSE
;
1106 SetRect(&window
->dst
, left
, top
, left
+ width
, top
+ height
);
1110 static HRESULT WINAPI
basic_video_GetDestinationPosition(IBasicVideo
*iface
,
1111 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
1113 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1115 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
1117 if (!left
|| !top
|| !width
|| !height
)
1120 *left
= window
->dst
.left
;
1121 *top
= window
->dst
.top
;
1122 *width
= window
->dst
.right
- window
->dst
.left
;
1123 *height
= window
->dst
.bottom
- window
->dst
.top
;
1127 static HRESULT WINAPI
basic_video_SetDefaultDestinationPosition(IBasicVideo
*iface
)
1129 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1131 TRACE("window %p.\n", window
);
1133 window
->default_dst
= TRUE
;
1134 GetClientRect(window
->hwnd
, &window
->dst
);
1138 static HRESULT WINAPI
basic_video_GetVideoSize(IBasicVideo
*iface
, LONG
*width
, LONG
*height
)
1140 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1141 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1143 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
1145 if (!width
|| !height
)
1148 *width
= bitmap_header
->biWidth
;
1149 *height
= bitmap_header
->biHeight
;
1153 static HRESULT WINAPI
basic_video_GetVideoPaletteEntries(IBasicVideo
*iface
,
1154 LONG start
, LONG count
, LONG
*ret_count
, LONG
*palette
)
1156 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1158 FIXME("window %p, start %ld, count %ld, ret_count %p, palette %p, stub!\n",
1159 window
, start
, count
, ret_count
, palette
);
1161 if (!ret_count
|| !palette
)
1165 return VFW_E_NO_PALETTE_AVAILABLE
;
1168 static HRESULT WINAPI
basic_video_GetCurrentImage(IBasicVideo
*iface
, LONG
*size
, LONG
*image
)
1170 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1172 TRACE("window %p, size %p, image %p.\n", window
, size
, image
);
1174 if (!size
|| !image
)
1177 return window
->ops
->get_current_image(window
, size
, image
);
1180 static HRESULT WINAPI
basic_video_IsUsingDefaultSource(IBasicVideo
*iface
)
1182 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1183 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1185 TRACE("window %p.\n", window
);
1187 if (!window
->src
.left
&& !window
->src
.top
1188 && window
->src
.right
== bitmap_header
->biWidth
1189 && window
->src
.bottom
== bitmap_header
->biHeight
)
1194 static HRESULT WINAPI
basic_video_IsUsingDefaultDestination(IBasicVideo
*iface
)
1196 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1198 TRACE("window %p.\n", window
);
1200 return window
->default_dst
? S_OK
: S_FALSE
;
1203 static const IBasicVideoVtbl basic_video_vtbl
=
1205 basic_video_QueryInterface
,
1207 basic_video_Release
,
1208 basic_video_GetTypeInfoCount
,
1209 basic_video_GetTypeInfo
,
1210 basic_video_GetIDsOfNames
,
1212 basic_video_get_AvgTimePerFrame
,
1213 basic_video_get_BitRate
,
1214 basic_video_get_BitErrorRate
,
1215 basic_video_get_VideoWidth
,
1216 basic_video_get_VideoHeight
,
1217 basic_video_put_SourceLeft
,
1218 basic_video_get_SourceLeft
,
1219 basic_video_put_SourceWidth
,
1220 basic_video_get_SourceWidth
,
1221 basic_video_put_SourceTop
,
1222 basic_video_get_SourceTop
,
1223 basic_video_put_SourceHeight
,
1224 basic_video_get_SourceHeight
,
1225 basic_video_put_DestinationLeft
,
1226 basic_video_get_DestinationLeft
,
1227 basic_video_put_DestinationWidth
,
1228 basic_video_get_DestinationWidth
,
1229 basic_video_put_DestinationTop
,
1230 basic_video_get_DestinationTop
,
1231 basic_video_put_DestinationHeight
,
1232 basic_video_get_DestinationHeight
,
1233 basic_video_SetSourcePosition
,
1234 basic_video_GetSourcePosition
,
1235 basic_video_SetDefaultSourcePosition
,
1236 basic_video_SetDestinationPosition
,
1237 basic_video_GetDestinationPosition
,
1238 basic_video_SetDefaultDestinationPosition
,
1239 basic_video_GetVideoSize
,
1240 basic_video_GetVideoPaletteEntries
,
1241 basic_video_GetCurrentImage
,
1242 basic_video_IsUsingDefaultSource
,
1243 basic_video_IsUsingDefaultDestination
1246 void video_window_unregister_class(void)
1248 if (!UnregisterClassW(class_name
, NULL
) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST
)
1249 ERR("Failed to unregister class, error %lu.\n", GetLastError());
1252 void video_window_init(struct video_window
*window
, const IVideoWindowVtbl
*vtbl
,
1253 struct strmbase_filter
*owner
, struct strmbase_pin
*pin
, const struct video_window_ops
*ops
)
1255 memset(window
, 0, sizeof(*window
));
1257 window
->IVideoWindow_iface
.lpVtbl
= vtbl
;
1258 window
->IBasicVideo_iface
.lpVtbl
= &basic_video_vtbl
;
1259 window
->default_dst
= TRUE
;
1260 window
->AutoShow
= OATRUE
;
1261 window
->pFilter
= owner
;
1265 void video_window_cleanup(struct video_window
*window
)
1269 /* Media Player Classic deadlocks if WM_PARENTNOTIFY is sent, so clear
1270 * the child style first. Just like Windows, we don't actually unparent
1271 * the window, to prevent extra focus events from being generated since
1272 * it would become top-level for a brief period before being destroyed. */
1273 SetWindowLongW(window
->hwnd
, GWL_STYLE
, GetWindowLongW(window
->hwnd
, GWL_STYLE
) & ~WS_CHILD
);
1275 SendMessageW(window
->hwnd
, WM_QUARTZ_DESTROY
, 0, 0);
1276 window
->hwnd
= NULL
;