vbscript: Added creation tests.
[wine] / dlls / mmdevapi / tests / render.c
1 /*
2  * Copyright 2010 Maarten Lankhorst for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 /* This test is for audio playback specific mechanisms
20  * Tests:
21  * - IAudioClient with eRender and IAudioRenderClient
22  */
23
24 #include <math.h>
25 #include <stdio.h>
26
27 #include "wine/test.h"
28
29 #define COBJMACROS
30
31 #ifdef STANDALONE
32 #include "initguid.h"
33 #endif
34
35 #include "unknwn.h"
36 #include "uuids.h"
37 #include "mmdeviceapi.h"
38 #include "audioclient.h"
39 #include "audiopolicy.h"
40
41 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
42
43 static IMMDeviceEnumerator *mme = NULL;
44 static IMMDevice *dev = NULL;
45
46 static inline const char *dbgstr_guid( const GUID *id )
47 {
48     static char ret[256];
49     sprintf(ret, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
50                              id->Data1, id->Data2, id->Data3,
51                              id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
52                              id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
53     return ret;
54 }
55
56 static void test_uninitialized(IAudioClient *ac)
57 {
58     HRESULT hr;
59     UINT32 num;
60     REFERENCE_TIME t1;
61
62     HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
63     IUnknown *unk;
64
65     hr = IAudioClient_GetBufferSize(ac, &num);
66     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
67
68     hr = IAudioClient_GetStreamLatency(ac, &t1);
69     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
70
71     hr = IAudioClient_GetCurrentPadding(ac, &num);
72     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
73
74     hr = IAudioClient_Start(ac);
75     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
76
77     hr = IAudioClient_Stop(ac);
78     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
79
80     hr = IAudioClient_Reset(ac);
81     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
82
83     hr = IAudioClient_SetEventHandle(ac, handle);
84     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
85
86     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
87     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
88
89     CloseHandle(handle);
90 }
91
92 static void test_audioclient(void)
93 {
94     IAudioClient *ac;
95     IUnknown *unk;
96     HRESULT hr;
97     ULONG ref;
98     WAVEFORMATEX *pwfx, *pwfx2;
99     REFERENCE_TIME t1, t2;
100     HANDLE handle;
101
102     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
103             NULL, (void**)&ac);
104     ok(hr == S_OK, "Activation failed with %08x\n", hr);
105     if(hr != S_OK)
106         return;
107
108     handle = CreateEventW(NULL, FALSE, FALSE, NULL);
109
110     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
111     ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
112
113     unk = (void*)(LONG_PTR)0x12345678;
114     hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
115     ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
116     ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
117
118     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
119     ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
120     if (unk)
121     {
122         ref = IUnknown_Release(unk);
123         ok(ref == 1, "Released count is %u\n", ref);
124     }
125
126     hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
127     ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
128     if (unk)
129     {
130         ref = IUnknown_Release(unk);
131         ok(ref == 1, "Released count is %u\n", ref);
132     }
133
134     hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
135     ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
136
137     hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
138     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
139
140     hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
141     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
142
143     hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
144     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
145     trace("Returned periods: %u.%05u ms %u.%05u ms\n",
146           (UINT)(t1/10000), (UINT)(t1 % 10000),
147           (UINT)(t2/10000), (UINT)(t2 % 10000));
148
149     hr = IAudioClient_GetMixFormat(ac, NULL);
150     ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
151
152     hr = IAudioClient_GetMixFormat(ac, &pwfx);
153     ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
154
155     if (hr == S_OK)
156     {
157         trace("pwfx: %p\n", pwfx);
158         trace("Tag: %04x\n", pwfx->wFormatTag);
159         trace("bits: %u\n", pwfx->wBitsPerSample);
160         trace("chan: %u\n", pwfx->nChannels);
161         trace("rate: %u\n", pwfx->nSamplesPerSec);
162         trace("align: %u\n", pwfx->nBlockAlign);
163         trace("extra: %u\n", pwfx->cbSize);
164         ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
165         if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
166         {
167             WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
168             trace("Res: %u\n", pwfxe->Samples.wReserved);
169             trace("Mask: %x\n", pwfxe->dwChannelMask);
170             trace("Alg: %s\n",
171                   IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
172                   (IsEqualGUID(&pwfxe->SubFormat,
173                                &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
174         }
175
176         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
177         ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
178         ok(pwfx2 == NULL, "pwfx2 is non-null\n");
179         CoTaskMemFree(pwfx2);
180
181         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
182         ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
183
184         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
185         ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
186
187         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
188         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
189
190         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
191         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
192         ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
193
194         hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
195         ok(hr == E_INVALIDARG ||
196            hr == AUDCLNT_E_UNSUPPORTED_FORMAT,
197            "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
198     }
199
200     test_uninitialized(ac);
201
202     hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
203     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
204
205     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
206     ok(hr == E_INVALIDARG, "Initialize with invalid flags returns %08x\n", hr);
207
208     /* It seems that if length > 2s or periodicity != 0 the length is ignored and call succeeds
209      * Since we can only initialize successfully once, skip those tests.
210      */
211     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
212     ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
213
214     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, pwfx, NULL);
215     ok(hr == S_OK, "Initialize with 0 buffer size returns %08x\n", hr);
216
217     IAudioClient_Release(ac);
218
219     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
220             NULL, (void**)&ac);
221     ok(hr == S_OK, "Activation failed with %08x\n", hr);
222
223     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
224     ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
225
226     if (hr != S_OK)
227     {
228         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
229         CoTaskMemFree(pwfx);
230         return;
231     }
232
233     hr = IAudioClient_GetStreamLatency(ac, NULL);
234     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
235
236     hr = IAudioClient_GetStreamLatency(ac, &t1);
237     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
238     trace("Returned latency: %u.%05u ms\n",
239           (UINT)(t1/10000), (UINT)(t1 % 10000));
240
241     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
242     ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
243
244     hr = IAudioClient_SetEventHandle(ac, NULL);
245     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
246
247     hr = IAudioClient_SetEventHandle(ac, handle);
248     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
249        broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
250        broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
251        broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
252        , "SetEventHandle returns %08x\n", hr);
253
254     hr = IAudioClient_Reset(ac);
255     ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
256
257     hr = IAudioClient_Stop(ac);
258     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
259
260     hr = IAudioClient_Start(ac);
261     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
262
263     IAudioClient_Release(ac);
264
265     CloseHandle(handle);
266     CoTaskMemFree(pwfx);
267 }
268
269 static void test_references(void)
270 {
271     IAudioClient *ac;
272     IAudioRenderClient *rc;
273     ISimpleAudioVolume *sav;
274     IAudioStreamVolume *asv;
275     IAudioClock *acl;
276     WAVEFORMATEX *pwfx;
277     HRESULT hr;
278     ULONG ref;
279
280     /* IAudioRenderClient */
281     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
282             NULL, (void**)&ac);
283     ok(hr == S_OK, "Activation failed with %08x\n", hr);
284     if(hr != S_OK)
285         return;
286
287     hr = IAudioClient_GetMixFormat(ac, &pwfx);
288     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
289     if(hr != S_OK)
290         return;
291
292     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
293             0, pwfx, NULL);
294     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
295
296     CoTaskMemFree(pwfx);
297
298     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
299     ok(hr == S_OK, "GetService failed: %08x\n", hr);
300
301     IAudioRenderClient_AddRef(rc);
302     ref = IAudioRenderClient_Release(rc);
303     ok(ref != 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
304
305     ref = IAudioClient_Release(ac);
306     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
307
308     ref = IAudioRenderClient_Release(rc);
309     ok(ref == 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
310
311     /* ISimpleAudioVolume */
312     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
313             NULL, (void**)&ac);
314     ok(hr == S_OK, "Activation failed with %08x\n", hr);
315     if(hr != S_OK)
316         return;
317
318     hr = IAudioClient_GetMixFormat(ac, &pwfx);
319     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
320
321     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
322             0, pwfx, NULL);
323     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
324
325     CoTaskMemFree(pwfx);
326
327     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
328     ok(hr == S_OK, "GetService failed: %08x\n", hr);
329
330     ISimpleAudioVolume_AddRef(sav);
331     ref = ISimpleAudioVolume_Release(sav);
332     ok(ref != 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
333
334     ref = IAudioClient_Release(ac);
335     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
336
337     ref = ISimpleAudioVolume_Release(sav);
338     ok(ref == 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
339
340     /* IAudioClock */
341     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
342             NULL, (void**)&ac);
343     ok(hr == S_OK, "Activation failed with %08x\n", hr);
344     if(hr != S_OK)
345         return;
346
347     hr = IAudioClient_GetMixFormat(ac, &pwfx);
348     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
349
350     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
351             0, pwfx, NULL);
352     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
353
354     CoTaskMemFree(pwfx);
355
356     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
357     ok(hr == S_OK, "GetService failed: %08x\n", hr);
358
359     IAudioClock_AddRef(acl);
360     ref = IAudioClock_Release(acl);
361     ok(ref != 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
362
363     ref = IAudioClient_Release(ac);
364     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
365
366     ref = IAudioClock_Release(acl);
367     ok(ref == 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
368
369     /* IAudioStreamVolume */
370     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
371             NULL, (void**)&ac);
372     ok(hr == S_OK, "Activation failed with %08x\n", hr);
373     if(hr != S_OK)
374         return;
375
376     hr = IAudioClient_GetMixFormat(ac, &pwfx);
377     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
378
379     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
380             0, pwfx, NULL);
381     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
382
383     CoTaskMemFree(pwfx);
384
385     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
386     ok(hr == S_OK, "GetService failed: %08x\n", hr);
387
388     IAudioStreamVolume_AddRef(asv);
389     ref = IAudioStreamVolume_Release(asv);
390     ok(ref != 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
391
392     ref = IAudioClient_Release(ac);
393     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
394
395     ref = IAudioStreamVolume_Release(asv);
396     ok(ref == 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
397 }
398
399 static void test_event(void)
400 {
401     HANDLE event;
402     HRESULT hr;
403     IAudioClient *ac;
404     WAVEFORMATEX *pwfx;
405
406     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
407             NULL, (void**)&ac);
408     ok(hr == S_OK, "Activation failed with %08x\n", hr);
409     if(hr != S_OK)
410         return;
411
412     hr = IAudioClient_GetMixFormat(ac, &pwfx);
413     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
414     if(hr != S_OK)
415         return;
416
417     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
418             AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
419             0, pwfx, NULL);
420     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
421
422     CoTaskMemFree(pwfx);
423
424     event = CreateEventW(NULL, FALSE, FALSE, NULL);
425     ok(event != NULL, "CreateEvent failed\n");
426
427     hr = IAudioClient_Start(ac);
428     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start failed: %08x\n", hr);
429
430     hr = IAudioClient_SetEventHandle(ac, event);
431     ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
432
433     hr = IAudioClient_Start(ac);
434     ok(hr == S_OK, "Start failed: %08x\n", hr);
435
436     hr = IAudioClient_Stop(ac);
437     ok(hr == S_OK, "Start failed: %08x\n", hr);
438
439     /* test releasing a playing stream */
440     hr = IAudioClient_Start(ac);
441     ok(hr == S_OK, "Start failed: %08x\n", hr);
442     IAudioClient_Release(ac);
443
444     CloseHandle(event);
445 }
446
447 static void test_padding(void)
448 {
449     HRESULT hr;
450     IAudioClient *ac;
451     IAudioRenderClient *arc;
452     WAVEFORMATEX *pwfx;
453     REFERENCE_TIME minp, defp;
454     BYTE *buf;
455     UINT32 psize, pad, written;
456
457     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
458             NULL, (void**)&ac);
459     ok(hr == S_OK, "Activation failed with %08x\n", hr);
460     if(hr != S_OK)
461         return;
462
463     hr = IAudioClient_GetMixFormat(ac, &pwfx);
464     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
465     if(hr != S_OK)
466         return;
467
468     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
469             0, 5000000, 0, pwfx, NULL);
470     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
471
472     hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
473     ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
474     ok(defp != 0, "Default period is 0\n");
475     ok(minp != 0, "Minimum period is 0\n");
476     ok(minp <= defp, "Mininum period is greater than default period\n");
477
478     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
479     ok(hr == S_OK, "GetService failed: %08x\n", hr);
480
481     psize = (defp / 10000000.) * pwfx->nSamplesPerSec * 10;
482
483     written = 0;
484     hr = IAudioClient_GetCurrentPadding(ac, &pad);
485     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
486     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
487
488     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
489     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
490     ok(buf != NULL, "NULL buffer returned\n");
491
492     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
493             AUDCLNT_BUFFERFLAGS_SILENT);
494     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
495     written += psize;
496
497     hr = IAudioClient_GetCurrentPadding(ac, &pad);
498     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
499     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
500
501     psize = (minp / 10000000.) * pwfx->nSamplesPerSec * 10;
502
503     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
504     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
505     ok(buf != NULL, "NULL buffer returned\n");
506
507     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
508             AUDCLNT_BUFFERFLAGS_SILENT);
509     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
510     written += psize;
511
512     hr = IAudioClient_GetCurrentPadding(ac, &pad);
513     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
514     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
515
516     /* overfull buffer. requested 1/2s buffer size, so try
517      * to get a 1/2s buffer, which should fail */
518     psize = pwfx->nSamplesPerSec / 2.;
519     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
520     ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
521
522     hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
523     ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
524
525     hr = IAudioClient_GetCurrentPadding(ac, &pad);
526     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
527     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
528
529     CoTaskMemFree(pwfx);
530
531     IAudioRenderClient_Release(arc);
532     IAudioClient_Release(ac);
533 }
534
535 static void test_clock(void)
536 {
537     HRESULT hr;
538     IAudioClient *ac;
539     IAudioClock *acl;
540     IAudioRenderClient *arc;
541     UINT64 freq, pos, pcpos, last;
542     BYTE *data;
543     WAVEFORMATEX *pwfx;
544
545     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
546             NULL, (void**)&ac);
547     ok(hr == S_OK, "Activation failed with %08x\n", hr);
548     if(hr != S_OK)
549         return;
550
551     hr = IAudioClient_GetMixFormat(ac, &pwfx);
552     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
553     if(hr != S_OK)
554         return;
555
556     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
557             0, 5000000, 0, pwfx, NULL);
558     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
559
560     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
561     ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
562
563     hr = IAudioClock_GetFrequency(acl, &freq);
564     ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
565
566     hr = IAudioClock_GetPosition(acl, NULL, NULL);
567     ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
568
569     pcpos = 0;
570     hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
571     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
572     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
573     ok(pcpos != 0, "GetPosition returned zero pcpos\n");
574     last = pos;
575
576     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
577     ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
578
579     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
580     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
581
582     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
583     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
584
585     hr = IAudioClock_GetPosition(acl, &pos, NULL);
586     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
587     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
588
589     hr = IAudioClient_Start(ac);
590     ok(hr == S_OK, "Start failed: %08x\n", hr);
591
592     Sleep(100);
593
594     hr = IAudioClock_GetPosition(acl, &pos, NULL);
595     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
596     ok(pos > 0, "Position should have been further along...\n");
597     last = pos;
598
599     hr = IAudioClient_Stop(ac);
600     ok(hr == S_OK, "Stop failed: %08x\n", hr);
601
602     hr = IAudioClock_GetPosition(acl, &pos, NULL);
603     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
604     ok(pos >= last, "Position should have been further along...\n");
605     last = pos;
606
607     hr = IAudioClient_Start(ac);
608     ok(hr == S_OK, "Start failed: %08x\n", hr);
609
610     Sleep(100);
611
612     hr = IAudioClient_Stop(ac);
613     ok(hr == S_OK, "Stop failed: %08x\n", hr);
614
615     hr = IAudioClock_GetPosition(acl, &pos, NULL);
616     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
617     ok(pos >= last, "Position should have been further along...\n");
618     last = pos;
619
620     hr = IAudioClock_GetPosition(acl, &pos, NULL);
621     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
622     ok(pos == last, "Position should have been further along...\n");
623
624     hr = IAudioClient_Reset(ac);
625     ok(hr == S_OK, "Reset failed: %08x\n", hr);
626
627     hr = IAudioClock_GetPosition(acl, &pos, NULL);
628     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
629     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
630
631     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
632     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
633
634     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
635     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
636
637     hr = IAudioClock_GetPosition(acl, &pos, NULL);
638     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
639     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
640     last = pos;
641
642     hr = IAudioClient_Start(ac);
643     ok(hr == S_OK, "Start failed: %08x\n", hr);
644
645     Sleep(100);
646
647     hr = IAudioClock_GetPosition(acl, &pos, NULL);
648     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
649     ok(pos > last, "Position should have been further along...\n");
650
651     hr = IAudioClient_Stop(ac);
652     ok(hr == S_OK, "Stop failed: %08x\n", hr);
653
654     hr = IAudioClock_GetPosition(acl, &pos, NULL);
655     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
656     ok(pos >= last, "Position should have been further along...\n");
657
658     CoTaskMemFree(pwfx);
659
660     IAudioClock_Release(acl);
661     IAudioRenderClient_Release(arc);
662     IAudioClient_Release(ac);
663 }
664
665 static void test_session(void)
666 {
667     IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac = NULL;
668     IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl;
669     IMMDevice *cap_dev;
670     GUID ses1_guid;
671     AudioSessionState state;
672     WAVEFORMATEX *pwfx;
673     ULONG ref;
674     HRESULT hr;
675
676     hr = CoCreateGuid(&ses1_guid);
677     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
678
679     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
680             NULL, (void**)&ses1_ac1);
681     ok(hr == S_OK, "Activation failed with %08x\n", hr);
682
683     hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
684     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
685
686     hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
687             0, 5000000, 0, pwfx, &ses1_guid);
688     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
689
690     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
691             NULL, (void**)&ses1_ac2);
692     ok(hr == S_OK, "Activation failed with %08x\n", hr);
693
694     hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
695             0, 5000000, 0, pwfx, &ses1_guid);
696     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
697
698     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
699             eMultimedia, &cap_dev);
700     if(hr == S_OK){
701         WAVEFORMATEX *cap_pwfx;
702
703         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
704                 NULL, (void**)&cap_ac);
705         ok(hr == S_OK, "Activate failed: %08x\n", hr);
706
707         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
708         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
709
710         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
711                 0, 5000000, 0, cap_pwfx, &ses1_guid);
712         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
713
714         hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
715         ok(hr == S_OK, "GetService failed: %08x\n", hr);
716
717         IMMDevice_Release(cap_dev);
718         CoTaskMemFree(cap_pwfx);
719     }else
720         skip("No capture device available; skipping capture device in render session tests\n");
721
722     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
723     ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
724
725     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
726     ok(hr == S_OK, "GetService failed: %08x\n", hr);
727
728     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
729     ok(hr == S_OK, "GetService failed: %08x\n", hr);
730     ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
731     ref = IAudioSessionControl_Release(ses1_ctl2);
732     ok(ref != 0, "AudioSessionControl was destroyed\n");
733
734     hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
735     ok(hr == S_OK, "GetService failed: %08x\n", hr);
736
737     hr = IAudioSessionControl_GetState(ses1_ctl, NULL);
738     ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
739
740     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
741     ok(hr == S_OK, "GetState failed: %08x\n", hr);
742     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
743
744     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
745     ok(hr == S_OK, "GetState failed: %08x\n", hr);
746     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
747
748     if(cap_ac){
749         hr = IAudioSessionControl_GetState(cap_ctl, &state);
750         ok(hr == S_OK, "GetState failed: %08x\n", hr);
751         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
752     }
753
754     hr = IAudioClient_Start(ses1_ac1);
755     ok(hr == S_OK, "Start failed: %08x\n", hr);
756
757     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
758     ok(hr == S_OK, "GetState failed: %08x\n", hr);
759     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
760
761     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
762     ok(hr == S_OK, "GetState failed: %08x\n", hr);
763     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
764
765     if(cap_ac){
766         hr = IAudioSessionControl_GetState(cap_ctl, &state);
767         ok(hr == S_OK, "GetState failed: %08x\n", hr);
768         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
769     }
770
771     hr = IAudioClient_Stop(ses1_ac1);
772     ok(hr == S_OK, "Start failed: %08x\n", hr);
773
774     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
775     ok(hr == S_OK, "GetState failed: %08x\n", hr);
776     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
777
778     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
779     ok(hr == S_OK, "GetState failed: %08x\n", hr);
780     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
781
782     if(cap_ac){
783         hr = IAudioSessionControl_GetState(cap_ctl, &state);
784         ok(hr == S_OK, "GetState failed: %08x\n", hr);
785         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
786
787         hr = IAudioClient_Start(cap_ac);
788         ok(hr == S_OK, "Start failed: %08x\n", hr);
789
790         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
791         ok(hr == S_OK, "GetState failed: %08x\n", hr);
792         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
793
794         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
795         ok(hr == S_OK, "GetState failed: %08x\n", hr);
796         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
797
798         hr = IAudioSessionControl_GetState(cap_ctl, &state);
799         ok(hr == S_OK, "GetState failed: %08x\n", hr);
800         ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
801
802         hr = IAudioClient_Stop(cap_ac);
803         ok(hr == S_OK, "Stop failed: %08x\n", hr);
804
805         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
806         ok(hr == S_OK, "GetState failed: %08x\n", hr);
807         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
808
809         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
810         ok(hr == S_OK, "GetState failed: %08x\n", hr);
811         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
812
813         hr = IAudioSessionControl_GetState(cap_ctl, &state);
814         ok(hr == S_OK, "GetState failed: %08x\n", hr);
815         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
816
817         ref = IAudioSessionControl_Release(cap_ctl);
818         ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
819
820         ref = IAudioClient_Release(cap_ac);
821         ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
822     }
823
824     ref = IAudioSessionControl_Release(ses1_ctl);
825     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
826
827     ref = IAudioClient_Release(ses1_ac1);
828     ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
829
830     ref = IAudioClient_Release(ses1_ac2);
831     ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
832
833     /* we've released all of our IAudioClient references, so check GetState */
834     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
835     ok(hr == S_OK, "GetState failed: %08x\n", hr);
836     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
837
838     ref = IAudioSessionControl_Release(ses1_ctl2);
839     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
840
841     CoTaskMemFree(pwfx);
842 }
843
844 static void test_streamvolume(void)
845 {
846     IAudioClient *ac;
847     IAudioStreamVolume *asv;
848     WAVEFORMATEX *fmt;
849     UINT32 chans, i;
850     HRESULT hr;
851     float vol, *vols;
852
853     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
854             NULL, (void**)&ac);
855     ok(hr == S_OK, "Activation failed with %08x\n", hr);
856     if(hr != S_OK)
857         return;
858
859     hr = IAudioClient_GetMixFormat(ac, &fmt);
860     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
861
862     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
863             0, fmt, NULL);
864     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
865
866     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
867     ok(hr == S_OK, "GetService failed: %08x\n", hr);
868
869     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
870     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
871
872     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
873     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
874     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
875
876     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
877     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
878
879     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
880     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
881
882     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
883     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
884
885     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
886     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
887     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
888
889     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
890     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
891
892     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
893     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
894
895     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
896     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
897
898     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
899     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
900
901     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
902     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
903     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
904
905     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
906     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
907
908     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
909     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
910
911     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
912     ok(vols != NULL, "HeapAlloc failed\n");
913
914     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
915     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
916
917     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
918     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
919     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
920     for(i = 1; i < fmt->nChannels; ++i)
921         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
922
923     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
924     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
925
926     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
927     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
928
929     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
930     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
931
932     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
933     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
934
935     HeapFree(GetProcessHeap(), 0, vols);
936     IAudioStreamVolume_Release(asv);
937     IAudioClient_Release(ac);
938     CoTaskMemFree(fmt);
939 }
940
941 static void test_channelvolume(void)
942 {
943     IAudioClient *ac;
944     IChannelAudioVolume *acv;
945     WAVEFORMATEX *fmt;
946     UINT32 chans, i;
947     HRESULT hr;
948     float vol, *vols;
949
950     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
951             NULL, (void**)&ac);
952     ok(hr == S_OK, "Activation failed with %08x\n", hr);
953     if(hr != S_OK)
954         return;
955
956     hr = IAudioClient_GetMixFormat(ac, &fmt);
957     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
958
959     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
960             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
961     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
962
963     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
964     ok(hr == S_OK, "GetService failed: %08x\n", hr);
965
966     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
967     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
968
969     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
970     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
971     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
972
973     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
974     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
975
976     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
977     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
978
979     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
980     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
981
982     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
983     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
984     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
985
986     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
987     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
988
989     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
990     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
991
992     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
993     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
994
995     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
996     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
997
998     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
999     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1000     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1001
1002     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
1003     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1004
1005     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
1006     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1007
1008     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1009     ok(vols != NULL, "HeapAlloc failed\n");
1010
1011     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
1012     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1013
1014     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1015     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1016     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1017     for(i = 1; i < fmt->nChannels; ++i)
1018         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1019
1020     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1021     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1022
1023     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1024     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1025
1026     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1027     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1028
1029     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1030     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1031
1032     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1033     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1034
1035     HeapFree(GetProcessHeap(), 0, vols);
1036     IChannelAudioVolume_Release(acv);
1037     IAudioClient_Release(ac);
1038     CoTaskMemFree(fmt);
1039 }
1040
1041 static void test_simplevolume(void)
1042 {
1043     IAudioClient *ac;
1044     ISimpleAudioVolume *sav;
1045     WAVEFORMATEX *fmt;
1046     HRESULT hr;
1047     float vol;
1048     BOOL mute;
1049
1050     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1051             NULL, (void**)&ac);
1052     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1053     if(hr != S_OK)
1054         return;
1055
1056     hr = IAudioClient_GetMixFormat(ac, &fmt);
1057     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1058
1059     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1060             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1061     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1062
1063     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1064     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1065
1066     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1067     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1068
1069     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1070     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1071     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1072
1073     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1074     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1075
1076     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1077     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1078
1079     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1080     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1081
1082     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1083     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1084     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1085
1086     hr = ISimpleAudioVolume_GetMute(sav, NULL);
1087     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1088
1089     mute = TRUE;
1090     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1091     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1092     ok(mute == FALSE, "Session is already muted\n");
1093
1094     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1095     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1096
1097     mute = FALSE;
1098     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1099     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1100     ok(mute == TRUE, "Session should have been muted\n");
1101
1102     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1103     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1104     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1105
1106     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1107     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1108
1109     mute = FALSE;
1110     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1111     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1112     ok(mute == TRUE, "Session should have been muted\n");
1113
1114     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1115     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1116
1117     ISimpleAudioVolume_Release(sav);
1118     IAudioClient_Release(ac);
1119     CoTaskMemFree(fmt);
1120 }
1121
1122 static void test_volume_dependence(void)
1123 {
1124     IAudioClient *ac, *ac2;
1125     ISimpleAudioVolume *sav;
1126     IChannelAudioVolume *cav;
1127     IAudioStreamVolume *asv;
1128     WAVEFORMATEX *fmt;
1129     HRESULT hr;
1130     float vol;
1131     GUID session;
1132     UINT32 nch;
1133
1134     hr = CoCreateGuid(&session);
1135     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1136
1137     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1138             NULL, (void**)&ac);
1139     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1140
1141     hr = IAudioClient_GetMixFormat(ac, &fmt);
1142     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1143
1144     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1145             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1146     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1147
1148     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1149     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1150
1151     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1152     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
1153
1154     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1155     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1156
1157     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1158     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1159
1160     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1161     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1162
1163     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1164     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1165
1166     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1167     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1168     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1169
1170     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1171     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1172     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1173
1174     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1175     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1176     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1177
1178     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1179             NULL, (void**)&ac2);
1180     if(SUCCEEDED(hr)){
1181         IChannelAudioVolume *cav2;
1182         IAudioStreamVolume *asv2;
1183
1184         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1185                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1186         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1187
1188         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1189         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1190
1191         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1192         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1193
1194         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1195         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1196         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1197
1198         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1199         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1200         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1201
1202         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1203         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1204         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1205
1206         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
1207         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1208         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1209
1210         IAudioStreamVolume_Release(asv2);
1211         IChannelAudioVolume_Release(cav2);
1212         IAudioClient_Release(ac2);
1213     }else
1214         skip("Unable to open the same device twice. Skipping session volume control tests\n");
1215
1216     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
1217     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1218
1219     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1220     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1221
1222     CoTaskMemFree(fmt);
1223     ISimpleAudioVolume_Release(sav);
1224     IChannelAudioVolume_Release(cav);
1225     IAudioStreamVolume_Release(asv);
1226     IAudioClient_Release(ac);
1227 }
1228
1229 static void test_session_creation(void)
1230 {
1231     IMMDevice *cap_dev;
1232     IAudioClient *ac;
1233     IAudioSessionManager *sesm;
1234     ISimpleAudioVolume *sav;
1235     GUID session_guid;
1236     float vol;
1237     HRESULT hr;
1238     WAVEFORMATEX *fmt;
1239
1240     CoCreateGuid(&session_guid);
1241
1242     hr = IMMDevice_Activate(dev, &IID_IAudioSessionManager,
1243             CLSCTX_INPROC_SERVER, NULL, (void**)&sesm);
1244     ok(hr == S_OK, "Activate failed: %08x\n", hr);
1245
1246     hr = IAudioSessionManager_GetSimpleAudioVolume(sesm, &session_guid,
1247             FALSE, &sav);
1248     ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1249
1250     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1251     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1252
1253     /* Release completely to show session persistence */
1254     ISimpleAudioVolume_Release(sav);
1255     IAudioSessionManager_Release(sesm);
1256
1257     /* test if we can create a capture audioclient in the session we just
1258      * created from a SessionManager derived from a render device */
1259     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1260             eMultimedia, &cap_dev);
1261     if(hr == S_OK){
1262         WAVEFORMATEX *cap_pwfx;
1263         IAudioClient *cap_ac;
1264         ISimpleAudioVolume *cap_sav;
1265         IAudioSessionManager *cap_sesm;
1266
1267         hr = IMMDevice_Activate(cap_dev, &IID_IAudioSessionManager,
1268                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_sesm);
1269         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1270
1271         hr = IAudioSessionManager_GetSimpleAudioVolume(cap_sesm, &session_guid,
1272                 FALSE, &cap_sav);
1273         ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1274
1275         vol = 0.5f;
1276         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1277         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1278         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1279
1280         ISimpleAudioVolume_Release(cap_sav);
1281         IAudioSessionManager_Release(cap_sesm);
1282
1283         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient,
1284                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_ac);
1285         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1286
1287         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1288         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1289
1290         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1291                 0, 5000000, 0, cap_pwfx, &session_guid);
1292         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1293
1294         hr = IAudioClient_GetService(cap_ac, &IID_ISimpleAudioVolume,
1295                 (void**)&cap_sav);
1296         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1297
1298         vol = 0.5f;
1299         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1300         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1301         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1302
1303         CoTaskMemFree(cap_pwfx);
1304         ISimpleAudioVolume_Release(cap_sav);
1305         IAudioClient_Release(cap_ac);
1306         IMMDevice_Release(cap_dev);
1307     }
1308
1309     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1310             NULL, (void**)&ac);
1311     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1312
1313     hr = IAudioClient_GetMixFormat(ac, &fmt);
1314     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1315
1316     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1317             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session_guid);
1318     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1319
1320     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1321     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1322
1323     vol = 0.5f;
1324     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1325     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1326     ok(fabs(vol - 0.6f) < 0.05f, "Got wrong volume: %f\n", vol);
1327
1328     CoTaskMemFree(fmt);
1329     ISimpleAudioVolume_Release(sav);
1330     IAudioClient_Release(ac);
1331 }
1332
1333 START_TEST(render)
1334 {
1335     HRESULT hr;
1336
1337     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1338     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1339     if (FAILED(hr))
1340     {
1341         skip("mmdevapi not available: 0x%08x\n", hr);
1342         goto cleanup;
1343     }
1344
1345     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
1346     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1347     if (hr != S_OK || !dev)
1348     {
1349         if (hr == E_NOTFOUND)
1350             skip("No sound card available\n");
1351         else
1352             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1353         goto cleanup;
1354     }
1355
1356     test_audioclient();
1357     test_references();
1358     test_event();
1359     test_padding();
1360     test_clock();
1361     test_session();
1362     test_streamvolume();
1363     test_channelvolume();
1364     test_simplevolume();
1365     test_volume_dependence();
1366     test_session_creation();
1367
1368     IMMDevice_Release(dev);
1369
1370 cleanup:
1371     if (mme)
1372         IMMDeviceEnumerator_Release(mme);
1373     CoUninitialize();
1374 }