[MMDEVAPI_WINETEST] Sync with Wine 3.0. CORE-14225
[reactos.git] / modules / rostests / winetests / mmdevapi / render.c
1 /*
2 * Copyright 2010 Maarten Lankhorst for CodeWeavers
3 * 2011-2012 Jörg Höhle
4 *
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.
9 *
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.
14 *
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
18 */
19
20 /* This test is for audio playback specific mechanisms
21 * Tests:
22 * - IAudioClient with eRender and IAudioRenderClient
23 */
24
25 #include <math.h>
26 #include <stdio.h>
27
28 #include "wine/test.h"
29
30 #define COBJMACROS
31
32 #include "unknwn.h"
33 #include "uuids.h"
34 #include "mmdeviceapi.h"
35 #include "mmsystem.h"
36 #include "audioclient.h"
37 #include "audiopolicy.h"
38 #include "initguid.h"
39 #include "endpointvolume.h"
40
41 static const unsigned int win_formats[][4] = {
42 { 8000, 8, 1}, { 8000, 8, 2}, { 8000, 16, 1}, { 8000, 16, 2},
43 {11025, 8, 1}, {11025, 8, 2}, {11025, 16, 1}, {11025, 16, 2},
44 {12000, 8, 1}, {12000, 8, 2}, {12000, 16, 1}, {12000, 16, 2},
45 {16000, 8, 1}, {16000, 8, 2}, {16000, 16, 1}, {16000, 16, 2},
46 {22050, 8, 1}, {22050, 8, 2}, {22050, 16, 1}, {22050, 16, 2},
47 {44100, 8, 1}, {44100, 8, 2}, {44100, 16, 1}, {44100, 16, 2},
48 {48000, 8, 1}, {48000, 8, 2}, {48000, 16, 1}, {48000, 16, 2},
49 {96000, 8, 1}, {96000, 8, 2}, {96000, 16, 1}, {96000, 16, 2}
50 };
51 #define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))
52
53 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
54
55 /* undocumented error code */
56 #define D3D11_ERROR_4E MAKE_HRESULT(SEVERITY_ERROR, FACILITY_DIRECT3D11, 0x4e)
57
58 static IMMDeviceEnumerator *mme = NULL;
59 static IMMDevice *dev = NULL;
60 static HRESULT hexcl = S_OK; /* or AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED */
61 static BOOL win10 = FALSE;
62
63 static const LARGE_INTEGER ullZero;
64
65 #define PI 3.14159265358979323846L
66 static DWORD wave_generate_tone(PWAVEFORMATEX pwfx, BYTE* data, UINT32 frames)
67 {
68 static double phase = 0.; /* normalized to unit, not 2*PI */
69 PWAVEFORMATEXTENSIBLE wfxe = (PWAVEFORMATEXTENSIBLE)pwfx;
70 DWORD cn, i;
71 double delta, y;
72
73 if(!winetest_interactive)
74 return AUDCLNT_BUFFERFLAGS_SILENT;
75 if(wfxe->Format.wBitsPerSample != ((wfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
76 IsEqualGUID(&wfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) ? 8 * sizeof(float) : 16))
77 return AUDCLNT_BUFFERFLAGS_SILENT;
78
79 for(delta = phase, cn = 0; cn < wfxe->Format.nChannels;
80 delta += .5/wfxe->Format.nChannels, cn++){
81 for(i = 0; i < frames; i++){
82 y = sin(2*PI*(440.* i / wfxe->Format.nSamplesPerSec + delta));
83 /* assume alignment is granted */
84 if(wfxe->Format.wBitsPerSample == 16)
85 ((short*)data)[cn+i*wfxe->Format.nChannels] = y * 32767.9;
86 else
87 ((float*)data)[cn+i*wfxe->Format.nChannels] = y;
88 }
89 }
90 phase += 440.* frames / wfxe->Format.nSamplesPerSec;
91 phase -= floor(phase);
92 return 0;
93 }
94
95 static void test_uninitialized(IAudioClient *ac)
96 {
97 HRESULT hr;
98 UINT32 num;
99 REFERENCE_TIME t1;
100
101 HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
102 IUnknown *unk;
103
104 hr = IAudioClient_GetBufferSize(ac, &num);
105 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
106
107 hr = IAudioClient_GetStreamLatency(ac, &t1);
108 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
109
110 hr = IAudioClient_GetCurrentPadding(ac, &num);
111 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
112
113 hr = IAudioClient_Start(ac);
114 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
115
116 hr = IAudioClient_Stop(ac);
117 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
118
119 hr = IAudioClient_Reset(ac);
120 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
121
122 hr = IAudioClient_SetEventHandle(ac, handle);
123 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
124
125 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
126 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
127
128 CloseHandle(handle);
129 }
130
131 static void test_audioclient(void)
132 {
133 IAudioClient *ac;
134 IUnknown *unk;
135 HRESULT hr;
136 ULONG ref;
137 WAVEFORMATEX *pwfx, *pwfx2;
138 REFERENCE_TIME t1, t2;
139 HANDLE handle;
140
141 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
142 NULL, (void**)&ac);
143 ok(hr == S_OK, "Activation failed with %08x\n", hr);
144 if(hr != S_OK)
145 return;
146
147 handle = CreateEventW(NULL, FALSE, FALSE, NULL);
148
149 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
150 ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
151
152 unk = (void*)(LONG_PTR)0x12345678;
153 hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
154 ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
155 ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
156
157 hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
158 ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
159 if (unk)
160 {
161 ref = IUnknown_Release(unk);
162 ok(ref == 1, "Released count is %u\n", ref);
163 }
164
165 hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
166 ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
167 if (unk)
168 {
169 ref = IUnknown_Release(unk);
170 ok(ref == 1, "Released count is %u\n", ref);
171 }
172
173 hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
174 ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
175
176 hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
177 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
178
179 hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
180 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
181
182 hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
183 ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
184 trace("Returned periods: %u.%04u ms %u.%04u ms\n",
185 (UINT)(t1/10000), (UINT)(t1 % 10000),
186 (UINT)(t2/10000), (UINT)(t2 % 10000));
187
188 hr = IAudioClient_GetMixFormat(ac, NULL);
189 ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
190
191 hr = IAudioClient_GetMixFormat(ac, &pwfx);
192 ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
193
194 if (hr == S_OK)
195 {
196 trace("pwfx: %p\n", pwfx);
197 trace("Tag: %04x\n", pwfx->wFormatTag);
198 trace("bits: %u\n", pwfx->wBitsPerSample);
199 trace("chan: %u\n", pwfx->nChannels);
200 trace("rate: %u\n", pwfx->nSamplesPerSec);
201 trace("align: %u\n", pwfx->nBlockAlign);
202 trace("extra: %u\n", pwfx->cbSize);
203 ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
204 if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
205 {
206 WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
207 trace("Res: %u\n", pwfxe->Samples.wReserved);
208 trace("Mask: %x\n", pwfxe->dwChannelMask);
209 trace("Alg: %s\n",
210 IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
211 (IsEqualGUID(&pwfxe->SubFormat,
212 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
213 }
214
215 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
216 ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
217 ok(pwfx2 == NULL, "pwfx2 is non-null\n");
218 CoTaskMemFree(pwfx2);
219
220 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
221 ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
222
223 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
224 ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
225
226 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
227 ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED,
228 "IsFormatSupported(Exclusive) call returns %08x\n", hr);
229 hexcl = hr;
230
231 pwfx2 = (WAVEFORMATEX*)0xDEADF00D;
232 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
233 ok(hr == hexcl, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
234 ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
235
236 if (hexcl != AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
237 hexcl = S_OK;
238
239 hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
240 ok(hr == E_INVALIDARG/*w32*/ ||
241 broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT/*w64 response from exclusive mode driver */),
242 "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
243 }
244
245 test_uninitialized(ac);
246
247 hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
248 ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
249
250 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
251 ok(hr == E_INVALIDARG ||
252 hr == AUDCLNT_E_INVALID_STREAM_FLAG, "Initialize with invalid flags returns %08x\n", hr);
253
254 /* A period != 0 is ignored and the call succeeds.
255 * Since we can only initialize successfully once, skip those tests.
256 */
257 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
258 ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
259
260 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, pwfx, NULL);
261 ok(hr == S_OK, "Initialize with 0 buffer size returns %08x\n", hr);
262 if(hr == S_OK){
263 UINT32 num;
264
265 hr = IAudioClient_GetBufferSize(ac, &num);
266 ok(hr == S_OK, "GetBufferSize from duration 0 returns %08x\n", hr);
267 if(hr == S_OK)
268 trace("Initialize(duration=0) GetBufferSize is %u\n", num);
269 }
270
271 IAudioClient_Release(ac);
272
273 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
274 NULL, (void**)&ac);
275 ok(hr == S_OK, "Activation failed with %08x\n", hr);
276
277 if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
278 WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)pwfx;
279 WAVEFORMATEX *fmt2 = NULL;
280
281 ok(fmtex->dwChannelMask != 0, "Got empty dwChannelMask\n");
282
283 fmtex->dwChannelMask = 0xffff;
284
285 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
286 ok(hr == S_OK ||
287 hr == AUDCLNT_E_UNSUPPORTED_FORMAT /* win10 */, "Initialize(dwChannelMask = 0xffff) returns %08x\n", hr);
288
289 IAudioClient_Release(ac);
290
291 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
292 NULL, (void**)&ac);
293 ok(hr == S_OK, "Activation failed with %08x\n", hr);
294
295 fmtex->dwChannelMask = 0;
296
297 hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &fmt2);
298 ok(hr == S_OK || broken(hr == S_FALSE /* w7 Realtek HDA */),
299 "IsFormatSupported(dwChannelMask = 0) call returns %08x\n", hr);
300 ok(fmtex->dwChannelMask == 0, "Passed format was modified\n");
301
302 CoTaskMemFree(fmt2);
303
304 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
305 ok(hr == S_OK, "Initialize(dwChannelMask = 0) returns %08x\n", hr);
306
307 IAudioClient_Release(ac);
308
309 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
310 NULL, (void**)&ac);
311 ok(hr == S_OK, "Activation failed with %08x\n", hr);
312
313 CoTaskMemFree(pwfx);
314
315 hr = IAudioClient_GetMixFormat(ac, &pwfx);
316 ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
317 }else
318 skip("Skipping dwChannelMask tests\n");
319
320 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
321 ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
322 if (hr != S_OK)
323 goto cleanup;
324
325 hr = IAudioClient_GetStreamLatency(ac, NULL);
326 ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
327
328 hr = IAudioClient_GetStreamLatency(ac, &t2);
329 ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
330 trace("Returned latency: %u.%04u ms\n",
331 (UINT)(t2/10000), (UINT)(t2 % 10000));
332 ok(t2 >= t1 || broken(t2 >= t1/2 && pwfx->nSamplesPerSec > 48000) ||
333 broken(t2 == 0) /* (!) win10 */,
334 "Latency < default period, delta %dus (%s vs %s)\n",
335 (LONG)((t2-t1)/10), wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t1));
336 /* Native appears to add the engine period to the HW latency in shared mode */
337 if(t2 == 0)
338 win10 = TRUE;
339
340 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
341 ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
342
343 hr = IAudioClient_SetEventHandle(ac, NULL);
344 ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
345
346 hr = IAudioClient_SetEventHandle(ac, handle);
347 ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
348 broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
349 broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
350 broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
351 , "SetEventHandle returns %08x\n", hr);
352
353 hr = IAudioClient_Reset(ac);
354 ok(hr == S_OK, "Reset on an initialized stream returns %08x\n", hr);
355
356 hr = IAudioClient_Reset(ac);
357 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
358
359 hr = IAudioClient_Stop(ac);
360 ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
361
362 hr = IAudioClient_Start(ac);
363 ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
364
365 hr = IAudioClient_Start(ac);
366 ok(hr == AUDCLNT_E_NOT_STOPPED, "Start twice returns %08x\n", hr);
367
368 cleanup:
369 IAudioClient_Release(ac);
370 CloseHandle(handle);
371 CoTaskMemFree(pwfx);
372 }
373
374 static void test_formats(AUDCLNT_SHAREMODE mode)
375 {
376 IAudioClient *ac;
377 HRESULT hr, hrs;
378 WAVEFORMATEX fmt, *pwfx, *pwfx2;
379 int i;
380
381 fmt.wFormatTag = WAVE_FORMAT_PCM;
382 fmt.cbSize = 0;
383
384 for(i = 0; i < NB_WIN_FORMATS; i++) {
385 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
386 NULL, (void**)&ac);
387 ok(hr == S_OK, "Activation failed with %08x\n", hr);
388 if(hr != S_OK)
389 continue;
390
391 hr = IAudioClient_GetMixFormat(ac, &pwfx);
392 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
393
394 fmt.nSamplesPerSec = win_formats[i][0];
395 fmt.wBitsPerSample = win_formats[i][1];
396 fmt.nChannels = win_formats[i][2];
397 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
398 fmt.nAvgBytesPerSec= fmt.nBlockAlign * fmt.nSamplesPerSec;
399
400 pwfx2 = (WAVEFORMATEX*)0xDEADF00D;
401 hr = IAudioClient_IsFormatSupported(ac, mode, &fmt, &pwfx2);
402 hrs = hr;
403 /* Only shared mode suggests something ... GetMixFormat! */
404 ok(hr == S_OK || (mode == AUDCLNT_SHAREMODE_SHARED
405 ? hr == S_FALSE || broken(hr == AUDCLNT_E_UNSUPPORTED_FORMAT &&
406 /* 5:1 card exception when asked for 1 channel at mixer rate */
407 pwfx->nChannels > 2 && fmt.nSamplesPerSec == pwfx->nSamplesPerSec)
408 : (hr == AUDCLNT_E_UNSUPPORTED_FORMAT || hr == hexcl)),
409 "IsFormatSupported(%d, %ux%2ux%u) returns %08x\n", mode,
410 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
411 if (hr == S_OK)
412 trace("IsSupported(%s, %ux%2ux%u)\n",
413 mode == AUDCLNT_SHAREMODE_SHARED ? "shared " : "exclus.",
414 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels);
415
416 /* Change GetMixFormat wBitsPerSample only => S_OK */
417 if (mode == AUDCLNT_SHAREMODE_SHARED
418 && fmt.nSamplesPerSec == pwfx->nSamplesPerSec
419 && fmt.nChannels == pwfx->nChannels)
420 ok(hr == S_OK, "Varying BitsPerSample %u\n", fmt.wBitsPerSample);
421
422 ok((hr == S_FALSE)^(pwfx2 == NULL), "hr %x<->suggest %p\n", hr, pwfx2);
423 if (pwfx2 == (WAVEFORMATEX*)0xDEADF00D)
424 pwfx2 = NULL; /* broken in Wine < 1.3.28 */
425 if (pwfx2) {
426 ok(pwfx2->nSamplesPerSec == pwfx->nSamplesPerSec &&
427 pwfx2->nChannels == pwfx->nChannels &&
428 pwfx2->wBitsPerSample == pwfx->wBitsPerSample,
429 "Suggestion %ux%2ux%u differs from GetMixFormat\n",
430 pwfx2->nSamplesPerSec, pwfx2->wBitsPerSample, pwfx2->nChannels);
431 }
432
433 /* Vista returns E_INVALIDARG upon AUDCLNT_STREAMFLAGS_RATEADJUST */
434 hr = IAudioClient_Initialize(ac, mode, 0, 5000000, 0, &fmt, NULL);
435 if ((hrs == S_OK) ^ (hr == S_OK))
436 trace("Initialize (%s, %ux%2ux%u) returns %08x unlike IsFormatSupported\n",
437 mode == AUDCLNT_SHAREMODE_SHARED ? "shared " : "exclus.",
438 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
439 if (mode == AUDCLNT_SHAREMODE_SHARED)
440 ok(hrs == S_OK ? hr == S_OK : hr == AUDCLNT_E_UNSUPPORTED_FORMAT,
441 "Initialize(shared, %ux%2ux%u) returns %08x\n",
442 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
443 else if (hrs == AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED)
444 /* Unsupported format implies "create failed" and shadows "not allowed" */
445 ok(hrs == hexcl && (hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == hrs),
446 "Initialize(noexcl., %ux%2ux%u) returns %08x(%08x)\n",
447 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr, hrs);
448 else
449 /* On testbot 48000x16x1 claims support, but does not Initialize.
450 * Some cards Initialize 44100|48000x16x1 yet claim no support;
451 * F. Gouget's w7 bots do that for 12000|96000x8|16x1|2 */
452 ok(hrs == S_OK ? hr == S_OK || broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED)
453 : hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED || hr == AUDCLNT_E_UNSUPPORTED_FORMAT ||
454 broken(hr == S_OK &&
455 ((fmt.nChannels == 1 && fmt.wBitsPerSample == 16) ||
456 (fmt.nSamplesPerSec == 12000 || fmt.nSamplesPerSec == 96000))),
457 "Initialize(exclus., %ux%2ux%u) returns %08x\n",
458 fmt.nSamplesPerSec, fmt.wBitsPerSample, fmt.nChannels, hr);
459
460 /* Bug in native (Vista/w2k8/w7): after Initialize failed, better
461 * Release this ac and Activate a new one.
462 * A second call (with a known working format) would yield
463 * ALREADY_INITIALIZED in shared mode yet be unusable, and in exclusive
464 * mode some entity keeps a lock on the device, causing DEVICE_IN_USE to
465 * all subsequent calls until the audio engine service is restarted. */
466
467 CoTaskMemFree(pwfx2);
468 CoTaskMemFree(pwfx);
469 IAudioClient_Release(ac);
470 }
471 }
472
473 static void test_references(void)
474 {
475 IAudioClient *ac;
476 IAudioRenderClient *rc;
477 ISimpleAudioVolume *sav;
478 IAudioStreamVolume *asv;
479 IAudioClock *acl;
480 WAVEFORMATEX *pwfx;
481 HRESULT hr;
482 ULONG ref;
483
484 /* IAudioRenderClient */
485 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
486 NULL, (void**)&ac);
487 ok(hr == S_OK, "Activation failed with %08x\n", hr);
488 if(hr != S_OK)
489 return;
490
491 hr = IAudioClient_GetMixFormat(ac, &pwfx);
492 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
493
494 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
495 0, pwfx, NULL);
496 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
497
498 CoTaskMemFree(pwfx);
499
500 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
501 ok(hr == S_OK, "GetService failed: %08x\n", hr);
502 if(hr != S_OK) {
503 IAudioClient_Release(ac);
504 return;
505 }
506
507 IAudioRenderClient_AddRef(rc);
508 ref = IAudioRenderClient_Release(rc);
509 ok(ref != 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
510
511 ref = IAudioClient_Release(ac);
512 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
513
514 ref = IAudioRenderClient_Release(rc);
515 ok(ref == 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
516
517 /* ISimpleAudioVolume */
518 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
519 NULL, (void**)&ac);
520 ok(hr == S_OK, "Activation failed with %08x\n", hr);
521 if(hr != S_OK)
522 return;
523
524 hr = IAudioClient_GetMixFormat(ac, &pwfx);
525 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
526
527 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
528 0, pwfx, NULL);
529 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
530
531 CoTaskMemFree(pwfx);
532
533 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
534 ok(hr == S_OK, "GetService failed: %08x\n", hr);
535
536 ISimpleAudioVolume_AddRef(sav);
537 ref = ISimpleAudioVolume_Release(sav);
538 ok(ref != 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
539
540 ref = IAudioClient_Release(ac);
541 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
542
543 ref = ISimpleAudioVolume_Release(sav);
544 ok(ref == 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
545
546 /* IAudioClock */
547 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
548 NULL, (void**)&ac);
549 ok(hr == S_OK, "Activation failed with %08x\n", hr);
550 if(hr != S_OK)
551 return;
552
553 hr = IAudioClient_GetMixFormat(ac, &pwfx);
554 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
555
556 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
557 0, pwfx, NULL);
558 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
559
560 CoTaskMemFree(pwfx);
561
562 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
563 ok(hr == S_OK, "GetService failed: %08x\n", hr);
564
565 IAudioClock_AddRef(acl);
566 ref = IAudioClock_Release(acl);
567 ok(ref != 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
568
569 ref = IAudioClient_Release(ac);
570 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
571
572 ref = IAudioClock_Release(acl);
573 ok(ref == 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
574
575 /* IAudioStreamVolume */
576 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
577 NULL, (void**)&ac);
578 ok(hr == S_OK, "Activation failed with %08x\n", hr);
579 if(hr != S_OK)
580 return;
581
582 hr = IAudioClient_GetMixFormat(ac, &pwfx);
583 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
584
585 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
586 0, pwfx, NULL);
587 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
588
589 CoTaskMemFree(pwfx);
590
591 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
592 ok(hr == S_OK, "GetService failed: %08x\n", hr);
593
594 IAudioStreamVolume_AddRef(asv);
595 ref = IAudioStreamVolume_Release(asv);
596 ok(ref != 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
597
598 ref = IAudioClient_Release(ac);
599 ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
600
601 ref = IAudioStreamVolume_Release(asv);
602 ok(ref == 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
603 }
604
605 static void test_event(void)
606 {
607 HANDLE event;
608 HRESULT hr;
609 DWORD r;
610 IAudioClient *ac;
611 WAVEFORMATEX *pwfx;
612
613 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
614 NULL, (void**)&ac);
615 ok(hr == S_OK, "Activation failed with %08x\n", hr);
616 if(hr != S_OK)
617 return;
618
619 hr = IAudioClient_GetMixFormat(ac, &pwfx);
620 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
621
622 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
623 AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
624 0, pwfx, NULL);
625 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
626
627 CoTaskMemFree(pwfx);
628
629 event = CreateEventW(NULL, FALSE, FALSE, NULL);
630 ok(event != NULL, "CreateEvent failed\n");
631
632 hr = IAudioClient_Start(ac);
633 ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET ||
634 hr == D3D11_ERROR_4E /* win10 */, "Start failed: %08x\n", hr);
635
636 hr = IAudioClient_SetEventHandle(ac, event);
637 ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
638
639 hr = IAudioClient_SetEventHandle(ac, event);
640 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME) ||
641 hr == E_UNEXPECTED /* win10 */, "SetEventHandle returns %08x\n", hr);
642
643 r = WaitForSingleObject(event, 40);
644 ok(r == WAIT_TIMEOUT, "Wait(event) before Start gave %x\n", r);
645
646 hr = IAudioClient_Start(ac);
647 ok(hr == S_OK, "Start failed: %08x\n", hr);
648
649 r = WaitForSingleObject(event, 20);
650 ok(r == WAIT_OBJECT_0, "Wait(event) after Start gave %x\n", r);
651
652 hr = IAudioClient_Stop(ac);
653 ok(hr == S_OK, "Stop failed: %08x\n", hr);
654
655 ok(ResetEvent(event), "ResetEvent\n");
656
657 /* Still receiving events! */
658 r = WaitForSingleObject(event, 20);
659 ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r);
660
661 hr = IAudioClient_Reset(ac);
662 ok(hr == S_OK, "Reset failed: %08x\n", hr);
663
664 ok(ResetEvent(event), "ResetEvent\n");
665
666 r = WaitForSingleObject(event, 120);
667 ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r);
668
669 hr = IAudioClient_SetEventHandle(ac, NULL);
670 ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
671
672 r = WaitForSingleObject(event, 70);
673 ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r);
674
675 /* test releasing a playing stream */
676 hr = IAudioClient_Start(ac);
677 ok(hr == S_OK, "Start failed: %08x\n", hr);
678 IAudioClient_Release(ac);
679
680 CloseHandle(event);
681 }
682
683 static void test_padding(void)
684 {
685 HRESULT hr;
686 IAudioClient *ac;
687 IAudioRenderClient *arc;
688 WAVEFORMATEX *pwfx;
689 REFERENCE_TIME minp, defp;
690 BYTE *buf, silence;
691 UINT32 psize, pad, written, i;
692
693 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
694 NULL, (void**)&ac);
695 ok(hr == S_OK, "Activation failed with %08x\n", hr);
696 if(hr != S_OK)
697 return;
698
699 hr = IAudioClient_GetMixFormat(ac, &pwfx);
700 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
701 if(hr != S_OK)
702 return;
703
704 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
705 0, 5000000, 0, pwfx, NULL);
706 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
707 if(hr != S_OK)
708 return;
709
710 if(pwfx->wBitsPerSample == 8)
711 silence = 128;
712 else
713 silence = 0;
714
715 /** GetDevicePeriod
716 * Default (= shared) device period is 10ms (e.g. 441 frames at 44100),
717 * except when the HW/OS forces a particular alignment,
718 * e.g. 10.1587ms is 28 * 16 = 448 frames at 44100 with HDA.
719 * 441 observed with Vista, 448 with w7 on the same HW! */
720 hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
721 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
722 /* some wineXYZ.drv use 20ms, not seen on native */
723 ok(defp == 100000 || broken(defp == 101587) || defp == 200000,
724 "Expected 10ms default period: %u\n", (ULONG)defp);
725 ok(minp != 0, "Minimum period is 0\n");
726 ok(minp <= defp, "Minimum period is greater than default period\n");
727
728 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
729 ok(hr == S_OK, "GetService failed: %08x\n", hr);
730
731 psize = MulDiv(defp, pwfx->nSamplesPerSec, 10000000) * 10;
732
733 written = 0;
734 hr = IAudioClient_GetCurrentPadding(ac, &pad);
735 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
736 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
737
738 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
739 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
740 ok(buf != NULL, "NULL buffer returned\n");
741 if(!win10){
742 /* win10 appears not to clear the buffer */
743 for(i = 0; i < psize * pwfx->nBlockAlign; ++i){
744 if(buf[i] != silence){
745 ok(0, "buffer has data in it already, i: %u, valu: %f\n", i, *((float*)buf));
746 break;
747 }
748 }
749 }
750
751 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
752 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "GetBuffer 0 size failed: %08x\n", hr);
753 ok(buf == NULL, "GetBuffer 0 gave %p\n", buf);
754 /* MSDN instead documents buf remains untouched */
755
756 hr = IAudioClient_Reset(ac);
757 ok(hr == AUDCLNT_E_BUFFER_OPERATION_PENDING, "Reset failed: %08x\n", hr);
758
759 hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
760 AUDCLNT_BUFFERFLAGS_SILENT);
761 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
762 if(hr == S_OK) written += psize;
763
764 hr = IAudioClient_GetCurrentPadding(ac, &pad);
765 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
766 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
767
768 psize = MulDiv(minp, pwfx->nSamplesPerSec, 10000000) * 10;
769
770 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
771 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
772 ok(buf != NULL, "NULL buffer returned\n");
773
774 hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
775 AUDCLNT_BUFFERFLAGS_SILENT);
776 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
777 written += psize;
778
779 hr = IAudioClient_GetCurrentPadding(ac, &pad);
780 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
781 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
782
783 /* overfull buffer. requested 1/2s buffer size, so try
784 * to get a 1/2s buffer, which should fail */
785 psize = pwfx->nSamplesPerSec / 2;
786 buf = (void*)0xDEADF00D;
787 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
788 ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
789 ok(buf == NULL, "NULL expected %p\n", buf);
790
791 hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
792 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
793
794 psize = MulDiv(minp, pwfx->nSamplesPerSec, 10000000) * 2;
795
796 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
797 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
798 ok(buf != NULL, "NULL buffer returned\n");
799
800 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
801 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
802
803 buf = (void*)0xDEADF00D;
804 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
805 ok(hr == S_OK, "GetBuffer 0 size failed: %08x\n", hr);
806 ok(buf == NULL, "GetBuffer 0 gave %p\n", buf);
807 /* MSDN instead documents buf remains untouched */
808
809 buf = (void*)0xDEADF00D;
810 hr = IAudioRenderClient_GetBuffer(arc, 0, &buf);
811 ok(hr == S_OK, "GetBuffer 0 size #2 failed: %08x\n", hr);
812 ok(buf == NULL, "GetBuffer 0 #2 gave %p\n", buf);
813
814 hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
815 ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer not size 0 gave %08x\n", hr);
816
817 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
818 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
819 ok(buf != NULL, "NULL buffer returned\n");
820
821 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
822 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
823
824 hr = IAudioClient_GetCurrentPadding(ac, &pad);
825 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
826 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
827
828 hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
829 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
830 ok(buf != NULL, "NULL buffer returned\n");
831
832 hr = IAudioRenderClient_ReleaseBuffer(arc, psize+1, AUDCLNT_BUFFERFLAGS_SILENT);
833 ok(hr == AUDCLNT_E_INVALID_SIZE, "ReleaseBuffer too large error: %08x\n", hr);
834 /* todo_wine means Wine may overwrite memory */
835 if(hr == S_OK) written += psize+1;
836
837 /* Buffer still hold */
838 hr = IAudioRenderClient_ReleaseBuffer(arc, psize/2, AUDCLNT_BUFFERFLAGS_SILENT);
839 ok(hr == S_OK, "ReleaseBuffer after error: %08x\n", hr);
840 if(hr == S_OK) written += psize/2;
841
842 hr = IAudioRenderClient_ReleaseBuffer(arc, 0, 0);
843 ok(hr == S_OK, "ReleaseBuffer 0 gave wrong error: %08x\n", hr);
844
845 hr = IAudioClient_GetCurrentPadding(ac, &pad);
846 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
847 ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
848
849 CoTaskMemFree(pwfx);
850
851 IAudioRenderClient_Release(arc);
852 IAudioClient_Release(ac);
853 }
854
855 static void test_clock(int share)
856 {
857 HRESULT hr;
858 IAudioClient *ac;
859 IAudioClock *acl;
860 IAudioRenderClient *arc;
861 UINT64 freq, pos, pcpos0, pcpos, last;
862 UINT32 pad, gbsize, bufsize, fragment, parts, avail, slept = 0, sum = 0;
863 BYTE *data;
864 WAVEFORMATEX *pwfx;
865 LARGE_INTEGER hpctime, hpctime0, hpcfreq;
866 REFERENCE_TIME minp, defp, t1, t2;
867 REFERENCE_TIME duration = 5000000, period = 150000;
868 int i;
869
870 ok(QueryPerformanceFrequency(&hpcfreq), "PerfFrequency failed\n");
871
872 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
873 NULL, (void**)&ac);
874 ok(hr == S_OK, "Activation failed with %08x\n", hr);
875 if(hr != S_OK)
876 return;
877
878 hr = IAudioClient_GetMixFormat(ac, &pwfx);
879 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
880 if(hr != S_OK)
881 return;
882
883 hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
884 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
885 ok(minp <= period, "desired period %u too small for %u\n", (ULONG)period, (ULONG)minp);
886
887 if (share) {
888 trace("Testing shared mode\n");
889 /* period is ignored */
890 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
891 0, duration, period, pwfx, NULL);
892 period = defp;
893 } else {
894 pwfx->wFormatTag = WAVE_FORMAT_PCM;
895 pwfx->nChannels = 2;
896 pwfx->cbSize = 0;
897 pwfx->wBitsPerSample = 16; /* no floating point */
898 pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
899 pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
900 trace("Testing exclusive mode at %u\n", pwfx->nSamplesPerSec);
901
902 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_EXCLUSIVE,
903 0, duration, period, pwfx, NULL);
904 }
905 ok(share ? hr == S_OK : hr == hexcl || hr == AUDCLNT_E_DEVICE_IN_USE, "Initialize failed: %08x\n", hr);
906 if (hr != S_OK) {
907 CoTaskMemFree(pwfx);
908 IAudioClient_Release(ac);
909 if(hr == AUDCLNT_E_DEVICE_IN_USE)
910 skip("Device in use, no %s access\n", share ? "shared" : "exclusive");
911 return;
912 }
913
914 /** GetStreamLatency
915 * Shared mode: 1x period + a little, but some 192000 devices return 5.3334ms.
916 * Exclusive mode: testbot returns 2x period + a little, but
917 * some HDA drivers return 1x period, some + a little. */
918 hr = IAudioClient_GetStreamLatency(ac, &t2);
919 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
920 trace("Latency: %u.%04u ms\n", (UINT)(t2/10000), (UINT)(t2 % 10000));
921 ok(t2 >= period || broken(t2 >= period/2 && share && pwfx->nSamplesPerSec > 48000) ||
922 broken(t2 == 0) /* win10 */,
923 "Latency < default period, delta %ldus\n", (long)((t2-period)/10));
924
925 /** GetBufferSize
926 * BufferSize must be rounded up, maximum 2s says MSDN.
927 * Both is wrong. Rounding may lead to size a little smaller than duration;
928 * duration > 2s is accepted in shared mode.
929 * Shared mode: round solely w.r.t. mixer rate,
930 * duration is no multiple of period.
931 * Exclusive mode: size appears as a multiple of some fragment that
932 * is either the rounded period or a fixed constant like 1024,
933 * whatever the driver implements. */
934 hr = IAudioClient_GetBufferSize(ac, &gbsize);
935 ok(hr == S_OK, "GetBufferSize failed: %08x\n", hr);
936
937 bufsize = MulDiv(duration, pwfx->nSamplesPerSec, 10000000);
938 fragment = MulDiv(period, pwfx->nSamplesPerSec, 10000000);
939 parts = MulDiv(bufsize, 1, fragment); /* instead of (duration, 1, period) */
940 trace("BufferSize %u estimated fragment %u x %u = %u\n", gbsize, fragment, parts, fragment * parts);
941 /* fragment size (= period in frames) is rounded up.
942 * BufferSize must be rounded up, maximum 2s says MSDN
943 * but it is rounded down modulo fragment ! */
944 if (share)
945 ok(gbsize == bufsize,
946 "BufferSize %u at rate %u\n", gbsize, pwfx->nSamplesPerSec);
947 else
948 ok(gbsize == parts * fragment || gbsize == MulDiv(bufsize, 1, 1024) * 1024,
949 "BufferSize %u misfits fragment size %u at rate %u\n", gbsize, fragment, pwfx->nSamplesPerSec);
950
951 /* In shared mode, GetCurrentPadding decreases in multiples of
952 * fragment size (i.e. updated only at period ticks), whereas
953 * GetPosition appears to be reporting continuous positions.
954 * In exclusive mode, testbot behaves likewise, but native's Intel
955 * HDA driver shows no such deltas, GetCurrentPadding closely
956 * matches GetPosition, as in
957 * GetCurrentPadding = GetPosition - frames held in mmdevapi */
958
959 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
960 ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
961
962 hr = IAudioClock_GetFrequency(acl, &freq);
963 ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
964 trace("Clock Frequency %u\n", (UINT)freq);
965
966 /* MSDN says it's arbitrary units, but shared mode is unlikely to change */
967 if (share)
968 ok(freq == pwfx->nSamplesPerSec * pwfx->nBlockAlign,
969 "Clock Frequency %u\n", (UINT)freq);
970 else
971 ok(freq == pwfx->nSamplesPerSec,
972 "Clock Frequency %u\n", (UINT)freq);
973
974 hr = IAudioClock_GetPosition(acl, NULL, NULL);
975 ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
976
977 pcpos0 = 0;
978 hr = IAudioClock_GetPosition(acl, &pos, &pcpos0);
979 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
980 ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
981 ok(pcpos0 != 0, "GetPosition returned zero pcpos\n");
982
983 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
984 ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
985
986 hr = IAudioRenderClient_GetBuffer(arc, gbsize+1, &data);
987 ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer too large failed: %08x\n", hr);
988
989 avail = gbsize;
990 data = NULL;
991 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
992 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
993 trace("data at %p\n", data);
994
995 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, winetest_debug>2 ?
996 wave_generate_tone(pwfx, data, avail) : AUDCLNT_BUFFERFLAGS_SILENT);
997 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
998 if(hr == S_OK) sum += avail;
999
1000 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1001 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1002 ok(pad == sum, "padding %u prior to start\n", pad);
1003
1004 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1005 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1006 ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
1007
1008 hr = IAudioClient_Start(ac); /* #1 */
1009 ok(hr == S_OK, "Start failed: %08x\n", hr);
1010
1011 Sleep(100);
1012 slept += 100;
1013
1014 hr = IAudioClient_GetStreamLatency(ac, &t1);
1015 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1016 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1017
1018 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1019 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1020 ok(pos > 0, "Position %u vs. last %u\n", (UINT)pos,0);
1021 /* in rare cases is slept*1.1 not enough with dmix */
1022 ok(pos*1000/freq <= slept*1.4, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1023 last = pos;
1024
1025 hr = IAudioClient_Stop(ac);
1026 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1027
1028 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1029 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1030 ok(pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1031 last = pos;
1032 if(/*share &&*/ winetest_debug>1)
1033 ok(pos*1000/freq <= slept*1.1, "Position %u too far after stop %ums\n", (UINT)pos, slept);
1034
1035 hr = IAudioClient_Start(ac); /* #2 */
1036 ok(hr == S_OK, "Start failed: %08x\n", hr);
1037
1038 Sleep(100);
1039 slept += 100;
1040
1041 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1042 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1043 trace("padding %u past sleep #2\n", pad);
1044
1045 /** IAudioClient_Stop
1046 * Exclusive mode: the audio engine appears to drop frames,
1047 * bumping GetPosition to a higher value than time allows, even
1048 * allowing GetPosition > sum Released - GetCurrentPadding (testbot)
1049 * Shared mode: no drop observed (or too small to be visible).
1050 * GetPosition = sum Released - GetCurrentPadding
1051 * Bugs: Some USB headset system drained the whole buffer, leaving
1052 * padding 0 and bumping pos to sum minus 17 frames! */
1053
1054 hr = IAudioClient_Stop(ac);
1055 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1056
1057 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1058 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1059
1060 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1061 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1062 trace("padding %u position %u past stop #2\n", pad, (UINT)pos);
1063 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1064 /* Prove that Stop must not drop frames (in shared mode). */
1065 ok(pad ? pos > last : pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1066 if (share && pad > 0 && winetest_debug>1)
1067 ok(pos*1000/freq <= slept*1.1, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1068 /* in exclusive mode, testbot's w7 machines yield pos > sum-pad */
1069 if(/*share &&*/ winetest_debug>1)
1070 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
1071 "Position %u after stop vs. %u padding\n", (UINT)pos, pad);
1072 last = pos;
1073
1074 Sleep(100);
1075
1076 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1077 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1078 ok(pos == last, "Position %u should stop.\n", (UINT)pos);
1079
1080 /* Restart from 0 */
1081 hr = IAudioClient_Reset(ac);
1082 ok(hr == S_OK, "Reset failed: %08x\n", hr);
1083 slept = sum = 0;
1084
1085 hr = IAudioClient_Reset(ac);
1086 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
1087
1088 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1089 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1090 ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
1091 ok(pcpos > pcpos0, "pcpos should increase\n");
1092
1093 avail = gbsize; /* implies GetCurrentPadding == 0 */
1094 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1095 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
1096 trace("data at %p\n", data);
1097
1098 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, winetest_debug>2 ?
1099 wave_generate_tone(pwfx, data, avail) : AUDCLNT_BUFFERFLAGS_SILENT);
1100 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
1101 if(hr == S_OK) sum += avail;
1102
1103 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1104 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1105 ok(pad == sum, "padding %u prior to start\n", pad);
1106
1107 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1108 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1109 ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
1110 last = pos;
1111
1112 hr = IAudioClient_Start(ac); /* #3 */
1113 ok(hr == S_OK, "Start failed: %08x\n", hr);
1114
1115 Sleep(100);
1116 slept += 100;
1117
1118 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1119 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1120 trace("position %u past %ums sleep #3\n", (UINT)pos, slept);
1121 ok(pos > last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1122 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1123 if (winetest_debug>1)
1124 ok(pos*1000/freq <= slept*1.1, "Position %u too far after playing %ums\n", (UINT)pos, slept);
1125 else
1126 skip("Rerun with WINETEST_DEBUG=2 for GetPosition tests.\n");
1127 last = pos;
1128
1129 hr = IAudioClient_Reset(ac);
1130 ok(hr == AUDCLNT_E_NOT_STOPPED, "Reset while playing: %08x\n", hr);
1131
1132 hr = IAudioClient_Stop(ac);
1133 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1134
1135 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1136 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1137
1138 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1139 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1140 trace("padding %u position %u past stop #3\n", pad, (UINT)pos);
1141 ok(pos >= last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1142 ok(pcpos > pcpos0, "pcpos should increase\n");
1143 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1144 if (pad > 0 && winetest_debug>1)
1145 ok(pos*1000/freq <= slept*1.1, "Position %u too far after stop %ums\n", (UINT)pos, slept);
1146 if(winetest_debug>1)
1147 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
1148 "Position %u after stop vs. %u padding\n", (UINT)pos, pad);
1149 last = pos;
1150
1151 /* Begin the big loop */
1152 hr = IAudioClient_Reset(ac);
1153 ok(hr == S_OK, "Reset failed: %08x\n", hr);
1154 slept = last = sum = 0;
1155 pcpos0 = pcpos;
1156
1157 ok(QueryPerformanceCounter(&hpctime0), "PerfCounter unavailable\n");
1158
1159 hr = IAudioClient_Reset(ac);
1160 ok(hr == S_OK, "Reset on an already reset stream returns %08x\n", hr);
1161
1162 hr = IAudioClient_Start(ac);
1163 ok(hr == S_OK, "Start failed: %08x\n", hr);
1164
1165 avail = pwfx->nSamplesPerSec * 15 / 16 / 2;
1166 data = NULL;
1167 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1168 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
1169 trace("data at %p for prefill %u\n", data, avail);
1170
1171 if (winetest_debug>2) {
1172 hr = IAudioClient_Stop(ac);
1173 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1174
1175 Sleep(20);
1176 slept += 20;
1177
1178 hr = IAudioClient_Reset(ac);
1179 ok(hr == AUDCLNT_E_BUFFER_OPERATION_PENDING, "Reset failed: %08x\n", hr);
1180
1181 hr = IAudioClient_Start(ac);
1182 ok(hr == S_OK, "Start failed: %08x\n", hr);
1183 }
1184
1185 /* Despite passed time, data must still point to valid memory... */
1186 hr = IAudioRenderClient_ReleaseBuffer(arc, avail,
1187 wave_generate_tone(pwfx, data, avail));
1188 ok(hr == S_OK, "ReleaseBuffer after stop+start failed: %08x\n", hr);
1189 if(hr == S_OK) sum += avail;
1190
1191 /* GetCurrentPadding(GCP) == 0 does not mean an underrun happened, as the
1192 * mixer may still have a little data. We believe an underrun will occur
1193 * when the mixer finds GCP smaller than a period size at the *end* of a
1194 * period cycle, i.e. shortly before calling SetEvent to signal the app
1195 * that it has ~10ms to supply data for the next cycle. IOW, a zero GCP
1196 * with no data written for over a period causes an underrun. */
1197
1198 Sleep(350);
1199 slept += 350;
1200 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1201 trace("hpctime %u after %ums\n",
1202 (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart), slept);
1203
1204 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1205 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1206 ok(pos > last, "Position %u vs. last %u\n", (UINT)pos,(UINT)last);
1207 last = pos;
1208
1209 for(i=0; i < 9; i++) {
1210 Sleep(100);
1211 slept += 100;
1212
1213 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
1214 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1215
1216 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1217 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1218
1219 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1220 trace("hpctime %u pcpos %u\n",
1221 (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart),
1222 (ULONG)((pcpos-pcpos0)/10000));
1223
1224 /* Use sum-pad to see whether position is ahead padding or not. */
1225 trace("padding %u position %u/%u slept %ums iteration %d\n", pad, (UINT)pos, sum-pad, slept, i);
1226 ok(pad ? pos > last : pos >= last, "No position increase at iteration %d\n", i);
1227 ok(pos * pwfx->nSamplesPerSec <= sum * freq, "Position %u > written %u\n", (UINT)pos, sum);
1228 if (winetest_debug>1) {
1229 /* Padding does not lag behind by much */
1230 ok(pos * pwfx->nSamplesPerSec <= (sum-pad+fragment) * freq, "Position %u > written %u\n", (UINT)pos, sum);
1231 ok(pos*1000/freq <= slept*1.1, "Position %u too far after %ums\n", (UINT)pos, slept);
1232 if (pad) /* not in case of underrun */
1233 ok((pos-last)*1000/freq >= 90 && 110 >= (pos-last)*1000/freq,
1234 "Position delta %ld not regular: %ld ms\n", (long)(pos-last), (long)((pos-last)*1000/freq));
1235 }
1236 last = pos;
1237
1238 hr = IAudioClient_GetStreamLatency(ac, &t1);
1239 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1240 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1241
1242 avail = pwfx->nSamplesPerSec * 15 / 16 / 2;
1243 data = NULL;
1244 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1245 /* ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE || (hr == S_OK && i==0) without todo_wine */
1246 ok(hr == S_OK || hr == AUDCLNT_E_BUFFER_TOO_LARGE,
1247 "GetBuffer large (%u) failed: %08x\n", avail, hr);
1248 if(hr == S_OK && i) ok(FALSE, "GetBuffer large (%u) at iteration %d\n", avail, i);
1249 /* Only the first iteration should allow that large a buffer
1250 * as prefill was drained during the first 350+100ms sleep.
1251 * Afterwards, only 100ms of data should find room per iteration. */
1252
1253 if(hr == S_OK) {
1254 trace("data at %p\n", data);
1255 } else {
1256 avail = gbsize - pad;
1257 hr = IAudioRenderClient_GetBuffer(arc, avail, &data);
1258 ok(hr == S_OK, "GetBuffer small %u failed: %08x\n", avail, hr);
1259 trace("data at %p (small %u)\n", data, avail);
1260 }
1261 ok(data != NULL, "NULL buffer returned\n");
1262 if(i % 3 && !winetest_interactive) {
1263 memset(data, 0, avail * pwfx->nBlockAlign);
1264 hr = IAudioRenderClient_ReleaseBuffer(arc, avail, 0);
1265 } else {
1266 hr = IAudioRenderClient_ReleaseBuffer(arc, avail,
1267 wave_generate_tone(pwfx, data, avail));
1268 }
1269 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
1270 if(hr == S_OK) sum += avail;
1271 }
1272
1273 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1274 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1275 trace("position %u\n", (UINT)pos);
1276
1277 Sleep(1000); /* 500ms buffer underrun past full buffer */
1278
1279 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1280 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
1281
1282 hr = IAudioClock_GetPosition(acl, &pos, NULL);
1283 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
1284 trace("position %u past underrun, %u padding left, %u frames written\n", (UINT)pos, pad, sum);
1285
1286 if (share) {
1287 /* Following underrun, all samples were played */
1288 ok(pad == 0, "GetCurrentPadding returned %u, should be 0\n", pad);
1289 ok(pos * pwfx->nSamplesPerSec == sum * freq,
1290 "Position %u at end vs. %u submitted frames\n", (UINT)pos, sum);
1291 } else {
1292 /* Vista and w2k8 leave partial fragments behind */
1293 ok(pad == 0 /* w7, w2k8R2 */||
1294 pos * pwfx->nSamplesPerSec == (sum-pad) * freq, "GetCurrentPadding returned %u, should be 0\n", pad);
1295 /* expect at most 5 fragments (75ms) away */
1296 ok(pos * pwfx->nSamplesPerSec <= sum * freq &&
1297 pos * pwfx->nSamplesPerSec + 5 * fragment * freq >= sum * freq,
1298 "Position %u at end vs. %u submitted frames\n", (UINT)pos, sum);
1299 }
1300
1301 hr = IAudioClient_GetStreamLatency(ac, &t1);
1302 ok(hr == S_OK, "GetStreamLatency failed: %08x\n", hr);
1303 ok(t1 == t2, "Latency not constant, delta %ld\n", (long)(t1-t2));
1304
1305 ok(QueryPerformanceCounter(&hpctime), "PerfCounter failed\n");
1306 trace("hpctime %u after underrun\n", (ULONG)((hpctime.QuadPart-hpctime0.QuadPart)*1000/hpcfreq.QuadPart));
1307
1308 hr = IAudioClient_Stop(ac);
1309 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1310
1311 CoTaskMemFree(pwfx);
1312
1313 IAudioClock_Release(acl);
1314 IAudioRenderClient_Release(arc);
1315 IAudioClient_Release(ac);
1316 }
1317
1318 static void test_session(void)
1319 {
1320 IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac;
1321 IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl = NULL;
1322 IMMDevice *cap_dev;
1323 GUID ses1_guid;
1324 AudioSessionState state;
1325 WAVEFORMATEX *pwfx;
1326 ULONG ref;
1327 HRESULT hr;
1328
1329 hr = CoCreateGuid(&ses1_guid);
1330 ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1331
1332 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1333 NULL, (void**)&ses1_ac1);
1334 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1335 if (FAILED(hr)) return;
1336
1337 hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
1338 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1339
1340 hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
1341 0, 5000000, 0, pwfx, &ses1_guid);
1342 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1343
1344 if(hr == S_OK){
1345 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1346 NULL, (void**)&ses1_ac2);
1347 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1348 }
1349 if(hr != S_OK){
1350 skip("Unable to open the same device twice. Skipping session tests\n");
1351
1352 ref = IAudioClient_Release(ses1_ac1);
1353 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1354 CoTaskMemFree(pwfx);
1355 return;
1356 }
1357
1358 hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
1359 0, 5000000, 0, pwfx, &ses1_guid);
1360 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1361
1362 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1363 eMultimedia, &cap_dev);
1364 if(hr == S_OK){
1365 hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1366 NULL, (void**)&cap_ac);
1367 ok((hr == S_OK)^(cap_ac == NULL), "Activate %08x &out pointer\n", hr);
1368 ok(hr == S_OK, "Activate failed: %08x\n", hr);
1369 IMMDevice_Release(cap_dev);
1370 }
1371 if(hr == S_OK){
1372 WAVEFORMATEX *cap_pwfx;
1373
1374 hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1375 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1376
1377 hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1378 0, 5000000, 0, cap_pwfx, &ses1_guid);
1379 ok(hr == S_OK, "Initialize failed for capture in rendering session: %08x\n", hr);
1380 CoTaskMemFree(cap_pwfx);
1381 }
1382 if(hr == S_OK){
1383 hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
1384 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1385 if(FAILED(hr))
1386 cap_ctl = NULL;
1387 }else
1388 skip("No capture session: %08x; skipping capture device in render session tests\n", hr);
1389
1390 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
1391 ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
1392
1393 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
1394 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1395
1396 hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
1397 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1398 ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
1399 ref = IAudioSessionControl2_Release(ses1_ctl2);
1400 ok(ref != 0, "AudioSessionControl was destroyed\n");
1401
1402 hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
1403 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1404
1405 hr = IAudioSessionControl2_GetState(ses1_ctl, NULL);
1406 ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
1407
1408 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1409 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1410 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1411
1412 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1413 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1414 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1415
1416 if(cap_ctl){
1417 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1418 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1419 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1420 }
1421
1422 hr = IAudioClient_Start(ses1_ac1);
1423 ok(hr == S_OK, "Start failed: %08x\n", hr);
1424
1425 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1426 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1427 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1428
1429 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1430 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1431 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1432
1433 if(cap_ctl){
1434 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1435 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1436 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1437 }
1438
1439 hr = IAudioClient_Stop(ses1_ac1);
1440 ok(hr == S_OK, "Start failed: %08x\n", hr);
1441
1442 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1443 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1444 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1445
1446 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1447 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1448 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1449
1450 if(cap_ctl){
1451 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1452 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1453 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1454
1455 hr = IAudioClient_Start(cap_ac);
1456 ok(hr == S_OK, "Start failed: %08x\n", hr);
1457
1458 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1459 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1460 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1461
1462 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1463 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1464 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1465
1466 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1467 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1468 ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
1469
1470 hr = IAudioClient_Stop(cap_ac);
1471 ok(hr == S_OK, "Stop failed: %08x\n", hr);
1472
1473 hr = IAudioSessionControl2_GetState(ses1_ctl, &state);
1474 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1475 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1476
1477 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1478 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1479 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1480
1481 hr = IAudioSessionControl2_GetState(cap_ctl, &state);
1482 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1483 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1484
1485 ref = IAudioSessionControl2_Release(cap_ctl);
1486 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1487
1488 ref = IAudioClient_Release(cap_ac);
1489 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1490 }
1491
1492 ref = IAudioSessionControl2_Release(ses1_ctl);
1493 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1494
1495 ref = IAudioClient_Release(ses1_ac1);
1496 ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
1497
1498 ref = IAudioClient_Release(ses1_ac2);
1499 ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
1500
1501 /* we've released all of our IAudioClient references, so check GetState */
1502 hr = IAudioSessionControl2_GetState(ses1_ctl2, &state);
1503 ok(hr == S_OK, "GetState failed: %08x\n", hr);
1504 ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
1505
1506 ref = IAudioSessionControl2_Release(ses1_ctl2);
1507 ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
1508
1509 CoTaskMemFree(pwfx);
1510 }
1511
1512 static void test_streamvolume(void)
1513 {
1514 IAudioClient *ac;
1515 IAudioStreamVolume *asv;
1516 WAVEFORMATEX *fmt;
1517 UINT32 chans, i;
1518 HRESULT hr;
1519 float vol, *vols;
1520
1521 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1522 NULL, (void**)&ac);
1523 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1524 if(hr != S_OK)
1525 return;
1526
1527 hr = IAudioClient_GetMixFormat(ac, &fmt);
1528 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1529
1530 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
1531 0, fmt, NULL);
1532 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1533
1534 if(hr == S_OK){
1535 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1536 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1537 }
1538 if(hr != S_OK){
1539 IAudioClient_Release(ac);
1540 CoTaskMemFree(fmt);
1541 return;
1542 }
1543
1544 hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
1545 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1546
1547 hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
1548 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1549 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
1550
1551 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
1552 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1553
1554 hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
1555 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
1556
1557 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
1558 ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
1559
1560 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1561 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1562 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
1563
1564 hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
1565 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1566
1567 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
1568 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1569
1570 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
1571 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1572
1573 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1574 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1575
1576 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1577 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1578 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1579
1580 hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
1581 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
1582
1583 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
1584 ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
1585
1586 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1587 ok(vols != NULL, "HeapAlloc failed\n");
1588
1589 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
1590 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1591
1592 hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
1593 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1594 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1595 for(i = 1; i < fmt->nChannels; ++i)
1596 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1597
1598 hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
1599 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
1600
1601 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
1602 ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
1603
1604 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
1605 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1606
1607 hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
1608 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1609
1610 HeapFree(GetProcessHeap(), 0, vols);
1611 IAudioStreamVolume_Release(asv);
1612 IAudioClient_Release(ac);
1613 CoTaskMemFree(fmt);
1614 }
1615
1616 static void test_channelvolume(void)
1617 {
1618 IAudioClient *ac;
1619 IChannelAudioVolume *acv;
1620 WAVEFORMATEX *fmt;
1621 UINT32 chans, i;
1622 HRESULT hr;
1623 float vol, *vols;
1624
1625 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1626 NULL, (void**)&ac);
1627 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1628 if(hr != S_OK)
1629 return;
1630
1631 hr = IAudioClient_GetMixFormat(ac, &fmt);
1632 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1633
1634 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1635 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1636 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1637
1638 if(hr == S_OK){
1639 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
1640 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1641 }
1642 if(hr != S_OK){
1643 IAudioClient_Release(ac);
1644 CoTaskMemFree(fmt);
1645 return;
1646 }
1647
1648 hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
1649 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1650
1651 hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
1652 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1653 ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
1654
1655 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
1656 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1657
1658 hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
1659 ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
1660
1661 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
1662 ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
1663
1664 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
1665 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1666 ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
1667
1668 hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
1669 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1670
1671 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
1672 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1673
1674 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
1675 ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
1676
1677 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
1678 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1679
1680 hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
1681 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1682 ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1683
1684 hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
1685 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1686
1687 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
1688 ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1689
1690 vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1691 ok(vols != NULL, "HeapAlloc failed\n");
1692
1693 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
1694 ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1695
1696 hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1697 ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1698 ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1699 for(i = 1; i < fmt->nChannels; ++i)
1700 ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1701
1702 hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1703 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1704
1705 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1706 ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1707
1708 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1709 ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1710
1711 hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1712 ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1713
1714 hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1715 ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1716
1717 HeapFree(GetProcessHeap(), 0, vols);
1718 IChannelAudioVolume_Release(acv);
1719 IAudioClient_Release(ac);
1720 CoTaskMemFree(fmt);
1721 }
1722
1723 static void test_simplevolume(void)
1724 {
1725 IAudioClient *ac;
1726 ISimpleAudioVolume *sav;
1727 WAVEFORMATEX *fmt;
1728 HRESULT hr;
1729 float vol;
1730 BOOL mute;
1731
1732 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1733 NULL, (void**)&ac);
1734 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1735 if(hr != S_OK)
1736 return;
1737
1738 hr = IAudioClient_GetMixFormat(ac, &fmt);
1739 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1740
1741 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1742 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1743 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1744
1745 if(hr == S_OK){
1746 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1747 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1748 }
1749 if(hr != S_OK){
1750 IAudioClient_Release(ac);
1751 CoTaskMemFree(fmt);
1752 return;
1753 }
1754
1755 hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1756 ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1757
1758 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1759 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1760 ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1761
1762 hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1763 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1764
1765 hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1766 ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1767
1768 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1769 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1770
1771 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1772 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1773 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1774
1775 hr = ISimpleAudioVolume_GetMute(sav, NULL);
1776 ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1777
1778 mute = TRUE;
1779 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1780 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1781 ok(mute == FALSE, "Session is already muted\n");
1782
1783 hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1784 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1785
1786 mute = FALSE;
1787 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1788 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1789 ok(mute == TRUE, "Session should have been muted\n");
1790
1791 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1792 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1793 ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1794
1795 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1796 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1797
1798 mute = FALSE;
1799 hr = ISimpleAudioVolume_GetMute(sav, &mute);
1800 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1801 ok(mute == TRUE, "Session should have been muted\n");
1802
1803 hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1804 ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1805
1806 ISimpleAudioVolume_Release(sav);
1807 IAudioClient_Release(ac);
1808 CoTaskMemFree(fmt);
1809 }
1810
1811 static void test_volume_dependence(void)
1812 {
1813 IAudioClient *ac, *ac2;
1814 ISimpleAudioVolume *sav;
1815 IChannelAudioVolume *cav;
1816 IAudioStreamVolume *asv;
1817 WAVEFORMATEX *fmt;
1818 HRESULT hr;
1819 float vol;
1820 GUID session;
1821 UINT32 nch;
1822
1823 hr = CoCreateGuid(&session);
1824 ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1825
1826 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1827 NULL, (void**)&ac);
1828 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1829 if(hr != S_OK)
1830 return;
1831
1832 hr = IAudioClient_GetMixFormat(ac, &fmt);
1833 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1834
1835 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1836 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1837 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1838
1839 if(hr == S_OK){
1840 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1841 ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1842 }
1843 if(hr != S_OK){
1844 IAudioClient_Release(ac);
1845 CoTaskMemFree(fmt);
1846 return;
1847 }
1848
1849 hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1850 ok(hr == S_OK, "GetService (ChannelAudioVolume) failed: %08x\n", hr);
1851
1852 hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1853 ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1854
1855 hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1856 ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1857
1858 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1859 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1860
1861 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1862 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1863
1864 hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1865 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1866 ok(fabsf(vol - 0.2f) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1867
1868 hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1869 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1870 ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1871
1872 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1873 ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1874 ok(fabsf(vol - 0.6f) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1875
1876 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1877 NULL, (void**)&ac2);
1878 ok(hr == S_OK, "Activation failed with %08x\n", hr);
1879
1880 if(hr == S_OK){
1881 hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1882 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1883 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1884 if(hr != S_OK)
1885 IAudioClient_Release(ac2);
1886 }
1887
1888 if(hr == S_OK){
1889 IChannelAudioVolume *cav2;
1890 IAudioStreamVolume *asv2;
1891
1892 hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1893 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1894
1895 hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1896 ok(hr == S_OK, "GetService failed: %08x\n", hr);
1897
1898 hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1899 ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1900 ok(fabsf(vol - 0.4f) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1901
1902 hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1903 ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1904 ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1905
1906 hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1907 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1908 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1909
1910 hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
1911 ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1912 ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1913
1914 IAudioStreamVolume_Release(asv2);
1915 IChannelAudioVolume_Release(cav2);
1916 IAudioClient_Release(ac2);
1917 }else
1918 skip("Unable to open the same device twice. Skipping session volume control tests\n");
1919
1920 hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
1921 ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1922
1923 hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1924 ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1925
1926 CoTaskMemFree(fmt);
1927 ISimpleAudioVolume_Release(sav);
1928 IChannelAudioVolume_Release(cav);
1929 IAudioStreamVolume_Release(asv);
1930 IAudioClient_Release(ac);
1931 }
1932
1933 static void test_session_creation(void)
1934 {
1935 IMMDevice *cap_dev;
1936 IAudioClient *ac;
1937 IAudioSessionManager *sesm;
1938 ISimpleAudioVolume *sav;
1939 GUID session_guid;
1940 float vol;
1941 HRESULT hr;
1942 WAVEFORMATEX *fmt;
1943
1944 CoCreateGuid(&session_guid);
1945
1946 hr = IMMDevice_Activate(dev, &IID_IAudioSessionManager,
1947 CLSCTX_INPROC_SERVER, NULL, (void**)&sesm);
1948 ok((hr == S_OK)^(sesm == NULL), "Activate %08x &out pointer\n", hr);
1949 ok(hr == S_OK, "Activate failed: %08x\n", hr);
1950
1951 hr = IAudioSessionManager_GetSimpleAudioVolume(sesm, &session_guid,
1952 FALSE, &sav);
1953 ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1954
1955 hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1956 ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1957
1958 /* Release completely to show session persistence */
1959 ISimpleAudioVolume_Release(sav);
1960 IAudioSessionManager_Release(sesm);
1961
1962 /* test if we can create a capture audioclient in the session we just
1963 * created from a SessionManager derived from a render device */
1964 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1965 eMultimedia, &cap_dev);
1966 if(hr == S_OK){
1967 WAVEFORMATEX *cap_pwfx;
1968 IAudioClient *cap_ac;
1969 ISimpleAudioVolume *cap_sav;
1970 IAudioSessionManager *cap_sesm;
1971
1972 hr = IMMDevice_Activate(cap_dev, &IID_IAudioSessionManager,
1973 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_sesm);
1974 ok((hr == S_OK)^(cap_sesm == NULL), "Activate %08x &out pointer\n", hr);
1975 ok(hr == S_OK, "Activate failed: %08x\n", hr);
1976
1977 hr = IAudioSessionManager_GetSimpleAudioVolume(cap_sesm, &session_guid,
1978 FALSE, &cap_sav);
1979 ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1980
1981 vol = 0.5f;
1982 hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1983 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1984
1985 ISimpleAudioVolume_Release(cap_sav);
1986 IAudioSessionManager_Release(cap_sesm);
1987
1988 hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient,
1989 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_ac);
1990 ok(hr == S_OK, "Activate failed: %08x\n", hr);
1991
1992 IMMDevice_Release(cap_dev);
1993
1994 hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1995 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1996
1997 hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1998 0, 5000000, 0, cap_pwfx, &session_guid);
1999 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2000
2001 CoTaskMemFree(cap_pwfx);
2002
2003 if(hr == S_OK){
2004 hr = IAudioClient_GetService(cap_ac, &IID_ISimpleAudioVolume,
2005 (void**)&cap_sav);
2006 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2007 }
2008 if(hr == S_OK){
2009 vol = 0.5f;
2010 hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
2011 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
2012
2013 ISimpleAudioVolume_Release(cap_sav);
2014 }
2015
2016 IAudioClient_Release(cap_ac);
2017 }
2018
2019 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2020 NULL, (void**)&ac);
2021 ok((hr == S_OK)^(ac == NULL), "Activate %08x &out pointer\n", hr);
2022 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2023 if(hr != S_OK)
2024 return;
2025
2026 hr = IAudioClient_GetMixFormat(ac, &fmt);
2027 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2028
2029 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
2030 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session_guid);
2031 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2032
2033 hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
2034 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2035 if(hr == S_OK){
2036 vol = 0.5f;
2037 hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
2038 ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
2039 ok(fabs(vol - 0.6f) < 0.05f, "Got wrong volume: %f\n", vol);
2040
2041 ISimpleAudioVolume_Release(sav);
2042 }
2043
2044 CoTaskMemFree(fmt);
2045 IAudioClient_Release(ac);
2046 }
2047
2048 static void test_worst_case(void)
2049 {
2050 HANDLE event;
2051 HRESULT hr;
2052 IAudioClient *ac;
2053 IAudioRenderClient *arc;
2054 IAudioClock *acl;
2055 WAVEFORMATEX *pwfx;
2056 REFERENCE_TIME defp;
2057 UINT64 freq, pos, pcpos0, pcpos;
2058 BYTE *data;
2059 DWORD r;
2060 UINT32 pad, fragment, sum;
2061 int i,j;
2062
2063 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2064 NULL, (void**)&ac);
2065 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2066 if(hr != S_OK)
2067 return;
2068
2069 hr = IAudioClient_GetMixFormat(ac, &pwfx);
2070 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2071
2072 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
2073 AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 500000, 0, pwfx, NULL);
2074 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2075 if(hr != S_OK)
2076 return;
2077
2078 hr = IAudioClient_GetDevicePeriod(ac, &defp, NULL);
2079 ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
2080
2081 fragment = MulDiv(defp, pwfx->nSamplesPerSec, 10000000);
2082
2083 event = CreateEventW(NULL, FALSE, FALSE, NULL);
2084 ok(event != NULL, "CreateEvent failed\n");
2085
2086 hr = IAudioClient_SetEventHandle(ac, event);
2087 ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
2088
2089 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
2090 ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
2091
2092 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
2093 ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
2094
2095 hr = IAudioClock_GetFrequency(acl, &freq);
2096 ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
2097
2098 for(j = 0; j <= (winetest_interactive ? 9 : 2); j++){
2099 sum = 0;
2100 trace("Should play %ums continuous tone with fragment size %u.\n",
2101 (ULONG)(defp/100), fragment);
2102
2103 hr = IAudioClock_GetPosition(acl, &pos, &pcpos0);
2104 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
2105
2106 /* XAudio2 prefills one period, play without it */
2107 if(winetest_debug>2){
2108 hr = IAudioRenderClient_GetBuffer(arc, fragment, &data);
2109 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
2110
2111 hr = IAudioRenderClient_ReleaseBuffer(arc, fragment, AUDCLNT_BUFFERFLAGS_SILENT);
2112 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
2113 if(hr == S_OK)
2114 sum += fragment;
2115 }
2116
2117 hr = IAudioClient_Start(ac);
2118 ok(hr == S_OK, "Start failed: %08x\n", hr);
2119
2120 for(i = 0; i <= 99; i++){ /* 100 x 10ms = 1 second */
2121 r = WaitForSingleObject(event, 60 + defp / 10000);
2122 ok(r == WAIT_OBJECT_0, "Wait iteration %d gave %x\n", i, r);
2123
2124 /* the app has nearly one period time to feed data */
2125 Sleep((i % 10) * defp / 120000);
2126
2127 hr = IAudioClient_GetCurrentPadding(ac, &pad);
2128 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
2129
2130 /* XAudio2 writes only when there's little data left */
2131 if(pad <= fragment){
2132 hr = IAudioRenderClient_GetBuffer(arc, fragment, &data);
2133 ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
2134
2135 hr = IAudioRenderClient_ReleaseBuffer(arc, fragment,
2136 wave_generate_tone(pwfx, data, fragment));
2137 ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
2138 if(hr == S_OK)
2139 sum += fragment;
2140 }
2141 }
2142
2143 hr = IAudioClient_Stop(ac);
2144 ok(hr == S_OK, "Stop failed: %08x\n", hr);
2145
2146 hr = IAudioClient_GetCurrentPadding(ac, &pad);
2147 ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
2148
2149 hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
2150 ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
2151
2152 Sleep(100);
2153
2154 trace("Released %u=%ux%u -%u frames at %u worth %ums in %ums\n",
2155 sum, sum/fragment, fragment, pad,
2156 pwfx->nSamplesPerSec, MulDiv(sum-pad, 1000, pwfx->nSamplesPerSec),
2157 (ULONG)((pcpos-pcpos0)/10000));
2158
2159 ok(pos * pwfx->nSamplesPerSec == (sum-pad) * freq,
2160 "Position %u at end vs. %u-%u submitted frames\n", (UINT)pos, sum, pad);
2161
2162 hr = IAudioClient_Reset(ac);
2163 ok(hr == S_OK, "Reset failed: %08x\n", hr);
2164
2165 Sleep(250);
2166 }
2167
2168 CoTaskMemFree(pwfx);
2169 IAudioClient_Release(ac);
2170 IAudioClock_Release(acl);
2171 IAudioRenderClient_Release(arc);
2172 }
2173
2174 static void test_marshal(void)
2175 {
2176 IStream *pStream;
2177 IAudioClient *ac, *acDest;
2178 IAudioRenderClient *rc, *rcDest;
2179 WAVEFORMATEX *pwfx;
2180 HRESULT hr;
2181
2182 /* IAudioRenderClient */
2183 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
2184 NULL, (void**)&ac);
2185 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2186 if(hr != S_OK)
2187 return;
2188
2189 hr = IAudioClient_GetMixFormat(ac, &pwfx);
2190 ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
2191
2192 hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
2193 0, pwfx, NULL);
2194 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
2195
2196 CoTaskMemFree(pwfx);
2197
2198 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
2199 ok(hr == S_OK, "GetService failed: %08x\n", hr);
2200 if(hr != S_OK) {
2201 IAudioClient_Release(ac);
2202 return;
2203 }
2204
2205 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2206 ok(hr == S_OK, "CreateStreamOnHGlobal failed 0x%08x\n", hr);
2207
2208 /* marshal IAudioClient */
2209
2210 hr = CoMarshalInterface(pStream, &IID_IAudioClient, (IUnknown*)ac, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2211 ok(hr == S_OK, "CoMarshalInterface IAudioClient failed 0x%08x\n", hr);
2212
2213 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2214 hr = CoUnmarshalInterface(pStream, &IID_IAudioClient, (void **)&acDest);
2215 ok(hr == S_OK, "CoUnmarshalInterface IAudioClient failed 0x%08x\n", hr);
2216 if (hr == S_OK)
2217 IAudioClient_Release(acDest);
2218
2219 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2220 /* marshal IAudioRenderClient */
2221
2222 hr = CoMarshalInterface(pStream, &IID_IAudioRenderClient, (IUnknown*)rc, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2223 ok(hr == S_OK, "CoMarshalInterface IAudioRenderClient failed 0x%08x\n", hr);
2224
2225 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2226 hr = CoUnmarshalInterface(pStream, &IID_IAudioRenderClient, (void **)&rcDest);
2227 ok(hr == S_OK, "CoUnmarshalInterface IAudioRenderClient failed 0x%08x\n", hr);
2228 if (hr == S_OK)
2229 IAudioRenderClient_Release(rcDest);
2230
2231
2232 IStream_Release(pStream);
2233
2234 IAudioClient_Release(ac);
2235 IAudioRenderClient_Release(rc);
2236
2237 }
2238
2239 static void test_endpointvolume(void)
2240 {
2241 HRESULT hr;
2242 IAudioEndpointVolume *aev;
2243 float mindb, maxdb, increment, volume;
2244 BOOL mute;
2245
2246 hr = IMMDevice_Activate(dev, &IID_IAudioEndpointVolume,
2247 CLSCTX_INPROC_SERVER, NULL, (void**)&aev);
2248 ok(hr == S_OK, "Activation failed with %08x\n", hr);
2249 if(hr != S_OK)
2250 return;
2251
2252 hr = IAudioEndpointVolume_GetVolumeRange(aev, &mindb, NULL, NULL);
2253 ok(hr == E_POINTER, "GetVolumeRange should have failed with E_POINTER: 0x%08x\n", hr);
2254
2255 hr = IAudioEndpointVolume_GetVolumeRange(aev, &mindb, &maxdb, &increment);
2256 ok(hr == S_OK, "GetVolumeRange failed: 0x%08x\n", hr);
2257 trace("got range: [%f,%f]/%f\n", mindb, maxdb, increment);
2258
2259 hr = IAudioEndpointVolume_SetMasterVolumeLevel(aev, mindb - increment, NULL);
2260 ok(hr == E_INVALIDARG, "SetMasterVolumeLevel failed: 0x%08x\n", hr);
2261
2262 hr = IAudioEndpointVolume_GetMasterVolumeLevel(aev, &volume);
2263 ok(hr == S_OK, "GetMasterVolumeLevel failed: 0x%08x\n", hr);
2264
2265 hr = IAudioEndpointVolume_SetMasterVolumeLevel(aev, volume, NULL);
2266 ok(hr == S_OK, "SetMasterVolumeLevel failed: 0x%08x\n", hr);
2267
2268 hr = IAudioEndpointVolume_GetMute(aev, &mute);
2269 ok(hr == S_OK, "GetMute failed: %08x\n", hr);
2270
2271 hr = IAudioEndpointVolume_SetMute(aev, mute, NULL);
2272 ok(hr == S_OK || hr == S_FALSE, "SetMute failed: %08x\n", hr);
2273
2274 IAudioEndpointVolume_Release(aev);
2275 }
2276
2277 START_TEST(render)
2278 {
2279 HRESULT hr;
2280
2281 CoInitializeEx(NULL, COINIT_MULTITHREADED);
2282 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
2283 if (FAILED(hr))
2284 {
2285 skip("mmdevapi not available: 0x%08x\n", hr);
2286 goto cleanup;
2287 }
2288
2289 hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
2290 ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
2291 if (hr != S_OK || !dev)
2292 {
2293 if (hr == E_NOTFOUND)
2294 skip("No sound card available\n");
2295 else
2296 skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
2297 goto cleanup;
2298 }
2299
2300 test_audioclient();
2301 test_formats(AUDCLNT_SHAREMODE_EXCLUSIVE);
2302 test_formats(AUDCLNT_SHAREMODE_SHARED);
2303 test_references();
2304 test_marshal();
2305 trace("Output to a MS-DOS console is particularly slow and disturbs timing.\n");
2306 trace("Please redirect output to a file.\n");
2307 test_event();
2308 test_padding();
2309 test_clock(1);
2310 test_clock(0);
2311 test_session();
2312 test_streamvolume();
2313 test_channelvolume();
2314 test_simplevolume();
2315 test_volume_dependence();
2316 test_session_creation();
2317 test_worst_case();
2318 test_endpointvolume();
2319
2320 IMMDevice_Release(dev);
2321
2322 cleanup:
2323 if (mme)
2324 IMMDeviceEnumerator_Release(mme);
2325 CoUninitialize();
2326 }