crypt32: Add additional path for Solaris 11 Express.
[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, 5000000, 0, pwfx, NULL);
215     ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
216
217     if (hr != S_OK)
218     {
219         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
220         CoTaskMemFree(pwfx);
221         return;
222     }
223
224     hr = IAudioClient_GetStreamLatency(ac, NULL);
225     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
226
227     hr = IAudioClient_GetStreamLatency(ac, &t1);
228     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
229     trace("Returned latency: %u.%05u ms\n",
230           (UINT)(t1/10000), (UINT)(t1 % 10000));
231
232     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
233     ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
234
235     hr = IAudioClient_SetEventHandle(ac, NULL);
236     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
237
238     hr = IAudioClient_SetEventHandle(ac, handle);
239     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
240        broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
241        broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
242        broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
243        , "SetEventHandle returns %08x\n", hr);
244
245     hr = IAudioClient_Reset(ac);
246     ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
247
248     hr = IAudioClient_Stop(ac);
249     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
250
251     hr = IAudioClient_Start(ac);
252     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
253
254     IAudioClient_Release(ac);
255
256     CloseHandle(handle);
257     CoTaskMemFree(pwfx);
258 }
259
260 static void test_references(void)
261 {
262     IAudioClient *ac;
263     IAudioRenderClient *rc;
264     ISimpleAudioVolume *sav;
265     IAudioStreamVolume *asv;
266     IAudioClock *acl;
267     WAVEFORMATEX *pwfx;
268     HRESULT hr;
269     ULONG ref;
270
271     /* IAudioRenderClient */
272     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
273             NULL, (void**)&ac);
274     ok(hr == S_OK, "Activation failed with %08x\n", hr);
275     if(hr != S_OK)
276         return;
277
278     hr = IAudioClient_GetMixFormat(ac, &pwfx);
279     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
280     if(hr != S_OK)
281         return;
282
283     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
284             0, pwfx, NULL);
285     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
286
287     CoTaskMemFree(pwfx);
288
289     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
290     ok(hr == S_OK, "GetService failed: %08x\n", hr);
291
292     IAudioRenderClient_AddRef(rc);
293     ref = IAudioRenderClient_Release(rc);
294     ok(ref != 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
295
296     ref = IAudioClient_Release(ac);
297     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
298
299     ref = IAudioRenderClient_Release(rc);
300     ok(ref == 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
301
302     /* ISimpleAudioVolume */
303     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
304             NULL, (void**)&ac);
305     ok(hr == S_OK, "Activation failed with %08x\n", hr);
306     if(hr != S_OK)
307         return;
308
309     hr = IAudioClient_GetMixFormat(ac, &pwfx);
310     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
311
312     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
313             0, pwfx, NULL);
314     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
315
316     CoTaskMemFree(pwfx);
317
318     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
319     ok(hr == S_OK, "GetService failed: %08x\n", hr);
320
321     ISimpleAudioVolume_AddRef(sav);
322     ref = ISimpleAudioVolume_Release(sav);
323     ok(ref != 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
324
325     ref = IAudioClient_Release(ac);
326     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
327
328     ref = ISimpleAudioVolume_Release(sav);
329     ok(ref == 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
330
331     /* IAudioClock */
332     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
333             NULL, (void**)&ac);
334     ok(hr == S_OK, "Activation failed with %08x\n", hr);
335     if(hr != S_OK)
336         return;
337
338     hr = IAudioClient_GetMixFormat(ac, &pwfx);
339     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
340
341     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
342             0, pwfx, NULL);
343     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
344
345     CoTaskMemFree(pwfx);
346
347     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
348     ok(hr == S_OK, "GetService failed: %08x\n", hr);
349
350     IAudioClock_AddRef(acl);
351     ref = IAudioClock_Release(acl);
352     ok(ref != 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
353
354     ref = IAudioClient_Release(ac);
355     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
356
357     ref = IAudioClock_Release(acl);
358     ok(ref == 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
359
360     /* IAudioStreamVolume */
361     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
362             NULL, (void**)&ac);
363     ok(hr == S_OK, "Activation failed with %08x\n", hr);
364     if(hr != S_OK)
365         return;
366
367     hr = IAudioClient_GetMixFormat(ac, &pwfx);
368     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
369
370     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
371             0, pwfx, NULL);
372     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
373
374     CoTaskMemFree(pwfx);
375
376     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
377     ok(hr == S_OK, "GetService failed: %08x\n", hr);
378
379     IAudioStreamVolume_AddRef(asv);
380     ref = IAudioStreamVolume_Release(asv);
381     ok(ref != 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
382
383     ref = IAudioClient_Release(ac);
384     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
385
386     ref = IAudioStreamVolume_Release(asv);
387     ok(ref == 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
388 }
389
390 static void test_event(void)
391 {
392     HANDLE event;
393     HRESULT hr;
394     IAudioClient *ac;
395     WAVEFORMATEX *pwfx;
396
397     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
398             NULL, (void**)&ac);
399     ok(hr == S_OK, "Activation failed with %08x\n", hr);
400     if(hr != S_OK)
401         return;
402
403     hr = IAudioClient_GetMixFormat(ac, &pwfx);
404     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
405     if(hr != S_OK)
406         return;
407
408     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
409             AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
410             0, pwfx, NULL);
411     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
412
413     CoTaskMemFree(pwfx);
414
415     event = CreateEventW(NULL, FALSE, FALSE, NULL);
416     ok(event != NULL, "CreateEvent failed\n");
417
418     hr = IAudioClient_Start(ac);
419     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start failed: %08x\n", hr);
420
421     hr = IAudioClient_SetEventHandle(ac, event);
422     ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
423
424     hr = IAudioClient_Start(ac);
425     ok(hr == S_OK, "Start failed: %08x\n", hr);
426
427     hr = IAudioClient_Stop(ac);
428     ok(hr == S_OK, "Start failed: %08x\n", hr);
429
430     /* test releasing a playing stream */
431     hr = IAudioClient_Start(ac);
432     ok(hr == S_OK, "Start failed: %08x\n", hr);
433     IAudioClient_Release(ac);
434
435     CloseHandle(event);
436 }
437
438 static void test_padding(void)
439 {
440     HRESULT hr;
441     IAudioClient *ac;
442     IAudioRenderClient *arc;
443     WAVEFORMATEX *pwfx;
444     REFERENCE_TIME minp, defp;
445     BYTE *buf;
446     UINT32 psize, pad, written;
447
448     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
449             NULL, (void**)&ac);
450     ok(hr == S_OK, "Activation failed with %08x\n", hr);
451     if(hr != S_OK)
452         return;
453
454     hr = IAudioClient_GetMixFormat(ac, &pwfx);
455     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
456     if(hr != S_OK)
457         return;
458
459     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
460             0, 5000000, 0, pwfx, NULL);
461     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
462
463     hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
464     ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
465     ok(defp != 0, "Default period is 0\n");
466     ok(minp != 0, "Minimum period is 0\n");
467     ok(minp <= defp, "Mininum period is greater than default period\n");
468
469     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
470     ok(hr == S_OK, "GetService failed: %08x\n", hr);
471
472     psize = (defp / 10000000.) * pwfx->nSamplesPerSec * 10;
473
474     written = 0;
475     hr = IAudioClient_GetCurrentPadding(ac, &pad);
476     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
477     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
478
479     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
480     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
481     ok(buf != NULL, "NULL buffer returned\n");
482
483     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
484             AUDCLNT_BUFFERFLAGS_SILENT);
485     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
486     written += psize;
487
488     hr = IAudioClient_GetCurrentPadding(ac, &pad);
489     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
490     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
491
492     psize = (minp / 10000000.) * pwfx->nSamplesPerSec * 10;
493
494     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
495     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
496     ok(buf != NULL, "NULL buffer returned\n");
497
498     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
499             AUDCLNT_BUFFERFLAGS_SILENT);
500     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
501     written += psize;
502
503     hr = IAudioClient_GetCurrentPadding(ac, &pad);
504     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
505     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
506
507     /* overfull buffer. requested 1/2s buffer size, so try
508      * to get a 1/2s buffer, which should fail */
509     psize = pwfx->nSamplesPerSec / 2.;
510     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
511     ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
512
513     hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
514     ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
515
516     hr = IAudioClient_GetCurrentPadding(ac, &pad);
517     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
518     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
519
520     CoTaskMemFree(pwfx);
521
522     IAudioRenderClient_Release(arc);
523     IAudioClient_Release(ac);
524 }
525
526 static void test_clock(void)
527 {
528     HRESULT hr;
529     IAudioClient *ac;
530     IAudioClock *acl;
531     IAudioRenderClient *arc;
532     UINT64 freq, pos, pcpos, last;
533     BYTE *data;
534     WAVEFORMATEX *pwfx;
535
536     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
537             NULL, (void**)&ac);
538     ok(hr == S_OK, "Activation failed with %08x\n", hr);
539     if(hr != S_OK)
540         return;
541
542     hr = IAudioClient_GetMixFormat(ac, &pwfx);
543     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
544     if(hr != S_OK)
545         return;
546
547     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
548             0, 5000000, 0, pwfx, NULL);
549     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
550
551     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
552     ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
553
554     hr = IAudioClock_GetFrequency(acl, &freq);
555     ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
556
557     hr = IAudioClock_GetPosition(acl, NULL, NULL);
558     ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
559
560     pcpos = 0;
561     hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
562     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
563     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
564     ok(pcpos != 0, "GetPosition returned zero pcpos\n");
565     last = pos;
566
567     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
568     ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
569
570     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
571     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
572
573     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
574     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
575
576     hr = IAudioClock_GetPosition(acl, &pos, NULL);
577     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
578     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
579
580     hr = IAudioClient_Start(ac);
581     ok(hr == S_OK, "Start failed: %08x\n", hr);
582
583     Sleep(100);
584
585     hr = IAudioClock_GetPosition(acl, &pos, NULL);
586     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
587     ok(pos > 0, "Position should have been further along...\n");
588     last = pos;
589
590     hr = IAudioClient_Stop(ac);
591     ok(hr == S_OK, "Stop failed: %08x\n", hr);
592
593     hr = IAudioClock_GetPosition(acl, &pos, NULL);
594     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
595     ok(pos >= last, "Position should have been further along...\n");
596     last = pos;
597
598     hr = IAudioClient_Start(ac);
599     ok(hr == S_OK, "Start failed: %08x\n", hr);
600
601     Sleep(100);
602
603     hr = IAudioClient_Stop(ac);
604     ok(hr == S_OK, "Stop failed: %08x\n", hr);
605
606     hr = IAudioClock_GetPosition(acl, &pos, NULL);
607     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
608     ok(pos >= last, "Position should have been further along...\n");
609     last = pos;
610
611     hr = IAudioClock_GetPosition(acl, &pos, NULL);
612     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
613     ok(pos == last, "Position should have been further along...\n");
614
615     hr = IAudioClient_Reset(ac);
616     ok(hr == S_OK, "Reset failed: %08x\n", hr);
617
618     hr = IAudioClock_GetPosition(acl, &pos, NULL);
619     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
620     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
621
622     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
623     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
624
625     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
626     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
627
628     hr = IAudioClock_GetPosition(acl, &pos, NULL);
629     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
630     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
631     last = pos;
632
633     hr = IAudioClient_Start(ac);
634     ok(hr == S_OK, "Start failed: %08x\n", hr);
635
636     Sleep(100);
637
638     hr = IAudioClock_GetPosition(acl, &pos, NULL);
639     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
640     ok(pos > last, "Position should have been further along...\n");
641
642     hr = IAudioClient_Stop(ac);
643     ok(hr == S_OK, "Stop failed: %08x\n", hr);
644
645     hr = IAudioClock_GetPosition(acl, &pos, NULL);
646     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
647     ok(pos >= last, "Position should have been further along...\n");
648
649     CoTaskMemFree(pwfx);
650
651     IAudioClock_Release(acl);
652     IAudioRenderClient_Release(arc);
653     IAudioClient_Release(ac);
654 }
655
656 static void test_session(void)
657 {
658     IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac = NULL;
659     IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl;
660     IMMDevice *cap_dev;
661     GUID ses1_guid;
662     AudioSessionState state;
663     WAVEFORMATEX *pwfx;
664     ULONG ref;
665     HRESULT hr;
666
667     hr = CoCreateGuid(&ses1_guid);
668     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
669
670     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
671             NULL, (void**)&ses1_ac1);
672     ok(hr == S_OK, "Activation failed with %08x\n", hr);
673
674     hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
675     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
676
677     hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
678             0, 5000000, 0, pwfx, &ses1_guid);
679     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
680
681     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
682             NULL, (void**)&ses1_ac2);
683     ok(hr == S_OK, "Activation failed with %08x\n", hr);
684
685     hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
686             0, 5000000, 0, pwfx, &ses1_guid);
687     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
688
689     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
690             eMultimedia, &cap_dev);
691     if(hr == S_OK){
692         WAVEFORMATEX *cap_pwfx;
693
694         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
695                 NULL, (void**)&cap_ac);
696         ok(hr == S_OK, "Activate failed: %08x\n", hr);
697
698         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
699         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
700
701         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
702                 0, 5000000, 0, cap_pwfx, &ses1_guid);
703         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
704
705         hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
706         ok(hr == S_OK, "GetService failed: %08x\n", hr);
707
708         IMMDevice_Release(cap_dev);
709         CoTaskMemFree(cap_pwfx);
710     }else
711         skip("No capture device available; skipping capture device in render session tests\n");
712
713     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
714     ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
715
716     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
717     ok(hr == S_OK, "GetService failed: %08x\n", hr);
718
719     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
720     ok(hr == S_OK, "GetService failed: %08x\n", hr);
721     ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
722     ref = IAudioSessionControl_Release(ses1_ctl2);
723     ok(ref != 0, "AudioSessionControl was destroyed\n");
724
725     hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
726     ok(hr == S_OK, "GetService failed: %08x\n", hr);
727
728     hr = IAudioSessionControl_GetState(ses1_ctl, NULL);
729     ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
730
731     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
732     ok(hr == S_OK, "GetState failed: %08x\n", hr);
733     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
734
735     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
736     ok(hr == S_OK, "GetState failed: %08x\n", hr);
737     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
738
739     if(cap_ac){
740         hr = IAudioSessionControl_GetState(cap_ctl, &state);
741         ok(hr == S_OK, "GetState failed: %08x\n", hr);
742         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
743     }
744
745     hr = IAudioClient_Start(ses1_ac1);
746     ok(hr == S_OK, "Start failed: %08x\n", hr);
747
748     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
749     ok(hr == S_OK, "GetState failed: %08x\n", hr);
750     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
751
752     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
753     ok(hr == S_OK, "GetState failed: %08x\n", hr);
754     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
755
756     if(cap_ac){
757         hr = IAudioSessionControl_GetState(cap_ctl, &state);
758         ok(hr == S_OK, "GetState failed: %08x\n", hr);
759         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
760     }
761
762     hr = IAudioClient_Stop(ses1_ac1);
763     ok(hr == S_OK, "Start failed: %08x\n", hr);
764
765     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
766     ok(hr == S_OK, "GetState failed: %08x\n", hr);
767     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
768
769     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
770     ok(hr == S_OK, "GetState failed: %08x\n", hr);
771     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
772
773     if(cap_ac){
774         hr = IAudioSessionControl_GetState(cap_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 = IAudioClient_Start(cap_ac);
779         ok(hr == S_OK, "Start failed: %08x\n", hr);
780
781         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
782         ok(hr == S_OK, "GetState failed: %08x\n", hr);
783         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
784
785         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
786         ok(hr == S_OK, "GetState failed: %08x\n", hr);
787         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
788
789         hr = IAudioSessionControl_GetState(cap_ctl, &state);
790         ok(hr == S_OK, "GetState failed: %08x\n", hr);
791         ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
792
793         hr = IAudioClient_Stop(cap_ac);
794         ok(hr == S_OK, "Stop failed: %08x\n", hr);
795
796         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
797         ok(hr == S_OK, "GetState failed: %08x\n", hr);
798         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
799
800         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
801         ok(hr == S_OK, "GetState failed: %08x\n", hr);
802         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
803
804         hr = IAudioSessionControl_GetState(cap_ctl, &state);
805         ok(hr == S_OK, "GetState failed: %08x\n", hr);
806         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
807
808         ref = IAudioSessionControl_Release(cap_ctl);
809         ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
810
811         ref = IAudioClient_Release(cap_ac);
812         ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
813     }
814
815     ref = IAudioSessionControl_Release(ses1_ctl);
816     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
817
818     ref = IAudioClient_Release(ses1_ac1);
819     ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
820
821     ref = IAudioClient_Release(ses1_ac2);
822     ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
823
824     /* we've released all of our IAudioClient references, so check GetState */
825     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
826     ok(hr == S_OK, "GetState failed: %08x\n", hr);
827     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
828
829     ref = IAudioSessionControl_Release(ses1_ctl2);
830     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
831
832     CoTaskMemFree(pwfx);
833 }
834
835 static void test_streamvolume(void)
836 {
837     IAudioClient *ac;
838     IAudioStreamVolume *asv;
839     WAVEFORMATEX *fmt;
840     UINT32 chans, i;
841     HRESULT hr;
842     float vol, *vols;
843
844     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
845             NULL, (void**)&ac);
846     ok(hr == S_OK, "Activation failed with %08x\n", hr);
847     if(hr != S_OK)
848         return;
849
850     hr = IAudioClient_GetMixFormat(ac, &fmt);
851     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
852
853     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
854             0, fmt, NULL);
855     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
856
857     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
858     ok(hr == S_OK, "GetService failed: %08x\n", hr);
859
860     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
861     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
862
863     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
864     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
865     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
866
867     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
868     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
869
870     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
871     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
872
873     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
874     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
875
876     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
877     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
878     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
879
880     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
881     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
882
883     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
884     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
885
886     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
887     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
888
889     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
890     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
891
892     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
893     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
894     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
895
896     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
897     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
898
899     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
900     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
901
902     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
903     ok(vols != NULL, "HeapAlloc failed\n");
904
905     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
906     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
907
908     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
909     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
910     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
911     for(i = 1; i < fmt->nChannels; ++i)
912         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
913
914     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
915     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
916
917     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
918     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
919
920     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
921     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
922
923     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
924     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
925
926     HeapFree(GetProcessHeap(), 0, vols);
927     IAudioStreamVolume_Release(asv);
928     IAudioClient_Release(ac);
929     CoTaskMemFree(fmt);
930 }
931
932 static void test_channelvolume(void)
933 {
934     IAudioClient *ac;
935     IChannelAudioVolume *acv;
936     WAVEFORMATEX *fmt;
937     UINT32 chans, i;
938     HRESULT hr;
939     float vol, *vols;
940
941     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
942             NULL, (void**)&ac);
943     ok(hr == S_OK, "Activation failed with %08x\n", hr);
944     if(hr != S_OK)
945         return;
946
947     hr = IAudioClient_GetMixFormat(ac, &fmt);
948     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
949
950     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
951             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
952     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
953
954     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
955     ok(hr == S_OK, "GetService failed: %08x\n", hr);
956
957     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
958     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
959
960     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
961     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
962     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
963
964     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
965     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
966
967     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
968     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
969
970     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
971     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
972
973     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
974     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
975     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
976
977     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
978     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
979
980     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
981     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
982
983     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
984     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
985
986     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
987     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
988
989     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
990     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
991     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
992
993     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
994     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
995
996     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
997     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
998
999     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1000     ok(vols != NULL, "HeapAlloc failed\n");
1001
1002     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
1003     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1004
1005     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1006     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1007     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1008     for(i = 1; i < fmt->nChannels; ++i)
1009         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1010
1011     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1012     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1013
1014     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1015     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1016
1017     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1018     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1019
1020     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1021     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1022
1023     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1024     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1025
1026     HeapFree(GetProcessHeap(), 0, vols);
1027     IChannelAudioVolume_Release(acv);
1028     IAudioClient_Release(ac);
1029     CoTaskMemFree(fmt);
1030 }
1031
1032 static void test_simplevolume(void)
1033 {
1034     IAudioClient *ac;
1035     ISimpleAudioVolume *sav;
1036     WAVEFORMATEX *fmt;
1037     HRESULT hr;
1038     float vol;
1039     BOOL mute;
1040
1041     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1042             NULL, (void**)&ac);
1043     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1044     if(hr != S_OK)
1045         return;
1046
1047     hr = IAudioClient_GetMixFormat(ac, &fmt);
1048     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1049
1050     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1051             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1052     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1053
1054     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1055     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1056
1057     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1058     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1059
1060     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1061     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1062     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1063
1064     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1065     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1066
1067     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1068     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1069
1070     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1071     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1072
1073     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1074     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1075     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1076
1077     hr = ISimpleAudioVolume_GetMute(sav, NULL);
1078     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1079
1080     mute = TRUE;
1081     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1082     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1083     ok(mute == FALSE, "Session is already muted\n");
1084
1085     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1086     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1087
1088     mute = FALSE;
1089     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1090     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1091     ok(mute == TRUE, "Session should have been muted\n");
1092
1093     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1094     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1095     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1096
1097     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1098     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1099
1100     mute = FALSE;
1101     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1102     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1103     ok(mute == TRUE, "Session should have been muted\n");
1104
1105     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1106     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1107
1108     ISimpleAudioVolume_Release(sav);
1109     IAudioClient_Release(ac);
1110     CoTaskMemFree(fmt);
1111 }
1112
1113 static void test_volume_dependence(void)
1114 {
1115     IAudioClient *ac, *ac2;
1116     ISimpleAudioVolume *sav;
1117     IChannelAudioVolume *cav;
1118     IAudioStreamVolume *asv;
1119     WAVEFORMATEX *fmt;
1120     HRESULT hr;
1121     float vol;
1122     GUID session;
1123     UINT32 nch;
1124
1125     hr = CoCreateGuid(&session);
1126     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1127
1128     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1129             NULL, (void**)&ac);
1130     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1131
1132     hr = IAudioClient_GetMixFormat(ac, &fmt);
1133     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1134
1135     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1136             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1137     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1138
1139     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1140     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1141
1142     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1143     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
1144
1145     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1146     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1147
1148     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1149     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1150
1151     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1152     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1153
1154     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1155     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1156
1157     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1158     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1159     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1160
1161     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1162     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1163     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1164
1165     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1166     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1167     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1168
1169     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1170             NULL, (void**)&ac2);
1171     if(SUCCEEDED(hr)){
1172         IChannelAudioVolume *cav2;
1173         IAudioStreamVolume *asv2;
1174
1175         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1176                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1177         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1178
1179         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1180         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1181
1182         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1183         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1184
1185         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1186         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1187         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1188
1189         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1190         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1191         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1192
1193         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1194         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1195         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1196
1197         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
1198         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1199         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1200
1201         IAudioStreamVolume_Release(asv2);
1202         IChannelAudioVolume_Release(cav2);
1203         IAudioClient_Release(ac2);
1204     }else
1205         skip("Unable to open the same device twice. Skipping session volume control tests\n");
1206
1207     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
1208     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1209
1210     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1211     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1212
1213     CoTaskMemFree(fmt);
1214     ISimpleAudioVolume_Release(sav);
1215     IChannelAudioVolume_Release(cav);
1216     IAudioStreamVolume_Release(asv);
1217     IAudioClient_Release(ac);
1218 }
1219
1220 static void test_session_creation(void)
1221 {
1222     IMMDevice *cap_dev;
1223     IAudioClient *ac;
1224     IAudioSessionManager *sesm;
1225     ISimpleAudioVolume *sav;
1226     GUID session_guid;
1227     float vol;
1228     HRESULT hr;
1229     WAVEFORMATEX *fmt;
1230
1231     CoCreateGuid(&session_guid);
1232
1233     hr = IMMDevice_Activate(dev, &IID_IAudioSessionManager,
1234             CLSCTX_INPROC_SERVER, NULL, (void**)&sesm);
1235     ok(hr == S_OK, "Activate failed: %08x\n", hr);
1236
1237     hr = IAudioSessionManager_GetSimpleAudioVolume(sesm, &session_guid,
1238             FALSE, &sav);
1239     ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1240
1241     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1242     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1243
1244     /* Release completely to show session persistence */
1245     ISimpleAudioVolume_Release(sav);
1246     IAudioSessionManager_Release(sesm);
1247
1248     /* test if we can create a capture audioclient in the session we just
1249      * created from a SessionManager derived from a render device */
1250     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1251             eMultimedia, &cap_dev);
1252     if(hr == S_OK){
1253         WAVEFORMATEX *cap_pwfx;
1254         IAudioClient *cap_ac;
1255         ISimpleAudioVolume *cap_sav;
1256         IAudioSessionManager *cap_sesm;
1257
1258         hr = IMMDevice_Activate(cap_dev, &IID_IAudioSessionManager,
1259                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_sesm);
1260         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1261
1262         hr = IAudioSessionManager_GetSimpleAudioVolume(cap_sesm, &session_guid,
1263                 FALSE, &cap_sav);
1264         ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1265
1266         vol = 0.5f;
1267         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1268         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1269         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1270
1271         ISimpleAudioVolume_Release(cap_sav);
1272         IAudioSessionManager_Release(cap_sesm);
1273
1274         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient,
1275                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_ac);
1276         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1277
1278         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1279         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1280
1281         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1282                 0, 5000000, 0, cap_pwfx, &session_guid);
1283         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1284
1285         hr = IAudioClient_GetService(cap_ac, &IID_ISimpleAudioVolume,
1286                 (void**)&cap_sav);
1287         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1288
1289         vol = 0.5f;
1290         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1291         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1292         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1293
1294         CoTaskMemFree(cap_pwfx);
1295         ISimpleAudioVolume_Release(cap_sav);
1296         IAudioClient_Release(cap_ac);
1297         IMMDevice_Release(cap_dev);
1298     }
1299
1300     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1301             NULL, (void**)&ac);
1302     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1303
1304     hr = IAudioClient_GetMixFormat(ac, &fmt);
1305     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1306
1307     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1308             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session_guid);
1309     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1310
1311     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1312     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1313
1314     vol = 0.5f;
1315     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1316     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1317     ok(fabs(vol - 0.6f) < 0.05f, "Got wrong volume: %f\n", vol);
1318
1319     CoTaskMemFree(fmt);
1320     ISimpleAudioVolume_Release(sav);
1321     IAudioClient_Release(ac);
1322 }
1323
1324 START_TEST(render)
1325 {
1326     HRESULT hr;
1327
1328     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1329     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1330     if (FAILED(hr))
1331     {
1332         skip("mmdevapi not available: 0x%08x\n", hr);
1333         goto cleanup;
1334     }
1335
1336     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
1337     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1338     if (hr != S_OK || !dev)
1339     {
1340         if (hr == E_NOTFOUND)
1341             skip("No sound card available\n");
1342         else
1343             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1344         goto cleanup;
1345     }
1346
1347     test_audioclient();
1348     test_references();
1349     test_event();
1350     test_padding();
1351     test_clock();
1352     test_session();
1353     test_streamvolume();
1354     test_channelvolume();
1355     test_simplevolume();
1356     test_volume_dependence();
1357     test_session_creation();
1358
1359     IMMDevice_Release(dev);
1360
1361 cleanup:
1362     if (mme)
1363         IMMDeviceEnumerator_Release(mme);
1364     CoUninitialize();
1365 }