mmdevapi: Implement ISimpleAudioVolume::{Set, Get}Mute.
[wine] / dlls / mmdevapi / tests / capture.c
1 /*
2  * Copyright 2010 Maarten Lankhorst for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 /* This test is for audio capture specific mechanisms
20  * Tests:
21  * - IAudioClient with eCapture and IAudioCaptureClient
22  */
23
24 #include <math.h>
25
26 #include "wine/test.h"
27
28 #define COBJMACROS
29
30 #ifdef STANDALONE
31 #include "initguid.h"
32 #endif
33
34 #include "unknwn.h"
35 #include "uuids.h"
36 #include "mmdeviceapi.h"
37 #include "audioclient.h"
38
39 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
40
41 static IMMDevice *dev = NULL;
42
43 static void test_uninitialized(IAudioClient *ac)
44 {
45     HRESULT hr;
46     UINT32 num;
47     REFERENCE_TIME t1;
48
49     HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
50     IUnknown *unk;
51
52     hr = IAudioClient_GetBufferSize(ac, &num);
53     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
54
55     hr = IAudioClient_GetStreamLatency(ac, &t1);
56     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
57
58     hr = IAudioClient_GetCurrentPadding(ac, &num);
59     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
60
61     hr = IAudioClient_Start(ac);
62     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
63
64     hr = IAudioClient_Stop(ac);
65     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
66
67     hr = IAudioClient_Reset(ac);
68     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
69
70     hr = IAudioClient_SetEventHandle(ac, handle);
71     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
72
73     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
74     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
75
76     CloseHandle(handle);
77 }
78
79 static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx)
80 {
81     IAudioCaptureClient *acc;
82     HRESULT hr;
83     UINT32 frames = 0;
84     BYTE *data = NULL;
85     DWORD flags;
86     UINT64 devpos, qpcpos;
87
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;
92
93     hr = IAudioCaptureClient_GetNextPacketSize(acc, NULL);
94     ok(hr == E_POINTER, "IAudioCaptureClient_GetNextPacketSize(NULL) returns %08x\n", hr);
95
96     ok(WaitForSingleObject(handle, 2000) == WAIT_OBJECT_0, "Waiting on event handle failed!\n");
97
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);
101
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);
106
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);
111
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);
116
117     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, NULL, NULL, NULL);
118     ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(&ata, &frames, NULL) returns %08x\n", hr);
119
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);
129
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);
133     }
134
135     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
136     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
137
138     if (frames) {
139         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
140         ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Releasing buffer twice returns %08x\n", hr);
141     }
142
143     IUnknown_Release(acc);
144 }
145
146 static void test_audioclient(void)
147 {
148     IAudioClient *ac;
149     IUnknown *unk;
150     HRESULT hr;
151     ULONG ref;
152     WAVEFORMATEX *pwfx, *pwfx2;
153     REFERENCE_TIME t1, t2;
154     HANDLE handle;
155
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;
161
162     handle = CreateEventW(NULL, FALSE, FALSE, NULL);
163
164     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
165     ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
166
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);
171
172     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
173     ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
174     if (unk)
175     {
176         ref = IUnknown_Release(unk);
177         ok(ref == 1, "Released count is %u\n", ref);
178     }
179
180     hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
181     ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
182     if (unk)
183     {
184         ref = IUnknown_Release(unk);
185         ok(ref == 1, "Released count is %u\n", ref);
186     }
187
188     hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
189     ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
190
191     hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
192     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
193
194     hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
195     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
196
197     hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
198     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
199     trace("Returned periods: %u.%05u ms %u.%05u ms\n",
200           (UINT)(t1/10000), (UINT)(t1 % 10000),
201           (UINT)(t2/10000), (UINT)(t2 % 10000));
202
203     hr = IAudioClient_GetMixFormat(ac, NULL);
204     ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
205
206     hr = IAudioClient_GetMixFormat(ac, &pwfx);
207     ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
208
209     if (hr == S_OK)
210     {
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)
220         {
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"));
228         }
229
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);
234
235         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
236         ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
237
238         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
239         ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
240
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);
243
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");
247
248         hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
249         ok(hr == E_INVALIDARG, "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
250     }
251
252     test_uninitialized(ac);
253
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);
256
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);
259
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
262      */
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);
265
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);
268
269     if (hr != S_OK)
270     {
271         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
272         CoTaskMemFree(pwfx);
273         return;
274     }
275
276     hr = IAudioClient_GetStreamLatency(ac, NULL);
277     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
278
279     hr = IAudioClient_GetStreamLatency(ac, &t1);
280     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
281     trace("Returned latency: %u.%05u ms\n",
282           (UINT)(t1/10000), (UINT)(t1 % 10000));
283
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);
286
287     hr = IAudioClient_SetEventHandle(ac, NULL);
288     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
289
290     hr = IAudioClient_Start(ac);
291     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start before SetEventHandle returns %08x\n", hr);
292
293     hr = IAudioClient_SetEventHandle(ac, handle);
294     ok(hr == S_OK, "SetEventHandle returns %08x\n", hr);
295
296     hr = IAudioClient_Reset(ac);
297     ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
298
299     hr = IAudioClient_Stop(ac);
300     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
301
302     hr = IAudioClient_Start(ac);
303     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
304
305     test_capture(ac, handle, pwfx);
306
307     IAudioClient_Release(ac);
308     CloseHandle(handle);
309     CoTaskMemFree(pwfx);
310 }
311
312 static void test_streamvolume(void)
313 {
314     IAudioClient *ac;
315     IAudioStreamVolume *asv;
316     WAVEFORMATEX *fmt;
317     UINT32 chans, i;
318     HRESULT hr;
319     float vol, *vols;
320
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;
326
327     hr = IAudioClient_GetMixFormat(ac, &fmt);
328     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
329
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
334     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
335     ok(hr == S_OK, "GetService failed: %08x\n", hr);
336
337     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
338     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
339
340     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
341     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
342     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
343
344     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
345     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
346
347     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
348     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
349
350     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
351     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
352
353     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
354     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
355     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
356
357     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
358     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
359
360     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
361     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
362
363     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
364     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
365
366     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
367     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
368
369     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
370     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
371     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
372
373     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
374     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
375
376     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
377     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
378
379     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
380     ok(vols != NULL, "HeapAlloc failed\n");
381
382     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
383     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
384
385     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
386     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
387     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
388     for(i = 1; i < fmt->nChannels; ++i)
389         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
390
391     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
392     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
393
394     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
395     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
396
397     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
398     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
399
400     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
401     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
402
403     HeapFree(GetProcessHeap(), 0, vols);
404     IAudioStreamVolume_Release(asv);
405     IAudioClient_Release(ac);
406     CoTaskMemFree(fmt);
407 }
408
409 static void test_channelvolume(void)
410 {
411     IAudioClient *ac;
412     IChannelAudioVolume *acv;
413     WAVEFORMATEX *fmt;
414     UINT32 chans, i;
415     HRESULT hr;
416     float vol, *vols;
417
418     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
419             NULL, (void**)&ac);
420     ok(hr == S_OK, "Activation failed with %08x\n", hr);
421     if(hr != S_OK)
422         return;
423
424     hr = IAudioClient_GetMixFormat(ac, &fmt);
425     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
426
427     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
428             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
429     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
430
431     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
432     ok(hr == S_OK, "GetService failed: %08x\n", hr);
433
434     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
435     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
436
437     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
438     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
439     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
440
441     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
442     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
443
444     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
445     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
446
447     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
448     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
449
450     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
451     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
452     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
453
454     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
455     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
456
457     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
458     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
459
460     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
461     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
462
463     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
464     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
465
466     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
467     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
468     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
469
470     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
471     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
472
473     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
474     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
475
476     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
477     ok(vols != NULL, "HeapAlloc failed\n");
478
479     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
480     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
481
482     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
483     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
484     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
485     for(i = 1; i < fmt->nChannels; ++i)
486         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
487
488     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
489     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
490
491     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
492     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
493
494     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
495     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
496
497     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
498     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
499
500     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
501     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
502
503     HeapFree(GetProcessHeap(), 0, vols);
504     IChannelAudioVolume_Release(acv);
505     IAudioClient_Release(ac);
506     CoTaskMemFree(fmt);
507 }
508
509 static void test_simplevolume(void)
510 {
511     IAudioClient *ac;
512     ISimpleAudioVolume *sav;
513     WAVEFORMATEX *fmt;
514     HRESULT hr;
515     float vol;
516     BOOL mute;
517
518     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
519             NULL, (void**)&ac);
520     ok(hr == S_OK, "Activation failed with %08x\n", hr);
521     if(hr != S_OK)
522         return;
523
524     hr = IAudioClient_GetMixFormat(ac, &fmt);
525     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
526
527     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
528             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
529     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
530
531     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
532     ok(hr == S_OK, "GetService failed: %08x\n", hr);
533
534     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
535     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
536
537     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
538     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
539     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
540
541     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
542     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
543
544     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
545     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
546
547     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
548     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
549
550     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
551     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
552     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
553
554     hr = ISimpleAudioVolume_GetMute(sav, NULL);
555     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
556
557     mute = TRUE;
558     hr = ISimpleAudioVolume_GetMute(sav, &mute);
559     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
560     ok(mute == FALSE, "Session is already muted\n");
561
562     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
563     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
564
565     mute = FALSE;
566     hr = ISimpleAudioVolume_GetMute(sav, &mute);
567     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
568     ok(mute == TRUE, "Session should have been muted\n");
569
570     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
571     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
572     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
573
574     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
575     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
576
577     mute = FALSE;
578     hr = ISimpleAudioVolume_GetMute(sav, &mute);
579     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
580     ok(mute == TRUE, "Session should have been muted\n");
581
582     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
583     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
584
585     ISimpleAudioVolume_Release(sav);
586     IAudioClient_Release(ac);
587     CoTaskMemFree(fmt);
588 }
589
590 static void test_volume_dependence(void)
591 {
592     IAudioClient *ac, *ac2;
593     ISimpleAudioVolume *sav;
594     IChannelAudioVolume *cav;
595     IAudioStreamVolume *asv;
596     WAVEFORMATEX *fmt;
597     HRESULT hr;
598     float vol;
599     GUID session;
600     UINT32 nch;
601
602     hr = CoCreateGuid(&session);
603     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
604
605     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
606             NULL, (void**)&ac);
607     ok(hr == S_OK, "Activation failed with %08x\n", hr);
608
609     hr = IAudioClient_GetMixFormat(ac, &fmt);
610     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
611
612     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
613             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
614     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
615
616     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
617     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
618
619     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
620     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
621
622     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
623     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
624
625     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
626     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
627
628     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
629     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
630
631     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
632     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
633
634     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
635     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
636     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
637
638     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
639     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
640     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
641
642     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
643     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
644     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
645
646     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
647             NULL, (void**)&ac2);
648     if(SUCCEEDED(hr)){
649         IChannelAudioVolume *cav2;
650         IAudioStreamVolume *asv2;
651
652         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
653                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
654         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
655
656         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
657         ok(hr == S_OK, "GetService failed: %08x\n", hr);
658
659         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
660         ok(hr == S_OK, "GetService failed: %08x\n", hr);
661
662         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
663         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
664         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
665
666         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
667         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
668         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
669
670         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
671         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
672         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
673
674         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
675         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
676         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
677
678         IAudioStreamVolume_Release(asv2);
679         IChannelAudioVolume_Release(cav2);
680         IAudioClient_Release(ac2);
681     }else
682         skip("Unable to open the same device twice. Skipping session volume control tests\n");
683
684     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
685     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
686
687     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
688     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
689
690     CoTaskMemFree(fmt);
691     ISimpleAudioVolume_Release(sav);
692     IChannelAudioVolume_Release(cav);
693     IAudioStreamVolume_Release(asv);
694     IAudioClient_Release(ac);
695 }
696
697 START_TEST(capture)
698 {
699     HRESULT hr;
700     IMMDeviceEnumerator *mme = NULL;
701
702     CoInitializeEx(NULL, COINIT_MULTITHREADED);
703     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
704     if (FAILED(hr))
705     {
706         skip("mmdevapi not available: 0x%08x\n", hr);
707         goto cleanup;
708     }
709
710     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture, eMultimedia, &dev);
711     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
712     if (hr != S_OK || !dev)
713     {
714         if (hr == E_NOTFOUND)
715             skip("No sound card available\n");
716         else
717             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
718         goto cleanup;
719     }
720
721     test_audioclient();
722     test_streamvolume();
723     test_channelvolume();
724     test_simplevolume();
725     test_volume_dependence();
726
727     IMMDevice_Release(dev);
728
729 cleanup:
730     if (mme)
731         IMMDeviceEnumerator_Release(mme);
732     CoUninitialize();
733 }