d3d10: Add a stub ID3D10StateBlock implementation.
[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.%04u ms %u.%04u 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.%04u 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     if(hr != S_OK)
334         return;
335
336     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
337     ok(hr == S_OK, "GetService failed: %08x\n", hr);
338
339     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
340     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
341
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);
345
346     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
347     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
348
349     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
350     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
351
352     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
353     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
354
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);
358
359     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
360     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
361
362     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
363     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
364
365     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
366     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
367
368     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
369     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
370
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);
374
375     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
376     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
377
378     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
379     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
380
381     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
382     ok(vols != NULL, "HeapAlloc failed\n");
383
384     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
385     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
386
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]);
392
393     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
394     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
395
396     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
397     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
398
399     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
400     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
401
402     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
403     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
404
405     HeapFree(GetProcessHeap(), 0, vols);
406     IAudioStreamVolume_Release(asv);
407     IAudioClient_Release(ac);
408     CoTaskMemFree(fmt);
409 }
410
411 static void test_channelvolume(void)
412 {
413     IAudioClient *ac;
414     IChannelAudioVolume *acv;
415     WAVEFORMATEX *fmt;
416     UINT32 chans, i;
417     HRESULT hr;
418     float vol, *vols;
419
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;
425
426     hr = IAudioClient_GetMixFormat(ac, &fmt);
427     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
428
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);
432
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;
437
438     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
439     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
440
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);
444
445     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
446     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
447
448     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
449     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
450
451     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
452     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
453
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);
457
458     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
459     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
460
461     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
462     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
463
464     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
465     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
466
467     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
468     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
469
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);
473
474     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
475     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
476
477     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
478     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
479
480     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
481     ok(vols != NULL, "HeapAlloc failed\n");
482
483     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
484     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
485
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]);
491
492     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
493     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
494
495     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
496     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
497
498     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
499     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
500
501     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
502     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
503
504     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
505     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
506
507     HeapFree(GetProcessHeap(), 0, vols);
508     IChannelAudioVolume_Release(acv);
509     IAudioClient_Release(ac);
510     CoTaskMemFree(fmt);
511 }
512
513 static void test_simplevolume(void)
514 {
515     IAudioClient *ac;
516     ISimpleAudioVolume *sav;
517     WAVEFORMATEX *fmt;
518     HRESULT hr;
519     float vol;
520     BOOL mute;
521
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;
527
528     hr = IAudioClient_GetMixFormat(ac, &fmt);
529     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
530
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);
534
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;
539
540     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
541     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
542
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);
546
547     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
548     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
549
550     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
551     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
552
553     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
554     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
555
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);
559
560     hr = ISimpleAudioVolume_GetMute(sav, NULL);
561     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
562
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");
567
568     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
569     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
570
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");
575
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);
579
580     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
581     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
582
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");
587
588     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
589     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
590
591     ISimpleAudioVolume_Release(sav);
592     IAudioClient_Release(ac);
593     CoTaskMemFree(fmt);
594 }
595
596 static void test_volume_dependence(void)
597 {
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;
607
608     hr = CoCreateGuid(&session);
609     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
610
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);
614
615     hr = IAudioClient_GetMixFormat(ac, &fmt);
616     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
617
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);
621
622     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
623     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
624
625     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
626     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
627
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;
632
633     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
634     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
635
636     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
637     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
638
639     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
640     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
641
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);
645
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);
649
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);
653
654     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
655             NULL, (void**)&ac2);
656     if(SUCCEEDED(hr)){
657         IChannelAudioVolume *cav2;
658         IAudioStreamVolume *asv2;
659
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);
663
664         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
665         ok(hr == S_OK, "GetService failed: %08x\n", hr);
666
667         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
668         ok(hr == S_OK, "GetService failed: %08x\n", hr);
669
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);
673
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);
677
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);
681
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);
685
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");
691
692     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
693     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
694
695     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
696     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
697
698     CoTaskMemFree(fmt);
699     ISimpleAudioVolume_Release(sav);
700     IChannelAudioVolume_Release(cav);
701     IAudioStreamVolume_Release(asv);
702     IAudioClient_Release(ac);
703 }
704
705 START_TEST(capture)
706 {
707     HRESULT hr;
708     IMMDeviceEnumerator *mme = NULL;
709
710     CoInitializeEx(NULL, COINIT_MULTITHREADED);
711     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
712     if (FAILED(hr))
713     {
714         skip("mmdevapi not available: 0x%08x\n", hr);
715         goto cleanup;
716     }
717
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)
721     {
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;
727     }
728
729     test_audioclient();
730     test_streamvolume();
731     test_channelvolume();
732     test_simplevolume();
733     test_volume_dependence();
734
735     IMMDevice_Release(dev);
736
737 cleanup:
738     if (mme)
739         IMMDeviceEnumerator_Release(mme);
740     CoUninitialize();
741 }