2 * Video Mixing Renderer 7 unit tests
4 * Copyright 2018 Zebediah Figura
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
25 #include "wine/heap.h"
26 #include "wine/strmbase.h"
27 #include "wine/test.h"
29 static IBaseFilter
*create_vmr7(DWORD mode
)
31 IBaseFilter
*filter
= NULL
;
32 IVMRFilterConfig
*config
;
33 HRESULT hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
34 &IID_IBaseFilter
, (void **)&filter
);
35 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
38 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig
, (void **)&config
);
39 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
40 hr
= IVMRFilterConfig_SetRenderingMode(config
, mode
);
41 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
42 IVMRFilterConfig_Release(config
);
47 static HRESULT
set_mixing_mode(IBaseFilter
*filter
)
49 IVMRFilterConfig
*config
;
52 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig
, (void **)&config
);
53 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
55 hr
= IVMRFilterConfig_SetNumberOfStreams(config
, 2);
56 todo_wine
ok(hr
== VFW_E_DDRAW_CAPS_NOT_SUITABLE
|| hr
== S_OK
, "Got hr %#x.\n", hr
);
58 IVMRFilterConfig_Release(config
);
62 static inline BOOL
compare_media_types(const AM_MEDIA_TYPE
*a
, const AM_MEDIA_TYPE
*b
)
64 return !memcmp(a
, b
, offsetof(AM_MEDIA_TYPE
, pbFormat
))
65 && !memcmp(a
->pbFormat
, b
->pbFormat
, a
->cbFormat
);
68 static IFilterGraph2
*create_graph(void)
72 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (void **)&ret
);
73 ok(hr
== S_OK
, "Failed to create FilterGraph: %#x\n", hr
);
77 static ULONG
get_refcount(void *iface
)
79 IUnknown
*unknown
= iface
;
80 IUnknown_AddRef(unknown
);
81 return IUnknown_Release(unknown
);
84 static void test_filter_config(void)
86 IVMRFilterConfig
*config
;
91 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
92 &IID_IVMRFilterConfig
, (void **)&config
);
93 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
95 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
96 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
97 ok(mode
== VMRMode_Windowed
, "Got mode %#x.\n", mode
);
99 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowed
);
100 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
102 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
103 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
104 ok(mode
== VMRMode_Windowed
, "Got mode %#x.\n", mode
);
106 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowed
);
107 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
109 ref
= IVMRFilterConfig_Release(config
);
110 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
112 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
113 &IID_IVMRFilterConfig
, (void **)&config
);
114 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
116 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowless
);
117 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
119 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
120 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
121 ok(mode
== VMRMode_Windowless
, "Got mode %#x.\n", mode
);
123 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowed
);
124 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
126 ref
= IVMRFilterConfig_Release(config
);
127 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
129 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
130 &IID_IVMRFilterConfig
, (void **)&config
);
131 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
133 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Renderless
);
134 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
136 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
137 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
138 ok(mode
== VMRMode_Renderless
, "Got mode %#x.\n", mode
);
140 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowless
);
141 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
143 ref
= IVMRFilterConfig_Release(config
);
144 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
146 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
147 &IID_IVMRFilterConfig
, (void **)&config
);
148 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
150 hr
= IVMRFilterConfig_GetNumberOfStreams(config
, &count
);
151 todo_wine
ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#x.\n", hr
);
153 hr
= IVMRFilterConfig_SetNumberOfStreams(config
, 3);
154 if (hr
!= VFW_E_DDRAW_CAPS_NOT_SUITABLE
)
156 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
158 hr
= IVMRFilterConfig_GetNumberOfStreams(config
, &count
);
160 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
161 ok(count
== 3, "Got count %u.\n", count
);
164 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
165 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
166 ok(mode
== VMRMode_Windowed
, "Got mode %#x.\n", mode
);
168 /* Despite MSDN, you can still change the rendering mode after setting the
170 hr
= IVMRFilterConfig_SetRenderingMode(config
, VMRMode_Windowless
);
171 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
173 hr
= IVMRFilterConfig_GetRenderingMode(config
, &mode
);
174 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
175 ok(mode
== VMRMode_Windowless
, "Got mode %#x.\n", mode
);
177 hr
= IVMRFilterConfig_GetNumberOfStreams(config
, &count
);
179 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
180 ok(count
== 3, "Got count %u.\n", count
);
184 skip("Mixing mode is not supported.\n");
186 ref
= IVMRFilterConfig_Release(config
);
187 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
190 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
191 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
193 IUnknown
*iface
= iface_ptr
;
194 HRESULT hr
, expected_hr
;
197 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
199 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
200 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
202 IUnknown_Release(unk
);
205 static void test_interfaces(void)
207 WCHAR sink_id
[] = {'V','M','R',' ','I','n','p','u','t','0',0};
208 IBaseFilter
*filter
= create_vmr7(0);
212 check_interface(filter
, &IID_IAMCertifiedOutputProtection
, TRUE
);
213 check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
214 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
215 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
216 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
217 todo_wine
check_interface(filter
, &IID_IKsPropertySet
, TRUE
);
218 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
219 check_interface(filter
, &IID_IMediaPosition
, TRUE
);
220 check_interface(filter
, &IID_IMediaSeeking
, TRUE
);
221 check_interface(filter
, &IID_IPersist
, TRUE
);
222 check_interface(filter
, &IID_IQualityControl
, TRUE
);
223 todo_wine
check_interface(filter
, &IID_IQualProp
, TRUE
);
224 check_interface(filter
, &IID_IUnknown
, TRUE
);
225 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
226 todo_wine
check_interface(filter
, &IID_IVMRAspectRatioControl
, TRUE
);
227 todo_wine
check_interface(filter
, &IID_IVMRDeinterlaceControl
, TRUE
);
228 check_interface(filter
, &IID_IVMRFilterConfig
, TRUE
);
229 todo_wine
check_interface(filter
, &IID_IVMRMixerBitmap
, TRUE
);
230 check_interface(filter
, &IID_IVMRMonitorConfig
, TRUE
);
232 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
233 check_interface(filter
, &IID_IDirectDrawVideo
, FALSE
);
234 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
235 check_interface(filter
, &IID_IPin
, FALSE
);
236 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
237 check_interface(filter
, &IID_IVMRAspectRatioControl9
, FALSE
);
238 check_interface(filter
, &IID_IVMRDeinterlaceControl9
, FALSE
);
239 todo_wine
check_interface(filter
, &IID_IVMRFilterConfig9
, FALSE
);
240 check_interface(filter
, &IID_IVMRMixerBitmap9
, FALSE
);
241 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
242 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
243 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
244 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, FALSE
);
245 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
246 check_interface(filter
, &IID_IVMRWindowlessControl
, FALSE
);
247 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
249 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
251 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
252 check_interface(pin
, &IID_IOverlay
, TRUE
);
253 check_interface(pin
, &IID_IPin
, TRUE
);
254 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
255 check_interface(pin
, &IID_IUnknown
, TRUE
);
257 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
258 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
259 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
263 IBaseFilter_Release(filter
);
264 filter
= create_vmr7(VMRMode_Windowless
);
266 check_interface(filter
, &IID_IVMRMonitorConfig
, TRUE
);
267 check_interface(filter
, &IID_IVMRWindowlessControl
, TRUE
);
269 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
270 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
271 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
272 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, FALSE
);
273 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
274 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
275 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
276 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
277 todo_wine
check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
279 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
281 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
282 check_interface(pin
, &IID_IOverlay
, TRUE
);
283 check_interface(pin
, &IID_IPin
, TRUE
);
284 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
285 check_interface(pin
, &IID_IUnknown
, TRUE
);
287 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
288 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
289 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
293 IBaseFilter_Release(filter
);
294 filter
= create_vmr7(VMRMode_Renderless
);
296 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, TRUE
);
298 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
299 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
300 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
301 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
302 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig
, FALSE
);
303 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
304 todo_wine
check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
305 check_interface(filter
, &IID_IVMRWindowlessControl
, FALSE
);
306 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
308 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
310 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
311 check_interface(pin
, &IID_IOverlay
, TRUE
);
312 check_interface(pin
, &IID_IPin
, TRUE
);
313 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
314 check_interface(pin
, &IID_IUnknown
, TRUE
);
316 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
317 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
318 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
322 ref
= IBaseFilter_Release(filter
);
323 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
326 static const GUID test_iid
= {0x33333333};
327 static LONG outer_ref
= 1;
329 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
331 if (IsEqualGUID(iid
, &IID_IUnknown
)
332 || IsEqualGUID(iid
, &IID_IBaseFilter
)
333 || IsEqualGUID(iid
, &test_iid
))
335 *out
= (IUnknown
*)0xdeadbeef;
338 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
339 return E_NOINTERFACE
;
342 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
344 return InterlockedIncrement(&outer_ref
);
347 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
349 return InterlockedDecrement(&outer_ref
);
352 static const IUnknownVtbl outer_vtbl
=
354 outer_QueryInterface
,
359 static IUnknown test_outer
= {&outer_vtbl
};
361 static void test_aggregation(void)
363 IBaseFilter
*filter
, *filter2
;
364 IUnknown
*unk
, *unk2
;
368 filter
= (IBaseFilter
*)0xdeadbeef;
369 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, &test_outer
, CLSCTX_INPROC_SERVER
,
370 &IID_IBaseFilter
, (void **)&filter
);
371 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
372 ok(!filter
, "Got interface %p.\n", filter
);
374 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer
, &test_outer
, CLSCTX_INPROC_SERVER
,
375 &IID_IUnknown
, (void **)&unk
);
376 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
377 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
378 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
379 ref
= get_refcount(unk
);
380 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
382 ref
= IUnknown_AddRef(unk
);
383 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
384 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
386 ref
= IUnknown_Release(unk
);
387 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
388 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
390 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
391 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
392 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
393 IUnknown_Release(unk2
);
395 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
396 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
398 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
399 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
400 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
402 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
403 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
404 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
406 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
407 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
408 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
410 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
411 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
412 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
414 IBaseFilter_Release(filter
);
415 ref
= IUnknown_Release(unk
);
416 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
417 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
420 static void test_enum_pins(void)
422 IBaseFilter
*filter
= create_vmr7(0);
423 IEnumPins
*enum1
, *enum2
;
428 ref
= get_refcount(filter
);
429 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
431 hr
= IBaseFilter_EnumPins(filter
, NULL
);
432 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
434 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
435 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
436 ref
= get_refcount(filter
);
437 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
438 ref
= get_refcount(enum1
);
439 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
441 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
442 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
444 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
445 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
446 ref
= get_refcount(filter
);
447 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
448 ref
= get_refcount(pins
[0]);
449 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
450 ref
= get_refcount(enum1
);
451 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
452 IPin_Release(pins
[0]);
453 ref
= get_refcount(filter
);
454 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
456 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
457 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
459 hr
= IEnumPins_Reset(enum1
);
460 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
462 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
463 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
464 ok(count
== 1, "Got count %u.\n", count
);
465 IPin_Release(pins
[0]);
467 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
468 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
469 ok(!count
, "Got count %u.\n", count
);
471 hr
= IEnumPins_Reset(enum1
);
472 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
474 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
475 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
477 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
478 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
479 ok(count
== 1, "Got count %u.\n", count
);
480 IPin_Release(pins
[0]);
482 hr
= IEnumPins_Reset(enum1
);
483 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
485 hr
= IEnumPins_Clone(enum1
, &enum2
);
486 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
488 hr
= IEnumPins_Skip(enum1
, 2);
489 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
491 hr
= IEnumPins_Skip(enum1
, 1);
492 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
494 hr
= IEnumPins_Skip(enum1
, 1);
495 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
497 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
498 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
500 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
501 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
502 IPin_Release(pins
[0]);
504 IEnumPins_Release(enum2
);
506 if (SUCCEEDED(set_mixing_mode(filter
)))
508 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
509 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
511 hr
= IEnumPins_Reset(enum1
);
512 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
514 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
515 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
516 IPin_Release(pins
[0]);
518 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
519 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
520 IPin_Release(pins
[0]);
522 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
523 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
525 hr
= IEnumPins_Reset(enum1
);
526 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
528 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
529 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
530 ok(count
== 2, "Got count %u.\n", count
);
531 IPin_Release(pins
[0]);
532 IPin_Release(pins
[1]);
534 hr
= IEnumPins_Reset(enum1
);
535 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
537 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
538 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
539 ok(count
== 2, "Got count %u.\n", count
);
540 IPin_Release(pins
[0]);
541 IPin_Release(pins
[1]);
544 skip("Mixing mode is not supported.\n");
546 IEnumPins_Release(enum1
);
547 ref
= IBaseFilter_Release(filter
);
548 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
551 static void test_find_pin(void)
553 static const WCHAR input_pinW
[] = {'i','n','p','u','t',' ','p','i','n',0};
554 static const WCHAR inW
[] = {'I','n',0};
556 WCHAR sink_id
[] = {'V','M','R',' ','I','n','p','u','t','0',0};
557 IBaseFilter
*filter
= create_vmr7(0);
558 IEnumPins
*enum_pins
;
563 IBaseFilter_EnumPins(filter
, &enum_pins
);
565 hr
= IBaseFilter_FindPin(filter
, input_pinW
, &pin
);
566 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
568 hr
= IBaseFilter_FindPin(filter
, inW
, &pin
);
569 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
571 hr
= IBaseFilter_FindPin(filter
, sink_id
, &pin
);
572 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
573 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
574 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
575 ok(pin
== pin2
, "Pins did not match.\n");
580 hr
= IBaseFilter_FindPin(filter
, sink_id
, &pin
);
581 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
583 if (SUCCEEDED(set_mixing_mode(filter
)))
585 IEnumPins_Reset(enum_pins
);
588 hr
= IBaseFilter_FindPin(filter
, sink_id
, &pin
);
589 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
590 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
591 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
592 ok(pin
== pin2
, "Pins did not match.\n");
597 hr
= IBaseFilter_FindPin(filter
, sink_id
, &pin
);
598 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
599 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
600 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
601 ok(pin
== pin2
, "Pins did not match.\n");
606 hr
= IBaseFilter_FindPin(filter
, sink_id
, &pin
);
607 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
610 skip("Mixing mode is not supported.\n");
612 IEnumPins_Release(enum_pins
);
613 ref
= IBaseFilter_Release(filter
);
614 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
617 static void test_pin_info(void)
619 WCHAR sink_id
[] = {'V','M','R',' ','I','n','p','u','t','0',0};
620 IBaseFilter
*filter
= create_vmr7(0);
628 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
629 hr
= IPin_QueryPinInfo(pin
, &info
);
630 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
631 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
632 ok(!lstrcmpW(info
.achName
, sink_id
), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
633 IBaseFilter_Release(info
.pFilter
);
635 hr
= IPin_QueryDirection(pin
, &dir
);
636 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
637 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
639 hr
= IPin_QueryId(pin
, &id
);
640 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
641 ok(!lstrcmpW(id
, sink_id
), "Got id %s.\n", wine_dbgstr_w(id
));
644 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
645 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
649 if (SUCCEEDED(set_mixing_mode(filter
)))
653 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
654 hr
= IPin_QueryPinInfo(pin
, &info
);
655 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
656 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
657 ok(!lstrcmpW(info
.achName
, sink_id
), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
658 IBaseFilter_Release(info
.pFilter
);
660 hr
= IPin_QueryDirection(pin
, &dir
);
661 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
662 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
664 hr
= IPin_QueryId(pin
, &id
);
665 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
666 ok(!lstrcmpW(id
, sink_id
), "Got id %s.\n", wine_dbgstr_w(id
));
669 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
670 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
675 skip("Mixing mode is not supported.\n");
677 ref
= IBaseFilter_Release(filter
);
678 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
681 static void test_media_types(void)
683 WCHAR sink_id
[] = {'V','M','R',' ','I','n','p','u','t','0',0};
684 IBaseFilter
*filter
= create_vmr7(0);
685 AM_MEDIA_TYPE
*mt
, req_mt
= {{0}};
686 VIDEOINFOHEADER vih
=
689 {sizeof(BITMAPINFOHEADER
), 32, 24, 1, 0, BI_RGB
}
691 IEnumMediaTypes
*enummt
;
697 static const GUID
*subtype_tests
[] =
700 &MEDIASUBTYPE_RGB565
,
705 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
707 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
708 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
710 hr
= IEnumMediaTypes_Next(enummt
, 1, &mt
, NULL
);
711 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
713 IEnumMediaTypes_Release(enummt
);
715 req_mt
.majortype
= MEDIATYPE_Video
;
716 req_mt
.formattype
= FORMAT_VideoInfo
;
717 req_mt
.cbFormat
= sizeof(VIDEOINFOHEADER
);
718 req_mt
.pbFormat
= (BYTE
*)&vih
;
720 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
722 req_mt
.subtype
= *subtype_tests
[i
];
723 hr
= IPin_QueryAccept(pin
, &req_mt
);
724 ok(hr
== S_OK
, "Got hr %#x for subtype %s.\n", hr
, wine_dbgstr_guid(subtype_tests
[i
]));
727 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
728 hr
= IPin_QueryAccept(pin
, &req_mt
);
729 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
730 req_mt
.subtype
= MEDIASUBTYPE_RGB24
;
732 req_mt
.majortype
= MEDIATYPE_NULL
;
733 hr
= IPin_QueryAccept(pin
, &req_mt
);
734 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
735 req_mt
.majortype
= MEDIATYPE_Video
;
737 req_mt
.formattype
= FORMAT_None
;
738 hr
= IPin_QueryAccept(pin
, &req_mt
);
739 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
741 req_mt
.formattype
= GUID_NULL
;
742 hr
= IPin_QueryAccept(pin
, &req_mt
);
743 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
746 ref
= IBaseFilter_Release(filter
);
747 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
750 static void test_enum_media_types(void)
752 WCHAR sink_id
[] = {'V','M','R',' ','I','n','p','u','t','0',0};
753 IBaseFilter
*filter
= create_vmr7(0);
754 IEnumMediaTypes
*enum1
, *enum2
;
755 AM_MEDIA_TYPE
*mts
[2];
760 IBaseFilter_FindPin(filter
, sink_id
, &pin
);
762 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
763 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
765 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
766 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
768 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
769 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
770 ok(!count
, "Got count %u.\n", count
);
772 hr
= IEnumMediaTypes_Reset(enum1
);
773 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
775 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
776 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
778 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
779 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
781 hr
= IEnumMediaTypes_Skip(enum1
, 1);
782 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
784 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
785 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
787 IEnumMediaTypes_Release(enum1
);
788 IEnumMediaTypes_Release(enum2
);
791 ref
= IBaseFilter_Release(filter
);
792 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
795 static void test_unconnected_filter_state(void)
797 IBaseFilter
*filter
= create_vmr7(0);
802 hr
= IBaseFilter_GetState(filter
, 0, &state
);
803 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
804 ok(state
== State_Stopped
, "Got state %u.\n", state
);
806 hr
= IBaseFilter_Pause(filter
);
807 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
809 hr
= IBaseFilter_GetState(filter
, 0, &state
);
810 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
811 ok(state
== State_Paused
, "Got state %u.\n", state
);
813 hr
= IBaseFilter_Run(filter
, 0);
814 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
816 hr
= IBaseFilter_GetState(filter
, 0, &state
);
817 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
818 ok(state
== State_Running
, "Got state %u.\n", state
);
820 hr
= IBaseFilter_Pause(filter
);
821 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
823 hr
= IBaseFilter_GetState(filter
, 0, &state
);
824 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
825 ok(state
== State_Paused
, "Got state %u.\n", state
);
827 hr
= IBaseFilter_Stop(filter
);
828 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
830 hr
= IBaseFilter_GetState(filter
, 0, &state
);
831 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
832 ok(state
== State_Stopped
, "Got state %u.\n", state
);
834 hr
= IBaseFilter_Run(filter
, 0);
835 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
837 hr
= IBaseFilter_GetState(filter
, 0, &state
);
838 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
839 ok(state
== State_Running
, "Got state %u.\n", state
);
841 hr
= IBaseFilter_Stop(filter
);
842 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
844 hr
= IBaseFilter_GetState(filter
, 0, &state
);
845 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
846 ok(state
== State_Stopped
, "Got state %u.\n", state
);
848 ref
= IBaseFilter_Release(filter
);
849 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
854 struct strmbase_filter filter
;
855 struct strmbase_source source
;
858 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
860 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
863 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
865 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
867 return &filter
->source
.pin
;
871 static void testfilter_destroy(struct strmbase_filter
*iface
)
873 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
874 strmbase_source_cleanup(&filter
->source
);
875 strmbase_filter_cleanup(&filter
->filter
);
878 static const struct strmbase_filter_ops testfilter_ops
=
880 .filter_get_pin
= testfilter_get_pin
,
881 .filter_destroy
= testfilter_destroy
,
884 static const IPinVtbl testsource_vtbl
=
886 BasePinImpl_QueryInterface
,
889 BaseOutputPinImpl_Connect
,
890 BaseOutputPinImpl_ReceiveConnection
,
891 BasePinImpl_Disconnect
,
892 BasePinImpl_ConnectedTo
,
893 BasePinImpl_ConnectionMediaType
,
894 BasePinImpl_QueryPinInfo
,
895 BasePinImpl_QueryDirection
,
897 BasePinImpl_QueryAccept
,
898 BasePinImpl_EnumMediaTypes
,
899 BasePinImpl_QueryInternalConnections
,
900 BaseOutputPinImpl_EndOfStream
,
901 BaseOutputPinImpl_BeginFlush
,
902 BaseOutputPinImpl_EndFlush
,
903 BasePinImpl_NewSegment
,
906 static HRESULT
testsource_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
911 static HRESULT WINAPI
testsource_AttemptConnection(struct strmbase_source
*iface
,
912 IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
916 iface
->pin
.peer
= peer
;
918 CopyMediaType(&iface
->pin
.mt
, mt
);
920 if (FAILED(hr
= IPin_ReceiveConnection(peer
, &iface
->pin
.IPin_iface
, mt
)))
922 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
924 iface
->pin
.peer
= NULL
;
925 FreeMediaType(&iface
->pin
.mt
);
931 static const struct strmbase_source_ops testsource_ops
=
933 .base
.pin_query_accept
= testsource_query_accept
,
934 .base
.pin_get_media_type
= strmbase_pin_get_media_type
,
935 .pfnAttemptConnection
= testsource_AttemptConnection
,
938 static void testfilter_init(struct testfilter
*filter
)
940 static const GUID clsid
= {0xabacab};
941 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
942 strmbase_source_init(&filter
->source
, &testsource_vtbl
, &filter
->filter
, L
"", &testsource_ops
);
945 static void test_allocator(IMemInputPin
*input
)
947 IMemAllocator
*req_allocator
, *ret_allocator
;
948 ALLOCATOR_PROPERTIES props
, req_props
;
951 hr
= IMemInputPin_GetAllocatorRequirements(input
, &props
);
952 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
954 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
955 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
959 hr
= IMemAllocator_GetProperties(ret_allocator
, &props
);
960 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
961 ok(!props
.cBuffers
, "Got %d buffers.\n", props
.cBuffers
);
962 ok(!props
.cbBuffer
, "Got size %d.\n", props
.cbBuffer
);
963 ok(!props
.cbAlign
, "Got alignment %d.\n", props
.cbAlign
);
964 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
966 hr
= IMemInputPin_NotifyAllocator(input
, ret_allocator
, TRUE
);
967 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
969 req_props
.cBuffers
= 1;
970 req_props
.cbBuffer
= 32 * 16 * 4;
971 req_props
.cbAlign
= 1;
972 req_props
.cbPrefix
= 0;
973 hr
= IMemAllocator_SetProperties(ret_allocator
, &req_props
, &props
);
974 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
975 ok(props
.cBuffers
== 1, "Got %d buffers.\n", props
.cBuffers
);
976 ok(props
.cbBuffer
== 32 * 16 * 4, "Got size %d.\n", props
.cbBuffer
);
977 ok(props
.cbAlign
== 1, "Got alignment %d.\n", props
.cbAlign
);
978 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
980 IMemAllocator_Release(ret_allocator
);
983 hr
= IMemInputPin_NotifyAllocator(input
, NULL
, TRUE
);
984 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
986 CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
987 &IID_IMemAllocator
, (void **)&req_allocator
);
989 hr
= IMemInputPin_NotifyAllocator(input
, req_allocator
, TRUE
);
990 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
992 IMemAllocator_Release(req_allocator
);
995 struct frame_thread_params
998 IMediaSample
*sample
;
1001 static DWORD WINAPI
frame_thread(void *arg
)
1003 struct frame_thread_params
*params
= arg
;
1006 if (winetest_debug
> 1) trace("%04x: Sending frame.\n", GetCurrentThreadId());
1007 hr
= IMemInputPin_Receive(params
->sink
, params
->sample
);
1008 if (winetest_debug
> 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr
);
1009 IMediaSample_Release(params
->sample
);
1014 static HANDLE
send_frame(IMemInputPin
*sink
)
1016 struct frame_thread_params
*params
= heap_alloc(sizeof(*params
));
1017 REFERENCE_TIME start_time
, end_time
;
1018 IMemAllocator
*allocator
;
1019 IMediaSample
*sample
;
1024 hr
= IMemInputPin_GetAllocator(sink
, &allocator
);
1025 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1027 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1028 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1030 hr
= IMediaSample_GetPointer(sample
, &data
);
1031 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1032 memset(data
, 0x55, IMediaSample_GetSize(sample
));
1034 hr
= IMediaSample_SetActualDataLength(sample
, IMediaSample_GetSize(sample
));
1035 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1038 end_time
= start_time
+ 10000000;
1039 hr
= IMediaSample_SetTime(sample
, &start_time
, &end_time
);
1040 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1042 params
->sink
= sink
;
1043 params
->sample
= sample
;
1044 thread
= CreateThread(NULL
, 0, frame_thread
, params
, 0, NULL
);
1046 IMemAllocator_Release(allocator
);
1050 static HRESULT
join_thread_(int line
, HANDLE thread
)
1053 ok_(__FILE__
, line
)(!WaitForSingleObject(thread
, 1000), "Wait failed.\n");
1054 GetExitCodeThread(thread
, &ret
);
1055 CloseHandle(thread
);
1058 #define join_thread(a) join_thread_(__LINE__, a)
1060 static void test_filter_state(IMemInputPin
*input
, IFilterGraph2
*graph
)
1062 IMemAllocator
*allocator
;
1063 IMediaControl
*control
;
1064 IMediaSample
*sample
;
1065 OAFilterState state
;
1069 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1071 thread
= send_frame(input
);
1072 hr
= join_thread(thread
);
1073 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1075 /* The renderer is not fully paused until it receives a sample. The thread
1076 * sending the sample blocks in IMemInputPin_Receive() until the filter is
1077 * stopped or run. */
1079 hr
= IMediaControl_Pause(control
);
1080 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1082 hr
= IMediaControl_GetState(control
, 0, &state
);
1083 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1085 thread
= send_frame(input
);
1087 hr
= IMediaControl_GetState(control
, 1000, &state
);
1088 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1090 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1092 hr
= IMediaControl_Stop(control
);
1093 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1095 hr
= join_thread(thread
);
1096 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1098 /* The sink will decommit our allocator for us when stopping, however it
1099 * will not recommit it when pausing. */
1100 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1101 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1102 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1103 todo_wine
ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#x.\n", hr
);
1104 if (hr
== S_OK
) IMediaSample_Release(sample
);
1106 hr
= IMemAllocator_Commit(allocator
);
1107 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1108 thread
= send_frame(input
);
1109 hr
= join_thread(thread
);
1110 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1112 hr
= IMediaControl_Pause(control
);
1113 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1115 hr
= IMediaControl_GetState(control
, 0, &state
);
1116 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1118 thread
= send_frame(input
);
1120 hr
= IMediaControl_GetState(control
, 1000, &state
);
1121 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1123 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1125 hr
= IMediaControl_Run(control
);
1126 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1128 hr
= IMediaControl_GetState(control
, 0, &state
);
1129 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1131 hr
= join_thread(thread
);
1132 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1134 thread
= send_frame(input
);
1135 hr
= join_thread(thread
);
1136 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1138 hr
= IMediaControl_Pause(control
);
1139 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1141 hr
= IMediaControl_GetState(control
, 0, &state
);
1142 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1144 thread
= send_frame(input
);
1146 hr
= IMediaControl_GetState(control
, 1000, &state
);
1147 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1149 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1151 hr
= IMediaControl_Run(control
);
1152 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1154 hr
= IMediaControl_GetState(control
, 0, &state
);
1155 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1157 hr
= join_thread(thread
);
1158 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1160 hr
= IMediaControl_Pause(control
);
1161 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1163 hr
= IMediaControl_GetState(control
, 0, &state
);
1164 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1166 hr
= IMediaControl_Stop(control
);
1167 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1169 hr
= IMediaControl_GetState(control
, 0, &state
);
1170 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1172 hr
= IMemAllocator_Commit(allocator
);
1173 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1175 hr
= IMediaControl_Pause(control
);
1176 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1178 hr
= IMediaControl_GetState(control
, 0, &state
);
1179 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1181 hr
= IMediaControl_Run(control
);
1182 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1184 hr
= IMediaControl_GetState(control
, 0, &state
);
1185 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1187 thread
= send_frame(input
);
1188 hr
= join_thread(thread
);
1189 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1191 hr
= IMediaControl_GetState(control
, 0, &state
);
1192 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1194 hr
= IMediaControl_Stop(control
);
1195 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1197 hr
= IMediaControl_GetState(control
, 0, &state
);
1198 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1200 IMemAllocator_Release(allocator
);
1201 IMediaControl_Release(control
);
1204 static void test_flushing(IPin
*pin
, IMemInputPin
*input
, IFilterGraph2
*graph
)
1206 IMemAllocator
*allocator
;
1207 IMediaControl
*control
;
1208 OAFilterState state
;
1212 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1214 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1215 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1216 hr
= IMemAllocator_Commit(allocator
);
1217 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1218 IMemAllocator_Release(allocator
);
1220 hr
= IMediaControl_Pause(control
);
1221 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1223 thread
= send_frame(input
);
1224 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1226 hr
= IMediaControl_GetState(control
, 0, &state
);
1227 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1229 hr
= IPin_BeginFlush(pin
);
1230 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1232 hr
= join_thread(thread
);
1233 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1235 thread
= send_frame(input
);
1236 hr
= join_thread(thread
);
1237 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1239 hr
= IPin_EndFlush(pin
);
1240 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1242 /* We dropped the sample we were holding, so now we need a new one... */
1244 hr
= IMediaControl_GetState(control
, 0, &state
);
1245 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1247 thread
= send_frame(input
);
1248 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1250 hr
= IMediaControl_Run(control
);
1251 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1252 hr
= join_thread(thread
);
1253 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1255 hr
= IPin_BeginFlush(pin
);
1256 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1258 thread
= send_frame(input
);
1259 hr
= join_thread(thread
);
1260 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1262 hr
= IPin_EndFlush(pin
);
1263 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1265 thread
= send_frame(input
);
1266 hr
= join_thread(thread
);
1267 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1269 hr
= IMediaControl_Stop(control
);
1270 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1272 IMediaControl_Release(control
);
1275 static void test_connect_pin(void)
1277 VIDEOINFOHEADER vih
=
1279 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
1280 .bmiHeader
.biWidth
= 32,
1281 .bmiHeader
.biHeight
= 16,
1282 .bmiHeader
.biPlanes
= 1,
1283 .bmiHeader
.biCompression
= BI_RGB
,
1285 AM_MEDIA_TYPE req_mt
=
1287 .majortype
= MEDIATYPE_Video
,
1288 .subtype
= MEDIASUBTYPE_WAVE
,
1289 .formattype
= FORMAT_VideoInfo
,
1290 .cbFormat
= sizeof(vih
),
1291 .pbFormat
= (BYTE
*)&vih
,
1293 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
1294 IBaseFilter
*filter
= create_vmr7(VMRMode_Windowed
);
1295 IFilterGraph2
*graph
= create_graph();
1296 struct testfilter source
;
1297 IMemAllocator
*allocator
;
1298 IMemInputPin
*input
;
1305 static const GUID
*subtype_tests
[] =
1307 &MEDIASUBTYPE_RGB565
,
1308 &MEDIASUBTYPE_RGB24
,
1309 &MEDIASUBTYPE_RGB32
,
1313 testfilter_init(&source
);
1315 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
1316 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
1318 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1320 vih
.bmiHeader
.biBitCount
= 16;
1321 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1322 todo_wine
ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1325 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1326 IFilterGraph2_Disconnect(graph
, pin
);
1328 vih
.bmiHeader
.biBitCount
= 32;
1329 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1330 if (hr
== VFW_E_TYPE_NOT_ACCEPTED
) /* w7u */
1332 vih
.bmiHeader
.biBitCount
= 24;
1333 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1334 /* w7u is also rather buggy with its allocator. Requesting a size of
1335 * 32 * 16 * 4 succeeds and returns that size from SetProperties(), but
1336 * the actual samples only have a size of 32 * 16 * 3. */
1337 req_props
.cbBuffer
= 32 * 16 * 3;
1339 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1340 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1341 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1342 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1343 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1345 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
1347 req_mt
.subtype
= *subtype_tests
[i
];
1348 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1349 ok(hr
== S_OK
, "Got hr %#x for subtype %s.\n", hr
, wine_dbgstr_guid(subtype_tests
[i
]));
1351 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1352 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1353 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1354 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1357 req_mt
.formattype
= FORMAT_None
;
1358 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1359 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1360 req_mt
.formattype
= GUID_NULL
;
1361 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1362 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1363 req_mt
.formattype
= FORMAT_VideoInfo
;
1365 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1366 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1367 todo_wine
ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1370 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1371 IFilterGraph2_Disconnect(graph
, pin
);
1373 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1375 peer
= (IPin
*)0xdeadbeef;
1376 hr
= IPin_ConnectedTo(pin
, &peer
);
1377 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1378 ok(!peer
, "Got peer %p.\n", peer
);
1380 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1381 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1383 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1384 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1386 hr
= IPin_ConnectedTo(pin
, &peer
);
1387 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1388 ok(peer
== &source
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1391 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1392 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1393 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1395 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
1397 test_allocator(input
);
1399 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1400 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1401 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
1402 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1403 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
1404 hr
= IMemAllocator_Commit(allocator
);
1405 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1406 IMemAllocator_Release(allocator
);
1408 hr
= IMemInputPin_ReceiveCanBlock(input
);
1409 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1411 test_filter_state(input
, graph
);
1412 test_flushing(pin
, input
, graph
);
1414 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1415 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1416 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1417 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1418 ok(source
.source
.pin
.peer
== pin
, "Got peer %p.\n", peer
);
1419 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1421 peer
= (IPin
*)0xdeadbeef;
1422 hr
= IPin_ConnectedTo(pin
, &peer
);
1423 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1424 ok(!peer
, "Got peer %p.\n", peer
);
1426 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1427 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1429 IMemInputPin_Release(input
);
1431 ref
= IFilterGraph2_Release(graph
);
1432 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1433 ref
= IBaseFilter_Release(filter
);
1434 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1435 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
1436 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1439 static void test_overlay(void)
1441 IBaseFilter
*filter
= create_vmr7(0);
1448 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1450 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1451 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1453 hwnd
= (HWND
)0xdeadbeef;
1454 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1455 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1456 ok(hwnd
&& hwnd
!= (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1458 IOverlay_Release(overlay
);
1460 ref
= IBaseFilter_Release(filter
);
1461 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1464 /* try to make sure pending X events have been processed before continuing */
1465 static void flush_events(void)
1471 time
= GetTickCount() + diff
;
1474 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, QS_ALLINPUT
) == WAIT_TIMEOUT
)
1476 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
1477 DispatchMessageA(&msg
);
1478 diff
= time
- GetTickCount();
1482 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1484 if (winetest_debug
> 1)
1485 trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd
, msg
, wparam
, lparam
);
1487 if (wparam
== 0xdeadbeef)
1490 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
1493 static void test_video_window_caption(IVideoWindow
*window
, HWND hwnd
)
1499 hr
= IVideoWindow_get_Caption(window
, &caption
);
1500 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1501 ok(!wcscmp(caption
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1502 SysFreeString(caption
);
1504 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1505 ok(!wcscmp(text
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text
));
1507 caption
= SysAllocString(L
"foo");
1508 hr
= IVideoWindow_put_Caption(window
, caption
);
1509 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1510 SysFreeString(caption
);
1512 hr
= IVideoWindow_get_Caption(window
, &caption
);
1513 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1514 ok(!wcscmp(caption
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1515 SysFreeString(caption
);
1517 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1518 ok(!wcscmp(text
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(text
));
1521 static void test_video_window_style(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1526 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1527 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1528 todo_wine
ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1529 "Got style %#x.\n", style
);
1531 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1532 todo_wine
ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1533 "Got style %#x.\n", style
);
1535 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_DISABLED
);
1536 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1537 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_HSCROLL
);
1538 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1539 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_VSCROLL
);
1540 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1541 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MAXIMIZE
);
1542 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1543 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MINIMIZE
);
1544 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1546 hr
= IVideoWindow_put_WindowStyle(window
, style
& ~WS_CLIPCHILDREN
);
1547 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1549 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1550 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1551 todo_wine
ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1553 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1554 todo_wine
ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1556 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1558 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1559 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1560 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1562 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1563 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1565 hr
= IVideoWindow_put_WindowStyleEx(window
, style
| WS_EX_TRANSPARENT
);
1566 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1568 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1569 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1570 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1572 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1573 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1576 static BOOL CALLBACK
top_window_cb(HWND hwnd
, LPARAM ctx
)
1579 GetWindowThreadProcessId(hwnd
, &pid
);
1580 if (pid
== GetCurrentProcessId() && (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
))
1582 *(HWND
*)ctx
= hwnd
;
1588 static HWND
get_top_window(void)
1591 EnumWindows(top_window_cb
, (LPARAM
)&hwnd
);
1595 static void test_video_window_state(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1601 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1603 hr
= IVideoWindow_get_WindowState(window
, &state
);
1604 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1605 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1607 hr
= IVideoWindow_get_Visible(window
, &state
);
1608 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1610 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1611 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1612 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1614 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
1615 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1617 hr
= IVideoWindow_get_WindowState(window
, &state
);
1618 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1619 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1621 hr
= IVideoWindow_get_Visible(window
, &state
);
1622 ok(state
== OATRUE
, "Got state %d.\n", state
);
1624 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1625 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1626 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1627 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1628 top
= get_top_window();
1629 ok(top
== hwnd
, "Got top window %p.\n", top
);
1631 hr
= IVideoWindow_put_WindowState(window
, SW_MINIMIZE
);
1632 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1634 hr
= IVideoWindow_get_WindowState(window
, &state
);
1635 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1636 ok(state
== SW_MINIMIZE
, "Got state %d.\n", state
);
1638 hr
= IVideoWindow_get_Visible(window
, &state
);
1639 ok(state
== OATRUE
, "Got state %d.\n", state
);
1641 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1642 ok(IsIconic(hwnd
), "Window should be minimized.\n");
1643 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1644 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1646 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1647 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1649 hr
= IVideoWindow_get_WindowState(window
, &state
);
1650 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1651 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1653 hr
= IVideoWindow_get_Visible(window
, &state
);
1654 ok(state
== OATRUE
, "Got state %d.\n", state
);
1656 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1657 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1658 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1659 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1661 hr
= IVideoWindow_put_WindowState(window
, SW_MAXIMIZE
);
1662 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1664 hr
= IVideoWindow_get_WindowState(window
, &state
);
1665 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1666 ok(state
== SW_MAXIMIZE
, "Got state %d.\n", state
);
1668 hr
= IVideoWindow_get_Visible(window
, &state
);
1669 ok(state
== OATRUE
, "Got state %d.\n", state
);
1671 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1672 ok(!IsIconic(hwnd
), "Window should be minimized.\n");
1673 ok(IsZoomed(hwnd
), "Window should not be maximized.\n");
1674 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1676 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1677 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1679 hr
= IVideoWindow_put_WindowState(window
, SW_HIDE
);
1680 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1682 hr
= IVideoWindow_get_WindowState(window
, &state
);
1683 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1684 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1686 hr
= IVideoWindow_get_Visible(window
, &state
);
1687 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1689 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1690 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1691 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1692 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1694 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
1695 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1697 hr
= IVideoWindow_get_WindowState(window
, &state
);
1698 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1699 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1701 hr
= IVideoWindow_get_Visible(window
, &state
);
1702 ok(state
== OATRUE
, "Got state %d.\n", state
);
1704 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1705 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1706 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1707 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1709 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
1710 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1712 hr
= IVideoWindow_get_WindowState(window
, &state
);
1713 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1714 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1716 hr
= IVideoWindow_get_Visible(window
, &state
);
1717 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1719 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1720 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1721 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1722 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1724 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
1725 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1727 hr
= IVideoWindow_SetWindowForeground(window
, TRUE
);
1728 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1730 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1731 hr
= IVideoWindow_SetWindowForeground(window
, OATRUE
);
1732 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1733 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1734 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
1735 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
1736 top
= get_top_window();
1737 ok(top
== hwnd
, "Got top window %p.\n", top
);
1739 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
1740 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1741 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1742 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
1743 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
1744 top
= get_top_window();
1745 ok(top
== hwnd
, "Got top window %p.\n", top
);
1747 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1748 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
1749 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1750 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1751 ok(GetFocus() == our_hwnd
, "Got focus window %p.\n", GetFocus());
1752 ok(GetForegroundWindow() == our_hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
1753 top
= get_top_window();
1754 ok(top
== hwnd
, "Got top window %p.\n", top
);
1757 static void test_video_window_position(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1759 LONG left
, width
, top
, height
, expect_width
, expect_height
;
1760 RECT rect
= {0, 0, 600, 400};
1764 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1766 AdjustWindowRect(&rect
, GetWindowLongA(hwnd
, GWL_STYLE
), FALSE
);
1767 expect_width
= rect
.right
- rect
.left
;
1768 expect_height
= rect
.bottom
- rect
.top
;
1770 hr
= IVideoWindow_put_Left(window
, 0);
1771 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1772 hr
= IVideoWindow_put_Top(window
, 0);
1773 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1775 hr
= IVideoWindow_get_Left(window
, &left
);
1776 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1777 ok(left
== 0, "Got left %d.\n", left
);
1778 hr
= IVideoWindow_get_Top(window
, &top
);
1779 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1780 ok(top
== 0, "Got top %d.\n", top
);
1781 hr
= IVideoWindow_get_Width(window
, &width
);
1782 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1783 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1784 hr
= IVideoWindow_get_Height(window
, &height
);
1785 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1786 todo_wine
ok(height
== expect_height
, "Got height %d.\n", height
);
1787 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
1788 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1789 ok(left
== 0, "Got left %d.\n", left
);
1790 ok(top
== 0, "Got top %d.\n", top
);
1791 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1792 todo_wine
ok(height
== expect_height
, "Got height %d.\n", height
);
1793 GetWindowRect(hwnd
, &rect
);
1794 ok(rect
.left
== 0, "Got window left %d.\n", rect
.left
);
1795 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
1796 todo_wine
ok(rect
.right
== expect_width
, "Got window right %d.\n", rect
.right
);
1797 todo_wine
ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
1799 hr
= IVideoWindow_put_Left(window
, 10);
1800 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1802 hr
= IVideoWindow_get_Left(window
, &left
);
1803 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1804 ok(left
== 10, "Got left %d.\n", left
);
1805 hr
= IVideoWindow_get_Top(window
, &top
);
1806 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1807 ok(top
== 0, "Got top %d.\n", top
);
1808 hr
= IVideoWindow_get_Width(window
, &width
);
1809 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1810 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1811 hr
= IVideoWindow_get_Height(window
, &height
);
1812 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1813 todo_wine
ok(height
== expect_height
, "Got height %d.\n", height
);
1814 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
1815 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1816 ok(left
== 10, "Got left %d.\n", left
);
1817 ok(top
== 0, "Got top %d.\n", top
);
1818 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1819 todo_wine
ok(height
== expect_height
, "Got height %d.\n", height
);
1820 GetWindowRect(hwnd
, &rect
);
1821 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
1822 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
1823 todo_wine
ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
1824 todo_wine
ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
1826 hr
= IVideoWindow_put_Height(window
, 200);
1827 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1829 hr
= IVideoWindow_get_Left(window
, &left
);
1830 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1831 ok(left
== 10, "Got left %d.\n", left
);
1832 hr
= IVideoWindow_get_Top(window
, &top
);
1833 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1834 ok(top
== 0, "Got top %d.\n", top
);
1835 hr
= IVideoWindow_get_Width(window
, &width
);
1836 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1837 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1838 hr
= IVideoWindow_get_Height(window
, &height
);
1839 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1840 ok(height
== 200, "Got height %d.\n", height
);
1841 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
1842 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1843 ok(left
== 10, "Got left %d.\n", left
);
1844 ok(top
== 0, "Got top %d.\n", top
);
1845 todo_wine
ok(width
== expect_width
, "Got width %d.\n", width
);
1846 ok(height
== 200, "Got height %d.\n", height
);
1847 GetWindowRect(hwnd
, &rect
);
1848 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
1849 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
1850 todo_wine
ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
1851 ok(rect
.bottom
== 200, "Got window bottom %d.\n", rect
.bottom
);
1853 hr
= IVideoWindow_SetWindowPosition(window
, 100, 200, 300, 400);
1854 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1856 hr
= IVideoWindow_get_Left(window
, &left
);
1857 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1858 ok(left
== 100, "Got left %d.\n", left
);
1859 hr
= IVideoWindow_get_Top(window
, &top
);
1860 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1861 ok(top
== 200, "Got top %d.\n", top
);
1862 hr
= IVideoWindow_get_Width(window
, &width
);
1863 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1864 ok(width
== 300, "Got width %d.\n", width
);
1865 hr
= IVideoWindow_get_Height(window
, &height
);
1866 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1867 ok(height
== 400, "Got height %d.\n", height
);
1868 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
1869 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1870 ok(left
== 100, "Got left %d.\n", left
);
1871 ok(top
== 200, "Got top %d.\n", top
);
1872 ok(width
== 300, "Got width %d.\n", width
);
1873 ok(height
== 400, "Got height %d.\n", height
);
1874 GetWindowRect(hwnd
, &rect
);
1875 ok(rect
.left
== 100, "Got window left %d.\n", rect
.left
);
1876 ok(rect
.top
== 200, "Got window top %d.\n", rect
.top
);
1877 ok(rect
.right
== 400, "Got window right %d.\n", rect
.right
);
1878 ok(rect
.bottom
== 600, "Got window bottom %d.\n", rect
.bottom
);
1880 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1881 top_hwnd
= get_top_window();
1882 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
1885 static void test_video_window_owner(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1887 HWND parent
, top_hwnd
;
1892 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1894 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
1895 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1896 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
1898 parent
= GetAncestor(hwnd
, GA_PARENT
);
1899 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
1900 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1901 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
1903 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
1904 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1906 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
1907 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1908 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got owner %#lx.\n", oahwnd
);
1910 parent
= GetAncestor(hwnd
, GA_PARENT
);
1911 ok(parent
== our_hwnd
, "Got parent %p.\n", parent
);
1912 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1913 ok((style
& WS_CHILD
), "Got style %#x.\n", style
);
1915 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1916 top_hwnd
= get_top_window();
1917 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
1919 ShowWindow(our_hwnd
, SW_HIDE
);
1921 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
1922 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1924 hr
= IVideoWindow_get_Visible(window
, &state
);
1925 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1926 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1928 hr
= IVideoWindow_put_Owner(window
, 0);
1929 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1931 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
1932 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1933 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
1935 parent
= GetAncestor(hwnd
, GA_PARENT
);
1936 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
1937 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1938 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
1940 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1941 top_hwnd
= get_top_window();
1942 ok(top_hwnd
== hwnd
, "Got top window %p.\n", top_hwnd
);
1944 hr
= IVideoWindow_get_Visible(window
, &state
);
1945 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1946 ok(state
== OATRUE
, "Got state %d.\n", state
);
1949 struct notify_message_params
1951 IVideoWindow
*window
;
1956 static DWORD CALLBACK
notify_message_proc(void *arg
)
1958 const struct notify_message_params
*params
= arg
;
1959 HRESULT hr
= IVideoWindow_NotifyOwnerMessage(params
->window
, (OAHWND
)params
->hwnd
, params
->message
, 0, 0);
1960 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1964 static void test_video_window_messages(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1966 struct notify_message_params params
;
1974 static UINT drain_tests
[] =
2002 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2003 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2004 ok(!oahwnd
, "Got window %#lx.\n", oahwnd
);
2006 hr
= IVideoWindow_put_MessageDrain(window
, (OAHWND
)our_hwnd
);
2007 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2009 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2010 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2011 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got window %#lx.\n", oahwnd
);
2013 for (i
= 0; i
< ARRAY_SIZE(drain_tests
); ++i
)
2015 SendMessageA(hwnd
, drain_tests
[i
], 0xdeadbeef, 0);
2016 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2017 ok(ret
, "Expected a message.\n");
2018 ok(msg
.hwnd
== our_hwnd
, "Got hwnd %p.\n", msg
.hwnd
);
2019 ok(msg
.message
== drain_tests
[i
], "Got message %#x.\n", msg
.message
);
2020 ok(msg
.wParam
== 0xdeadbeef, "Got wparam %#lx.\n", msg
.wParam
);
2021 ok(!msg
.lParam
, "Got lparam %#lx.\n", msg
.lParam
);
2022 DispatchMessageA(&msg
);
2024 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2025 ok(!ret
, "Got unexpected message %#x.\n", msg
.message
);
2028 hr
= IVideoWindow_put_MessageDrain(window
, 0);
2029 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2031 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2032 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2036 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SYSCOLORCHANGE
, 0, 0);
2037 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2039 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2040 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2042 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SETCURSOR
,
2043 (WPARAM
)hwnd
, MAKELONG(HTCLIENT
, WM_MOUSEMOVE
));
2044 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2046 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2047 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2049 params
.window
= window
;
2050 params
.hwnd
= our_hwnd
;
2051 params
.message
= WM_SYSCOLORCHANGE
;
2052 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2053 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block.\n");
2054 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2055 ok(ret
== ((QS_SENDMESSAGE
<< 16) | QS_SENDMESSAGE
), "Got unexpected status %#x.\n", ret
);
2057 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
2058 ok(!WaitForSingleObject(thread
, 1000), "Wait timed out.\n");
2059 CloseHandle(thread
);
2061 params
.message
= WM_SETCURSOR
;
2062 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2063 ok(!WaitForSingleObject(thread
, 1000), "Thread should not block.\n");
2064 CloseHandle(thread
);
2065 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2066 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2068 hr
= IVideoWindow_put_Owner(window
, 0);
2069 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2072 static void test_video_window_autoshow(IVideoWindow
*window
, IFilterGraph2
*graph
, HWND hwnd
)
2074 IMediaControl
*control
;
2078 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2080 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2081 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2082 ok(l
== OATRUE
, "Got %d.\n", l
);
2084 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2085 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2087 hr
= IMediaControl_Pause(control
);
2088 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2090 hr
= IVideoWindow_get_Visible(window
, &l
);
2091 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2092 todo_wine
ok(l
== OATRUE
, "Got %d.\n", l
);
2094 hr
= IMediaControl_Stop(control
);
2095 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2097 hr
= IVideoWindow_get_Visible(window
, &l
);
2098 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2099 todo_wine
ok(l
== OATRUE
, "Got %d.\n", l
);
2101 hr
= IVideoWindow_put_AutoShow(window
, OAFALSE
);
2102 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2104 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2105 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2107 hr
= IMediaControl_Pause(control
);
2108 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2110 hr
= IVideoWindow_get_Visible(window
, &l
);
2111 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2112 ok(l
== OAFALSE
, "Got %d.\n", l
);
2114 hr
= IMediaControl_Stop(control
);
2115 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2117 IMediaControl_Release(control
);
2120 static void test_video_window(void)
2122 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
2123 VIDEOINFOHEADER vih
=
2125 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
2126 .bmiHeader
.biBitCount
= 32,
2127 .bmiHeader
.biWidth
= 600,
2128 .bmiHeader
.biHeight
= 400,
2129 .bmiHeader
.biPlanes
= 1,
2130 .bmiHeader
.biCompression
= BI_RGB
,
2132 AM_MEDIA_TYPE req_mt
=
2134 .majortype
= MEDIATYPE_Video
,
2135 .subtype
= MEDIASUBTYPE_RGB32
,
2136 .formattype
= FORMAT_VideoInfo
,
2137 .cbFormat
= sizeof(vih
),
2138 .pbFormat
= (BYTE
*)&vih
,
2140 IFilterGraph2
*graph
= create_graph();
2141 WNDCLASSA window_class
= {0};
2142 struct testfilter source
;
2143 IMemAllocator
*allocator
;
2144 LONG width
, height
, l
;
2145 IVideoWindow
*window
;
2146 IMemInputPin
*input
;
2147 IBaseFilter
*filter
;
2148 HWND hwnd
, our_hwnd
;
2157 window_class
.lpszClassName
= "wine_test_class";
2158 window_class
.lpfnWndProc
= window_proc
;
2159 RegisterClassA(&window_class
);
2160 our_hwnd
= CreateWindowA("wine_test_class", "test window", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
,
2161 100, 200, 300, 400, NULL
, NULL
, NULL
, NULL
);
2164 filter
= create_vmr7(0);
2167 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2169 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
2170 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
2172 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
2173 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2175 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
2176 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2177 if (winetest_debug
> 1) trace("ours %p, theirs %p\n", our_hwnd
, hwnd
);
2178 GetWindowRect(hwnd
, &rect
);
2180 tid
= GetWindowThreadProcessId(hwnd
, NULL
);
2181 ok(tid
== GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid
);
2183 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVideoWindow
, (void **)&window
);
2184 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2186 hr
= IVideoWindow_get_Caption(window
, &caption
);
2187 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2189 hr
= IVideoWindow_get_WindowStyle(window
, &l
);
2190 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2192 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2193 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2195 testfilter_init(&source
);
2196 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
2197 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
2198 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
2199 if (hr
== VFW_E_TYPE_NOT_ACCEPTED
) /* w7u */
2201 req_mt
.subtype
= MEDIASUBTYPE_RGB24
;
2202 vih
.bmiHeader
.biBitCount
= 24;
2203 req_props
.cbBuffer
= 32 * 16 * 3;
2204 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
2206 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2208 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
2209 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2212 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
2213 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2214 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
2215 hr
= IMemAllocator_Commit(allocator
);
2216 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2217 IMemAllocator_Release(allocator
);
2220 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2222 test_video_window_caption(window
, hwnd
);
2223 test_video_window_style(window
, hwnd
, our_hwnd
);
2224 test_video_window_state(window
, hwnd
, our_hwnd
);
2225 test_video_window_position(window
, hwnd
, our_hwnd
);
2226 test_video_window_autoshow(window
, graph
, hwnd
);
2227 test_video_window_owner(window
, hwnd
, our_hwnd
);
2228 test_video_window_messages(window
, hwnd
, our_hwnd
);
2230 hr
= IVideoWindow_put_FullScreenMode(window
, OATRUE
);
2231 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2232 hr
= IVideoWindow_get_FullScreenMode(window
, &l
);
2233 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2235 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2236 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2237 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2238 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2240 IFilterGraph2_Release(graph
);
2241 IVideoWindow_Release(window
);
2242 IOverlay_Release(overlay
);
2243 IMemInputPin_Release(input
);
2245 ref
= IBaseFilter_Release(filter
);
2246 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2247 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
2248 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2249 DestroyWindow(our_hwnd
);
2256 test_filter_config();
2263 test_enum_media_types();
2264 test_unconnected_filter_state();
2267 test_video_window();