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