mshtml: Rename call_event to fire_event.
[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
575     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
576     ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
577
578     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
579     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
580
581     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
582     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
583
584     hr = IAudioClock_GetPosition(acl, &pos, NULL);
585     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
586     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
587
588     hr = IAudioClient_Start(ac);
589     ok(hr == S_OK, "Start failed: %08x\n", hr);
590
591     Sleep(100);
592
593     hr = IAudioClock_GetPosition(acl, &pos, NULL);
594     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
595     ok(pos > 0, "Position should have been further along...\n");
596     last = pos;
597
598     hr = IAudioClient_Stop(ac);
599     ok(hr == S_OK, "Stop failed: %08x\n", hr);
600
601     hr = IAudioClock_GetPosition(acl, &pos, NULL);
602     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
603     ok(pos >= last, "Position should have been further along...\n");
604     last = pos;
605
606     hr = IAudioClient_Start(ac);
607     ok(hr == S_OK, "Start failed: %08x\n", hr);
608
609     Sleep(100);
610
611     hr = IAudioClient_Stop(ac);
612     ok(hr == S_OK, "Stop failed: %08x\n", hr);
613
614     hr = IAudioClock_GetPosition(acl, &pos, NULL);
615     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
616     ok(pos >= last, "Position should have been further along...\n");
617     last = pos;
618
619     hr = IAudioClock_GetPosition(acl, &pos, NULL);
620     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
621     ok(pos == last, "Position should have been further along...\n");
622
623     hr = IAudioClient_Reset(ac);
624     ok(hr == S_OK, "Reset failed: %08x\n", hr);
625
626     hr = IAudioClock_GetPosition(acl, &pos, NULL);
627     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
628     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
629
630     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
631     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
632
633     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
634     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
635
636     hr = IAudioClock_GetPosition(acl, &pos, NULL);
637     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
638     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
639     last = pos;
640
641     hr = IAudioClient_Start(ac);
642     ok(hr == S_OK, "Start failed: %08x\n", hr);
643
644     Sleep(100);
645
646     hr = IAudioClock_GetPosition(acl, &pos, NULL);
647     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
648     ok(pos > last, "Position should have been further along...\n");
649
650     hr = IAudioClient_Stop(ac);
651     ok(hr == S_OK, "Stop failed: %08x\n", hr);
652
653     hr = IAudioClock_GetPosition(acl, &pos, NULL);
654     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
655     ok(pos >= last, "Position should have been further along...\n");
656
657     CoTaskMemFree(pwfx);
658
659     IAudioClock_Release(acl);
660     IAudioRenderClient_Release(arc);
661     IAudioClient_Release(ac);
662 }
663
664 static void test_session(void)
665 {
666     IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac = NULL;
667     IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl;
668     IMMDevice *cap_dev;
669     GUID ses1_guid;
670     AudioSessionState state;
671     WAVEFORMATEX *pwfx;
672     ULONG ref;
673     HRESULT hr;
674
675     hr = CoCreateGuid(&ses1_guid);
676     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
677
678     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
679             NULL, (void**)&ses1_ac1);
680     ok(hr == S_OK, "Activation failed with %08x\n", hr);
681
682     hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
683     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
684
685     hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
686             0, 5000000, 0, pwfx, &ses1_guid);
687     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
688
689     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
690             NULL, (void**)&ses1_ac2);
691     ok(hr == S_OK, "Activation failed with %08x\n", hr);
692
693     hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
694             0, 5000000, 0, pwfx, &ses1_guid);
695     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
696
697     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
698             eMultimedia, &cap_dev);
699     if(hr == S_OK){
700         WAVEFORMATEX *cap_pwfx;
701
702         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
703                 NULL, (void**)&cap_ac);
704         ok(hr == S_OK, "Activate failed: %08x\n", hr);
705
706         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
707         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
708
709         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
710                 0, 5000000, 0, cap_pwfx, &ses1_guid);
711         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
712
713         hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
714         ok(hr == S_OK, "GetService failed: %08x\n", hr);
715
716         IMMDevice_Release(cap_dev);
717         CoTaskMemFree(cap_pwfx);
718     }else
719         skip("No capture device available; skipping capture device in render session tests\n");
720
721     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
722     ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
723
724     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
725     ok(hr == S_OK, "GetService failed: %08x\n", hr);
726
727     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
728     ok(hr == S_OK, "GetService failed: %08x\n", hr);
729     ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
730     ref = IAudioSessionControl_Release(ses1_ctl2);
731     ok(ref != 0, "AudioSessionControl was destroyed\n");
732
733     hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
734     ok(hr == S_OK, "GetService failed: %08x\n", hr);
735
736     hr = IAudioSessionControl_GetState(ses1_ctl, NULL);
737     ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
738
739     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
740     ok(hr == S_OK, "GetState failed: %08x\n", hr);
741     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
742
743     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
744     ok(hr == S_OK, "GetState failed: %08x\n", hr);
745     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
746
747     if(cap_ac){
748         hr = IAudioSessionControl_GetState(cap_ctl, &state);
749         ok(hr == S_OK, "GetState failed: %08x\n", hr);
750         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
751     }
752
753     hr = IAudioClient_Start(ses1_ac1);
754     ok(hr == S_OK, "Start failed: %08x\n", hr);
755
756     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
757     ok(hr == S_OK, "GetState failed: %08x\n", hr);
758     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
759
760     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
761     ok(hr == S_OK, "GetState failed: %08x\n", hr);
762     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
763
764     if(cap_ac){
765         hr = IAudioSessionControl_GetState(cap_ctl, &state);
766         ok(hr == S_OK, "GetState failed: %08x\n", hr);
767         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
768     }
769
770     hr = IAudioClient_Stop(ses1_ac1);
771     ok(hr == S_OK, "Start failed: %08x\n", hr);
772
773     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
774     ok(hr == S_OK, "GetState failed: %08x\n", hr);
775     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
776
777     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
778     ok(hr == S_OK, "GetState failed: %08x\n", hr);
779     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
780
781     if(cap_ac){
782         hr = IAudioSessionControl_GetState(cap_ctl, &state);
783         ok(hr == S_OK, "GetState failed: %08x\n", hr);
784         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
785
786         hr = IAudioClient_Start(cap_ac);
787         ok(hr == S_OK, "Start failed: %08x\n", hr);
788
789         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
790         ok(hr == S_OK, "GetState failed: %08x\n", hr);
791         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
792
793         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
794         ok(hr == S_OK, "GetState failed: %08x\n", hr);
795         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
796
797         hr = IAudioSessionControl_GetState(cap_ctl, &state);
798         ok(hr == S_OK, "GetState failed: %08x\n", hr);
799         ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
800
801         hr = IAudioClient_Stop(cap_ac);
802         ok(hr == S_OK, "Stop failed: %08x\n", hr);
803
804         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
805         ok(hr == S_OK, "GetState failed: %08x\n", hr);
806         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
807
808         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
809         ok(hr == S_OK, "GetState failed: %08x\n", hr);
810         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
811
812         hr = IAudioSessionControl_GetState(cap_ctl, &state);
813         ok(hr == S_OK, "GetState failed: %08x\n", hr);
814         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
815
816         ref = IAudioSessionControl_Release(cap_ctl);
817         ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
818
819         ref = IAudioClient_Release(cap_ac);
820         ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
821     }
822
823     ref = IAudioSessionControl_Release(ses1_ctl);
824     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
825
826     ref = IAudioClient_Release(ses1_ac1);
827     ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
828
829     ref = IAudioClient_Release(ses1_ac2);
830     ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
831
832     /* we've released all of our IAudioClient references, so check GetState */
833     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
834     ok(hr == S_OK, "GetState failed: %08x\n", hr);
835     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
836
837     ref = IAudioSessionControl_Release(ses1_ctl2);
838     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
839
840     CoTaskMemFree(pwfx);
841 }
842
843 static void test_streamvolume(void)
844 {
845     IAudioClient *ac;
846     IAudioStreamVolume *asv;
847     WAVEFORMATEX *fmt;
848     UINT32 chans, i;
849     HRESULT hr;
850     float vol, *vols;
851
852     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
853             NULL, (void**)&ac);
854     ok(hr == S_OK, "Activation failed with %08x\n", hr);
855     if(hr != S_OK)
856         return;
857
858     hr = IAudioClient_GetMixFormat(ac, &fmt);
859     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
860
861     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
862             0, fmt, NULL);
863     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
864
865     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
866     ok(hr == S_OK, "GetService failed: %08x\n", hr);
867
868     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
869     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
870
871     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
872     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
873     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
874
875     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
876     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
877
878     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
879     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
880
881     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
882     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
883
884     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
885     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
886     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
887
888     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
889     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
890
891     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
892     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
893
894     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
895     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
896
897     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
898     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
899
900     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
901     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
902     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
903
904     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
905     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
906
907     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
908     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
909
910     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
911     ok(vols != NULL, "HeapAlloc failed\n");
912
913     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
914     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
915
916     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
917     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
918     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
919     for(i = 1; i < fmt->nChannels; ++i)
920         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
921
922     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
923     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
924
925     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
926     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
927
928     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
929     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
930
931     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
932     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
933
934     HeapFree(GetProcessHeap(), 0, vols);
935     IAudioStreamVolume_Release(asv);
936     IAudioClient_Release(ac);
937     CoTaskMemFree(fmt);
938 }
939
940 static void test_channelvolume(void)
941 {
942     IAudioClient *ac;
943     IChannelAudioVolume *acv;
944     WAVEFORMATEX *fmt;
945     UINT32 chans, i;
946     HRESULT hr;
947     float vol, *vols;
948
949     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
950             NULL, (void**)&ac);
951     ok(hr == S_OK, "Activation failed with %08x\n", hr);
952     if(hr != S_OK)
953         return;
954
955     hr = IAudioClient_GetMixFormat(ac, &fmt);
956     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
957
958     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
959             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
960     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
961
962     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
963     ok(hr == S_OK, "GetService failed: %08x\n", hr);
964
965     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
966     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
967
968     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
969     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
970     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
971
972     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
973     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
974
975     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
976     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
977
978     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
979     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
980
981     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
982     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
983     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
984
985     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
986     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
987
988     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
989     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
990
991     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
992     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
993
994     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
995     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
996
997     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
998     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
999     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
1000
1001     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
1002     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1003
1004     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
1005     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
1006
1007     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1008     ok(vols != NULL, "HeapAlloc failed\n");
1009
1010     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
1011     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1012
1013     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1014     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1015     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1016     for(i = 1; i < fmt->nChannels; ++i)
1017         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1018
1019     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1020     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1021
1022     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1023     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1024
1025     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1026     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1027
1028     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1029     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1030
1031     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1032     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1033
1034     HeapFree(GetProcessHeap(), 0, vols);
1035     IChannelAudioVolume_Release(acv);
1036     IAudioClient_Release(ac);
1037     CoTaskMemFree(fmt);
1038 }
1039
1040 static void test_simplevolume(void)
1041 {
1042     IAudioClient *ac;
1043     ISimpleAudioVolume *sav;
1044     WAVEFORMATEX *fmt;
1045     HRESULT hr;
1046     float vol;
1047     BOOL mute;
1048
1049     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1050             NULL, (void**)&ac);
1051     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1052     if(hr != S_OK)
1053         return;
1054
1055     hr = IAudioClient_GetMixFormat(ac, &fmt);
1056     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1057
1058     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1059             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1060     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1061
1062     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1063     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1064
1065     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1066     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1067
1068     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1069     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1070     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1071
1072     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1073     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1074
1075     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1076     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1077
1078     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1079     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1080
1081     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1082     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1083     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1084
1085     hr = ISimpleAudioVolume_GetMute(sav, NULL);
1086     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1087
1088     mute = TRUE;
1089     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1090     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1091     ok(mute == FALSE, "Session is already muted\n");
1092
1093     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1094     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1095
1096     mute = FALSE;
1097     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1098     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1099     ok(mute == TRUE, "Session should have been muted\n");
1100
1101     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1102     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1103     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1104
1105     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1106     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1107
1108     mute = FALSE;
1109     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1110     ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1111     ok(mute == TRUE, "Session should have been muted\n");
1112
1113     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1114     ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1115
1116     ISimpleAudioVolume_Release(sav);
1117     IAudioClient_Release(ac);
1118     CoTaskMemFree(fmt);
1119 }
1120
1121 static void test_volume_dependence(void)
1122 {
1123     IAudioClient *ac, *ac2;
1124     ISimpleAudioVolume *sav;
1125     IChannelAudioVolume *cav;
1126     IAudioStreamVolume *asv;
1127     WAVEFORMATEX *fmt;
1128     HRESULT hr;
1129     float vol;
1130     GUID session;
1131     UINT32 nch;
1132
1133     hr = CoCreateGuid(&session);
1134     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1135
1136     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1137             NULL, (void**)&ac);
1138     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1139
1140     hr = IAudioClient_GetMixFormat(ac, &fmt);
1141     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1142
1143     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1144             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1145     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1146
1147     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1148     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1149
1150     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1151     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
1152
1153     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1154     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1155
1156     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1157     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1158
1159     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1160     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1161
1162     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1163     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1164
1165     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1166     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1167     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1168
1169     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1170     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1171     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1172
1173     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1174     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1175     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1176
1177     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1178             NULL, (void**)&ac2);
1179     if(SUCCEEDED(hr)){
1180         IChannelAudioVolume *cav2;
1181         IAudioStreamVolume *asv2;
1182
1183         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1184                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1185         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1186
1187         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1188         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1189
1190         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1191         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1192
1193         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1194         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1195         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1196
1197         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1198         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1199         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1200
1201         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1202         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1203         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1204
1205         hr = IAudioStreamVolume_GetChannelCount(asv2, &nch);
1206         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1207         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1208
1209         IAudioStreamVolume_Release(asv2);
1210         IChannelAudioVolume_Release(cav2);
1211         IAudioClient_Release(ac2);
1212     }else
1213         skip("Unable to open the same device twice. Skipping session volume control tests\n");
1214
1215     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
1216     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1217
1218     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1219     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1220
1221     CoTaskMemFree(fmt);
1222     ISimpleAudioVolume_Release(sav);
1223     IChannelAudioVolume_Release(cav);
1224     IAudioStreamVolume_Release(asv);
1225     IAudioClient_Release(ac);
1226 }
1227
1228 static void test_session_creation(void)
1229 {
1230     IMMDevice *cap_dev;
1231     IAudioClient *ac;
1232     IAudioSessionManager *sesm;
1233     ISimpleAudioVolume *sav;
1234     GUID session_guid;
1235     float vol;
1236     HRESULT hr;
1237     WAVEFORMATEX *fmt;
1238
1239     CoCreateGuid(&session_guid);
1240
1241     hr = IMMDevice_Activate(dev, &IID_IAudioSessionManager,
1242             CLSCTX_INPROC_SERVER, NULL, (void**)&sesm);
1243     ok(hr == S_OK, "Activate failed: %08x\n", hr);
1244
1245     hr = IAudioSessionManager_GetSimpleAudioVolume(sesm, &session_guid,
1246             FALSE, &sav);
1247     ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1248
1249     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1250     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1251
1252     /* Release completely to show session persistence */
1253     ISimpleAudioVolume_Release(sav);
1254     IAudioSessionManager_Release(sesm);
1255
1256     /* test if we can create a capture audioclient in the session we just
1257      * created from a SessionManager derived from a render device */
1258     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
1259             eMultimedia, &cap_dev);
1260     if(hr == S_OK){
1261         WAVEFORMATEX *cap_pwfx;
1262         IAudioClient *cap_ac;
1263         ISimpleAudioVolume *cap_sav;
1264         IAudioSessionManager *cap_sesm;
1265
1266         hr = IMMDevice_Activate(cap_dev, &IID_IAudioSessionManager,
1267                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_sesm);
1268         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1269
1270         hr = IAudioSessionManager_GetSimpleAudioVolume(cap_sesm, &session_guid,
1271                 FALSE, &cap_sav);
1272         ok(hr == S_OK, "GetSimpleAudioVolume failed: %08x\n", hr);
1273
1274         vol = 0.5f;
1275         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1276         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1277         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1278
1279         ISimpleAudioVolume_Release(cap_sav);
1280         IAudioSessionManager_Release(cap_sesm);
1281
1282         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient,
1283                 CLSCTX_INPROC_SERVER, NULL, (void**)&cap_ac);
1284         ok(hr == S_OK, "Activate failed: %08x\n", hr);
1285
1286         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
1287         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1288
1289         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
1290                 0, 5000000, 0, cap_pwfx, &session_guid);
1291         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1292
1293         hr = IAudioClient_GetService(cap_ac, &IID_ISimpleAudioVolume,
1294                 (void**)&cap_sav);
1295         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1296
1297         vol = 0.5f;
1298         hr = ISimpleAudioVolume_GetMasterVolume(cap_sav, &vol);
1299         ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1300         ok(vol == 1.f, "Got wrong volume: %f\n", vol);
1301
1302         CoTaskMemFree(cap_pwfx);
1303         ISimpleAudioVolume_Release(cap_sav);
1304         IAudioClient_Release(cap_ac);
1305         IMMDevice_Release(cap_dev);
1306     }
1307
1308     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1309             NULL, (void**)&ac);
1310     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1311
1312     hr = IAudioClient_GetMixFormat(ac, &fmt);
1313     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1314
1315     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1316             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session_guid);
1317     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1318
1319     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1320     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1321
1322     vol = 0.5f;
1323     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1324     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1325     ok(fabs(vol - 0.6f) < 0.05f, "Got wrong volume: %f\n", vol);
1326
1327     CoTaskMemFree(fmt);
1328     ISimpleAudioVolume_Release(sav);
1329     IAudioClient_Release(ac);
1330 }
1331
1332 START_TEST(render)
1333 {
1334     HRESULT hr;
1335
1336     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1337     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1338     if (FAILED(hr))
1339     {
1340         skip("mmdevapi not available: 0x%08x\n", hr);
1341         goto cleanup;
1342     }
1343
1344     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
1345     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1346     if (hr != S_OK || !dev)
1347     {
1348         if (hr == E_NOTFOUND)
1349             skip("No sound card available\n");
1350         else
1351             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1352         goto cleanup;
1353     }
1354
1355     test_audioclient();
1356     test_references();
1357     test_event();
1358     test_padding();
1359     test_clock();
1360     test_session();
1361     test_streamvolume();
1362     test_channelvolume();
1363     test_simplevolume();
1364     test_volume_dependence();
1365     test_session_creation();
1366
1367     IMMDevice_Release(dev);
1368
1369 cleanup:
1370     if (mme)
1371         IMMDeviceEnumerator_Release(mme);
1372     CoUninitialize();
1373 }