ReactOS  0.4.14-dev-323-g6fe6a88
capture.c
Go to the documentation of this file.
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 
48 {
49  HRESULT hr;
50  UINT32 num;
51  REFERENCE_TIME t1;
52 
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 
81 }
82 
84 {
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 
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){
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 
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",
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);
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);
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);
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);
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 
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;
1058 
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();
1083  test_marshal();
1084 
1085  IMMDevice_Release(dev);
1086 
1087 cleanup:
1088  if (mme)
1089  IMMDeviceEnumerator_Release(mme);
1090  CoUninitialize();
1091 }
HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
Definition: marshal.c:1981
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static void test_simplevolume(void)
Definition: capture.c:798
#define E_NOINTERFACE
Definition: winerror.h:2364
static void test_volume_dependence(void)
Definition: capture.c:880
static const LARGE_INTEGER ullZero
Definition: capture.c:45
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
HRESULT hr
Definition: shlfolder.c:183
union WAVEFORMATEXTENSIBLE::@2921 Samples
#define AUDCLNT_STREAMFLAGS_NOPERSIST
const char * fmt
Definition: wsprintf.c:30
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
static void test_audioclient(void)
Definition: capture.c:428
GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
Definition: send.c:47
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static void test_channelvolume(void)
Definition: capture.c:696
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int UINT32
#define NULL_PTR_ERR
Definition: capture.c:39
unsigned int BOOL
Definition: ntddk_ex.h:94
static void test_uninitialized(IAudioClient *ac)
Definition: capture.c:47
GLenum GLint ref
Definition: glext.h:6028
WORD wBitsPerSample
Definition: audioclient.idl:45
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
GUID KSDATAFORMAT_SUBTYPE_PCM
Definition: audio_test.c:26
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
DWORD nSamplesPerSec
Definition: audioclient.idl:42
#define todo_wine_if(is_todo)
Definition: test.h:155
GLfloat f
Definition: glext.h:7540
#define WAIT_OBJECT_0
Definition: winbase.h:387
#define GetProcessHeap()
Definition: compat.h:395
#define trace
Definition: atltest.h:70
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint num
Definition: glext.h:9618
static void test_marshal(void)
Definition: capture.c:991
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
HRESULT WINAPI CoCreateGuid(GUID *pguid)
Definition: compobj.c:2206
static IMMDeviceEnumerator * mme
Definition: render.c:63
#define IID_NULL
Definition: guiddef.h:98
#define todo_wine
Definition: test.h:154
unsigned char BYTE
Definition: mem.h:68
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define broken(x)
Definition: _sntprintf.h:21
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
uint32_t cc
Definition: isohybrid.c:75
#define S_OK
Definition: intsafe.h:59
static unsigned __int64 next
Definition: rand_nt.c:6
static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx)
Definition: capture.c:83
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define ok(value,...)
Definition: atltest.h:57
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
int nch
Definition: scanf.h:135
#define skip(...)
Definition: atltest.h:64
#define AUDCLNT_STREAMFLAGS_EVENTCALLBACK
#define D3D11_ERROR_4E
Definition: capture.c:42
unsigned int ULONG
Definition: retypes.h:1
_Check_return_ __CRT_INLINE float __CRTDECL fabsf(_In_ float x)
Definition: math.h:164
char * cleanup(char *str)
Definition: wpickclick.c:99
unsigned long long UINT64
HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags)
Definition: marshal.c:1876
#define E_POINTER
Definition: winerror.h:2365
Definition: dsound.c:943
#define HeapFree(x, y, z)
Definition: compat.h:394
#define MulDiv(x, y, z)
Definition: gdifloat.h:86
START_TEST(capture)
Definition: capture.c:749
static void test_streamvolume(void)
Definition: capture.c:597
#define WAVE_FORMAT_EXTENSIBLE
Definition: ksmedia.h:551
#define SUCCEEDED(hr)
Definition: intsafe.h:57
Definition: tftpd.h:137