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         /* The discontinuity is reported here, but is this an old or new packet? */
312         todo_wine_if(!(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY)) {
313             /* FIXME: Some drivers fail */
314             ok(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY, "expect DISCONTINUITY %x\n", flags);
315             /* Native's position is one period further than what we read.
316              * Perhaps that's precisely the meaning of DATA_DISCONTINUITY:
317              * signal when the position jump left a gap. */
318             ok(pos == sum + frames, "Position %u gap %d\n", (UINT)pos, (UINT)pos - sum);
319         }
320 
321         ok(pad == next, "GCP %u vs. BufferSize %u\n", (UINT32)pad, next);
322 
323         if(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY)
324             sum = pos;
325     }
326 
327     hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
328     ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
329     sum += frames;
330 
331     hr = IAudioClient_GetCurrentPadding(ac, &pad);
332     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
333 
334     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
335     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
336 
337     trace("Cont'ed position %d pad %u flags %x, amount of frames locked: %u\n",
338           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
339 
340     if(hr == S_OK){
341         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
342         ok(!flags, "flags %u\n", flags);
343 
344         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
345         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
346         sum += frames;
347     }
348 
349     hr = IAudioClient_Stop(ac);
350     ok(hr == S_OK, "Stop on a started stream returns %08x\n", hr);
351 
352     hr = IAudioClient_Start(ac);
353     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
354 
355     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
356     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
357 
358     hr = IAudioClient_GetCurrentPadding(ac, &pad);
359     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
360 
361     trace("Restart position %d pad %u flags %x, amount of frames locked: %u\n",
362           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
363     ok(pad > sum, "restarted GCP %u\n", pad); /* GCP is still near buffer size */
364 
365     if(frames){
366         ok(pos == sum, "Position %u expected %u\n", (UINT)pos, sum);
367         ok(!flags, "flags %u\n", flags);
368 
369         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
370         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
371         sum += frames;
372     }
373 
374     hr = IAudioClient_Stop(ac);
375     ok(hr == S_OK, "Stop on a started stream returns %08x\n", hr);
376 
377     hr = IAudioClient_Reset(ac);
378     ok(hr == S_OK, "Reset on a stopped stream returns %08x\n", hr);
379     sum += pad - frames;
380 
381     hr = IAudioClient_Start(ac);
382     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
383 
384     hr = IAudioClient_GetCurrentPadding(ac, &pad);
385     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
386 
387     flags = 0xabadcafe;
388     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
389     ok(hr == AUDCLNT_S_BUFFER_EMPTY || /*PulseAudio*/hr == S_OK,
390        "Initial IAudioCaptureClient_GetBuffer returns %08x\n", hr);
391 
392     trace("Reset   position %d pad %u flags %x, amount of frames locked: %u\n",
393           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
394 
395     if(hr == S_OK){
396         /* Only PulseAudio goes here; despite snd_pcm_drop it manages
397          * to fill GetBufferSize with a single snd_pcm_read */
398         trace("Test marked todo: only PulseAudio gets here\n");
399         todo_wine ok(flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY, "expect DISCONTINUITY %x\n", flags);
400         /* Reset zeroes padding, not the position */
401         ok(pos >= sum, "Position %u last %u\n", (UINT)pos, sum);
402         /*sum = pos; check after next GetBuffer */
403 
404         hr = IAudioCaptureClient_ReleaseBuffer(acc, frames);
405         ok(hr == S_OK, "Releasing buffer returns %08x\n", hr);
406         sum += frames;
407     }
408     else if(hr == AUDCLNT_S_BUFFER_EMPTY){
409         ok(!pad, "reset GCP %u\n", pad);
410         Sleep(180);
411     }
412 
413     hr = IAudioClient_GetCurrentPadding(ac, &pad);
414     ok(hr == S_OK, "GetCurrentPadding call returns %08x\n", hr);
415 
416     hr = IAudioCaptureClient_GetBuffer(acc, &data, &frames, &flags, &pos, &qpc);
417     ok(hr == S_OK, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr);
418     trace("Running position %d pad %u flags %x, amount of frames locked: %u\n",
419           hr==S_OK ? (UINT)pos : -1, pad, flags, frames);
420 
421     if(hr == S_OK){
422         /* Some w7 machines signal DATA_DISCONTINUITY here following the
423          * previous AUDCLNT_S_BUFFER_EMPTY, others not.  What logic? */
424         ok(pos >= sum, "Position %u gap %d\n", (UINT)pos, (UINT)pos - sum);
425         IAudioCaptureClient_ReleaseBuffer(acc, frames);
426     }
427 
428     IAudioCaptureClient_Release(acc);
429 }
430 
431 static void test_audioclient(void)
432 {
433     IAudioClient *ac;
434     IUnknown *unk;
435     HRESULT hr;
436     ULONG ref;
437     WAVEFORMATEX *pwfx, *pwfx2;
438     REFERENCE_TIME t1, t2;
439     HANDLE handle;
440 
441     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
442             NULL, (void**)&ac);
443     ok(hr == S_OK, "Activation failed with %08x\n", hr);
444     if(hr != S_OK)
445         return;
446 
447     handle = CreateEventW(NULL, FALSE, FALSE, NULL);
448 
449     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
450     ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
451 
452     unk = (void*)(LONG_PTR)0x12345678;
453     hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
454     ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
455     ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
456 
457     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
458     ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
459     if (unk)
460     {
461         ref = IUnknown_Release(unk);
462         ok(ref == 1, "Released count is %u\n", ref);
463     }
464 
465     hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
466     ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
467     if (unk)
468     {
469         ref = IUnknown_Release(unk);
470         ok(ref == 1, "Released count is %u\n", ref);
471     }
472 
473     hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
474     ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
475 
476     hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
477     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
478 
479     hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
480     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
481 
482     hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
483     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
484     trace("Returned periods: %u.%04u ms %u.%04u ms\n",
485           (UINT)(t1/10000), (UINT)(t1 % 10000),
486           (UINT)(t2/10000), (UINT)(t2 % 10000));
487 
488     hr = IAudioClient_GetMixFormat(ac, NULL);
489     ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
490 
491     hr = IAudioClient_GetMixFormat(ac, &pwfx);
492     ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
493 
494     if (hr == S_OK)
495     {
496         trace("pwfx: %p\n", pwfx);
497         trace("Tag: %04x\n", pwfx->wFormatTag);
498         trace("bits: %u\n", pwfx->wBitsPerSample);
499         trace("chan: %u\n", pwfx->nChannels);
500         trace("rate: %u\n", pwfx->nSamplesPerSec);
501         trace("align: %u\n", pwfx->nBlockAlign);
502         trace("extra: %u\n", pwfx->cbSize);
503         ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
504         if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
505         {
506             WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
507             trace("Res: %u\n", pwfxe->Samples.wReserved);
508             trace("Mask: %x\n", pwfxe->dwChannelMask);
509             trace("Alg: %s\n",
510                   IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
511                   (IsEqualGUID(&pwfxe->SubFormat,
512                                &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
513         }
514 
515         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
516         ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
517         ok(pwfx2 == NULL, "pwfx2 is non-null\n");
518         CoTaskMemFree(pwfx2);
519 
520         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
521         ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
522 
523         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
524         ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
525 
526         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
527         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
528 
529         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
530         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
531         ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
532 
533         hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
534         ok(hr == E_INVALIDARG/*w32*/ ||
535            broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT/*w64 response from exclusive mode driver */),
536            "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
537     }
538 
539     test_uninitialized(ac);
540 
541     hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
542     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
543 
544     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
545     ok(hr == E_INVALIDARG || hr == AUDCLNT_E_INVALID_STREAM_FLAG, "Initialize with invalid flags returns %08x\n", hr);
546 
547     /* A period != 0 is ignored and the call succeeds.
548      * Since we can only initialize successfully once, skip those tests.
549      */
550     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
551     ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
552 
553     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 4987654, 0, pwfx, NULL);
554     ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
555 
556     if (hr != S_OK)
557     {
558         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
559         goto cleanup;
560     }
561 
562     hr = IAudioClient_GetStreamLatency(ac, NULL);
563     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
564 
565     hr = IAudioClient_GetStreamLatency(ac, &t1);
566     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
567     trace("Returned latency: %u.%04u ms\n",
568           (UINT)(t1/10000), (UINT)(t1 % 10000));
569 
570     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
571     ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
572 
573     hr = IAudioClient_SetEventHandle(ac, NULL);
574     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
575 
576     hr = IAudioClient_Start(ac);
577     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET ||
578             hr == D3D11_ERROR_4E /* win10 */, "Start before SetEventHandle returns %08x\n", hr);
579 
580     hr = IAudioClient_SetEventHandle(ac, handle);
581     ok(hr == S_OK, "SetEventHandle returns %08x\n", hr);
582 
583     hr = IAudioClient_Reset(ac);
584     ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
585 
586     hr = IAudioClient_Stop(ac);
587     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
588 
589     hr = IAudioClient_Start(ac);
590     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
591 
592     test_capture(ac, handle, pwfx);
593 
594 cleanup:
595     IAudioClient_Release(ac);
596     CloseHandle(handle);
597     CoTaskMemFree(pwfx);
598 }
599 
600 static void test_streamvolume(void)
601 {
602     IAudioClient *ac;
603     IAudioStreamVolume *asv;
604     WAVEFORMATEX *fmt;
605     UINT32 chans, i;
606     HRESULT hr;
607     float vol, *vols;
608 
609     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
610             NULL, (void**)&ac);
611     ok(hr == S_OK, "Activation failed with %08x\n", hr);
612     if(hr != S_OK)
613         return;
614 
615     hr = IAudioClient_GetMixFormat(ac, &fmt);
616     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
617 
618     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
619             0, fmt, NULL);
620     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
621     if(hr != S_OK)
622         return;
623 
624     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
625     ok(hr == S_OK, "GetService failed: %08x\n", hr);
626 
627     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
628     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
629 
630     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
631     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
632     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
633 
634     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
635     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
636 
637     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
638     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
639 
640     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
641     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
642 
643     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
644     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
645     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
646 
647     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
648     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
649 
650     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
651     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
652 
653     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
654     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
655 
656     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
657     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
658 
659     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
660     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
661     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
662 
663     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
664     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
665 
666     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
667     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
668 
669     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
670     ok(vols != NULL, "HeapAlloc failed\n");
671 
672     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
673     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
674 
675     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
676     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
677     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
678     for(i = 1; i < fmt->nChannels; ++i)
679         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
680 
681     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
682     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
683 
684     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
685     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
686 
687     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
688     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
689 
690     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
691     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
692 
693     HeapFree(GetProcessHeap(), 0, vols);
694     IAudioStreamVolume_Release(asv);
695     IAudioClient_Release(ac);
696     CoTaskMemFree(fmt);
697 }
698 
699 static void test_channelvolume(void)
700 {
701     IAudioClient *ac;
702     IChannelAudioVolume *acv;
703     WAVEFORMATEX *fmt;
704     UINT32 chans, i;
705     HRESULT hr;
706     float vol, *vols;
707 
708     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
709             NULL, (void**)&ac);
710     ok(hr == S_OK, "Activation failed with %08x\n", hr);
711     if(hr != S_OK)
712         return;
713 
714     hr = IAudioClient_GetMixFormat(ac, &fmt);
715     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
716 
717     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
718             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
719     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
720 
721     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
722     ok(hr == S_OK, "GetService failed: %08x\n", hr);
723     if(hr != S_OK)
724         return;
725 
726     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
727     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
728 
729     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
730     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
731     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
732 
733     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
734     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
735 
736     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
737     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
738 
739     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
740     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
741 
742     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
743     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
744     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
745 
746     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
747     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
748 
749     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
750     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
751 
752     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
753     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
754 
755     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
756     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
757 
758     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
759     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
760     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
761 
762     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
763     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
764 
765     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
766     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
767 
768     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
769     ok(vols != NULL, "HeapAlloc failed\n");
770 
771     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
772     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
773 
774     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
775     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
776     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
777     for(i = 1; i < fmt->nChannels; ++i)
778         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
779 
780     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
781     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
782 
783     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
784     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
785 
786     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
787     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
788 
789     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
790     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
791 
792     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
793     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
794 
795     HeapFree(GetProcessHeap(), 0, vols);
796     IChannelAudioVolume_Release(acv);
797     IAudioClient_Release(ac);
798     CoTaskMemFree(fmt);
799 }
800 
801 static void test_simplevolume(void)
802 {
803     IAudioClient *ac;
804     ISimpleAudioVolume *sav;
805     WAVEFORMATEX *fmt;
806     HRESULT hr;
807     float vol;
808     BOOL mute;
809 
810     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
811             NULL, (void**)&ac);
812     ok(hr == S_OK, "Activation failed with %08x\n", hr);
813     if(hr != S_OK)
814         return;
815 
816     hr = IAudioClient_GetMixFormat(ac, &fmt);
817     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
818 
819     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
820             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
821     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
822 
823     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
824     ok(hr == S_OK, "GetService failed: %08x\n", hr);
825     if(hr != S_OK)
826         return;
827 
828     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
829     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
830 
831     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
832     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
833 
834     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
835     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
836 
837     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
838     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
839 
840     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
841     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
842 
843     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
844     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
845     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
846 
847     hr = ISimpleAudioVolume_GetMute(sav, NULL);
848     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
849 
850     mute = TRUE;
851     hr = ISimpleAudioVolume_GetMute(sav, &mute);
852     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
853     ok(mute == FALSE, "Session is already muted\n");
854 
855     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
856     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
857 
858     mute = FALSE;
859     hr = ISimpleAudioVolume_GetMute(sav, &mute);
860     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
861     ok(mute == TRUE, "Session should have been muted\n");
862 
863     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
864     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
865     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
866 
867     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
868     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
869 
870     mute = FALSE;
871     hr = ISimpleAudioVolume_GetMute(sav, &mute);
872     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
873     ok(mute == TRUE, "Session should have been muted\n");
874 
875     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
876     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
877 
878     ISimpleAudioVolume_Release(sav);
879     IAudioClient_Release(ac);
880     CoTaskMemFree(fmt);
881 }
882 
883 static void test_volume_dependence(void)
884 {
885     IAudioClient *ac, *ac2;
886     ISimpleAudioVolume *sav;
887     IChannelAudioVolume *cav;
888     IAudioStreamVolume *asv;
889     WAVEFORMATEX *fmt;
890     HRESULT hr;
891     float vol;
892     GUID session;
893     UINT32 nch;
894 
895     hr = CoCreateGuid(&session);
896     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
897 
898     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
899             NULL, (void**)&ac);
900     ok(hr == S_OK, "Activation failed with %08x\n", hr);
901     if(hr != S_OK)
902         return;
903 
904     hr = IAudioClient_GetMixFormat(ac, &fmt);
905     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
906 
907     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
908             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
909     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
910 
911     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
912     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
913 
914     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
915     ok(hr == S_OK, "GetService (ChannelAudioVolume) failed: %08x\n", hr);
916 
917     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
918     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
919     if(hr != S_OK)
920         return;
921 
922     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
923     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
924 
925     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
926     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
927 
928     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
929     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
930 
931     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
932     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
933     ok(fabsf(vol - 0.2f) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
934 
935     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
936     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
937     ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
938 
939     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
940     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
941     ok(fabsf(vol - 0.6f) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
942 
943     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
944             NULL, (void**)&ac2);
945     if(SUCCEEDED(hr)){
946         IChannelAudioVolume *cav2;
947         IAudioStreamVolume *asv2;
948 
949         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
950                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
951         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
952 
953         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
954         ok(hr == S_OK, "GetService failed: %08x\n", hr);
955 
956         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
957         ok(hr == S_OK, "GetService failed: %08x\n", hr);
958 
959         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
960         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
961         ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
962 
963         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
964         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
965         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
966 
967         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
968         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
969         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
970 
971         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
972         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
973         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
974 
975         IAudioStreamVolume_Release(asv2);
976         IChannelAudioVolume_Release(cav2);
977         IAudioClient_Release(ac2);
978     }else
979         skip("Unable to open the same device twice. Skipping session volume control tests\n");
980 
981     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
982     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
983 
984     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
985     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
986 
987     CoTaskMemFree(fmt);
988     ISimpleAudioVolume_Release(sav);
989     IChannelAudioVolume_Release(cav);
990     IAudioStreamVolume_Release(asv);
991     IAudioClient_Release(ac);
992 }
993 
994 static void test_marshal(void)
995 {
996     IStream *pStream;
997     IAudioClient *ac, *acDest;
998     IAudioCaptureClient *cc, *ccDest;
999     WAVEFORMATEX *pwfx;
1000     HRESULT hr;
1001 
1002     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1003             NULL, (void**)&ac);
1004     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1005     if(hr != S_OK)
1006         return;
1007 
1008     hr = IAudioClient_GetMixFormat(ac, &pwfx);
1009     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1010 
1011     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
1012             0, pwfx, NULL);
1013     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1014 
1015     CoTaskMemFree(pwfx);
1016 
1017     hr = IAudioClient_GetService(ac, &IID_IAudioCaptureClient, (void**)&cc);
1018     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1019     if(hr != S_OK) {
1020         IAudioClient_Release(ac);
1021         return;
1022     }
1023 
1024     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1025     ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x\n", hr);
1026 
1027     /* marshal IAudioClient */
1028 
1029     hr = CoMarshalInterface(pStream, &IID_IAudioClient, (IUnknown*)ac, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1030     ok(hr == S_OK, "CoMarshalInterface IAudioClient failed 0x%08x\n", hr);
1031 
1032     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1033     hr = CoUnmarshalInterface(pStream, &IID_IAudioClient, (void **)&acDest);
1034     ok(hr == S_OK, "CoUnmarshalInterface IAudioClient failed 0x%08x\n", hr);
1035     if (hr == S_OK)
1036         IAudioClient_Release(acDest);
1037 
1038     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1039     /* marshal IAudioCaptureClient */
1040 
1041     hr = CoMarshalInterface(pStream, &IID_IAudioCaptureClient, (IUnknown*)cc, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1042     ok(hr == S_OK, "CoMarshalInterface IAudioCaptureClient failed 0x%08x\n", hr);
1043 
1044     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1045     hr = CoUnmarshalInterface(pStream, &IID_IAudioCaptureClient, (void **)&ccDest);
1046     ok(hr == S_OK, "CoUnmarshalInterface IAudioCaptureClient failed 0x%08x\n", hr);
1047     if (hr == S_OK)
1048         IAudioCaptureClient_Release(ccDest);
1049 
1050     IStream_Release(pStream);
1051 
1052     IAudioClient_Release(ac);
1053     IAudioCaptureClient_Release(cc);
1054 
1055 }
1056 
1057 START_TEST(capture)
1058 {
1059     HRESULT hr;
1060     IMMDeviceEnumerator *mme = NULL;
1061 
1062     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1063     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1064     if (FAILED(hr))
1065     {
1066         skip("mmdevapi not available: 0x%08x\n", hr);
1067         goto cleanup;
1068     }
1069 
1070     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture, eMultimedia, &dev);
1071     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1072     if (hr != S_OK || !dev)
1073     {
1074         if (hr == E_NOTFOUND)
1075             skip("No sound card available\n");
1076         else
1077             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1078         goto cleanup;
1079     }
1080 
1081     test_audioclient();
1082     test_streamvolume();
1083     test_channelvolume();
1084     test_simplevolume();
1085     test_volume_dependence();
1086     test_marshal();
1087 
1088     IMMDevice_Release(dev);
1089 
1090 cleanup:
1091     if (mme)
1092         IMMDeviceEnumerator_Release(mme);
1093     CoUninitialize();
1094 }
1095