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