Release 1.5.29.
[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, next, pad, sum = 0;
84     BYTE *data;
85     DWORD flags, r;
86     UINT64 pos, qpc;
87     REFERENCE_TIME period;
88
89     hr = IAudioClient_GetService(ac, &IID_IAudioCaptureClient, (void**)&acc);
90     ok(hr == S_OK, "IAudioClient_GetService(IID_IAudioCaptureClient) returns %08x\n", hr);
91     if (hr != S_OK)
92         return;
93
94     frames = 0xabadcafe;
95     data = (void*)0xdeadf00d;
96     flags = 0xabadcafe;
97     pos = qpc = 0xdeadbeef;
98     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
99     ok(hr == AUDCLNT_S_BUFFER_EMPTY, "Initial IAudioCaptureClient_GetBuffer returns %08x\n", hr);
100
101     /* should be empty right after start. Otherwise consume one packet */
102     if(hr == S_OK){
103         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
104         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
105         sum += frames;
106
107         frames = 0xabadcafe;
108         data = (void*)0xdeadf00d;
109         flags = 0xabadcafe;
110         pos = qpc = 0xdeadbeef;
111         hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
112         ok(hr == AUDCLNT_S_BUFFER_EMPTY, "Initial IAudioCaptureClient_GetBuffer returns %08x\n", hr);
113     }
114
115     if(hr == AUDCLNT_S_BUFFER_EMPTY){
116         ok(!frames, "frames changed to %u\n", frames);
117         ok(data == (void*)0xdeadf00d, "data changed to %p\n", data);
118         ok(flags == 0xabadcafe, "flags changed to %x\n", flags);
119         ok(pos == 0xdeadbeef, "position changed to %u\n", (UINT)pos);
120         ok(qpc == 0xdeadbeef, "timer changed to %u\n", (UINT)qpc);
121
122         /* GetNextPacketSize yields 0 if no data is yet available
123          * it is not constantly period_size * SamplesPerSec */
124         hr = IAudioCaptureClient_GetNextPacketSize(acc, &next);
125         ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
126         ok(!next, "GetNextPacketSize %u\n", next);
127     }
128
129     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
130     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
131     sum += frames;
132
133     ok(ResetEvent(handle), "ResetEvent\n");
134
135     hr = IAudioCaptureClient_GetNextPacketSize(acc, &next);
136     ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
137
138     hr = IAudioClient_GetCurrentPadding(ac, &pad);
139     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
140     ok(next == pad, "GetNextPacketSize %u vs. GCP %u\n", next, pad);
141     /* later GCP will grow, while GNPS is 0 or period size */
142
143     hr = IAudioCaptureClient_GetNextPacketSize(acc, NULL);
144     ok(hr == E_POINTER, "IAudioCaptureClient_GetNextPacketSize(NULL) returns %08x\n", hr);
145
146     data = (void*)0xdeadf00d;
147     frames = 0xdeadbeef;
148     flags = 0xabadcafe;
149     hr = IAudioCaptureClient_GetBuffer(acc, &data, NULL, NULL, NULL, NULL);
150     ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(data, NULL, NULL) returns %08x\n", hr);
151
152     hr = IAudioCaptureClient_GetBuffer(acc, NULL, &frames, NULL, NULL, NULL);
153     ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(NULL, &frames, NULL) returns %08x\n", hr);
154
155     hr = IAudioCaptureClient_GetBuffer(acc, NULL, NULL, &flags, NULL, NULL);
156     ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(NULL, NULL, &flags) returns %08x\n", hr);
157
158     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, NULL, NULL, NULL);
159     ok(hr == E_POINTER, "IAudioCaptureClient_GetBuffer(&ata, &frames, NULL) returns %08x\n", hr);
160     ok((DWORD_PTR)data == 0xdeadf00d, "data is reset to %p\n", data);
161     ok(frames == 0xdeadbeef, "frames is reset to %08x\n", frames);
162     ok(flags == 0xabadcafe, "flags is reset to %08x\n", flags);
163
164     hr = IAudioClient_GetDevicePeriod(ac, &period, NULL);
165     ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
166     period = MulDiv(period, wfx->nSamplesPerSec, 10000000); /* as in render.c */
167
168     ok(WaitForSingleObject(handle, 1000) == WAIT_OBJECT_0, "Waiting on event handle failed!\n");
169
170     data = (void*)0xdeadf00d;
171     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
172     ok(hr == S_OK || hr == AUDCLNT_S_BUFFER_EMPTY, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
173     if (hr == S_OK){
174         ok(frames, "Amount of frames locked is 0!\n");
175         /* broken: some w7 machines return pad == 0 and DATA_DISCONTINUITY here,
176          * AUDCLNT_S_BUFFER_EMPTY above, yet pos == 1-2 * period rather than 0 */
177         ok(pos == sum || broken(pos == period || pos == 2*period),
178            "Position %u expected %u\n", (UINT)pos, sum);
179         sum = pos;
180     }else if (hr == AUDCLNT_S_BUFFER_EMPTY){
181         ok(!frames, "Amount of frames locked with empty buffer is %u!\n", frames);
182         ok(data == (void*)0xdeadf00d, "No data changed to %p\n", data);
183     }
184
185     trace("Wait'ed position %d pad %u flags %x, amount of frames locked: %u\n",
186           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
187
188     hr = IAudioCaptureClient_GetNextPacketSize(acc, &next);
189     ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
190     ok(next == frames, "GetNextPacketSize %u vs. GetBuffer %u\n", next, frames);
191
192     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
193     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
194
195     hr = IAudioCaptureClient_ReleaseBuffer(acc, 0);
196     ok(hr == S_OK, "Releasing 0 returns %08x\n", hr);
197
198     hr = IAudioCaptureClient_GetNextPacketSize(acc, &next);
199     ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
200
201     if (frames) {
202         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
203         ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Releasing buffer twice returns %08x\n", hr);
204         sum += frames;
205     }
206
207     Sleep(350); /* for sure there's data now */
208
209     hr = IAudioClient_GetCurrentPadding(ac, &pad);
210     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
211
212     /** GetNextPacketSize
213      * returns either 0 or one period worth of frames
214      * whereas GetCurrentPadding grows when input is not consumed. */
215     hr = IAudioCaptureClient_GetNextPacketSize(acc, &next);
216     ok(hr == S_OK, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr);
217     ok(next <  pad, "GetNextPacketSize %u vs. GCP %u\n", next, pad);
218
219     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
220     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
221     ok(next == frames, "GetNextPacketSize %u vs. GetBuffer %u\n", next, frames);
222
223     if(hr == S_OK){
224         UINT32 frames2 = frames;
225         UINT64 pos2, qpc2;
226         ok(frames, "Amount of frames locked is 0!\n");
227         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
228
229         hr = IAudioCaptureClient_ReleaseBuffer(acc, 0);
230         ok(hr == S_OK, "Releasing 0 returns %08x\n", hr);
231
232         /* GCP did not decrement, no data consumed */
233         hr = IAudioClient_GetCurrentPadding(ac, &frames);
234         ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
235         ok(frames == pad || frames == pad + next /* concurrent feeder */,
236            "GCP %u past ReleaseBuffer(0) initially %u\n", frames, pad);
237
238         /* should re-get the same data */
239         hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos2, &qpc2);
240         ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
241         ok(frames2 == frames, "GetBuffer after ReleaseBuffer(0) %u/%u\n", frames2, frames);
242         ok(pos2 == pos, "Position after ReleaseBuffer(0) %u/%u\n", (UINT)pos2, (UINT)pos);
243         todo_wine ok(qpc2 == qpc, "HPC after ReleaseBuffer(0) %u vs. %u\n", (UINT)qpc2, (UINT)qpc);
244     }
245
246     /* trace after the GCP test because log output to MS-DOS console disturbs timing */
247     trace("Sleep.1 position %d pad %u flags %x, amount of frames locked: %u\n",
248           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
249
250     if(hr == S_OK){
251         UINT32 frames2 = 0xabadcafe;
252         BYTE *data2 = (void*)0xdeadf00d;
253         flags = 0xabadcafe;
254
255         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
256
257         pos = qpc = 0xdeadbeef;
258         hr = IAudioCaptureClient_GetBuffer(acc, &data2, &frames2, &flags, &pos, &qpc);
259         ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Out of order IAudioCaptureClient_GetBuffer returns %08x\n", hr);
260         ok(frames2 == 0xabadcafe, "Out of order frames changed to %x\n", frames2);
261         ok(data2 == (void*)0xdeadf00d, "Out of order data changed to %p\n", data2);
262         ok(flags == 0xabadcafe, "Out of order flags changed to %x\n", flags);
263         ok(pos == 0xdeadbeef, "Out of order position changed to %x\n", (UINT)pos);
264         ok(qpc == 0xdeadbeef, "Out of order timer changed to %x\n", (UINT)qpc);
265
266         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames+1);
267         ok(hr == AUDCLNT_E_INVALID_SIZE, "Releasing buffer+1 returns %08x\n", hr);
268
269         hr = IAudioCaptureClient_ReleaseBuffer(acc, 1);
270         ok(hr == AUDCLNT_E_INVALID_SIZE, "Releasing 1 returns %08x\n", hr);
271
272         hr = IAudioClient_Reset(ac);
273         ok(hr == AUDCLNT_E_NOT_STOPPED, "Reset failed: %08x\n", hr);
274     }
275
276     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
277     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
278
279     if (frames) {
280         sum += frames;
281         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
282         ok(hr == AUDCLNT_E_OUT_OF_ORDER, "Releasing buffer twice returns %08x\n", hr);
283     }
284
285     frames = period;
286     ok(next == frames, "GetNextPacketSize %u vs. GetDevicePeriod %u\n", next, frames);
287
288     /* GetBufferSize is not a multiple of the period size! */
289     hr = IAudioClient_GetBufferSize(ac, &next);
290     ok(hr == S_OK, "GetBufferSize failed: %08x\n", hr);
291     trace("GetBufferSize %u period size %u\n", next, frames);
292
293     Sleep(400); /* overrun */
294
295     hr = IAudioClient_GetCurrentPadding(ac, &pad);
296     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
297
298     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
299     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
300
301     trace("Overrun position %d pad %u flags %x, amount of frames locked: %u\n",
302           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
303
304     if(hr == S_OK){
305         /* The discontinuity is reported here, but is this an old or new packet? */
306         todo_wine ok(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY, "expect DISCONTINUITY %x\n", flags);
307         ok(pad == next, "GCP %u vs. BufferSize %u\n", (UINT32)pad, next);
308
309         /* Native's position is one period further than what we read.
310          * Perhaps that's precisely the meaning of DATA_DISCONTINUITY:
311          * signal when the position jump left a gap. */
312         todo_wine ok(pos == sum + frames, "Position %u gap %d\n",
313                      (UINT)pos, (UINT)pos - sum);
314         if(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY)
315             sum = pos;
316     }
317
318     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
319     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
320     sum += frames;
321
322     hr = IAudioClient_GetCurrentPadding(ac, &pad);
323     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
324
325     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
326     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
327
328     trace("Cont'ed position %d pad %u flags %x, amount of frames locked: %u\n",
329           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
330
331     if(hr == S_OK){
332         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
333         ok(!flags, "flags %u\n", flags);
334
335         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
336         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
337         sum += frames;
338     }
339
340     hr = IAudioClient_Stop(ac);
341     ok(hr == S_OK, "Stop on a started stream returns %08x\n", hr);
342
343     hr = IAudioClient_Start(ac);
344     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
345
346     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
347     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
348
349     hr = IAudioClient_GetCurrentPadding(ac, &pad);
350     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
351
352     trace("Restart position %d pad %u flags %x, amount of frames locked: %u\n",
353           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
354     ok(pad > sum, "restarted GCP %u\n", pad); /* GCP is still near buffer size */
355
356     if(frames){
357         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
358         ok(!flags, "flags %u\n", flags);
359
360         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
361         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
362         sum += frames;
363     }
364
365     hr = IAudioClient_Stop(ac);
366     ok(hr == S_OK, "Stop on a started stream returns %08x\n", hr);
367
368     hr = IAudioClient_Reset(ac);
369     ok(hr == S_OK, "Reset on a stopped stream returns %08x\n", hr);
370     sum += pad - frames;
371
372     hr = IAudioClient_Start(ac);
373     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
374
375     hr = IAudioClient_GetCurrentPadding(ac, &pad);
376     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
377
378     flags = 0xabadcafe;
379     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
380     ok(hr == AUDCLNT_S_BUFFER_EMPTY || /*PulseAudio*/hr == S_OK,
381        "Initial IAudioCaptureClient_GetBuffer returns %08x\n", hr);
382
383     trace("Reset   position %d pad %u flags %x, amount of frames locked: %u\n",
384           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
385
386     if(hr == S_OK){
387         /* Only PulseAudio goes here; despite snd_pcm_drop it manages
388          * to fill GetBufferSize with a single snd_pcm_read */
389         trace("Test marked todo: only PulseAudio gets here\n");
390         todo_wine ok(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY, "expect DISCONTINUITY %x\n", flags);
391         /* Reset zeroes padding, not the position */
392         ok(pos >= sum, "Position %u last %u\n", (UINT)pos, sum);
393         /*sum = pos; check after next GetBuffer */
394
395         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
396         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
397         sum += frames;
398     }
399     else if(hr == AUDCLNT_S_BUFFER_EMPTY){
400         ok(!pad, "resetted GCP %u\n", pad);
401         Sleep(180);
402     }
403
404     hr = IAudioClient_GetCurrentPadding(ac, &pad);
405     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
406
407     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
408     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
409     trace("Running position %d pad %u flags %x, amount of frames locked: %u\n",
410           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
411
412     if(hr == S_OK){
413         /* Some w7 machines signal DATA_DISCONTINUITY here following the
414          * previous AUDCLNT_S_BUFFER_EMPTY, others not.  What logic? */
415         ok(pos >= sum, "Position %u gap %d\n", (UINT)pos, (UINT)pos - sum);
416         IAudioCaptureClient_ReleaseBuffer(acc, frames);
417     }
418
419     hr = IAudioClient_Stop(ac);
420     ok(hr == S_OK, "Stop failed: %08x\n", hr);
421
422     ok(ResetEvent(handle), "ResetEvent\n");
423
424     /* Still receiving events! */
425     r = WaitForSingleObject(handle, 20);
426     todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r);
427
428     hr = IAudioClient_Reset(ac);
429     ok(hr == S_OK, "Reset failed: %08x\n", hr);
430
431     ok(ResetEvent(handle), "ResetEvent\n");
432
433     r = WaitForSingleObject(handle, 120);
434     todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r);
435
436     hr = IAudioClient_SetEventHandle(ac, NULL);
437     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
438
439     r = WaitForSingleObject(handle, 70);
440     todo_wine ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r);
441
442     hr = IAudioClient_Start(ac);
443     ok(hr == S_OK, "Start failed: %08x\n", hr);
444
445     IAudioCaptureClient_Release(acc);
446 }
447
448 static void test_audioclient(void)
449 {
450     IAudioClient *ac;
451     IUnknown *unk;
452     HRESULT hr;
453     ULONG ref;
454     WAVEFORMATEX *pwfx, *pwfx2;
455     REFERENCE_TIME t1, t2;
456     HANDLE handle;
457
458     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
459             NULL, (void**)&ac);
460     ok(hr == S_OK, "Activation failed with %08x\n", hr);
461     if(hr != S_OK)
462         return;
463
464     handle = CreateEventW(NULL, FALSE, FALSE, NULL);
465
466     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
467     ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
468
469     unk = (void*)(LONG_PTR)0x12345678;
470     hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
471     ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
472     ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
473
474     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
475     ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
476     if (unk)
477     {
478         ref = IUnknown_Release(unk);
479         ok(ref == 1, "Released count is %u\n", ref);
480     }
481
482     hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
483     ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
484     if (unk)
485     {
486         ref = IUnknown_Release(unk);
487         ok(ref == 1, "Released count is %u\n", ref);
488     }
489
490     hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
491     ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
492
493     hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
494     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
495
496     hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
497     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
498
499     hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
500     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
501     trace("Returned periods: %u.%04u ms %u.%04u ms\n",
502           (UINT)(t1/10000), (UINT)(t1 % 10000),
503           (UINT)(t2/10000), (UINT)(t2 % 10000));
504
505     hr = IAudioClient_GetMixFormat(ac, NULL);
506     ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
507
508     hr = IAudioClient_GetMixFormat(ac, &pwfx);
509     ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
510
511     if (hr == S_OK)
512     {
513         trace("pwfx: %p\n", pwfx);
514         trace("Tag: %04x\n", pwfx->wFormatTag);
515         trace("bits: %u\n", pwfx->wBitsPerSample);
516         trace("chan: %u\n", pwfx->nChannels);
517         trace("rate: %u\n", pwfx->nSamplesPerSec);
518         trace("align: %u\n", pwfx->nBlockAlign);
519         trace("extra: %u\n", pwfx->cbSize);
520         ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
521         if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
522         {
523             WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
524             trace("Res: %u\n", pwfxe->Samples.wReserved);
525             trace("Mask: %x\n", pwfxe->dwChannelMask);
526             trace("Alg: %s\n",
527                   IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
528                   (IsEqualGUID(&pwfxe->SubFormat,
529                                &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
530         }
531
532         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
533         ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
534         ok(pwfx2 == NULL, "pwfx2 is non-null\n");
535         CoTaskMemFree(pwfx2);
536
537         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
538         ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
539
540         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
541         ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
542
543         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
544         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
545
546         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
547         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
548         ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
549
550         hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
551         ok(hr == E_INVALIDARG/*w32*/ ||
552            broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT/*w64 response from exclusive mode driver */),
553            "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
554     }
555
556     test_uninitialized(ac);
557
558     hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
559     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
560
561     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
562     ok(hr == E_INVALIDARG || hr == AUDCLNT_E_INVALID_STREAM_FLAG, "Initialize with invalid flags returns %08x\n", hr);
563
564     /* A period != 0 is ignored and the call succeeds.
565      * Since we can only initialize successfully once, skip those tests.
566      */
567     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
568     ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
569
570     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 4987654, 0, pwfx, NULL);
571     ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
572
573     if (hr != S_OK)
574     {
575         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
576         CoTaskMemFree(pwfx);
577         return;
578     }
579
580     hr = IAudioClient_GetStreamLatency(ac, NULL);
581     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
582
583     hr = IAudioClient_GetStreamLatency(ac, &t1);
584     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
585     trace("Returned latency: %u.%04u ms\n",
586           (UINT)(t1/10000), (UINT)(t1 % 10000));
587
588     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
589     ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
590
591     hr = IAudioClient_SetEventHandle(ac, NULL);
592     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
593
594     hr = IAudioClient_Start(ac);
595     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start before SetEventHandle returns %08x\n", hr);
596
597     hr = IAudioClient_SetEventHandle(ac, handle);
598     ok(hr == S_OK, "SetEventHandle returns %08x\n", hr);
599
600     hr = IAudioClient_Reset(ac);
601     ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
602
603     hr = IAudioClient_Stop(ac);
604     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
605
606     hr = IAudioClient_Start(ac);
607     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
608
609     test_capture(ac, handle, pwfx);
610
611     IAudioClient_Release(ac);
612     CloseHandle(handle);
613     CoTaskMemFree(pwfx);
614 }
615
616 static void test_streamvolume(void)
617 {
618     IAudioClient *ac;
619     IAudioStreamVolume *asv;
620     WAVEFORMATEX *fmt;
621     UINT32 chans, i;
622     HRESULT hr;
623     float vol, *vols;
624
625     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
626             NULL, (void**)&ac);
627     ok(hr == S_OK, "Activation failed with %08x\n", hr);
628     if(hr != S_OK)
629         return;
630
631     hr = IAudioClient_GetMixFormat(ac, &fmt);
632     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
633
634     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
635             0, fmt, NULL);
636     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
637     if(hr != S_OK)
638         return;
639
640     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
641     ok(hr == S_OK, "GetService failed: %08x\n", hr);
642
643     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
644     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
645
646     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
647     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
648     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
649
650     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
651     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
652
653     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
654     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
655
656     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
657     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
658
659     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
660     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
661     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
662
663     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
664     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
665
666     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
667     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
668
669     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
670     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
671
672     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
673     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
674
675     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
676     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
677     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
678
679     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
680     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
681
682     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
683     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
684
685     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
686     ok(vols != NULL, "HeapAlloc failed\n");
687
688     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
689     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
690
691     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
692     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
693     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
694     for(i = 1; i < fmt->nChannels; ++i)
695         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
696
697     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
698     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
699
700     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
701     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
702
703     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
704     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
705
706     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
707     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
708
709     HeapFree(GetProcessHeap(), 0, vols);
710     IAudioStreamVolume_Release(asv);
711     IAudioClient_Release(ac);
712     CoTaskMemFree(fmt);
713 }
714
715 static void test_channelvolume(void)
716 {
717     IAudioClient *ac;
718     IChannelAudioVolume *acv;
719     WAVEFORMATEX *fmt;
720     UINT32 chans, i;
721     HRESULT hr;
722     float vol, *vols;
723
724     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
725             NULL, (void**)&ac);
726     ok(hr == S_OK, "Activation failed with %08x\n", hr);
727     if(hr != S_OK)
728         return;
729
730     hr = IAudioClient_GetMixFormat(ac, &fmt);
731     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
732
733     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
734             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
735     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
736
737     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
738     ok(hr == S_OK, "GetService failed: %08x\n", hr);
739     if(hr != S_OK)
740         return;
741
742     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
743     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
744
745     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
746     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
747     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
748
749     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
750     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
751
752     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
753     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
754
755     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
756     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
757
758     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
759     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
760     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
761
762     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
763     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
764
765     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
766     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
767
768     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
769     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
770
771     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
772     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
773
774     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
775     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
776     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
777
778     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
779     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
780
781     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
782     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
783
784     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
785     ok(vols != NULL, "HeapAlloc failed\n");
786
787     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
788     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
789
790     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
791     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
792     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
793     for(i = 1; i < fmt->nChannels; ++i)
794         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
795
796     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
797     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
798
799     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
800     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
801
802     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
803     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
804
805     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
806     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
807
808     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
809     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
810
811     HeapFree(GetProcessHeap(), 0, vols);
812     IChannelAudioVolume_Release(acv);
813     IAudioClient_Release(ac);
814     CoTaskMemFree(fmt);
815 }
816
817 static void test_simplevolume(void)
818 {
819     IAudioClient *ac;
820     ISimpleAudioVolume *sav;
821     WAVEFORMATEX *fmt;
822     HRESULT hr;
823     float vol;
824     BOOL mute;
825
826     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
827             NULL, (void**)&ac);
828     ok(hr == S_OK, "Activation failed with %08x\n", hr);
829     if(hr != S_OK)
830         return;
831
832     hr = IAudioClient_GetMixFormat(ac, &fmt);
833     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
834
835     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
836             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
837     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
838
839     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
840     ok(hr == S_OK, "GetService failed: %08x\n", hr);
841     if(hr != S_OK)
842         return;
843
844     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
845     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
846
847     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
848     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
849     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
850
851     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
852     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
853
854     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
855     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
856
857     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
858     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
859
860     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
861     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
862     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
863
864     hr = ISimpleAudioVolume_GetMute(sav, NULL);
865     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
866
867     mute = TRUE;
868     hr = ISimpleAudioVolume_GetMute(sav, &mute);
869     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
870     ok(mute == FALSE, "Session is already muted\n");
871
872     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
873     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
874
875     mute = FALSE;
876     hr = ISimpleAudioVolume_GetMute(sav, &mute);
877     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
878     ok(mute == TRUE, "Session should have been muted\n");
879
880     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
881     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
882     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
883
884     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
885     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
886
887     mute = FALSE;
888     hr = ISimpleAudioVolume_GetMute(sav, &mute);
889     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
890     ok(mute == TRUE, "Session should have been muted\n");
891
892     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
893     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
894
895     ISimpleAudioVolume_Release(sav);
896     IAudioClient_Release(ac);
897     CoTaskMemFree(fmt);
898 }
899
900 static void test_volume_dependence(void)
901 {
902     IAudioClient *ac, *ac2;
903     ISimpleAudioVolume *sav;
904     IChannelAudioVolume *cav;
905     IAudioStreamVolume *asv;
906     WAVEFORMATEX *fmt;
907     HRESULT hr;
908     float vol;
909     GUID session;
910     UINT32 nch;
911
912     hr = CoCreateGuid(&session);
913     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
914
915     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
916             NULL, (void**)&ac);
917     ok(hr == S_OK, "Activation failed with %08x\n", hr);
918
919     hr = IAudioClient_GetMixFormat(ac, &fmt);
920     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
921
922     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
923             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
924     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
925
926     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
927     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
928
929     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
930     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
931
932     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
933     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
934     if(hr != S_OK)
935         return;
936
937     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
938     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
939
940     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
941     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
942
943     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
944     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
945
946     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
947     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
948     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
949
950     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
951     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
952     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
953
954     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
955     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
956     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
957
958     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
959             NULL, (void**)&ac2);
960     if(SUCCEEDED(hr)){
961         IChannelAudioVolume *cav2;
962         IAudioStreamVolume *asv2;
963
964         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
965                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
966         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
967
968         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
969         ok(hr == S_OK, "GetService failed: %08x\n", hr);
970
971         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
972         ok(hr == S_OK, "GetService failed: %08x\n", hr);
973
974         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
975         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
976         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
977
978         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
979         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
980         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
981
982         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
983         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
984         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
985
986         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
987         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
988         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
989
990         IAudioStreamVolume_Release(asv2);
991         IChannelAudioVolume_Release(cav2);
992         IAudioClient_Release(ac2);
993     }else
994         skip("Unable to open the same device twice. Skipping session volume control tests\n");
995
996     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
997     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
998
999     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1000     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1001
1002     CoTaskMemFree(fmt);
1003     ISimpleAudioVolume_Release(sav);
1004     IChannelAudioVolume_Release(cav);
1005     IAudioStreamVolume_Release(asv);
1006     IAudioClient_Release(ac);
1007 }
1008
1009 START_TEST(capture)
1010 {
1011     HRESULT hr;
1012     IMMDeviceEnumerator *mme = NULL;
1013
1014     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1015     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1016     if (FAILED(hr))
1017     {
1018         skip("mmdevapi not available: 0x%08x\n", hr);
1019         goto cleanup;
1020     }
1021
1022     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture, eMultimedia, &dev);
1023     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1024     if (hr != S_OK || !dev)
1025     {
1026         if (hr == E_NOTFOUND)
1027             skip("No sound card available\n");
1028         else
1029             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1030         goto cleanup;
1031     }
1032
1033     test_audioclient();
1034     test_streamvolume();
1035     test_channelvolume();
1036     test_simplevolume();
1037     test_volume_dependence();
1038
1039     IMMDevice_Release(dev);
1040
1041 cleanup:
1042     if (mme)
1043         IMMDeviceEnumerator_Release(mme);
1044     CoUninitialize();
1045 }