2 * Copyright 2010 Maarten Lankhorst for CodeWeavers
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.
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.
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
19 /* This test is for audio capture specific mechanisms
21 * - IAudioClient with eCapture and IAudioCaptureClient
26 #include "wine/test.h"
36 #include "mmdeviceapi.h"
37 #include "audioclient.h"
39 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
41 /* undocumented error code */
42 #define D3D11_ERROR_4E MAKE_HRESULT(SEVERITY_ERROR, FACILITY_DIRECT3D11, 0x4e)
44 static IMMDevice
*dev
= NULL
;
45 static const LARGE_INTEGER ullZero
;
47 static void test_uninitialized(IAudioClient
*ac
)
53 HANDLE handle
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
56 hr
= IAudioClient_GetBufferSize(ac
, &num
);
57 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized GetBufferSize call returns %08x\n", hr
);
59 hr
= IAudioClient_GetStreamLatency(ac
, &t1
);
60 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized GetStreamLatency call returns %08x\n", hr
);
62 hr
= IAudioClient_GetCurrentPadding(ac
, &num
);
63 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized GetCurrentPadding call returns %08x\n", hr
);
65 hr
= IAudioClient_Start(ac
);
66 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized Start call returns %08x\n", hr
);
68 hr
= IAudioClient_Stop(ac
);
69 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized Stop call returns %08x\n", hr
);
71 hr
= IAudioClient_Reset(ac
);
72 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized Reset call returns %08x\n", hr
);
74 hr
= IAudioClient_SetEventHandle(ac
, handle
);
75 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized SetEventHandle call returns %08x\n", hr
);
77 hr
= IAudioClient_GetService(ac
, &IID_IAudioStreamVolume
, (void**)&unk
);
78 ok(hr
== AUDCLNT_E_NOT_INITIALIZED
, "Uninitialized GetService call returns %08x\n", hr
);
83 static void test_capture(IAudioClient
*ac
, HANDLE handle
, WAVEFORMATEX
*wfx
)
85 IAudioCaptureClient
*acc
;
87 UINT32 frames
, next
, pad
, sum
= 0;
91 REFERENCE_TIME period
;
93 hr
= IAudioClient_GetService(ac
, &IID_IAudioCaptureClient
, (void**)&acc
);
94 ok(hr
== S_OK
, "IAudioClient_GetService(IID_IAudioCaptureClient) returns %08x\n", hr
);
99 data
= (void*)0xdeadf00d;
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
);
105 /* should be empty right after start. Otherwise consume one packet */
107 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
108 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
112 data
= (void*)0xdeadf00d;
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
);
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
);
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
);
133 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
134 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
137 ok(ResetEvent(handle
), "ResetEvent\n");
139 hr
= IAudioCaptureClient_GetNextPacketSize(acc
, &next
);
140 ok(hr
== S_OK
, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr
);
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 */
147 hr
= IAudioCaptureClient_GetNextPacketSize(acc
, NULL
);
148 ok(hr
== E_POINTER
, "IAudioCaptureClient_GetNextPacketSize(NULL) returns %08x\n", hr
);
150 data
= (void*)0xdeadf00d;
153 hr
= IAudioCaptureClient_GetBuffer(acc
, &data
, NULL
, NULL
, NULL
, NULL
);
154 ok(hr
== E_POINTER
, "IAudioCaptureClient_GetBuffer(data, NULL, NULL) returns %08x\n", hr
);
156 hr
= IAudioCaptureClient_GetBuffer(acc
, NULL
, &frames
, NULL
, NULL
, NULL
);
157 ok(hr
== E_POINTER
, "IAudioCaptureClient_GetBuffer(NULL, &frames, NULL) returns %08x\n", hr
);
159 hr
= IAudioCaptureClient_GetBuffer(acc
, NULL
, NULL
, &flags
, NULL
, NULL
);
160 ok(hr
== E_POINTER
, "IAudioCaptureClient_GetBuffer(NULL, NULL, &flags) returns %08x\n", hr
);
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
);
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 */
172 ok(WaitForSingleObject(handle
, 1000) == WAIT_OBJECT_0
, "Waiting on event handle failed!\n");
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
);
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
);
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
);
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
);
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
);
196 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
197 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
199 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, 0);
200 ok(hr
== S_OK
, "Releasing 0 returns %08x\n", hr
);
202 hr
= IAudioCaptureClient_GetNextPacketSize(acc
, &next
);
203 ok(hr
== S_OK
, "IAudioCaptureClient_GetNextPacketSize returns %08x\n", hr
);
206 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
207 ok(hr
== AUDCLNT_E_OUT_OF_ORDER
, "Releasing buffer twice returns %08x\n", hr
);
211 Sleep(350); /* for sure there's data now */
213 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
214 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
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
);
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
);
228 UINT32 frames2
= frames
;
230 ok(frames
, "Amount of frames locked is 0!\n");
231 ok(pos
== sum
, "Position %u expected %u\n", (UINT
)pos
, sum
);
233 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, 0);
234 ok(hr
== S_OK
, "Releasing 0 returns %08x\n", hr
);
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
);
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
);
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
);
257 UINT32 frames2
= 0xabadcafe;
258 BYTE
*data2
= (void*)0xdeadf00d;
261 ok(pos
== sum
, "Position %u expected %u\n", (UINT
)pos
, sum
);
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
);
272 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
+1);
273 ok(hr
== AUDCLNT_E_INVALID_SIZE
, "Releasing buffer+1 returns %08x\n", hr
);
275 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, 1);
276 ok(hr
== AUDCLNT_E_INVALID_SIZE
, "Releasing 1 returns %08x\n", hr
);
278 hr
= IAudioClient_Reset(ac
);
279 ok(hr
== AUDCLNT_E_NOT_STOPPED
, "Reset failed: %08x\n", hr
);
282 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
283 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
287 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
288 ok(hr
== AUDCLNT_E_OUT_OF_ORDER
, "Releasing buffer twice returns %08x\n", hr
);
292 ok(next
== frames
, "GetNextPacketSize %u vs. GetDevicePeriod %u\n", next
, frames
);
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
);
299 Sleep(400); /* overrun */
301 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
302 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
304 hr
= IAudioCaptureClient_GetBuffer(acc
, &data
, &frames
, &flags
, &pos
, &qpc
);
305 ok(hr
== S_OK
, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr
);
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
);
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
);
321 ok(pad
== next
, "GCP %u vs. BufferSize %u\n", (UINT32
)pad
, next
);
323 if(flags
& AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
)
327 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
328 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
331 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
332 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
334 hr
= IAudioCaptureClient_GetBuffer(acc
, &data
, &frames
, &flags
, &pos
, &qpc
);
335 ok(hr
== S_OK
, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr
);
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
);
341 ok(pos
== sum
, "Position %u expected %u\n", (UINT
)pos
, sum
);
342 ok(!flags
, "flags %u\n", flags
);
344 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
345 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
349 hr
= IAudioClient_Stop(ac
);
350 ok(hr
== S_OK
, "Stop on a started stream returns %08x\n", hr
);
352 hr
= IAudioClient_Start(ac
);
353 ok(hr
== S_OK
, "Start on a stopped stream returns %08x\n", hr
);
355 hr
= IAudioCaptureClient_GetBuffer(acc
, &data
, &frames
, &flags
, &pos
, &qpc
);
356 ok(hr
== S_OK
, "Valid IAudioCaptureClient_GetBuffer returns %08x\n", hr
);
358 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
359 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
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 */
366 ok(pos
== sum
, "Position %u expected %u\n", (UINT
)pos
, sum
);
367 ok(!flags
, "flags %u\n", flags
);
369 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
370 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
374 hr
= IAudioClient_Stop(ac
);
375 ok(hr
== S_OK
, "Stop on a started stream returns %08x\n", hr
);
377 hr
= IAudioClient_Reset(ac
);
378 ok(hr
== S_OK
, "Reset on a stopped stream returns %08x\n", hr
);
381 hr
= IAudioClient_Start(ac
);
382 ok(hr
== S_OK
, "Start on a stopped stream returns %08x\n", hr
);
384 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
385 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
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
);
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
);
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 */
404 hr
= IAudioCaptureClient_ReleaseBuffer(acc
, frames
);
405 ok(hr
== S_OK
, "Releasing buffer returns %08x\n", hr
);
408 else if(hr
== AUDCLNT_S_BUFFER_EMPTY
){
409 ok(!pad
, "reset GCP %u\n", pad
);
413 hr
= IAudioClient_GetCurrentPadding(ac
, &pad
);
414 ok(hr
== S_OK
, "GetCurrentPadding call returns %08x\n", hr
);
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
);
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
);
428 IAudioCaptureClient_Release(acc
);
431 static void test_audioclient(void)
437 WAVEFORMATEX
*pwfx
, *pwfx2
;
438 REFERENCE_TIME t1
, t2
;
441 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
443 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
447 handle
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
449 hr
= IAudioClient_QueryInterface(ac
, &IID_IUnknown
, NULL
);
450 ok(hr
== E_POINTER
, "QueryInterface(NULL) returned %08x\n", hr
);
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
);
457 hr
= IAudioClient_QueryInterface(ac
, &IID_IUnknown
, (void**)&unk
);
458 ok(hr
== S_OK
, "QueryInterface(IID_IUnknown) returned %08x\n", hr
);
461 ref
= IUnknown_Release(unk
);
462 ok(ref
== 1, "Released count is %u\n", ref
);
465 hr
= IAudioClient_QueryInterface(ac
, &IID_IAudioClient
, (void**)&unk
);
466 ok(hr
== S_OK
, "QueryInterface(IID_IAudioClient) returned %08x\n", hr
);
469 ref
= IUnknown_Release(unk
);
470 ok(ref
== 1, "Released count is %u\n", ref
);
473 hr
= IAudioClient_GetDevicePeriod(ac
, NULL
, NULL
);
474 ok(hr
== E_POINTER
, "Invalid GetDevicePeriod call returns %08x\n", hr
);
476 hr
= IAudioClient_GetDevicePeriod(ac
, &t1
, NULL
);
477 ok(hr
== S_OK
, "Valid GetDevicePeriod call returns %08x\n", hr
);
479 hr
= IAudioClient_GetDevicePeriod(ac
, NULL
, &t2
);
480 ok(hr
== S_OK
, "Valid GetDevicePeriod call returns %08x\n", hr
);
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));
488 hr
= IAudioClient_GetMixFormat(ac
, NULL
);
489 ok(hr
== E_POINTER
, "GetMixFormat returns %08x\n", hr
);
491 hr
= IAudioClient_GetMixFormat(ac
, &pwfx
);
492 ok(hr
== S_OK
, "Valid GetMixFormat returns %08x\n", hr
);
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
)
506 WAVEFORMATEXTENSIBLE
*pwfxe
= (void*)pwfx
;
507 trace("Res: %u\n", pwfxe
->Samples
.wReserved
);
508 trace("Mask: %x\n", pwfxe
->dwChannelMask
);
510 IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)?"PCM":
511 (IsEqualGUID(&pwfxe
->SubFormat
,
512 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)?"FLOAT":"Other"));
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
);
520 hr
= IAudioClient_IsFormatSupported(ac
, AUDCLNT_SHAREMODE_SHARED
, NULL
, NULL
);
521 ok(hr
== E_POINTER
, "IsFormatSupported(NULL) call returns %08x\n", hr
);
523 hr
= IAudioClient_IsFormatSupported(ac
, AUDCLNT_SHAREMODE_SHARED
, pwfx
, NULL
);
524 ok(hr
== E_POINTER
, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr
);
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
);
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");
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
);
539 test_uninitialized(ac
);
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
);
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
);
547 /* A period != 0 is ignored and the call succeeds.
548 * Since we can only initialize successfully once, skip those tests.
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
);
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
);
558 skip("Cannot initialize %08x, remainder of tests is useless\n", hr
);
563 hr
= IAudioClient_GetStreamLatency(ac
, NULL
);
564 ok(hr
== E_POINTER
, "GetStreamLatency(NULL) call returns %08x\n", hr
);
566 hr
= IAudioClient_GetStreamLatency(ac
, &t1
);
567 ok(hr
== S_OK
, "Valid GetStreamLatency call returns %08x\n", hr
);
568 trace("Returned latency: %u.%04u ms\n",
569 (UINT
)(t1
/10000), (UINT
)(t1
% 10000));
571 hr
= IAudioClient_Initialize(ac
, AUDCLNT_SHAREMODE_SHARED
, 0, 5000000, 0, pwfx
, NULL
);
572 ok(hr
== AUDCLNT_E_ALREADY_INITIALIZED
, "Calling Initialize twice returns %08x\n", hr
);
574 hr
= IAudioClient_SetEventHandle(ac
, NULL
);
575 ok(hr
== E_INVALIDARG
, "SetEventHandle(NULL) returns %08x\n", hr
);
577 hr
= IAudioClient_Start(ac
);
578 ok(hr
== AUDCLNT_E_EVENTHANDLE_NOT_SET
||
579 hr
== D3D11_ERROR_4E
/* win10 */, "Start before SetEventHandle returns %08x\n", hr
);
581 hr
= IAudioClient_SetEventHandle(ac
, handle
);
582 ok(hr
== S_OK
, "SetEventHandle returns %08x\n", hr
);
584 hr
= IAudioClient_Reset(ac
);
585 ok(hr
== S_OK
, "Reset on an already reset stream returns %08x\n", hr
);
587 hr
= IAudioClient_Stop(ac
);
588 ok(hr
== S_FALSE
, "Stop on a stopped stream returns %08x\n", hr
);
590 hr
= IAudioClient_Start(ac
);
591 ok(hr
== S_OK
, "Start on a stopped stream returns %08x\n", hr
);
593 test_capture(ac
, handle
, pwfx
);
595 IAudioClient_Release(ac
);
600 static void test_streamvolume(void)
603 IAudioStreamVolume
*asv
;
609 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
611 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
615 hr
= IAudioClient_GetMixFormat(ac
, &fmt
);
616 ok(hr
== S_OK
, "GetMixFormat failed: %08x\n", hr
);
618 hr
= IAudioClient_Initialize(ac
, AUDCLNT_SHAREMODE_SHARED
, 0, 5000000,
620 ok(hr
== S_OK
, "Initialize failed: %08x\n", hr
);
624 hr
= IAudioClient_GetService(ac
, &IID_IAudioStreamVolume
, (void**)&asv
);
625 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
627 hr
= IAudioStreamVolume_GetChannelCount(asv
, NULL
);
628 ok(hr
== E_POINTER
, "GetChannelCount gave wrong error: %08x\n", hr
);
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
);
634 hr
= IAudioStreamVolume_GetChannelVolume(asv
, fmt
->nChannels
, NULL
);
635 ok(hr
== E_POINTER
, "GetChannelCount gave wrong error: %08x\n", hr
);
637 hr
= IAudioStreamVolume_GetChannelVolume(asv
, fmt
->nChannels
, &vol
);
638 ok(hr
== E_INVALIDARG
, "GetChannelCount gave wrong error: %08x\n", hr
);
640 hr
= IAudioStreamVolume_GetChannelVolume(asv
, 0, NULL
);
641 ok(hr
== E_POINTER
, "GetChannelCount gave wrong error: %08x\n", hr
);
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
);
647 hr
= IAudioStreamVolume_SetChannelVolume(asv
, fmt
->nChannels
, -1.f
);
648 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
650 hr
= IAudioStreamVolume_SetChannelVolume(asv
, 0, -1.f
);
651 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
653 hr
= IAudioStreamVolume_SetChannelVolume(asv
, 0, 2.f
);
654 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
656 hr
= IAudioStreamVolume_SetChannelVolume(asv
, 0, 0.2f
);
657 ok(hr
== S_OK
, "SetChannelVolume failed: %08x\n", hr
);
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
);
663 hr
= IAudioStreamVolume_GetAllVolumes(asv
, 0, NULL
);
664 ok(hr
== E_POINTER
, "GetAllVolumes gave wrong error: %08x\n", hr
);
666 hr
= IAudioStreamVolume_GetAllVolumes(asv
, fmt
->nChannels
, NULL
);
667 ok(hr
== E_POINTER
, "GetAllVolumes gave wrong error: %08x\n", hr
);
669 vols
= HeapAlloc(GetProcessHeap(), 0, fmt
->nChannels
* sizeof(float));
670 ok(vols
!= NULL
, "HeapAlloc failed\n");
672 hr
= IAudioStreamVolume_GetAllVolumes(asv
, fmt
->nChannels
- 1, vols
);
673 ok(hr
== E_INVALIDARG
, "GetAllVolumes gave wrong error: %08x\n", hr
);
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
]);
681 hr
= IAudioStreamVolume_SetAllVolumes(asv
, 0, NULL
);
682 ok(hr
== E_POINTER
, "SetAllVolumes gave wrong error: %08x\n", hr
);
684 hr
= IAudioStreamVolume_SetAllVolumes(asv
, fmt
->nChannels
, NULL
);
685 ok(hr
== E_POINTER
, "SetAllVolumes gave wrong error: %08x\n", hr
);
687 hr
= IAudioStreamVolume_SetAllVolumes(asv
, fmt
->nChannels
- 1, vols
);
688 ok(hr
== E_INVALIDARG
, "SetAllVolumes gave wrong error: %08x\n", hr
);
690 hr
= IAudioStreamVolume_SetAllVolumes(asv
, fmt
->nChannels
, vols
);
691 ok(hr
== S_OK
, "SetAllVolumes failed: %08x\n", hr
);
693 HeapFree(GetProcessHeap(), 0, vols
);
694 IAudioStreamVolume_Release(asv
);
695 IAudioClient_Release(ac
);
699 static void test_channelvolume(void)
702 IChannelAudioVolume
*acv
;
708 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
710 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
714 hr
= IAudioClient_GetMixFormat(ac
, &fmt
);
715 ok(hr
== S_OK
, "GetMixFormat failed: %08x\n", hr
);
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
);
721 hr
= IAudioClient_GetService(ac
, &IID_IChannelAudioVolume
, (void**)&acv
);
722 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
726 hr
= IChannelAudioVolume_GetChannelCount(acv
, NULL
);
727 ok(hr
== NULL_PTR_ERR
, "GetChannelCount gave wrong error: %08x\n", hr
);
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
);
733 hr
= IChannelAudioVolume_GetChannelVolume(acv
, fmt
->nChannels
, NULL
);
734 ok(hr
== NULL_PTR_ERR
, "GetChannelCount gave wrong error: %08x\n", hr
);
736 hr
= IChannelAudioVolume_GetChannelVolume(acv
, fmt
->nChannels
, &vol
);
737 ok(hr
== E_INVALIDARG
, "GetChannelCount gave wrong error: %08x\n", hr
);
739 hr
= IChannelAudioVolume_GetChannelVolume(acv
, 0, NULL
);
740 ok(hr
== NULL_PTR_ERR
, "GetChannelCount gave wrong error: %08x\n", hr
);
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
);
746 hr
= IChannelAudioVolume_SetChannelVolume(acv
, fmt
->nChannels
, -1.f
, NULL
);
747 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
749 hr
= IChannelAudioVolume_SetChannelVolume(acv
, 0, -1.f
, NULL
);
750 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
752 hr
= IChannelAudioVolume_SetChannelVolume(acv
, 0, 2.f
, NULL
);
753 ok(hr
== E_INVALIDARG
, "SetChannelVolume gave wrong error: %08x\n", hr
);
755 hr
= IChannelAudioVolume_SetChannelVolume(acv
, 0, 0.2f
, NULL
);
756 ok(hr
== S_OK
, "SetChannelVolume failed: %08x\n", hr
);
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
);
762 hr
= IChannelAudioVolume_GetAllVolumes(acv
, 0, NULL
);
763 ok(hr
== NULL_PTR_ERR
, "GetAllVolumes gave wrong error: %08x\n", hr
);
765 hr
= IChannelAudioVolume_GetAllVolumes(acv
, fmt
->nChannels
, NULL
);
766 ok(hr
== NULL_PTR_ERR
, "GetAllVolumes gave wrong error: %08x\n", hr
);
768 vols
= HeapAlloc(GetProcessHeap(), 0, fmt
->nChannels
* sizeof(float));
769 ok(vols
!= NULL
, "HeapAlloc failed\n");
771 hr
= IChannelAudioVolume_GetAllVolumes(acv
, fmt
->nChannels
- 1, vols
);
772 ok(hr
== E_INVALIDARG
, "GetAllVolumes gave wrong error: %08x\n", hr
);
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
]);
780 hr
= IChannelAudioVolume_SetAllVolumes(acv
, 0, NULL
, NULL
);
781 ok(hr
== NULL_PTR_ERR
, "SetAllVolumes gave wrong error: %08x\n", hr
);
783 hr
= IChannelAudioVolume_SetAllVolumes(acv
, fmt
->nChannels
, NULL
, NULL
);
784 ok(hr
== NULL_PTR_ERR
, "SetAllVolumes gave wrong error: %08x\n", hr
);
786 hr
= IChannelAudioVolume_SetAllVolumes(acv
, fmt
->nChannels
- 1, vols
, NULL
);
787 ok(hr
== E_INVALIDARG
, "SetAllVolumes gave wrong error: %08x\n", hr
);
789 hr
= IChannelAudioVolume_SetAllVolumes(acv
, fmt
->nChannels
, vols
, NULL
);
790 ok(hr
== S_OK
, "SetAllVolumes failed: %08x\n", hr
);
792 hr
= IChannelAudioVolume_SetChannelVolume(acv
, 0, 1.0f
, NULL
);
793 ok(hr
== S_OK
, "SetChannelVolume failed: %08x\n", hr
);
795 HeapFree(GetProcessHeap(), 0, vols
);
796 IChannelAudioVolume_Release(acv
);
797 IAudioClient_Release(ac
);
801 static void test_simplevolume(void)
804 ISimpleAudioVolume
*sav
;
810 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
812 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
816 hr
= IAudioClient_GetMixFormat(ac
, &fmt
);
817 ok(hr
== S_OK
, "GetMixFormat failed: %08x\n", hr
);
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
);
823 hr
= IAudioClient_GetService(ac
, &IID_ISimpleAudioVolume
, (void**)&sav
);
824 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
828 hr
= ISimpleAudioVolume_GetMasterVolume(sav
, NULL
);
829 ok(hr
== NULL_PTR_ERR
, "GetMasterVolume gave wrong error: %08x\n", hr
);
831 hr
= ISimpleAudioVolume_GetMasterVolume(sav
, &vol
);
832 ok(hr
== S_OK
, "GetMasterVolume failed: %08x\n", hr
);
834 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, -1.f
, NULL
);
835 ok(hr
== E_INVALIDARG
, "SetMasterVolume gave wrong error: %08x\n", hr
);
837 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, 2.f
, NULL
);
838 ok(hr
== E_INVALIDARG
, "SetMasterVolume gave wrong error: %08x\n", hr
);
840 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, 0.2f
, NULL
);
841 ok(hr
== S_OK
, "SetMasterVolume failed: %08x\n", hr
);
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
);
847 hr
= ISimpleAudioVolume_GetMute(sav
, NULL
);
848 ok(hr
== NULL_PTR_ERR
, "GetMute gave wrong error: %08x\n", hr
);
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");
855 hr
= ISimpleAudioVolume_SetMute(sav
, TRUE
, NULL
);
856 ok(hr
== S_OK
, "SetMute failed: %08x\n", hr
);
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");
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
);
867 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, 1.f
, NULL
);
868 ok(hr
== S_OK
, "SetMasterVolume failed: %08x\n", hr
);
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");
875 hr
= ISimpleAudioVolume_SetMute(sav
, FALSE
, NULL
);
876 ok(hr
== S_OK
, "SetMute failed: %08x\n", hr
);
878 ISimpleAudioVolume_Release(sav
);
879 IAudioClient_Release(ac
);
883 static void test_volume_dependence(void)
885 IAudioClient
*ac
, *ac2
;
886 ISimpleAudioVolume
*sav
;
887 IChannelAudioVolume
*cav
;
888 IAudioStreamVolume
*asv
;
895 hr
= CoCreateGuid(&session
);
896 ok(hr
== S_OK
, "CoCreateGuid failed: %08x\n", hr
);
898 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
900 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
904 hr
= IAudioClient_GetMixFormat(ac
, &fmt
);
905 ok(hr
== S_OK
, "GetMixFormat failed: %08x\n", hr
);
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
);
911 hr
= IAudioClient_GetService(ac
, &IID_ISimpleAudioVolume
, (void**)&sav
);
912 ok(hr
== S_OK
, "GetService (SimpleAudioVolume) failed: %08x\n", hr
);
914 hr
= IAudioClient_GetService(ac
, &IID_IChannelAudioVolume
, (void**)&cav
);
915 ok(hr
== S_OK
, "GetService (ChannelAudioVolume) failed: %08x\n", hr
);
917 hr
= IAudioClient_GetService(ac
, &IID_IAudioStreamVolume
, (void**)&asv
);
918 ok(hr
== S_OK
, "GetService (AudioStreamVolume) failed: %08x\n", hr
);
922 hr
= IAudioStreamVolume_SetChannelVolume(asv
, 0, 0.2f
);
923 ok(hr
== S_OK
, "ASV_SetChannelVolume failed: %08x\n", hr
);
925 hr
= IChannelAudioVolume_SetChannelVolume(cav
, 0, 0.4f
, NULL
);
926 ok(hr
== S_OK
, "CAV_SetChannelVolume failed: %08x\n", hr
);
928 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, 0.6f
, NULL
);
929 ok(hr
== S_OK
, "SAV_SetMasterVolume failed: %08x\n", hr
);
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
);
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
);
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
);
943 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
946 IChannelAudioVolume
*cav2
;
947 IAudioStreamVolume
*asv2
;
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
);
953 hr
= IAudioClient_GetService(ac2
, &IID_IChannelAudioVolume
, (void**)&cav2
);
954 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
956 hr
= IAudioClient_GetService(ac2
, &IID_IAudioStreamVolume
, (void**)&asv2
);
957 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
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
);
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
);
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
);
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
);
975 IAudioStreamVolume_Release(asv2
);
976 IChannelAudioVolume_Release(cav2
);
977 IAudioClient_Release(ac2
);
979 skip("Unable to open the same device twice. Skipping session volume control tests\n");
981 hr
= IChannelAudioVolume_SetChannelVolume(cav
, 0, 1.f
, NULL
);
982 ok(hr
== S_OK
, "CAV_SetChannelVolume failed: %08x\n", hr
);
984 hr
= ISimpleAudioVolume_SetMasterVolume(sav
, 1.f
, NULL
);
985 ok(hr
== S_OK
, "SAV_SetMasterVolume failed: %08x\n", hr
);
988 ISimpleAudioVolume_Release(sav
);
989 IChannelAudioVolume_Release(cav
);
990 IAudioStreamVolume_Release(asv
);
991 IAudioClient_Release(ac
);
994 static void test_marshal(void)
997 IAudioClient
*ac
, *acDest
;
998 IAudioCaptureClient
*cc
, *ccDest
;
1002 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
1004 ok(hr
== S_OK
, "Activation failed with %08x\n", hr
);
1008 hr
= IAudioClient_GetMixFormat(ac
, &pwfx
);
1009 ok(hr
== S_OK
, "GetMixFormat failed: %08x\n", hr
);
1011 hr
= IAudioClient_Initialize(ac
, AUDCLNT_SHAREMODE_SHARED
, 0, 5000000,
1013 ok(hr
== S_OK
, "Initialize failed: %08x\n", hr
);
1015 CoTaskMemFree(pwfx
);
1017 hr
= IAudioClient_GetService(ac
, &IID_IAudioCaptureClient
, (void**)&cc
);
1018 ok(hr
== S_OK
, "GetService failed: %08x\n", hr
);
1020 IAudioClient_Release(ac
);
1024 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1025 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed 0x%08x\n", hr
);
1027 /* marshal IAudioClient */
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
);
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
);
1036 IAudioClient_Release(acDest
);
1038 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1039 /* marshal IAudioCaptureClient */
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
);
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
);
1048 IAudioCaptureClient_Release(ccDest
);
1050 IStream_Release(pStream
);
1052 IAudioClient_Release(ac
);
1053 IAudioCaptureClient_Release(cc
);
1060 IMMDeviceEnumerator
*mme
= NULL
;
1062 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1063 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme
);
1066 skip("mmdevapi not available: 0x%08x\n", hr
);
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
)
1074 if (hr
== E_NOTFOUND
)
1075 skip("No sound card available\n");
1077 skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr
);
1082 test_streamvolume();
1083 test_channelvolume();
1084 test_simplevolume();
1085 test_volume_dependence();
1088 IMMDevice_Release(dev
);
1092 IMMDeviceEnumerator_Release(mme
);