mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / mmdevapi / tests / render.c
blob495c1c6f496f73e7e9b2ba31735b66fd03690a22
1 /*
2 * Copyright 2010 Maarten Lankhorst for CodeWeavers
3 * 2011-2012 Jörg Höhle
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* This test is for audio playback specific mechanisms
21 * Tests:
22 * - IAudioClient with eRender and IAudioRenderClient
25 #include <math.h>
26 #include <stdio.h>
28 #include "wine/test.h"
30 #define COBJMACROS
32 #ifdef STANDALONE
33 #include "initguid.h"
34 #endif
36 #include "unknwn.h"
37 #include "uuids.h"
38 #include "mmdeviceapi.h"
39 #include "mmsystem.h"
40 #include "audioclient.h"
41 #include "audiopolicy.h"
42 #include "endpointvolume.h"
44 static const unsigned int win_formats[][4] = {
45 { 8000, 8, 1}, { 8000, 8, 2}, { 8000, 16, 1}, { 8000, 16, 2},
46 {11025, 8, 1}, {11025, 8, 2}, {11025, 16, 1}, {11025, 16, 2},
47 {12000, 8, 1}, {12000, 8, 2}, {12000, 16, 1}, {12000, 16, 2},
48 {16000, 8, 1}, {16000, 8, 2}, {16000, 16, 1}, {16000, 16, 2},
49 {22050, 8, 1}, {22050, 8, 2}, {22050, 16, 1}, {22050, 16, 2},
50 {44100, 8, 1}, {44100, 8, 2}, {44100, 16, 1}, {44100, 16, 2},
51 {48000, 8, 1}, {48000, 8, 2}, {48000, 16, 1}, {48000, 16, 2},
52 {96000, 8, 1}, {96000, 8, 2}, {96000, 16, 1}, {96000, 16, 2}
55 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
57 /* undocumented error code */
58 #define D3D11_ERROR_4E MAKE_HRESULT(SEVERITY_ERROR, FACILITY_DIRECT3D11, 0x4e)
60 static IMMDeviceEnumerator *mme = NULL;
61 static IMMDevice *dev = NULL;
62 static HRESULT hexcl = S_OK; /* or AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED */
63 static BOOL win10 = FALSE;
65 static const LARGE_INTEGER ullZero;
67 #define PI 3.14159265358979323846L
68 static DWORD wave_generate_tone(PWAVEFORMATEX pwfx, BYTE* data, UINT32 frames)
70 static double phase = 0.; /* normalized to unit, not 2*PI */
71 PWAVEFORMATEXTENSIBLE wfxe = (PWAVEFORMATEXTENSIBLE)pwfx;
72 DWORD cn, i;
73 double delta, y;
75 if(!winetest_interactive)
76 return AUDCLNT_BUFFERFLAGS_SILENT;
77 if(wfxe->Format.wBitsPerSample != ((wfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
78 IsEqualGUID(&wfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) ? 8 * sizeof(float) : 16))
79 return AUDCLNT_BUFFERFLAGS_SILENT;
81 for(delta = phase, cn = 0; cn < wfxe->Format.nChannels;
82 delta += .5/wfxe->Format.nChannels, cn++){
83 for(i = 0; i < frames; i++){
84 y = sin(2*PI*(440.* i / wfxe->Format.nSamplesPerSec + delta));
85 /* assume alignment is granted */
86 if(wfxe->Format.wBitsPerSample == 16)
87 ((short*)data)[cn+i*wfxe->Format.nChannels] = y * 32767.9;
88 else
89 ((float*)data)[cn+i*wfxe->Format.nChannels] = y;
92 phase += 440.* frames / wfxe->Format.nSamplesPerSec;
93 phase -= floor(phase);
94 return 0;
97 static void test_uninitialized(IAudioClient *ac)
99 HRESULT hr;
100 UINT32 num;
101 REFERENCE_TIME t1;
103 HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
104 IUnknown *unk;
106 hr = IAudioClient_GetBufferSize(ac, &num);
107 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
109 hr = IAudioClient_GetStreamLatency(ac, &t1);
110 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
112 hr = IAudioClient_GetCurrentPadding(ac, &num);
113 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
115 hr = IAudioClient_Start(ac);
116 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
118 hr = IAudioClient_Stop(ac);
119 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
121 hr = IAudioClient_Reset(ac);
122 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
124 hr = IAudioClient_SetEventHandle(ac, handle);
125 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
127 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
128 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
130 CloseHandle(handle);
133 static void test_audioclient(void)
135 IAudioClient *ac;
136 IAudioClient2 *ac2;
137 IAudioClient3 *ac3;
138 IUnknown *unk;
139 HRESULT hr;
140 ULONG ref;
141 WAVEFORMATEX *pwfx, *pwfx2;
142 REFERENCE_TIME t1, t2;
143 HANDLE handle;
144 BOOL offload_capable;
145 AudioClientProperties client_props;
147 hr = IMMDevice_Activate(dev, &IID_IAudioClient3, CLSCTX_INPROC_SERVER,
148 NULL, (void**)&ac3);
149 ok(hr == S_OK ||
150 broken(hr == E_NOINTERFACE) /* win8 */,
151 "IAudioClient3 Activation failed with %08x\n", hr);
152 if(hr == S_OK)
153 IAudioClient3_Release(ac3);
155 hr = IMMDevice_Activate(dev, &IID_IAudioClient2, CLSCTX_INPROC_SERVER,
156 NULL, (void**)&ac2);
157 ok(hr == S_OK ||
158 broken(hr == E_NOINTERFACE) /* win7 */,
159 "IAudioClient2 Activation failed with %08x\n", hr);
160 if(hr == S_OK)
161 IAudioClient2_Release(ac2);
163 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
164 NULL, (void**)&ac);
165 ok(hr == S_OK, "Activation failed with %08x\n", hr);
166 if(hr != S_OK)
167 return;
169 handle = CreateEventW(NULL, FALSE, FALSE, NULL);
171 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
172 ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
174 unk = (void*)(LONG_PTR)0x12345678;
175 hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
176 ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
177 ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
179 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
180 ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
181 if (unk)
183 ref = IUnknown_Release(unk);
184 ok(ref == 1, "Released count is %u\n", ref);
187 hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
188 ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
189 if (unk)
191 ref = IUnknown_Release(unk);
192 ok(ref == 1, "Released count is %u\n", ref);
195 hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
196 ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
198 hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
199 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
201 hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
202 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
204 hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
205 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
206 trace("Returned periods: %u.%04u ms %u.%04u ms\n",
207 (UINT)(t1/10000), (UINT)(t1 % 10000),
208 (UINT)(t2/10000), (UINT)(t2 % 10000));
210 hr = IAudioClient_GetMixFormat(ac, NULL);
211 ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
213 hr = IAudioClient_GetMixFormat(ac, &pwfx);
214 ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
216 if (hr == S_OK)
218 trace("pwfx: %p\n", pwfx);
219 trace("Tag: %04x\n", pwfx->wFormatTag);
220 trace("bits: %u\n", pwfx->wBitsPerSample);
221 trace("chan: %u\n", pwfx->nChannels);
222 trace("rate: %u\n", pwfx->nSamplesPerSec);
223 trace("align: %u\n", pwfx->nBlockAlign);
224 trace("extra: %u\n", pwfx->cbSize);
225 ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
226 if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
228 WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
229 trace("Res: %u\n", pwfxe->Samples.wReserved);
230 trace("Mask: %x\n", pwfxe->dwChannelMask);
231 trace("Alg: %s\n",
232 IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
233 (IsEqualGUID(&pwfxe->SubFormat,
234 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
237 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
238 ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
239 ok(pwfx2 == NULL, "pwfx2 is non-null\n");
240 CoTaskMemFree(pwfx2);
242 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
243 ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
245 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
246 ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
248 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
249 ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED,
250 "IsFormatSupported(Exclusive) call returns %08x\n", hr);
251 hexcl = hr;
253 pwfx2 = (WAVEFORMATEX*)0xDEADF00D;
254 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
255 ok(hr == hexcl, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
256 ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
258 if (hexcl != AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
259 hexcl = S_OK;
261 hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
262 ok(hr == E_INVALIDARG/*w32*/ ||
263 broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT/*w64 response from exclusive mode driver */),
264 "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
267 hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient2, (void**)&ac2);
268 if (hr == S_OK)
270 hr = IAudioClient2_IsOffloadCapable(ac2, AudioCategory_BackgroundCapableMedia, NULL);
271 ok(hr == E_INVALIDARG, "IsOffloadCapable gave wrong error: %08x\n", hr);
273 hr = IAudioClient2_IsOffloadCapable(ac2, AudioCategory_BackgroundCapableMedia, &offload_capable);
274 ok(hr == S_OK, "IsOffloadCapable failed: %08x\n", hr);
276 hr = IAudioClient2_SetClientProperties(ac2, NULL);
277 ok(hr == E_POINTER, "SetClientProperties with NULL props gave wrong error: %08x\n", hr);
279 /* invalid cbSize */
280 client_props.cbSize = 0;
281 client_props.bIsOffload = FALSE;
282 client_props.eCategory = AudioCategory_BackgroundCapableMedia;
283 client_props.Options = 0;
285 hr = IAudioClient2_SetClientProperties(ac2, &client_props);
286 ok(hr == E_INVALIDARG, "SetClientProperties with invalid cbSize gave wrong error: %08x\n", hr);
288 /* offload consistency */
289 client_props.cbSize = sizeof(client_props) - sizeof(client_props.Options);
290 client_props.bIsOffload = TRUE;
292 hr = IAudioClient2_SetClientProperties(ac2, &client_props);
293 if(!offload_capable)
294 ok(hr == AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE, "SetClientProperties(offload) gave wrong error: %08x\n", hr);
295 else
296 ok(hr == S_OK, "SetClientProperties(offload) failed: %08x\n", hr);
298 /* disable offload */
299 client_props.bIsOffload = FALSE;
300 hr = IAudioClient2_SetClientProperties(ac2, &client_props);
301 ok(hr == S_OK, "SetClientProperties failed: %08x\n", hr);
303 /* Options field added in Win 8.1 */
304 client_props.cbSize = sizeof(client_props);
305 hr = IAudioClient2_SetClientProperties(ac2, &client_props);
306 ok(hr == S_OK ||
307 broken(hr == E_INVALIDARG) /* <= win8 */,
308 "SetClientProperties failed: %08x\n", hr);
310 IAudioClient2_Release(ac2);
312 else
313 win_skip("IAudioClient2 is not present on Win <= 7\n");
315 hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient3, (void**)&ac3);
316 ok(hr == S_OK ||
317 broken(hr == E_NOINTERFACE) /* win8 */,
318 "Failed to query IAudioClient3 interface: %08x\n", hr);
320 if(hr == S_OK)
321 IAudioClient3_Release(ac3);
323 test_uninitialized(ac);
325 hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
326 ok(broken(hr == AUDCLNT_E_NOT_INITIALIZED) || /* <= win8 */
327 hr == E_INVALIDARG, "Initialize with invalid sharemode returns %08x\n", hr);
329 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
330 ok(hr == E_INVALIDARG ||
331 hr == AUDCLNT_E_INVALID_STREAM_FLAG, "Initialize with invalid flags returns %08x\n", hr);
333 /* A period != 0 is ignored and the call succeeds.
334 * Since we can only initialize successfully once, skip those tests.
336 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
337 ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
339 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, pwfx, NULL);
340 ok(hr == S_OK, "Initialize with 0 buffer size returns %08x\n", hr);
341 if(hr == S_OK){
342 UINT32 num;
344 hr = IAudioClient_GetBufferSize(ac, &num);
345 ok(hr == S_OK, "GetBufferSize from duration 0 returns %08x\n", hr);
346 if(hr == S_OK)
347 trace("Initialize(duration=0) GetBufferSize is %u\n", num);
350 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
351 ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
353 hr = IAudioClient_Start(ac);
354 ok(hr == S_OK ||
355 broken(hr == AUDCLNT_E_DEVICE_INVALIDATED), /* Win10 >= 1607 */
356 "Start on a doubly initialized stream returns %08x\n", hr);
358 IAudioClient_Release(ac);
360 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
361 NULL, (void**)&ac);
362 ok(hr == S_OK, "Activation failed with %08x\n", hr);
364 if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
365 WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)pwfx;
366 WAVEFORMATEX *fmt2 = NULL;
368 ok(fmtex->dwChannelMask != 0, "Got empty dwChannelMask\n");
370 fmtex->dwChannelMask = 0xffff;
372 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
373 ok(hr == S_OK ||
374 hr == AUDCLNT_E_UNSUPPORTED_FORMAT /* win10 */, "Initialize(dwChannelMask = 0xffff) returns %08x\n", hr);
376 IAudioClient_Release(ac);
378 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
379 NULL, (void**)&ac);
380 ok(hr == S_OK, "Activation failed with %08x\n", hr);
382 fmtex->dwChannelMask = 0;
384 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &fmt2);
385 ok(hr == S_OK || broken(hr == S_FALSE /* w7 Realtek HDA */),
386 "IsFormatSupported(dwChannelMask = 0) call returns %08x\n", hr);
387 ok(fmtex->dwChannelMask == 0, "Passed format was modified\n");
389 CoTaskMemFree(fmt2);
391 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
392 ok(hr == S_OK, "Initialize(dwChannelMask = 0) returns %08x\n", hr);
394 IAudioClient_Release(ac);
396 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
397 NULL, (void**)&ac);
398 ok(hr == S_OK, "Activation failed with %08x\n", hr);
400 CoTaskMemFree(pwfx);
402 hr = IAudioClient_GetMixFormat(ac, &pwfx);
403 ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
404 }else
405 skip("Skipping dwChannelMask tests\n");
407 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
408 ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
409 if (hr != S_OK)
410 goto cleanup;
412 hr = IAudioClient_GetStreamLatency(ac, NULL);
413 ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
415 hr = IAudioClient_GetStreamLatency(ac, &t2);
416 ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
417 trace("Returned latency: %u.%04u ms\n",
418 (UINT)(t2/10000), (UINT)(t2 % 10000));
419 ok(t2 >= t1 || broken(t2 >= t1/2 && pwfx->nSamplesPerSec > 48000) ||
420 broken(t2 == 0) /* (!) win10 */,
421 "Latency < default period, delta %dus (%s vs %s)\n",
422 (LONG)((t2-t1)/10), wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t1));
423 /* Native appears to add the engine period to the HW latency in shared mode */
424 if(t2 == 0)
425 win10 = TRUE;
427 hr = IAudioClient_SetEventHandle(ac, NULL);
428 ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
430 hr = IAudioClient_SetEventHandle(ac, handle);
431 ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
432 broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
433 broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
434 broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
435 , "SetEventHandle returns %08x\n", hr);
437 hr = IAudioClient_Reset(ac);
438 ok(hr == S_OK, "Reset on an initialized stream returns %08x\n", hr);
440 hr = IAudioClient_Reset(ac);
441 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
443 hr = IAudioClient_Stop(ac);
444 ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
446 hr = IAudioClient_Start(ac);
447 ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
449 hr = IAudioClient_Start(ac);
450 ok(hr == AUDCLNT_E_NOT_STOPPED, "Start twice returns %08x\n", hr);
452 cleanup:
453 IAudioClient_Release(ac);
454 CloseHandle(handle);
455 CoTaskMemFree(pwfx);
458 static void test_formats(AUDCLNT_SHAREMODE mode)
460 IAudioClient *ac;
461 HRESULT hr, hrs;
462 WAVEFORMATEX fmt, *pwfx, *pwfx2;
463 int i;
465 fmt.wFormatTag = WAVE_FORMAT_PCM;
466 fmt.cbSize = 0;
468 for(i = 0; i < ARRAY_SIZE(win_formats); i++) {
469 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
470 NULL, (void**)&ac);
471 ok(hr == S_OK, "Activation failed with %08x\n", hr);
472 if(hr != S_OK)
473 continue;
475 hr = IAudioClient_GetMixFormat(ac, &pwfx);
476 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
478 fmt.nSamplesPerSec = win_formats[i][0];
479 fmt.wBitsPerSample = win_formats[i][1];
480 fmt.nChannels = win_formats[i][2];
481 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
482 fmt.nAvgBytesPerSec= fmt.nBlockAlign * fmt.nSamplesPerSec;
484 pwfx2 = (WAVEFORMATEX*)0xDEADF00D;
485 hr = IAudioClient_IsFormatSupported(ac, mode, &fmt, &pwfx2);
486 hrs = hr;
487 /* Only shared mode suggests something ... GetMixFormat! */
488 ok(hr == S_OK || (mode == AUDCLNT_SHAREMODE_SHARED
489 ? hr == S_FALSE || broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT &&
490 /* 5:1 card exception when asked for 1 channel at mixer rate */
491 pwfx->nChannels > 2 && fmt.nSamplesPerSec == pwfx->nSamplesPerSec)
492 : (hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == hexcl)),
493 "IsFormatSupported(%d, %ux%2ux%u) returns %08x\n", mode,
494 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
495 if (hr == S_OK)
496 trace("IsSupported(%s, %ux%2ux%u)\n",
497 mode == AUDCLNT_SHAREMODE_SHARED ? "shared " : "exclus.",
498 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels);
500 /* Change GetMixFormat wBitsPerSample only => S_OK */
501 if (mode == AUDCLNT_SHAREMODE_SHARED
502 && fmt.nSamplesPerSec == pwfx->nSamplesPerSec
503 && fmt.nChannels == pwfx->nChannels)
504 ok(hr == S_OK, "Varying BitsPerSample %u\n", fmt.wBitsPerSample);
506 ok((hr == S_FALSE)^(pwfx2 == NULL), "hr %x<->suggest %p\n", hr, pwfx2);
507 if (pwfx2 == (WAVEFORMATEX*)0xDEADF00D)
508 pwfx2 = NULL; /* broken in Wine < 1.3.28 */
509 if (pwfx2) {
510 ok(pwfx2->nSamplesPerSec == pwfx->nSamplesPerSec &&
511 pwfx2->nChannels == pwfx->nChannels &&
512 pwfx2->wBitsPerSample == pwfx->wBitsPerSample,
513 "Suggestion %ux%2ux%u differs from GetMixFormat\n",
514 pwfx2->nSamplesPerSec, pwfx2->wBitsPerSample, pwfx2->nChannels);
517 /* Vista returns E_INVALIDARG upon AUDCLNT_STREAMFLAGS_RATEADJUST */
518 hr = IAudioClient_Initialize(ac, mode, 0, 5000000, 0, &fmt, NULL);
519 if ((hrs == S_OK) ^ (hr == S_OK))
520 trace("Initialize (%s, %ux%2ux%u) returns %08x unlike IsFormatSupported\n",
521 mode == AUDCLNT_SHAREMODE_SHARED ? "shared " : "exclus.",
522 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
523 if (mode == AUDCLNT_SHAREMODE_SHARED)
524 ok(hrs == S_OK ? hr == S_OK : hr == AUDCLNT_E_UNSUPPORTED_FORMAT,
525 "Initialize(shared, %ux%2ux%u) returns %08x\n",
526 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
527 else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
528 /* Unsupported format implies "create failed" and shadows "not allowed" */
529 ok(hrs == hexcl && (hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == hrs),
530 "Initialize(noexcl., %ux%2ux%u) returns %08x(%08x)\n",
531 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr, hrs);
532 else
533 /* On testbot 48000x16x1 claims support, but does not Initialize.
534 * Some cards Initialize 44100|48000x16x1 yet claim no support;
535 * F. Gouget's w7 bots do that for 12000|96000x8|16x1|2 */
536 ok(hrs == S_OK ? hr == S_OK || broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED)
537 : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT ||
538 broken(hr == S_OK &&
539 ((fmt.nChannels == 1 && fmt.wBitsPerSample == 16) ||
540 (fmt.nSamplesPerSec == 12000 || fmt.nSamplesPerSec == 96000))),
541 "Initialize(exclus., %ux%2ux%u) returns %08x\n",
542 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
544 /* Bug in native (Vista/w2k8/w7): after Initialize failed, better
545 * Release this ac and Activate a new one.
546 * A second call (with a known working format) would yield
547 * ALREADY_INITIALIZED in shared mode yet be unusable, and in exclusive
548 * mode some entity keeps a lock on the device, causing DEVICE_IN_USE to
549 * all subsequent calls until the audio engine service is restarted. */
551 CoTaskMemFree(pwfx2);
552 CoTaskMemFree(pwfx);
553 IAudioClient_Release(ac);
557 static void test_references(void)
559 IAudioClient *ac;
560 IAudioRenderClient *rc;
561 ISimpleAudioVolume *sav;
562 IAudioStreamVolume *asv;
563 IAudioClock *acl;
564 WAVEFORMATEX *pwfx;
565 HRESULT hr;
566 ULONG ref;
568 /* IAudioRenderClient */
569 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
570 NULL, (void**)&ac);
571 ok(hr == S_OK, "Activation failed with %08x\n", hr);
572 if(hr != S_OK)
573 return;
575 hr = IAudioClient_GetMixFormat(ac, &pwfx);
576 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
578 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
579 0, pwfx, NULL);
580 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
582 CoTaskMemFree(pwfx);
584 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
585 ok(hr == S_OK, "GetService failed: %08x\n", hr);
586 if(hr != S_OK) {
587 IAudioClient_Release(ac);
588 return;
591 IAudioRenderClient_AddRef(rc);
592 ref = IAudioRenderClient_Release(rc);
593 ok(ref != 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
595 ref = IAudioClient_Release(ac);
596 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
598 ref = IAudioRenderClient_Release(rc);
599 ok(ref == 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
601 /* ISimpleAudioVolume */
602 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
603 NULL, (void**)&ac);
604 ok(hr == S_OK, "Activation failed with %08x\n", hr);
605 if(hr != S_OK)
606 return;
608 hr = IAudioClient_GetMixFormat(ac, &pwfx);
609 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
611 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
612 0, pwfx, NULL);
613 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
615 CoTaskMemFree(pwfx);
617 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
618 ok(hr == S_OK, "GetService failed: %08x\n", hr);
620 ISimpleAudioVolume_AddRef(sav);
621 ref = ISimpleAudioVolume_Release(sav);
622 ok(ref != 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
624 ref = IAudioClient_Release(ac);
625 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
627 ref = ISimpleAudioVolume_Release(sav);
628 ok(ref == 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
630 /* IAudioClock */
631 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
632 NULL, (void**)&ac);
633 ok(hr == S_OK, "Activation failed with %08x\n", hr);
634 if(hr != S_OK)
635 return;
637 hr = IAudioClient_GetMixFormat(ac, &pwfx);
638 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
640 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
641 0, pwfx, NULL);
642 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
644 CoTaskMemFree(pwfx);
646 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
647 ok(hr == S_OK, "GetService failed: %08x\n", hr);
649 IAudioClock_AddRef(acl);
650 ref = IAudioClock_Release(acl);
651 ok(ref != 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
653 ref = IAudioClient_Release(ac);
654 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
656 ref = IAudioClock_Release(acl);
657 ok(ref == 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
659 /* IAudioStreamVolume */
660 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
661 NULL, (void**)&ac);
662 ok(hr == S_OK, "Activation failed with %08x\n", hr);
663 if(hr != S_OK)
664 return;
666 hr = IAudioClient_GetMixFormat(ac, &pwfx);
667 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
669 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
670 0, pwfx, NULL);
671 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
673 CoTaskMemFree(pwfx);
675 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
676 ok(hr == S_OK, "GetService failed: %08x\n", hr);
678 IAudioStreamVolume_AddRef(asv);
679 ref = IAudioStreamVolume_Release(asv);
680 ok(ref != 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
682 ref = IAudioClient_Release(ac);
683 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
685 ref = IAudioStreamVolume_Release(asv);
686 ok(ref == 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
689 static void test_event(void)
691 HANDLE event;
692 HRESULT hr;
693 DWORD r;
694 IAudioClient *ac;
695 WAVEFORMATEX *pwfx;
697 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
698 NULL, (void**)&ac);
699 ok(hr == S_OK, "Activation failed with %08x\n", hr);
700 if(hr != S_OK)
701 return;
703 hr = IAudioClient_GetMixFormat(ac, &pwfx);
704 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
706 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
707 AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
708 0, pwfx, NULL);
709 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
711 CoTaskMemFree(pwfx);
713 event = CreateEventW(NULL, FALSE, FALSE, NULL);
714 ok(event != NULL, "CreateEvent failed\n");
716 hr = IAudioClient_Start(ac);
717 ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET ||
718 hr == D3D11_ERROR_4E /* win10 */, "Start failed: %08x\n", hr);
720 hr = IAudioClient_SetEventHandle(ac, event);
721 ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
723 hr = IAudioClient_SetEventHandle(ac, event);
724 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME) ||
725 hr == E_UNEXPECTED /* win10 */, "SetEventHandle returns %08x\n", hr);
727 r = WaitForSingleObject(event, 40);
728 ok(r == WAIT_TIMEOUT, "Wait(event) before Start gave %x\n", r);
730 hr = IAudioClient_Start(ac);
731 ok(hr == S_OK, "Start failed: %08x\n", hr);
733 r = WaitForSingleObject(event, 20);
734 ok(r == WAIT_OBJECT_0, "Wait(event) after Start gave %x\n", r);
736 hr = IAudioClient_Stop(ac);
737 ok(hr == S_OK, "Stop failed: %08x\n", hr);
739 ok(ResetEvent(event), "ResetEvent\n");
741 /* Still receiving events! */
742 r = WaitForSingleObject(event, 20);
743 ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r);
745 hr = IAudioClient_Reset(ac);
746 ok(hr == S_OK, "Reset failed: %08x\n", hr);
748 ok(ResetEvent(event), "ResetEvent\n");
750 r = WaitForSingleObject(event, 120);
751 ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r);
753 hr = IAudioClient_SetEventHandle(ac, NULL);
754 ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
756 r = WaitForSingleObject(event, 70);
757 ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r);
759 /* test releasing a playing stream */
760 hr = IAudioClient_Start(ac);
761 ok(hr == S_OK, "Start failed: %08x\n", hr);
762 IAudioClient_Release(ac);
764 CloseHandle(event);
767 static void test_padding(void)
769 HRESULT hr;
770 IAudioClient *ac;
771 IAudioRenderClient *arc;
772 WAVEFORMATEX *pwfx;
773 REFERENCE_TIME minp, defp;
774 BYTE *buf, silence;
775 UINT32 psize, pad, written, i;
777 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
778 NULL, (void**)&ac);
779 ok(hr == S_OK, "Activation failed with %08x\n", hr);
780 if(hr != S_OK)
781 return;
783 hr = IAudioClient_GetMixFormat(ac, &pwfx);
784 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
785 if(hr != S_OK)
786 return;
788 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
789 0, 5000000, 0, pwfx, NULL);
790 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
791 if(hr != S_OK)
792 return;
794 if(pwfx->wBitsPerSample == 8)
795 silence = 128;
796 else
797 silence = 0;
799 /** GetDevicePeriod
800 * Default (= shared) device period is 10ms (e.g. 441 frames at 44100),
801 * except when the HW/OS forces a particular alignment,
802 * e.g. 10.1587ms is 28 * 16 = 448 frames at 44100 with HDA.
803 * 441 observed with Vista, 448 with w7 on the same HW! */
804 hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
805 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
806 /* some wineXYZ.drv use 20ms, not seen on native */
807 ok(defp == 100000 || broken(defp == 101587) || defp == 200000,
808 "Expected 10ms default period: %u\n", (ULONG)defp);
809 ok(minp != 0, "Minimum period is 0\n");
810 ok(minp <= defp, "Minimum period is greater than default period\n");
812 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
813 ok(hr == S_OK, "GetService failed: %08x\n", hr);
815 psize = MulDiv(defp, pwfx->nSamplesPerSec, 10000000) * 10;
817 written = 0;
818 hr = IAudioClient_GetCurrentPadding(ac, &pad);
819 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
820 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
822 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
823 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
824 ok(buf != NULL, "NULL buffer returned\n");
825 if(!win10){
826 /* win10 appears not to clear the buffer */
827 for(i = 0; i < psize * pwfx->nBlockAlign; ++i){
828 if(buf[i] != silence){
829 ok(0, "buffer has data in it already, i: %u, value: %f\n", i, *((float*)buf));
830 break;
835 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
836 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "GetBuffer 0 size failed: %08x\n", hr);
837 ok(buf == NULL, "GetBuffer 0 gave %p\n", buf);
838 /* MSDN instead documents buf remains untouched */
840 hr = IAudioClient_Reset(ac);
841 ok(hr == AUDCLNT_E_BUFFER_OPERATION_PENDING, "Reset failed: %08x\n", hr);
843 hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
844 AUDCLNT_BUFFERFLAGS_SILENT);
845 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
846 if(hr == S_OK) written += psize;
848 hr = IAudioClient_GetCurrentPadding(ac, &pad);
849 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
850 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
852 psize = MulDiv(minp, pwfx->nSamplesPerSec, 10000000) * 10;
854 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
855 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
856 ok(buf != NULL, "NULL buffer returned\n");
858 hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
859 AUDCLNT_BUFFERFLAGS_SILENT);
860 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
861 written += psize;
863 hr = IAudioClient_GetCurrentPadding(ac, &pad);
864 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
865 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
867 /* overfull buffer. requested 1/2s buffer size, so try
868 * to get a 1/2s buffer, which should fail */
869 psize = pwfx->nSamplesPerSec / 2;
870 buf = (void*)0xDEADF00D;
871 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
872 ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
873 ok(buf == NULL, "NULL expected %p\n", buf);
875 hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
876 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
878 psize = MulDiv(minp, pwfx->nSamplesPerSec, 10000000) * 2;
880 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
881 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
882 ok(buf != NULL, "NULL buffer returned\n");
884 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
885 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
887 buf = (void*)0xDEADF00D;
888 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
889 ok(hr == S_OK, "GetBuffer 0 size failed: %08x\n", hr);
890 ok(buf == NULL, "GetBuffer 0 gave %p\n", buf);
891 /* MSDN instead documents buf remains untouched */
893 buf = (void*)0xDEADF00D;
894 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
895 ok(hr == S_OK, "GetBuffer 0 size #2 failed: %08x\n", hr);
896 ok(buf == NULL, "GetBuffer 0 #2 gave %p\n", buf);
898 hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
899 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer not size 0 gave %08x\n", hr);
901 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
902 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
903 ok(buf != NULL, "NULL buffer returned\n");
905 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
906 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
908 hr = IAudioClient_GetCurrentPadding(ac, &pad);
909 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
910 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
912 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
913 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
914 ok(buf != NULL, "NULL buffer returned\n");
916 hr = IAudioRenderClient_ReleaseBuffer(arc, psize+1, AUDCLNT_BUFFERFLAGS_SILENT);
917 ok(hr == AUDCLNT_E_INVALID_SIZE, "ReleaseBuffer too large error: %08x\n", hr);
918 /* todo_wine means Wine may overwrite memory */
919 if(hr == S_OK) written += psize+1;
921 /* Buffer still hold */
922 hr = IAudioRenderClient_ReleaseBuffer(arc, psize/2, AUDCLNT_BUFFERFLAGS_SILENT);
923 ok(hr == S_OK, "ReleaseBuffer after error: %08x\n", hr);
924 if(hr == S_OK) written += psize/2;
926 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
927 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
929 hr = IAudioClient_GetCurrentPadding(ac, &pad);
930 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
931 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
933 CoTaskMemFree(pwfx);
935 IAudioRenderClient_Release(arc);
936 IAudioClient_Release(ac);
939 static void test_clock(int share)
941 HRESULT hr;
942 IAudioClient *ac;
943 IAudioClock *acl;
944 IAudioRenderClient *arc;
945 UINT64 freq, pos, pcpos0, pcpos, last;
946 UINT32 pad, gbsize, bufsize, fragment, parts, avail, slept = 0, sum = 0;
947 BYTE *data;
948 WAVEFORMATEX *pwfx;
949 LARGE_INTEGER hpctime, hpctime0, hpcfreq;
950 REFERENCE_TIME minp, defp, t1, t2;
951 REFERENCE_TIME duration = 5000000, period = 150000;
952 int i;
954 ok(QueryPerformanceFrequency(&hpcfreq), "PerfFrequency failed\n");
956 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
957 NULL, (void**)&ac);
958 ok(hr == S_OK, "Activation failed with %08x\n", hr);
959 if(hr != S_OK)
960 return;
962 hr = IAudioClient_GetMixFormat(ac, &pwfx);
963 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
964 if(hr != S_OK)
965 return;
967 hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
968 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
969 ok(minp <= period, "desired period %u too small for %u\n", (ULONG)period, (ULONG)minp);
971 if (share) {
972 trace("Testing shared mode\n");
973 /* period is ignored */
974 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
975 0, duration, period, pwfx, NULL);
976 period = defp;
977 } else {
978 pwfx->wFormatTag = WAVE_FORMAT_PCM;
979 pwfx->nChannels = 2;
980 pwfx->cbSize = 0;
981 pwfx->wBitsPerSample = 16; /* no floating point */
982 pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
983 pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
984 trace("Testing exclusive mode at %u\n", pwfx->nSamplesPerSec);
986 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_EXCLUSIVE,
987 0, duration, period, pwfx, NULL);
989 ok(share ? hr == S_OK : hr == hexcl || hr == AUDCLNT_E_DEVICE_IN_USE, "Initialize failed: %08x\n", hr);
990 if (hr != S_OK) {
991 CoTaskMemFree(pwfx);
992 IAudioClient_Release(ac);
993 if(hr == AUDCLNT_E_DEVICE_IN_USE)
994 skip("Device in use, no %s access\n", share ? "shared" : "exclusive");
995 return;
998 /** GetStreamLatency
999 * Shared mode: 1x period + a little, but some 192000 devices return 5.3334ms.
1000 * Exclusive mode: testbot returns 2x period + a little, but
1001 * some HDA drivers return 1x period, some + a little. */
1002 hr = IAudioClient_GetStreamLatency(ac, &t2);
1003 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1004 trace("Latency: %u.%04u ms\n", (UINT)(t2/10000), (UINT)(t2 % 10000));
1005 ok(t2 >= period || broken(t2 >= period/2 && share && pwfx->nSamplesPerSec > 48000) ||
1006 broken(t2 == 0) /* win10 */,
1007 "Latency < default period, delta %ldus\n", (long)((t2-period)/10));
1009 /** GetBufferSize
1010 * BufferSize must be rounded up, maximum 2s says MSDN.
1011 * Both is wrong. Rounding may lead to size a little smaller than duration;
1012 * duration > 2s is accepted in shared mode.
1013 * Shared mode: round solely w.r.t. mixer rate,
1014 * duration is no multiple of period.
1015 * Exclusive mode: size appears as a multiple of some fragment that
1016 * is either the rounded period or a fixed constant like 1024,
1017 * whatever the driver implements. */
1018 hr = IAudioClient_GetBufferSize(ac, &gbsize);
1019 ok(hr == S_OK, "GetBufferSize failed: %08x\n", hr);
1021 bufsize = MulDiv(duration, pwfx->nSamplesPerSec, 10000000);
1022 fragment = MulDiv(period, pwfx->nSamplesPerSec, 10000000);
1023 parts = MulDiv(bufsize, 1, fragment); /* instead of (duration, 1, period) */
1024 trace("BufferSize %u estimated fragment %u x %u = %u\n", gbsize, fragment, parts, fragment * parts);
1025 /* fragment size (= period in frames) is rounded up.
1026 * BufferSize must be rounded up, maximum 2s says MSDN
1027 * but it is rounded down modulo fragment ! */
1028 if (share)
1029 ok(gbsize == bufsize,
1030 "BufferSize %u at rate %u\n", gbsize, pwfx->nSamplesPerSec);
1031 else
1032 ok(gbsize == parts * fragment || gbsize == MulDiv(bufsize, 1, 1024) * 1024,
1033 "BufferSize %u misfits fragment size %u at rate %u\n", gbsize, fragment, pwfx->nSamplesPerSec);
1035 /* In shared mode, GetCurrentPadding decreases in multiples of
1036 * fragment size (i.e. updated only at period ticks), whereas
1037 * GetPosition appears to be reporting continuous positions.
1038 * In exclusive mode, testbot behaves likewise, but native's Intel
1039 * HDA driver shows no such deltas, GetCurrentPadding closely
1040 * matches GetPosition, as in
1041 * GetCurrentPadding = GetPosition - frames held in mmdevapi */
1043 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
1044 ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
1046 hr = IAudioClock_GetFrequency(acl, &freq);
1047 ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
1048 trace("Clock Frequency %u\n", (UINT)freq);
1050 /* MSDN says it's arbitrary units, but shared mode is unlikely to change */
1051 if (share)
1052 ok(freq == pwfx->nSamplesPerSec * pwfx->nBlockAlign,
1053 "Clock Frequency %u\n", (UINT)freq);
1054 else
1055 ok(freq == pwfx->nSamplesPerSec,
1056 "Clock Frequency %u\n", (UINT)freq);
1058 hr = IAudioClock_GetPosition(acl, NULL, NULL);
1059 ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
1061 pcpos0 = 0;
1062 hr = IAudioClock_GetPosition(acl, &pos, &pcpos0);
1063 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1064 ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
1065 ok(pcpos0 != 0, "GetPosition returned zero pcpos\n");
1067 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
1068 ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
1070 hr = IAudioRenderClient_GetBuffer(arc, gbsize+1, &data);
1071 ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer too large failed: %08x\n", hr);
1073 avail = gbsize;
1074 data = NULL;
1075 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1076 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
1077 trace("data at %p\n", data);
1079 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, winetest_debug>2 ?
1080 wave_generate_tone(pwfx, data, avail) : AUDCLNT_BUFFERFLAGS_SILENT);
1081 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
1082 if(hr == S_OK) sum += avail;
1084 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1085 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1086 ok(pad == sum, "padding %u prior to start\n", pad);
1088 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1089 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1090 ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
1092 hr = IAudioClient_Start(ac); /* #1 */
1093 ok(hr == S_OK, "Start failed: %08x\n", hr);
1095 Sleep(100);
1096 slept += 100;
1098 hr = IAudioClient_GetStreamLatency(ac, &t1);
1099 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1100 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1102 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1103 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1104 ok(pos > 0, "Position %u vs. last %u\n", (UINT)pos,0);
1105 /* in rare cases is slept*1.1 not enough with dmix */
1106 ok(pos*1000/freq <= slept*1.4, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1107 last = pos;
1109 hr = IAudioClient_Stop(ac);
1110 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1112 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1113 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1114 ok(pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1115 last = pos;
1116 if(/*share &&*/ winetest_debug>1)
1117 ok(pos*1000/freq <= slept*1.1, "Position %u too far after stop %ums\n", (UINT)pos, slept);
1119 hr = IAudioClient_Start(ac); /* #2 */
1120 ok(hr == S_OK, "Start failed: %08x\n", hr);
1122 Sleep(100);
1123 slept += 100;
1125 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1126 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1127 trace("padding %u past sleep #2\n", pad);
1129 /** IAudioClient_Stop
1130 * Exclusive mode: the audio engine appears to drop frames,
1131 * bumping GetPosition to a higher value than time allows, even
1132 * allowing GetPosition > sum Released - GetCurrentPadding (testbot)
1133 * Shared mode: no drop observed (or too small to be visible).
1134 * GetPosition = sum Released - GetCurrentPadding
1135 * Bugs: Some USB headset system drained the whole buffer, leaving
1136 * padding 0 and bumping pos to sum minus 17 frames! */
1138 hr = IAudioClient_Stop(ac);
1139 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1141 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1142 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1144 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1145 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1146 trace("padding %u position %u past stop #2\n", pad, (UINT)pos);
1147 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1148 /* Prove that Stop must not drop frames (in shared mode). */
1149 ok(pad ? pos > last : pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1150 if (share && pad > 0 && winetest_debug>1)
1151 ok(pos*1000/freq <= slept*1.1, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1152 /* in exclusive mode, testbot's w7 machines yield pos > sum-pad */
1153 if(/*share &&*/ winetest_debug>1)
1154 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
1155 "Position %u after stop vs. %u padding\n", (UINT)pos, pad);
1156 last = pos;
1158 Sleep(100);
1160 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1161 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1162 ok(pos == last, "Position %u should stop.\n", (UINT)pos);
1164 /* Restart from 0 */
1165 hr = IAudioClient_Reset(ac);
1166 ok(hr == S_OK, "Reset failed: %08x\n", hr);
1167 slept = sum = 0;
1169 hr = IAudioClient_Reset(ac);
1170 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
1172 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1173 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1174 ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
1175 ok(pcpos > pcpos0, "pcpos should increase\n");
1177 avail = gbsize; /* implies GetCurrentPadding == 0 */
1178 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1179 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
1180 trace("data at %p\n", data);
1182 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, winetest_debug>2 ?
1183 wave_generate_tone(pwfx, data, avail) : AUDCLNT_BUFFERFLAGS_SILENT);
1184 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
1185 if(hr == S_OK) sum += avail;
1187 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1188 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1189 ok(pad == sum, "padding %u prior to start\n", pad);
1191 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1192 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1193 ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
1194 last = pos;
1196 hr = IAudioClient_Start(ac); /* #3 */
1197 ok(hr == S_OK, "Start failed: %08x\n", hr);
1199 Sleep(100);
1200 slept += 100;
1202 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1203 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1204 trace("position %u past %ums sleep #3\n", (UINT)pos, slept);
1205 ok(pos > last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1206 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1207 if (winetest_debug>1)
1208 ok(pos*1000/freq <= slept*1.1, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1209 else
1210 skip("Rerun with WINETEST_DEBUG=2 for GetPosition tests.\n");
1211 last = pos;
1213 hr = IAudioClient_Reset(ac);
1214 ok(hr == AUDCLNT_E_NOT_STOPPED, "Reset while playing: %08x\n", hr);
1216 hr = IAudioClient_Stop(ac);
1217 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1219 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1220 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1222 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1223 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1224 trace("padding %u position %u past stop #3\n", pad, (UINT)pos);
1225 ok(pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1226 ok(pcpos > pcpos0, "pcpos should increase\n");
1227 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1228 if (pad > 0 && winetest_debug>1)
1229 ok(pos*1000/freq <= slept*1.1, "Position %u too far after stop %ums\n", (UINT)pos, slept);
1230 if(winetest_debug>1)
1231 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
1232 "Position %u after stop vs. %u padding\n", (UINT)pos, pad);
1233 last = pos;
1235 /* Begin the big loop */
1236 hr = IAudioClient_Reset(ac);
1237 ok(hr == S_OK, "Reset failed: %08x\n", hr);
1238 slept = last = sum = 0;
1239 pcpos0 = pcpos;
1241 ok(QueryPerformanceCounter(&hpctime0), "PerfCounter unavailable\n");
1243 hr = IAudioClient_Reset(ac);
1244 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
1246 hr = IAudioClient_Start(ac);
1247 ok(hr == S_OK, "Start failed: %08x\n", hr);
1249 avail = pwfx->nSamplesPerSec * 15 / 16 / 2;
1250 data = NULL;
1251 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1252 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
1253 trace("data at %p for prefill %u\n", data, avail);
1255 if (winetest_debug>2) {
1256 hr = IAudioClient_Stop(ac);
1257 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1259 Sleep(20);
1260 slept += 20;
1262 hr = IAudioClient_Reset(ac);
1263 ok(hr == AUDCLNT_E_BUFFER_OPERATION_PENDING, "Reset failed: %08x\n", hr);
1265 hr = IAudioClient_Start(ac);
1266 ok(hr == S_OK, "Start failed: %08x\n", hr);
1269 /* Despite passed time, data must still point to valid memory... */
1270 hr = IAudioRenderClient_ReleaseBuffer(arc, avail,
1271 wave_generate_tone(pwfx, data, avail));
1272 ok(hr == S_OK, "ReleaseBuffer after stop+start failed: %08x\n", hr);
1273 if(hr == S_OK) sum += avail;
1275 /* GetCurrentPadding(GCP) == 0 does not mean an underrun happened, as the
1276 * mixer may still have a little data. We believe an underrun will occur
1277 * when the mixer finds GCP smaller than a period size at the *end* of a
1278 * period cycle, i.e. shortly before calling SetEvent to signal the app
1279 * that it has ~10ms to supply data for the next cycle. IOW, a zero GCP
1280 * with no data written for over a period causes an underrun. */
1282 Sleep(350);
1283 slept += 350;
1284 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1285 trace("hpctime %u after %ums\n",
1286 (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart), slept);
1288 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1289 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1290 ok(pos > last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1291 last = pos;
1293 for(i=0; i < 9; i++) {
1294 Sleep(100);
1295 slept += 100;
1297 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1298 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1300 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1301 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1303 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1304 trace("hpctime %u pcpos %u\n",
1305 (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart),
1306 (ULONG)((pcpos-pcpos0)/10000));
1308 /* Use sum-pad to see whether position is ahead padding or not. */
1309 trace("padding %u position %u/%u slept %ums iteration %d\n", pad, (UINT)pos, sum-pad, slept, i);
1310 ok(pad ? pos > last : pos >= last, "No position increase at iteration %d\n", i);
1311 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1312 if (winetest_debug>1) {
1313 /* Padding does not lag behind by much */
1314 ok(pos * pwfx->nSamplesPerSec <= (sum-pad+fragment) * freq, "Position %u > written %u\n", (UINT)pos, sum);
1315 ok(pos*1000/freq <= slept*1.1, "Position %u too far after %ums\n", (UINT)pos, slept);
1316 if (pad) /* not in case of underrun */
1317 ok((pos-last)*1000/freq >= 90 && 110 >= (pos-last)*1000/freq,
1318 "Position delta %ld not regular: %ld ms\n", (long)(pos-last), (long)((pos-last)*1000/freq));
1320 last = pos;
1322 hr = IAudioClient_GetStreamLatency(ac, &t1);
1323 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1324 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1326 avail = pwfx->nSamplesPerSec * 15 / 16 / 2;
1327 data = NULL;
1328 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1329 /* ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE || (hr == S_OK && i==0) without todo_wine */
1330 ok(hr == S_OK || hr == AUDCLNT_E_BUFFER_TOO_LARGE,
1331 "GetBuffer large (%u) failed: %08x\n", avail, hr);
1332 if(hr == S_OK && i) ok(FALSE, "GetBuffer large (%u) at iteration %d\n", avail, i);
1333 /* Only the first iteration should allow that large a buffer
1334 * as prefill was drained during the first 350+100ms sleep.
1335 * Afterwards, only 100ms of data should find room per iteration. */
1337 if(hr == S_OK) {
1338 trace("data at %p\n", data);
1339 } else {
1340 avail = gbsize - pad;
1341 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1342 ok(hr == S_OK, "GetBuffer small %u failed: %08x\n", avail, hr);
1343 trace("data at %p (small %u)\n", data, avail);
1345 ok(data != NULL, "NULL buffer returned\n");
1346 if(i % 3 && !winetest_interactive) {
1347 memset(data, 0, avail * pwfx->nBlockAlign);
1348 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, 0);
1349 } else {
1350 hr = IAudioRenderClient_ReleaseBuffer(arc, avail,
1351 wave_generate_tone(pwfx, data, avail));
1353 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
1354 if(hr == S_OK) sum += avail;
1357 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1358 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1359 trace("position %u\n", (UINT)pos);
1361 Sleep(1000); /* 500ms buffer underrun past full buffer */
1363 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1364 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1366 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1367 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1368 trace("position %u past underrun, %u padding left, %u frames written\n", (UINT)pos, pad, sum);
1370 if (share) {
1371 /* Following underrun, all samples were played */
1372 ok(pad == 0, "GetCurrentPadding returned %u, should be 0\n", pad);
1373 ok(pos * pwfx->nSamplesPerSec == sum * freq,
1374 "Position %u at end vs. %u submitted frames\n", (UINT)pos, sum);
1375 } else {
1376 /* Vista and w2k8 leave partial fragments behind */
1377 ok(pad == 0 /* w7, w2k8R2 */||
1378 pos * pwfx->nSamplesPerSec == (sum-pad) * freq, "GetCurrentPadding returned %u, should be 0\n", pad);
1379 /* expect at most 5 fragments (75ms) away */
1380 ok(pos * pwfx->nSamplesPerSec <= sum * freq &&
1381 pos * pwfx->nSamplesPerSec + 5 * fragment * freq >= sum * freq,
1382 "Position %u at end vs. %u submitted frames\n", (UINT)pos, sum);
1385 hr = IAudioClient_GetStreamLatency(ac, &t1);
1386 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1387 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1389 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1390 trace("hpctime %u after underrun\n", (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart));
1392 hr = IAudioClient_Stop(ac);
1393 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1395 CoTaskMemFree(pwfx);
1397 IAudioClock_Release(acl);
1398 IAudioRenderClient_Release(arc);
1399 IAudioClient_Release(ac);
1402 static void test_session(void)
1404 IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac;
1405 IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl = NULL;
1406 IMMDevice *cap_dev;
1407 GUID ses1_guid;
1408 AudioSessionState state;
1409 WAVEFORMATEX *pwfx;
1410 ULONG ref;
1411 HRESULT hr;
1413 hr = CoCreateGuid(&ses1_guid);
1414 ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1416 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1417 NULL, (void**)&ses1_ac1);
1418 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1419 if (FAILED(hr)) return;
1421 hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
1422 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1424 hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
1425 0, 5000000, 0, pwfx, &ses1_guid);
1426 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1428 if(hr == S_OK){
1429 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1430 NULL, (void**)&ses1_ac2);
1431 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1433 if(hr != S_OK){
1434 skip("Unable to open the same device twice. Skipping session tests\n");
1436 ref = IAudioClient_Release(ses1_ac1);
1437 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1438 CoTaskMemFree(pwfx);
1439 return;
1442 hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
1443 0, 5000000, 0, pwfx, &ses1_guid);
1444 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1446 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1447 eMultimedia, &cap_dev);
1448 if(hr == S_OK){
1449 hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1450 NULL, (void**)&cap_ac);
1451 ok((hr == S_OK)^(cap_ac == NULL), "Activate %08x &out pointer\n", hr);
1452 ok(hr == S_OK, "Activate failed: %08x\n", hr);
1453 IMMDevice_Release(cap_dev);
1455 if(hr == S_OK){
1456 WAVEFORMATEX *cap_pwfx;
1458 hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1459 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1461 hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1462 0, 5000000, 0, cap_pwfx, &ses1_guid);
1463 ok(hr == S_OK, "Initialize failed for capture in rendering session: %08x\n", hr);
1464 CoTaskMemFree(cap_pwfx);
1466 if(hr == S_OK){
1467 hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
1468 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1469 if(FAILED(hr))
1470 cap_ctl = NULL;
1471 }else
1472 skip("No capture session: %08x; skipping capture device in render session tests\n", hr);
1474 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
1475 ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
1477 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
1478 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1480 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
1481 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1482 ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
1483 ref = IAudioSessionControl2_Release(ses1_ctl2);
1484 ok(ref != 0, "AudioSessionControl was destroyed\n");
1486 hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
1487 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1489 hr = IAudioSessionControl2_GetState(ses1_ctl, NULL);
1490 ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
1492 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1493 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1494 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1496 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1497 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1498 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1500 if(cap_ctl){
1501 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1502 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1503 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1506 hr = IAudioClient_Start(ses1_ac1);
1507 ok(hr == S_OK, "Start failed: %08x\n", hr);
1509 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1510 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1511 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1513 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1514 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1515 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1517 if(cap_ctl){
1518 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1519 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1520 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1523 hr = IAudioClient_Stop(ses1_ac1);
1524 ok(hr == S_OK, "Start failed: %08x\n", hr);
1526 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1527 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1528 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1530 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1531 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1532 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1534 if(cap_ctl){
1535 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1536 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1537 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1539 hr = IAudioClient_Start(cap_ac);
1540 ok(hr == S_OK, "Start failed: %08x\n", hr);
1542 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1543 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1544 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1546 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1547 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1548 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1550 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1551 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1552 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1554 hr = IAudioClient_Stop(cap_ac);
1555 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1557 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1558 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1559 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1561 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1562 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1563 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1565 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1566 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1567 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1569 ref = IAudioSessionControl2_Release(cap_ctl);
1570 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1572 ref = IAudioClient_Release(cap_ac);
1573 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1576 ref = IAudioSessionControl2_Release(ses1_ctl);
1577 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1579 ref = IAudioClient_Release(ses1_ac1);
1580 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1582 ref = IAudioClient_Release(ses1_ac2);
1583 ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
1585 /* we've released all of our IAudioClient references, so check GetState */
1586 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1587 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1588 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1590 ref = IAudioSessionControl2_Release(ses1_ctl2);
1591 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1593 CoTaskMemFree(pwfx);
1596 static void test_streamvolume(void)
1598 IAudioClient *ac;
1599 IAudioStreamVolume *asv;
1600 WAVEFORMATEX *fmt;
1601 UINT32 chans, i;
1602 HRESULT hr;
1603 float vol, *vols;
1605 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1606 NULL, (void**)&ac);
1607 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1608 if(hr != S_OK)
1609 return;
1611 hr = IAudioClient_GetMixFormat(ac, &fmt);
1612 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1614 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
1615 0, fmt, NULL);
1616 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1618 if(hr == S_OK){
1619 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1620 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1622 if(hr != S_OK){
1623 IAudioClient_Release(ac);
1624 CoTaskMemFree(fmt);
1625 return;
1628 hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
1629 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1631 hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
1632 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1633 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
1635 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
1636 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1638 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
1639 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
1641 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
1642 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1644 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1645 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1646 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
1648 hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
1649 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1651 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
1652 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1654 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
1655 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1657 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1658 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1660 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1661 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1662 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1664 hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
1665 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
1667 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
1668 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
1670 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1671 ok(vols != NULL, "HeapAlloc failed\n");
1673 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
1674 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1676 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
1677 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1678 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1679 for(i = 1; i < fmt->nChannels; ++i)
1680 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1682 hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
1683 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
1685 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
1686 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
1688 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
1689 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1691 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
1692 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1694 HeapFree(GetProcessHeap(), 0, vols);
1695 IAudioStreamVolume_Release(asv);
1696 IAudioClient_Release(ac);
1697 CoTaskMemFree(fmt);
1700 static void test_channelvolume(void)
1702 IAudioClient *ac;
1703 IChannelAudioVolume *acv;
1704 WAVEFORMATEX *fmt;
1705 UINT32 chans, i;
1706 HRESULT hr;
1707 float vol, *vols;
1709 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1710 NULL, (void**)&ac);
1711 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1712 if(hr != S_OK)
1713 return;
1715 hr = IAudioClient_GetMixFormat(ac, &fmt);
1716 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1718 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1719 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1720 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1722 if(hr == S_OK){
1723 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
1724 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1726 if(hr != S_OK){
1727 IAudioClient_Release(ac);
1728 CoTaskMemFree(fmt);
1729 return;
1732 hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
1733 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1735 hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
1736 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1737 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
1739 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
1740 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1742 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
1743 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
1745 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
1746 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1748 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
1749 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1750 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
1752 hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
1753 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1755 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
1756 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1758 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
1759 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1761 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
1762 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1764 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
1765 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1766 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1768 hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
1769 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1771 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
1772 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1774 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1775 ok(vols != NULL, "HeapAlloc failed\n");
1777 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
1778 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1780 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1781 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1782 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1783 for(i = 1; i < fmt->nChannels; ++i)
1784 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1786 hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1787 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1789 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1790 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1792 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1793 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1795 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1796 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1798 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1799 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1801 HeapFree(GetProcessHeap(), 0, vols);
1802 IChannelAudioVolume_Release(acv);
1803 IAudioClient_Release(ac);
1804 CoTaskMemFree(fmt);
1807 static void test_simplevolume(void)
1809 IAudioClient *ac;
1810 ISimpleAudioVolume *sav;
1811 WAVEFORMATEX *fmt;
1812 HRESULT hr;
1813 float vol;
1814 BOOL mute;
1816 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1817 NULL, (void**)&ac);
1818 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1819 if(hr != S_OK)
1820 return;
1822 hr = IAudioClient_GetMixFormat(ac, &fmt);
1823 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1825 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1826 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1827 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1829 if(hr == S_OK){
1830 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1831 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1833 if(hr != S_OK){
1834 IAudioClient_Release(ac);
1835 CoTaskMemFree(fmt);
1836 return;
1839 hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1840 ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1842 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1843 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1844 ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1846 hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1847 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1849 hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1850 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1852 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1853 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1855 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1856 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1857 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1859 hr = ISimpleAudioVolume_GetMute(sav, NULL);
1860 ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1862 mute = TRUE;
1863 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1864 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1865 ok(mute == FALSE, "Session is already muted\n");
1867 hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1868 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1870 mute = FALSE;
1871 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1872 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1873 ok(mute == TRUE, "Session should have been muted\n");
1875 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1876 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1877 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1879 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1880 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1882 mute = FALSE;
1883 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1884 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1885 ok(mute == TRUE, "Session should have been muted\n");
1887 hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1888 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1890 ISimpleAudioVolume_Release(sav);
1891 IAudioClient_Release(ac);
1892 CoTaskMemFree(fmt);
1895 static void test_volume_dependence(void)
1897 IAudioClient *ac, *ac2;
1898 ISimpleAudioVolume *sav;
1899 IChannelAudioVolume *cav;
1900 IAudioStreamVolume *asv;
1901 WAVEFORMATEX *fmt;
1902 HRESULT hr;
1903 float vol;
1904 GUID session;
1905 UINT32 nch;
1907 hr = CoCreateGuid(&session);
1908 ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1910 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1911 NULL, (void**)&ac);
1912 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1913 if(hr != S_OK)
1914 return;
1916 hr = IAudioClient_GetMixFormat(ac, &fmt);
1917 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1919 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1920 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1921 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1923 if(hr == S_OK){
1924 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1925 ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1927 if(hr != S_OK){
1928 IAudioClient_Release(ac);
1929 CoTaskMemFree(fmt);
1930 return;
1933 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1934 ok(hr == S_OK, "GetService (ChannelAudioVolume) failed: %08x\n", hr);
1936 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1937 ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1939 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1940 ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1942 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1943 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1945 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1946 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1948 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1949 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1950 ok(fabsf(vol - 0.2f) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1952 hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1953 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1954 ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1956 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1957 ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1958 ok(fabsf(vol - 0.6f) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1960 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1961 NULL, (void**)&ac2);
1962 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1964 if(hr == S_OK){
1965 hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1966 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1967 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1968 if(hr != S_OK)
1969 IAudioClient_Release(ac2);
1972 if(hr == S_OK){
1973 IChannelAudioVolume *cav2;
1974 IAudioStreamVolume *asv2;
1976 hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1977 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1979 hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1980 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1982 hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1983 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1984 ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1986 hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1987 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1988 ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1990 hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1991 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1992 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1994 hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
1995 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1996 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1998 IAudioStreamVolume_Release(asv2);
1999 IChannelAudioVolume_Release(cav2);
2000 IAudioClient_Release(ac2);
2001 }else
2002 skip("Unable to open the same device twice. Skipping session volume control tests\n");
2004 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
2005 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
2007 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
2008 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
2010 CoTaskMemFree(fmt);
2011 ISimpleAudioVolume_Release(sav);
2012 IChannelAudioVolume_Release(cav);
2013 IAudioStreamVolume_Release(asv);
2014 IAudioClient_Release(ac);
2017 static void test_session_creation(void)
2019 IMMDevice *cap_dev;
2020 IAudioClient *ac;
2021 IAudioSessionManager *sesm;
2022 ISimpleAudioVolume *sav;
2023 GUID session_guid;
2024 float vol;
2025 HRESULT hr;
2026 WAVEFORMATEX *fmt;
2028 CoCreateGuid(&session_guid);
2030 hr = IMMDevice_Activate(dev, &IID_IAudioSessionManager,
2031 CLSCTX_INPROC_SERVER, NULL, (void**)&sesm);
2032 ok((hr == S_OK)^(sesm == NULL), "Activate %08x &out pointer\n", hr);
2033 ok(hr == S_OK, "Activate failed: %08x\n", hr);
2035 hr = IAudioSessionManager_GetSimpleAudioVolume(sesm, &session_guid,
2036 FALSE, &sav);
2037 ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
2039 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
2040 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
2042 /* Release completely to show session persistence */
2043 ISimpleAudioVolume_Release(sav);
2044 IAudioSessionManager_Release(sesm);
2046 /* test if we can create a capture audioclient in the session we just
2047 * created from a SessionManager derived from a render device */
2048 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
2049 eMultimedia, &cap_dev);
2050 if(hr == S_OK){
2051 WAVEFORMATEX *cap_pwfx;
2052 IAudioClient *cap_ac;
2053 ISimpleAudioVolume *cap_sav;
2054 IAudioSessionManager *cap_sesm;
2056 hr = IMMDevice_Activate(cap_dev, &IID_IAudioSessionManager,
2057 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_sesm);
2058 ok((hr == S_OK)^(cap_sesm == NULL), "Activate %08x &out pointer\n", hr);
2059 ok(hr == S_OK, "Activate failed: %08x\n", hr);
2061 hr = IAudioSessionManager_GetSimpleAudioVolume(cap_sesm, &session_guid,
2062 FALSE, &cap_sav);
2063 ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
2065 vol = 0.5f;
2066 hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
2067 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
2069 ISimpleAudioVolume_Release(cap_sav);
2070 IAudioSessionManager_Release(cap_sesm);
2072 hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient,
2073 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_ac);
2074 ok(hr == S_OK, "Activate failed: %08x\n", hr);
2076 IMMDevice_Release(cap_dev);
2078 hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
2079 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2081 hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
2082 0, 5000000, 0, cap_pwfx, &session_guid);
2083 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2085 CoTaskMemFree(cap_pwfx);
2087 if(hr == S_OK){
2088 hr = IAudioClient_GetService(cap_ac, &IID_ISimpleAudioVolume,
2089 (void**)&cap_sav);
2090 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2092 if(hr == S_OK){
2093 vol = 0.5f;
2094 hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
2095 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
2097 ISimpleAudioVolume_Release(cap_sav);
2100 IAudioClient_Release(cap_ac);
2103 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2104 NULL, (void**)&ac);
2105 ok((hr == S_OK)^(ac == NULL), "Activate %08x &out pointer\n", hr);
2106 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2107 if(hr != S_OK)
2108 return;
2110 hr = IAudioClient_GetMixFormat(ac, &fmt);
2111 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2113 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
2114 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session_guid);
2115 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2117 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
2118 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2119 if(hr == S_OK){
2120 vol = 0.5f;
2121 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
2122 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
2123 ok(fabs(vol - 0.6f) < 0.05f, "Got wrong volume: %f\n", vol);
2125 ISimpleAudioVolume_Release(sav);
2128 CoTaskMemFree(fmt);
2129 IAudioClient_Release(ac);
2132 static void test_worst_case(void)
2134 HANDLE event;
2135 HRESULT hr;
2136 IAudioClient *ac;
2137 IAudioRenderClient *arc;
2138 IAudioClock *acl;
2139 WAVEFORMATEX *pwfx;
2140 REFERENCE_TIME defp;
2141 UINT64 freq, pos, pcpos0, pcpos;
2142 BYTE *data;
2143 DWORD r;
2144 UINT32 pad, fragment, sum;
2145 int i,j;
2147 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2148 NULL, (void**)&ac);
2149 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2150 if(hr != S_OK)
2151 return;
2153 hr = IAudioClient_GetMixFormat(ac, &pwfx);
2154 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2156 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
2157 AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 500000, 0, pwfx, NULL);
2158 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2159 if(hr != S_OK)
2160 return;
2162 hr = IAudioClient_GetDevicePeriod(ac, &defp, NULL);
2163 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
2165 fragment = MulDiv(defp, pwfx->nSamplesPerSec, 10000000);
2167 event = CreateEventW(NULL, FALSE, FALSE, NULL);
2168 ok(event != NULL, "CreateEvent failed\n");
2170 hr = IAudioClient_SetEventHandle(ac, event);
2171 ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
2173 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
2174 ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
2176 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
2177 ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
2179 hr = IAudioClock_GetFrequency(acl, &freq);
2180 ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
2182 for(j = 0; j <= (winetest_interactive ? 9 : 2); j++){
2183 sum = 0;
2184 trace("Should play %ums continuous tone with fragment size %u.\n",
2185 (ULONG)(defp/100), fragment);
2187 hr = IAudioClock_GetPosition(acl, &pos, &pcpos0);
2188 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
2190 /* XAudio2 prefills one period, play without it */
2191 if(winetest_debug>2){
2192 hr = IAudioRenderClient_GetBuffer(arc, fragment, &data);
2193 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
2195 hr = IAudioRenderClient_ReleaseBuffer(arc, fragment, AUDCLNT_BUFFERFLAGS_SILENT);
2196 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
2197 if(hr == S_OK)
2198 sum += fragment;
2201 hr = IAudioClient_Start(ac);
2202 ok(hr == S_OK, "Start failed: %08x\n", hr);
2204 for(i = 0; i <= 99; i++){ /* 100 x 10ms = 1 second */
2205 r = WaitForSingleObject(event, 60 + defp / 10000);
2206 ok(r == WAIT_OBJECT_0, "Wait iteration %d gave %x\n", i, r);
2208 /* the app has nearly one period time to feed data */
2209 Sleep((i % 10) * defp / 120000);
2211 hr = IAudioClient_GetCurrentPadding(ac, &pad);
2212 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
2214 /* XAudio2 writes only when there's little data left */
2215 if(pad <= fragment){
2216 hr = IAudioRenderClient_GetBuffer(arc, fragment, &data);
2217 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
2219 hr = IAudioRenderClient_ReleaseBuffer(arc, fragment,
2220 wave_generate_tone(pwfx, data, fragment));
2221 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
2222 if(hr == S_OK)
2223 sum += fragment;
2227 hr = IAudioClient_Stop(ac);
2228 ok(hr == S_OK, "Stop failed: %08x\n", hr);
2230 hr = IAudioClient_GetCurrentPadding(ac, &pad);
2231 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
2233 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
2234 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
2236 Sleep(100);
2238 trace("Released %u=%ux%u -%u frames at %u worth %ums in %ums\n",
2239 sum, sum/fragment, fragment, pad,
2240 pwfx->nSamplesPerSec, MulDiv(sum-pad, 1000, pwfx->nSamplesPerSec),
2241 (ULONG)((pcpos-pcpos0)/10000));
2243 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
2244 "Position %u at end vs. %u-%u submitted frames\n", (UINT)pos, sum, pad);
2246 hr = IAudioClient_Reset(ac);
2247 ok(hr == S_OK, "Reset failed: %08x\n", hr);
2249 Sleep(250);
2252 CoTaskMemFree(pwfx);
2253 IAudioClient_Release(ac);
2254 IAudioClock_Release(acl);
2255 IAudioRenderClient_Release(arc);
2258 static void test_marshal(void)
2260 IStream *pStream;
2261 IAudioClient *ac, *acDest;
2262 IAudioRenderClient *rc, *rcDest;
2263 WAVEFORMATEX *pwfx;
2264 HRESULT hr;
2266 /* IAudioRenderClient */
2267 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2268 NULL, (void**)&ac);
2269 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2270 if(hr != S_OK)
2271 return;
2273 hr = IAudioClient_GetMixFormat(ac, &pwfx);
2274 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2276 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
2277 0, pwfx, NULL);
2278 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2280 CoTaskMemFree(pwfx);
2282 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
2283 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2284 if(hr != S_OK) {
2285 IAudioClient_Release(ac);
2286 return;
2289 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2290 ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x\n", hr);
2292 /* marshal IAudioClient */
2294 hr = CoMarshalInterface(pStream, &IID_IAudioClient, (IUnknown*)ac, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2295 ok(hr == S_OK, "CoMarshalInterface IAudioClient failed 0x%08x\n", hr);
2297 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2298 hr = CoUnmarshalInterface(pStream, &IID_IAudioClient, (void **)&acDest);
2299 ok(hr == S_OK, "CoUnmarshalInterface IAudioClient failed 0x%08x\n", hr);
2300 if (hr == S_OK)
2301 IAudioClient_Release(acDest);
2303 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2304 /* marshal IAudioRenderClient */
2306 hr = CoMarshalInterface(pStream, &IID_IAudioRenderClient, (IUnknown*)rc, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2307 ok(hr == S_OK, "CoMarshalInterface IAudioRenderClient failed 0x%08x\n", hr);
2309 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2310 hr = CoUnmarshalInterface(pStream, &IID_IAudioRenderClient, (void **)&rcDest);
2311 ok(hr == S_OK, "CoUnmarshalInterface IAudioRenderClient failed 0x%08x\n", hr);
2312 if (hr == S_OK)
2313 IAudioRenderClient_Release(rcDest);
2316 IStream_Release(pStream);
2318 IAudioClient_Release(ac);
2319 IAudioRenderClient_Release(rc);
2323 static void test_endpointvolume(void)
2325 HRESULT hr;
2326 IAudioEndpointVolume *aev;
2327 float mindb, maxdb, increment, volume;
2328 BOOL mute;
2330 hr = IMMDevice_Activate(dev, &IID_IAudioEndpointVolume,
2331 CLSCTX_INPROC_SERVER, NULL, (void**)&aev);
2332 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2333 if(hr != S_OK)
2334 return;
2336 hr = IAudioEndpointVolume_GetVolumeRange(aev, &mindb, NULL, NULL);
2337 ok(hr == E_POINTER, "GetVolumeRange should have failed with E_POINTER: 0x%08x\n", hr);
2339 hr = IAudioEndpointVolume_GetVolumeRange(aev, &mindb, &maxdb, &increment);
2340 ok(hr == S_OK, "GetVolumeRange failed: 0x%08x\n", hr);
2341 trace("got range: [%f,%f]/%f\n", mindb, maxdb, increment);
2343 hr = IAudioEndpointVolume_SetMasterVolumeLevel(aev, mindb - increment, NULL);
2344 ok(hr == E_INVALIDARG, "SetMasterVolumeLevel failed: 0x%08x\n", hr);
2346 hr = IAudioEndpointVolume_GetMasterVolumeLevel(aev, &volume);
2347 ok(hr == S_OK, "GetMasterVolumeLevel failed: 0x%08x\n", hr);
2349 hr = IAudioEndpointVolume_SetMasterVolumeLevel(aev, volume, NULL);
2350 ok(hr == S_OK, "SetMasterVolumeLevel failed: 0x%08x\n", hr);
2352 hr = IAudioEndpointVolume_GetMute(aev, &mute);
2353 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
2355 hr = IAudioEndpointVolume_SetMute(aev, mute, NULL);
2356 ok(hr == S_OK || hr == S_FALSE, "SetMute failed: %08x\n", hr);
2358 IAudioEndpointVolume_Release(aev);
2361 START_TEST(render)
2363 HRESULT hr;
2364 DWORD mode;
2366 CoInitializeEx(NULL, COINIT_MULTITHREADED);
2367 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
2368 if (FAILED(hr))
2370 skip("mmdevapi not available: 0x%08x\n", hr);
2371 goto cleanup;
2374 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
2375 ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
2376 if (hr != S_OK || !dev)
2378 if (hr == E_NOTFOUND)
2379 skip("No sound card available\n");
2380 else
2381 skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
2382 goto cleanup;
2385 test_audioclient();
2386 test_formats(AUDCLNT_SHAREMODE_EXCLUSIVE);
2387 test_formats(AUDCLNT_SHAREMODE_SHARED);
2388 test_references();
2389 test_marshal();
2390 if (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &mode))
2392 trace("Output to a MS-DOS console is particularly slow and disturbs timing.\n");
2393 trace("Please redirect output to a file.\n");
2395 test_event();
2396 test_padding();
2397 test_clock(1);
2398 test_clock(0);
2399 test_session();
2400 test_streamvolume();
2401 test_channelvolume();
2402 test_simplevolume();
2403 test_volume_dependence();
2404 test_session_creation();
2405 test_worst_case();
2406 test_endpointvolume();
2408 IMMDevice_Release(dev);
2410 cleanup:
2411 if (mme)
2412 IMMDeviceEnumerator_Release(mme);
2413 CoUninitialize();