qcap: Build without -DWINE_NO_LONG_TYPES.
[wine.git] / dlls / qcap / tests / audiorecord.c
blob350ae986b4435aa79758bc3cf5084eda86f6d46a
1 /*
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
21 #define COBJMACROS
22 #include "dshow.h"
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;
37 IUnknown *unk;
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);
43 if (SUCCEEDED(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;
78 return S_OK;
80 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
81 return E_NOINTERFACE;
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 =
96 outer_QueryInterface,
97 outer_AddRef,
98 outer_Release,
101 static IUnknown test_outer = {&outer_vtbl};
103 static void test_aggregation(void)
105 IBaseFilter *filter, *filter2;
106 IUnknown *unk, *unk2;
107 HRESULT hr;
108 ULONG ref;
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");
171 return 2;
174 static ULONG WINAPI property_bag_Release(IPropertyBag *iface)
176 ok(0, "Unexpected call.\n");
177 return 1;
179 static int ppb_id;
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);
190 ppb_got_read++;
191 return S_OK;
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));
197 return E_FAIL;
200 static const IPropertyBagVtbl property_bag_vtbl =
202 property_bag_QueryInterface,
203 property_bag_AddRef,
204 property_bag_Release,
205 property_bag_Read,
206 property_bag_Write,
209 static void test_property_bag(IMoniker *mon)
211 IPropertyBag property_bag = {&property_bag_vtbl};
212 IPropertyBag *devenum_bag;
213 IPersistPropertyBag *ppb;
214 VARIANT var;
215 HRESULT hr;
216 ULONG ref;
218 hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&devenum_bag);
219 ok(hr == S_OK, "Got hr %#x.\n", hr);
221 VariantInit(&var);
222 hr = IPropertyBag_Read(devenum_bag, L"WaveInId", &var, NULL);
223 ok(hr == S_OK, "Got hr %#x.\n", hr);
224 ppb_id = V_I4(&var);
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);
233 ppb_got_read = 0;
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);
241 VariantClear(&var);
242 IPropertyBag_Release(devenum_bag);
245 static void test_unconnected_filter_state(IBaseFilter *filter)
247 FILTER_STATE state;
248 HRESULT hr;
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;
301 IBaseFilter *filter;
302 IMoniker *mon;
303 WCHAR *name;
304 HRESULT hr;
305 ULONG ref;
307 CoInitialize(NULL);
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);
313 if (hr == S_FALSE)
315 skip("No audio input devices present.\n");
316 ICreateDevEnum_Release(devenum);
317 CoUninitialize();
318 return;
320 ok(hr == S_OK, "Got hr %#x.\n", hr);
322 test_aggregation();
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));
329 CoTaskMemFree(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);
346 CoUninitialize();