2 * Audio capture filter 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
23 #include "wine/test.h"
25 static ULONG
get_refcount(void *iface
)
27 IUnknown
*unknown
= iface
;
28 IUnknown_AddRef(unknown
);
29 return IUnknown_Release(unknown
);
32 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
33 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
35 IUnknown
*iface
= iface_ptr
;
36 HRESULT hr
, expected_hr
;
39 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
41 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
42 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
44 IUnknown_Release(unk
);
47 static void test_interfaces(IBaseFilter
*filter
)
49 todo_wine
check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
50 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
51 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
52 check_interface(filter
, &IID_IPersist
, TRUE
);
53 check_interface(filter
, &IID_IPersistPropertyBag
, TRUE
);
54 check_interface(filter
, &IID_IUnknown
, TRUE
);
56 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
57 check_interface(filter
, &IID_IBasicVideo
, FALSE
);
58 check_interface(filter
, &IID_IKsPropertySet
, FALSE
);
59 check_interface(filter
, &IID_IMediaPosition
, FALSE
);
60 check_interface(filter
, &IID_IMediaSeeking
, FALSE
);
61 check_interface(filter
, &IID_IPin
, FALSE
);
62 check_interface(filter
, &IID_IQualityControl
, FALSE
);
63 check_interface(filter
, &IID_IQualProp
, FALSE
);
64 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
65 check_interface(filter
, &IID_IVideoWindow
, FALSE
);
68 static const GUID test_iid
= {0x33333333};
69 static LONG outer_ref
= 1;
71 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
73 if (IsEqualGUID(iid
, &IID_IUnknown
)
74 || IsEqualGUID(iid
, &IID_IBaseFilter
)
75 || IsEqualGUID(iid
, &test_iid
))
77 *out
= (IUnknown
*)0xdeadbeef;
80 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
84 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
86 return InterlockedIncrement(&outer_ref
);
89 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
91 return InterlockedDecrement(&outer_ref
);
94 static const IUnknownVtbl outer_vtbl
=
101 static IUnknown test_outer
= {&outer_vtbl
};
103 static void test_aggregation(void)
105 IBaseFilter
*filter
, *filter2
;
106 IUnknown
*unk
, *unk2
;
110 filter
= (IBaseFilter
*)0xdeadbeef;
111 hr
= CoCreateInstance(&CLSID_AudioRecord
, &test_outer
, CLSCTX_INPROC_SERVER
,
112 &IID_IBaseFilter
, (void **)&filter
);
113 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
114 ok(!filter
, "Got interface %p.\n", filter
);
116 hr
= CoCreateInstance(&CLSID_AudioRecord
, &test_outer
, CLSCTX_INPROC_SERVER
,
117 &IID_IUnknown
, (void **)&unk
);
118 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
119 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
120 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
121 ref
= get_refcount(unk
);
122 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
124 ref
= IUnknown_AddRef(unk
);
125 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
126 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
128 ref
= IUnknown_Release(unk
);
129 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
130 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
132 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
133 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
134 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
135 IUnknown_Release(unk2
);
137 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
138 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
140 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
141 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
142 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
144 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
145 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
146 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
148 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
149 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
150 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
152 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
153 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
154 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
156 IBaseFilter_Release(filter
);
157 ref
= IUnknown_Release(unk
);
158 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
159 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
162 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
164 ok(0, "Unexpected call (iid %s).\n", wine_dbgstr_guid(iid
));
165 return E_NOINTERFACE
;
168 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
170 ok(0, "Unexpected call.\n");
174 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
176 ok(0, "Unexpected call.\n");
180 static unsigned int ppb_got_read
;
182 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*name
, VARIANT
*var
, IErrorLog
*log
)
184 if (!lstrcmpW(name
, L
"UseMixer"))
185 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
187 todo_wine
ok(!lstrcmpW(name
, L
"WaveInId"), "Got unexpected name %s.\n", wine_dbgstr_w(name
));
188 ok(V_VT(var
) == VT_I4
, "Got unexpected type %u.\n", V_VT(var
));
189 ok(!log
, "Got unexpected error log %p.\n", log
);
194 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*name
, VARIANT
*var
)
196 ok(0, "Unexpected call (name %s).\n", wine_dbgstr_w(name
));
200 static const IPropertyBagVtbl property_bag_vtbl
=
202 property_bag_QueryInterface
,
204 property_bag_Release
,
209 static void test_property_bag(IMoniker
*mon
)
211 IPropertyBag property_bag
= {&property_bag_vtbl
};
212 IPropertyBag
*devenum_bag
;
213 IPersistPropertyBag
*ppb
;
218 hr
= IMoniker_BindToStorage(mon
, NULL
, NULL
, &IID_IPropertyBag
, (void **)&devenum_bag
);
219 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
222 hr
= IPropertyBag_Read(devenum_bag
, L
"WaveInId", &var
, NULL
);
223 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
226 hr
= CoCreateInstance(&CLSID_AudioRecord
, NULL
, CLSCTX_INPROC_SERVER
,
227 &IID_IPersistPropertyBag
, (void **)&ppb
);
228 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
230 hr
= IPersistPropertyBag_InitNew(ppb
);
231 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
234 hr
= IPersistPropertyBag_Load(ppb
, &property_bag
, NULL
);
235 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* 8+, intermittent */, "Got hr %#x.\n", hr
);
236 ok(ppb_got_read
== 1, "Got %u calls to Read().\n", ppb_got_read
);
238 ref
= IPersistPropertyBag_Release(ppb
);
239 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
242 IPropertyBag_Release(devenum_bag
);
245 static void test_unconnected_filter_state(IBaseFilter
*filter
)
250 hr
= IBaseFilter_GetState(filter
, 0, &state
);
251 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
252 ok(state
== State_Stopped
, "Got state %u.\n", state
);
254 hr
= IBaseFilter_Pause(filter
);
255 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
257 hr
= IBaseFilter_GetState(filter
, 0, &state
);
258 todo_wine
ok(hr
== VFW_S_CANT_CUE
, "Got hr %#x.\n", hr
);
259 ok(state
== State_Paused
, "Got state %u.\n", state
);
261 hr
= IBaseFilter_Run(filter
, 0);
262 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
264 hr
= IBaseFilter_GetState(filter
, 0, &state
);
265 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
266 ok(state
== State_Running
, "Got state %u.\n", state
);
268 hr
= IBaseFilter_Pause(filter
);
269 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
271 hr
= IBaseFilter_GetState(filter
, 0, &state
);
272 todo_wine
ok(hr
== VFW_S_CANT_CUE
, "Got hr %#x.\n", hr
);
273 ok(state
== State_Paused
, "Got state %u.\n", state
);
275 hr
= IBaseFilter_Stop(filter
);
276 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
278 hr
= IBaseFilter_GetState(filter
, 0, &state
);
279 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
280 ok(state
== State_Stopped
, "Got state %u.\n", state
);
282 hr
= IBaseFilter_Run(filter
, 0);
283 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
285 hr
= IBaseFilter_GetState(filter
, 0, &state
);
286 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
287 ok(state
== State_Running
, "Got state %u.\n", state
);
289 hr
= IBaseFilter_Stop(filter
);
290 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
292 hr
= IBaseFilter_GetState(filter
, 0, &state
);
293 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
294 ok(state
== State_Stopped
, "Got state %u.\n", state
);
297 START_TEST(audiorecord
)
299 ICreateDevEnum
*devenum
;
300 IEnumMoniker
*enummon
;
309 hr
= CoCreateInstance(&CLSID_SystemDeviceEnum
, NULL
, CLSCTX_INPROC_SERVER
,
310 &IID_ICreateDevEnum
, (void **)&devenum
);
311 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
312 hr
= ICreateDevEnum_CreateClassEnumerator(devenum
, &CLSID_AudioInputDeviceCategory
, &enummon
, 0);
315 skip("No audio input devices present.\n");
316 ICreateDevEnum_Release(devenum
);
320 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
324 while (IEnumMoniker_Next(enummon
, 1, &mon
, NULL
) == S_OK
)
326 hr
= IMoniker_GetDisplayName(mon
, NULL
, NULL
, &name
);
327 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
328 trace("Testing device %s.\n", wine_dbgstr_w(name
));
331 test_property_bag(mon
);
333 hr
= IMoniker_BindToObject(mon
, NULL
, NULL
, &IID_IBaseFilter
, (void **)&filter
);
334 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
336 test_interfaces(filter
);
337 test_unconnected_filter_state(filter
);
339 ref
= IBaseFilter_Release(filter
);
340 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
341 IMoniker_Release(mon
);
344 IEnumMoniker_Release(enummon
);
345 ICreateDevEnum_Release(devenum
);