msxml3: Try IStream if IPersistStream save failed.
[wine/multimedia.git] / dlls / mmdevapi / tests / capture.c
blobeed56dd45bb1240854001432606dfcde3d2443f2
1 /*
2 * Copyright 2010 Maarten Lankhorst for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 /* This test is for audio capture specific mechanisms
20 * Tests:
21 * - IAudioClient with eCapture and IAudioCaptureClient
24 #include <math.h>
26 #include "wine/test.h"
28 #define COBJMACROS
30 #ifdef STANDALONE
31 #include "initguid.h"
32 #endif
34 #include "unknwn.h"
35 #include "uuids.h"
36 #include "mmdeviceapi.h"
37 #include "audioclient.h"
39 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
41 static IMMDevice *dev = NULL;
43 static void test_uninitialized(IAudioClient *ac)
45 HRESULT hr;
46 UINT32 num;
47 REFERENCE_TIME t1;
49 HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
50 IUnknown *unk;
52 hr = IAudioClient_GetBufferSize(ac, &num);
53 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
55 hr = IAudioClient_GetStreamLatency(ac, &t1);
56 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
58 hr = IAudioClient_GetCurrentPadding(ac, &num);
59 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
61 hr = IAudioClient_Start(ac);
62 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
64 hr = IAudioClient_Stop(ac);
65 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
67 hr = IAudioClient_Reset(ac);
68 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
70 hr = IAudioClient_SetEventHandle(ac, handle);
71 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
73 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
74 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
76 CloseHandle(handle);
79 static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx)
81 IAudioCaptureClient *acc;
82 HRESULT hr;
83 UINT32 frames = 0;
84 BYTE *data = NULL;
85 DWORD flags;
86 UINT64 devpos, qpcpos;
88 hr = IAudioClient_GetService(ac, &IID_IAudioCaptureClient, (void**)&acc);
89 ok(hr == S_OK, "IAudioClient_GetService(IID_IAudioCaptureClient) returns %08x\n", hr);
90 if (hr != S_OK)
91 return;
93 hr = IAudioCaptureClient_GetNextPacketSize(acc, NULL);
94 ok(hr == E_POINTER, "IAudioCaptureClient_GetNextPacketSize(NULL) returns %08x\n", hr);
96 ok(WaitForSingleObject(handle, 2000) == WAIT_OBJECT_0, "Waiting on event handle failed!\n");
98 /* frames can be 0 if no data is available yet.. */
99 hr = IAudioCaptureClient_GetNextPacketSize(acc, &frames);
100 ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
102 data = (BYTE*)(DWORD_PTR)0xdeadbeef;
103 hr = IAudioCaptureClient_GetBuffer(acc, &data, NULL, NULL, NULL, NULL);
104 ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(data, NULL, NULL) returns %08x\n", hr);
105 ok((DWORD_PTR)data == 0xdeadbeef, "data is reset to %p\n", data);
107 frames = 0xdeadbeef;
108 hr = IAudioCaptureClient_GetBuffer(acc, NULL, &frames, NULL, NULL, NULL);
109 ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(NULL, &frames, NULL) returns %08x\n", hr);
110 ok(frames == 0xdeadbeef, "frames is reset to %08x\n", frames);
112 flags = 0xdeadbeef;
113 hr = IAudioCaptureClient_GetBuffer(acc, NULL, NULL, &flags, NULL, NULL);
114 ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(NULL, NULL, &flags) returns %08x\n", hr);
115 ok(flags == 0xdeadbeef, "flags is reset to %08x\n", flags);
117 hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, NULL, NULL, NULL);
118 ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(&ata, &frames, NULL) returns %08x\n", hr);
120 hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &devpos, &qpcpos);
121 ok(hr == S_OK || hr == AUDCLNT_S_BUFFER_EMPTY, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
122 if (hr == S_OK)
123 ok(frames, "Amount of frames locked is 0!\n");
124 else if (hr == AUDCLNT_S_BUFFER_EMPTY)
125 ok(!frames, "Amount of frames locked with empty buffer is %u!\n", frames);
126 else
127 ok(0, "GetBuffer returned %08x\n", hr);
128 trace("Device position is at %u, amount of frames locked: %u\n", (DWORD)devpos, frames);
130 if (frames) {
131 hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &devpos, &qpcpos);
132 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Out of order IAudioCaptureClient_GetBuffer returns %08x\n", hr);
135 hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
136 ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
138 if (frames) {
139 hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
140 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Releasing buffer twice returns %08x\n", hr);
143 IUnknown_Release(acc);
146 static void test_audioclient(void)
148 IAudioClient *ac;
149 IUnknown *unk;
150 HRESULT hr;
151 ULONG ref;
152 WAVEFORMATEX *pwfx, *pwfx2;
153 REFERENCE_TIME t1, t2;
154 HANDLE handle;
156 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
157 NULL, (void**)&ac);
158 ok(hr == S_OK, "Activation failed with %08x\n", hr);
159 if(hr != S_OK)
160 return;
162 handle = CreateEventW(NULL, FALSE, FALSE, NULL);
164 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
165 ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
167 unk = (void*)(LONG_PTR)0x12345678;
168 hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
169 ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
170 ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
172 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
173 ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
174 if (unk)
176 ref = IUnknown_Release(unk);
177 ok(ref == 1, "Released count is %u\n", ref);
180 hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
181 ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
182 if (unk)
184 ref = IUnknown_Release(unk);
185 ok(ref == 1, "Released count is %u\n", ref);
188 hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
189 ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
191 hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
192 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
194 hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
195 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
197 hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
198 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
199 trace("Returned periods: %u.%04u ms %u.%04u ms\n",
200 (UINT)(t1/10000), (UINT)(t1 % 10000),
201 (UINT)(t2/10000), (UINT)(t2 % 10000));
203 hr = IAudioClient_GetMixFormat(ac, NULL);
204 ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
206 hr = IAudioClient_GetMixFormat(ac, &pwfx);
207 ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
209 if (hr == S_OK)
211 trace("pwfx: %p\n", pwfx);
212 trace("Tag: %04x\n", pwfx->wFormatTag);
213 trace("bits: %u\n", pwfx->wBitsPerSample);
214 trace("chan: %u\n", pwfx->nChannels);
215 trace("rate: %u\n", pwfx->nSamplesPerSec);
216 trace("align: %u\n", pwfx->nBlockAlign);
217 trace("extra: %u\n", pwfx->cbSize);
218 ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
219 if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
221 WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
222 trace("Res: %u\n", pwfxe->Samples.wReserved);
223 trace("Mask: %x\n", pwfxe->dwChannelMask);
224 trace("Alg: %s\n",
225 IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
226 (IsEqualGUID(&pwfxe->SubFormat,
227 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
230 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
231 ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
232 ok(pwfx2 == NULL, "pwfx2 is non-null\n");
233 CoTaskMemFree(pwfx2);
235 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
236 ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
238 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
239 ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
241 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
242 ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
244 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
245 ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
246 ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
248 hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
249 ok(hr == E_INVALIDARG, "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
252 test_uninitialized(ac);
254 hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
255 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
257 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
258 ok(hr == E_INVALIDARG, "Initialize with invalid flags returns %08x\n", hr);
260 /* It seems that if length > 2s or periodicity != 0 the length is ignored and call succeeds
261 * Since we can only initialize successfully once skip those tests
263 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
264 ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
266 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000, 0, pwfx, NULL);
267 ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
269 if (hr != S_OK)
271 skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
272 CoTaskMemFree(pwfx);
273 return;
276 hr = IAudioClient_GetStreamLatency(ac, NULL);
277 ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
279 hr = IAudioClient_GetStreamLatency(ac, &t1);
280 ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
281 trace("Returned latency: %u.%04u ms\n",
282 (UINT)(t1/10000), (UINT)(t1 % 10000));
284 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
285 ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
287 hr = IAudioClient_SetEventHandle(ac, NULL);
288 ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
290 hr = IAudioClient_Start(ac);
291 ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start before SetEventHandle returns %08x\n", hr);
293 hr = IAudioClient_SetEventHandle(ac, handle);
294 ok(hr == S_OK, "SetEventHandle returns %08x\n", hr);
296 hr = IAudioClient_Reset(ac);
297 ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
299 hr = IAudioClient_Stop(ac);
300 ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
302 hr = IAudioClient_Start(ac);
303 ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
305 test_capture(ac, handle, pwfx);
307 IAudioClient_Release(ac);
308 CloseHandle(handle);
309 CoTaskMemFree(pwfx);
312 static void test_streamvolume(void)
314 IAudioClient *ac;
315 IAudioStreamVolume *asv;
316 WAVEFORMATEX *fmt;
317 UINT32 chans, i;
318 HRESULT hr;
319 float vol, *vols;
321 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
322 NULL, (void**)&ac);
323 ok(hr == S_OK, "Activation failed with %08x\n", hr);
324 if(hr != S_OK)
325 return;
327 hr = IAudioClient_GetMixFormat(ac, &fmt);
328 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
330 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
331 0, fmt, NULL);
332 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
333 if(hr != S_OK)
334 return;
336 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
337 ok(hr == S_OK, "GetService failed: %08x\n", hr);
339 hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
340 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
342 hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
343 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
344 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
346 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
347 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
349 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
350 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
352 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
353 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
355 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
356 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
357 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
359 hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
360 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
362 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
363 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
365 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
366 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
368 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
369 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
371 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
372 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
373 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
375 hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
376 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
378 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
379 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
381 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
382 ok(vols != NULL, "HeapAlloc failed\n");
384 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
385 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
387 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
388 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
389 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
390 for(i = 1; i < fmt->nChannels; ++i)
391 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
393 hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
394 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
396 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
397 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
399 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
400 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
402 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
403 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
405 HeapFree(GetProcessHeap(), 0, vols);
406 IAudioStreamVolume_Release(asv);
407 IAudioClient_Release(ac);
408 CoTaskMemFree(fmt);
411 static void test_channelvolume(void)
413 IAudioClient *ac;
414 IChannelAudioVolume *acv;
415 WAVEFORMATEX *fmt;
416 UINT32 chans, i;
417 HRESULT hr;
418 float vol, *vols;
420 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
421 NULL, (void**)&ac);
422 ok(hr == S_OK, "Activation failed with %08x\n", hr);
423 if(hr != S_OK)
424 return;
426 hr = IAudioClient_GetMixFormat(ac, &fmt);
427 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
429 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
430 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
431 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
433 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
434 ok(hr == S_OK, "GetService failed: %08x\n", hr);
435 if(hr != S_OK)
436 return;
438 hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
439 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
441 hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
442 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
443 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
445 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
446 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
448 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
449 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
451 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
452 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
454 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
455 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
456 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
458 hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
459 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
461 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
462 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
464 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
465 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
467 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
468 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
470 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
471 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
472 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
474 hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
475 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
477 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
478 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
480 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
481 ok(vols != NULL, "HeapAlloc failed\n");
483 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
484 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
486 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
487 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
488 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
489 for(i = 1; i < fmt->nChannels; ++i)
490 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
492 hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
493 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
495 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
496 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
498 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
499 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
501 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
502 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
504 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
505 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
507 HeapFree(GetProcessHeap(), 0, vols);
508 IChannelAudioVolume_Release(acv);
509 IAudioClient_Release(ac);
510 CoTaskMemFree(fmt);
513 static void test_simplevolume(void)
515 IAudioClient *ac;
516 ISimpleAudioVolume *sav;
517 WAVEFORMATEX *fmt;
518 HRESULT hr;
519 float vol;
520 BOOL mute;
522 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
523 NULL, (void**)&ac);
524 ok(hr == S_OK, "Activation failed with %08x\n", hr);
525 if(hr != S_OK)
526 return;
528 hr = IAudioClient_GetMixFormat(ac, &fmt);
529 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
531 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
532 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
533 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
535 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
536 ok(hr == S_OK, "GetService failed: %08x\n", hr);
537 if(hr != S_OK)
538 return;
540 hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
541 ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
543 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
544 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
545 ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
547 hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
548 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
550 hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
551 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
553 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
554 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
556 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
557 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
558 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
560 hr = ISimpleAudioVolume_GetMute(sav, NULL);
561 ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
563 mute = TRUE;
564 hr = ISimpleAudioVolume_GetMute(sav, &mute);
565 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
566 ok(mute == FALSE, "Session is already muted\n");
568 hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
569 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
571 mute = FALSE;
572 hr = ISimpleAudioVolume_GetMute(sav, &mute);
573 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
574 ok(mute == TRUE, "Session should have been muted\n");
576 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
577 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
578 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
580 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
581 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
583 mute = FALSE;
584 hr = ISimpleAudioVolume_GetMute(sav, &mute);
585 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
586 ok(mute == TRUE, "Session should have been muted\n");
588 hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
589 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
591 ISimpleAudioVolume_Release(sav);
592 IAudioClient_Release(ac);
593 CoTaskMemFree(fmt);
596 static void test_volume_dependence(void)
598 IAudioClient *ac, *ac2;
599 ISimpleAudioVolume *sav;
600 IChannelAudioVolume *cav;
601 IAudioStreamVolume *asv;
602 WAVEFORMATEX *fmt;
603 HRESULT hr;
604 float vol;
605 GUID session;
606 UINT32 nch;
608 hr = CoCreateGuid(&session);
609 ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
611 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
612 NULL, (void**)&ac);
613 ok(hr == S_OK, "Activation failed with %08x\n", hr);
615 hr = IAudioClient_GetMixFormat(ac, &fmt);
616 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
618 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
619 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
620 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
622 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
623 ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
625 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
626 ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
628 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
629 ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
630 if(hr != S_OK)
631 return;
633 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
634 ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
636 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
637 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
639 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
640 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
642 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
643 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
644 ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
646 hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
647 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
648 ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
650 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
651 ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
652 ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
654 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
655 NULL, (void**)&ac2);
656 if(SUCCEEDED(hr)){
657 IChannelAudioVolume *cav2;
658 IAudioStreamVolume *asv2;
660 hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
661 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
662 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
664 hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
665 ok(hr == S_OK, "GetService failed: %08x\n", hr);
667 hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
668 ok(hr == S_OK, "GetService failed: %08x\n", hr);
670 hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
671 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
672 ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
674 hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
675 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
676 ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
678 hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
679 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
680 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
682 hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
683 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
684 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
686 IAudioStreamVolume_Release(asv2);
687 IChannelAudioVolume_Release(cav2);
688 IAudioClient_Release(ac2);
689 }else
690 skip("Unable to open the same device twice. Skipping session volume control tests\n");
692 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
693 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
695 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
696 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
698 CoTaskMemFree(fmt);
699 ISimpleAudioVolume_Release(sav);
700 IChannelAudioVolume_Release(cav);
701 IAudioStreamVolume_Release(asv);
702 IAudioClient_Release(ac);
705 START_TEST(capture)
707 HRESULT hr;
708 IMMDeviceEnumerator *mme = NULL;
710 CoInitializeEx(NULL, COINIT_MULTITHREADED);
711 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
712 if (FAILED(hr))
714 skip("mmdevapi not available: 0x%08x\n", hr);
715 goto cleanup;
718 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture, eMultimedia, &dev);
719 ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
720 if (hr != S_OK || !dev)
722 if (hr == E_NOTFOUND)
723 skip("No sound card available\n");
724 else
725 skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
726 goto cleanup;
729 test_audioclient();
730 test_streamvolume();
731 test_channelvolume();
732 test_simplevolume();
733 test_volume_dependence();
735 IMMDevice_Release(dev);
737 cleanup:
738 if (mme)
739 IMMDeviceEnumerator_Release(mme);
740 CoUninitialize();