usp10/test: Add Tibetan shaping test.
[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     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
375     ok(hr == S_OK, "GetService failed: %08x\n", hr);
376
377     IAudioStreamVolume_AddRef(asv);
378     ref = IAudioStreamVolume_Release(asv);
379     ok(ref != 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
380
381     ref = IAudioClient_Release(ac);
382     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
383
384     ref = IAudioStreamVolume_Release(asv);
385     ok(ref == 0, "AudioStreamVolume_Release gave wrong refcount: %u\n", ref);
386 }
387
388 static void test_event(void)
389 {
390     HANDLE event;
391     HRESULT hr;
392     IAudioClient *ac;
393     WAVEFORMATEX *pwfx;
394
395     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
396             NULL, (void**)&ac);
397     ok(hr == S_OK, "Activation failed with %08x\n", hr);
398     if(hr != S_OK)
399         return;
400
401     hr = IAudioClient_GetMixFormat(ac, &pwfx);
402     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
403     if(hr != S_OK)
404         return;
405
406     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
407             AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
408             0, pwfx, NULL);
409     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
410
411     CoTaskMemFree(pwfx);
412
413     event = CreateEventW(NULL, FALSE, FALSE, NULL);
414     ok(event != NULL, "CreateEvent failed\n");
415
416     hr = IAudioClient_Start(ac);
417     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start failed: %08x\n", hr);
418
419     hr = IAudioClient_SetEventHandle(ac, event);
420     ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
421
422     hr = IAudioClient_Start(ac);
423     ok(hr == S_OK, "Start failed: %08x\n", hr);
424
425     hr = IAudioClient_Stop(ac);
426     ok(hr == S_OK, "Start failed: %08x\n", hr);
427
428     /* test releasing a playing stream */
429     hr = IAudioClient_Start(ac);
430     ok(hr == S_OK, "Start failed: %08x\n", hr);
431     IAudioClient_Release(ac);
432
433     CloseHandle(event);
434 }
435
436 static void test_padding(void)
437 {
438     HRESULT hr;
439     IAudioClient *ac;
440     IAudioRenderClient *arc;
441     WAVEFORMATEX *pwfx;
442     REFERENCE_TIME minp, defp;
443     BYTE *buf;
444     UINT32 psize, pad, written;
445
446     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
447             NULL, (void**)&ac);
448     ok(hr == S_OK, "Activation failed with %08x\n", hr);
449     if(hr != S_OK)
450         return;
451
452     hr = IAudioClient_GetMixFormat(ac, &pwfx);
453     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
454     if(hr != S_OK)
455         return;
456
457     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
458             0, 5000000, 0, pwfx, NULL);
459     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
460
461     hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
462     ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
463     ok(defp != 0, "Default period is 0\n");
464     ok(minp != 0, "Minimum period is 0\n");
465     ok(minp <= defp, "Mininum period is greater than default period\n");
466
467     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
468     ok(hr == S_OK, "GetService failed: %08x\n", hr);
469
470     psize = (defp / 10000000.) * pwfx->nSamplesPerSec * pwfx->nBlockAlign;
471
472     written = 0;
473     hr = IAudioClient_GetCurrentPadding(ac, &pad);
474     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
475     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
476
477     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
478     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
479     ok(buf != NULL, "NULL buffer returned\n");
480
481     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
482             AUDCLNT_BUFFERFLAGS_SILENT);
483     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
484     written += psize;
485
486     hr = IAudioClient_GetCurrentPadding(ac, &pad);
487     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
488     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
489
490     psize = (minp / 10000000.) * pwfx->nSamplesPerSec * pwfx->nBlockAlign;
491
492     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
493     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
494     ok(buf != NULL, "NULL buffer returned\n");
495
496     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
497             AUDCLNT_BUFFERFLAGS_SILENT);
498     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
499     written += psize;
500
501     hr = IAudioClient_GetCurrentPadding(ac, &pad);
502     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
503     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
504
505     /* overfull buffer. requested 1/2s buffer size, so try
506      * to get a 1/2s buffer, which should fail */
507     psize = pwfx->nSamplesPerSec / 2.;
508     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
509     ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
510
511     hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
512     ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
513
514     hr = IAudioClient_GetCurrentPadding(ac, &pad);
515     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
516     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
517
518     CoTaskMemFree(pwfx);
519
520     IAudioRenderClient_Release(arc);
521     IAudioClient_Release(ac);
522 }
523
524 static void test_clock(void)
525 {
526     HRESULT hr;
527     IAudioClient *ac;
528     IAudioClock *acl;
529     IAudioRenderClient *arc;
530     UINT64 freq, pos, pcpos, last;
531     BYTE *data;
532     WAVEFORMATEX *pwfx;
533
534     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
535             NULL, (void**)&ac);
536     ok(hr == S_OK, "Activation failed with %08x\n", hr);
537     if(hr != S_OK)
538         return;
539
540     hr = IAudioClient_GetMixFormat(ac, &pwfx);
541     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
542     if(hr != S_OK)
543         return;
544
545     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
546             0, 5000000, 0, pwfx, NULL);
547     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
548
549     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
550     ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
551
552     hr = IAudioClock_GetFrequency(acl, &freq);
553     ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
554
555     hr = IAudioClock_GetPosition(acl, NULL, NULL);
556     ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
557
558     pcpos = 0;
559     hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
560     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
561     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
562     ok(pcpos != 0, "GetPosition returned zero pcpos\n");
563     last = pos;
564
565     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
566     ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
567
568     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
569     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
570
571     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
572     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
573
574     hr = IAudioClock_GetPosition(acl, &pos, NULL);
575     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
576     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
577
578     hr = IAudioClient_Start(ac);
579     ok(hr == S_OK, "Start failed: %08x\n", hr);
580
581     Sleep(100);
582
583     hr = IAudioClock_GetPosition(acl, &pos, NULL);
584     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
585     ok(pos > 0, "Position should have been further along...\n");
586     last = pos;
587
588     hr = IAudioClient_Stop(ac);
589     ok(hr == S_OK, "Stop failed: %08x\n", hr);
590
591     hr = IAudioClock_GetPosition(acl, &pos, NULL);
592     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
593     ok(pos >= last, "Position should have been further along...\n");
594     last = pos;
595
596     hr = IAudioClient_Start(ac);
597     ok(hr == S_OK, "Start failed: %08x\n", hr);
598
599     Sleep(100);
600
601     hr = IAudioClient_Stop(ac);
602     ok(hr == S_OK, "Stop failed: %08x\n", hr);
603
604     hr = IAudioClock_GetPosition(acl, &pos, NULL);
605     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
606     ok(pos >= last, "Position should have been further along...\n");
607     last = pos;
608
609     hr = IAudioClock_GetPosition(acl, &pos, NULL);
610     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
611     ok(pos == last, "Position should have been further along...\n");
612
613     hr = IAudioClient_Reset(ac);
614     ok(hr == S_OK, "Reset failed: %08x\n", hr);
615
616     hr = IAudioClock_GetPosition(acl, &pos, NULL);
617     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
618     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
619     last = pos;
620
621     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
622     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
623
624     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
625     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
626
627     hr = IAudioClock_GetPosition(acl, &pos, NULL);
628     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
629     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
630     last = pos;
631
632     hr = IAudioClient_Start(ac);
633     ok(hr == S_OK, "Start failed: %08x\n", hr);
634
635     Sleep(100);
636
637     hr = IAudioClock_GetPosition(acl, &pos, NULL);
638     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
639     ok(pos > last, "Position should have been further along...\n");
640
641     hr = IAudioClient_Stop(ac);
642     ok(hr == S_OK, "Stop failed: %08x\n", hr);
643
644     hr = IAudioClock_GetPosition(acl, &pos, NULL);
645     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
646     ok(pos >= last, "Position should have been further along...\n");
647
648     IAudioClock_Release(acl);
649     IAudioClient_Release(ac);
650 }
651
652 static void test_session(void)
653 {
654     IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac = NULL;
655     IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl;
656     IMMDevice *cap_dev;
657     GUID ses1_guid;
658     AudioSessionState state;
659     WAVEFORMATEX *pwfx;
660     ULONG ref;
661     HRESULT hr;
662
663     hr = CoCreateGuid(&ses1_guid);
664     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
665
666     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
667             NULL, (void**)&ses1_ac1);
668     ok(hr == S_OK, "Activation failed with %08x\n", hr);
669
670     hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
671     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
672
673     hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
674             0, 5000000, 0, pwfx, &ses1_guid);
675     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
676
677     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
678             NULL, (void**)&ses1_ac2);
679     ok(hr == S_OK, "Activation failed with %08x\n", hr);
680
681     hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
682             0, 5000000, 0, pwfx, &ses1_guid);
683     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
684
685     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
686             eMultimedia, &cap_dev);
687     if(hr == S_OK){
688         WAVEFORMATEX *cap_pwfx;
689
690         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
691                 NULL, (void**)&cap_ac);
692         ok(hr == S_OK, "Activate failed: %08x\n", hr);
693
694         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
695         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
696
697         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
698                 0, 5000000, 0, cap_pwfx, &ses1_guid);
699         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
700
701         hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
702         ok(hr == S_OK, "GetService failed: %08x\n", hr);
703
704         IMMDevice_Release(cap_dev);
705         CoTaskMemFree(cap_pwfx);
706     }else
707         skip("No capture device available; skipping capture device in render session tests\n");
708
709     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
710     ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
711
712     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
713     ok(hr == S_OK, "GetService failed: %08x\n", hr);
714
715     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
716     ok(hr == S_OK, "GetService failed: %08x\n", hr);
717     ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
718     ref = IAudioSessionControl_Release(ses1_ctl2);
719     ok(ref != 0, "AudioSessionControl was destroyed\n");
720
721     hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
722     ok(hr == S_OK, "GetService failed: %08x\n", hr);
723
724     hr = IAudioSessionControl_GetState(ses1_ctl, NULL);
725     ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
726
727     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
728     ok(hr == S_OK, "GetState failed: %08x\n", hr);
729     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
730
731     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
732     ok(hr == S_OK, "GetState failed: %08x\n", hr);
733     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
734
735     if(cap_ac){
736         hr = IAudioSessionControl_GetState(cap_ctl, &state);
737         ok(hr == S_OK, "GetState failed: %08x\n", hr);
738         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
739     }
740
741     hr = IAudioClient_Start(ses1_ac1);
742     ok(hr == S_OK, "Start failed: %08x\n", hr);
743
744     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
745     ok(hr == S_OK, "GetState failed: %08x\n", hr);
746     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
747
748     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
749     ok(hr == S_OK, "GetState failed: %08x\n", hr);
750     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
751
752     if(cap_ac){
753         hr = IAudioSessionControl_GetState(cap_ctl, &state);
754         ok(hr == S_OK, "GetState failed: %08x\n", hr);
755         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
756     }
757
758     hr = IAudioClient_Stop(ses1_ac1);
759     ok(hr == S_OK, "Start failed: %08x\n", hr);
760
761     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
762     ok(hr == S_OK, "GetState failed: %08x\n", hr);
763     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
764
765     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
766     ok(hr == S_OK, "GetState failed: %08x\n", hr);
767     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
768
769     if(cap_ac){
770         hr = IAudioSessionControl_GetState(cap_ctl, &state);
771         ok(hr == S_OK, "GetState failed: %08x\n", hr);
772         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
773
774         hr = IAudioClient_Start(cap_ac);
775         ok(hr == S_OK, "Start failed: %08x\n", hr);
776
777         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
778         ok(hr == S_OK, "GetState failed: %08x\n", hr);
779         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
780
781         hr = IAudioSessionControl_GetState(ses1_ctl2, &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(cap_ctl, &state);
786         ok(hr == S_OK, "GetState failed: %08x\n", hr);
787         ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
788
789         hr = IAudioClient_Stop(cap_ac);
790         ok(hr == S_OK, "Stop failed: %08x\n", hr);
791
792         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
793         ok(hr == S_OK, "GetState failed: %08x\n", hr);
794         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
795
796         hr = IAudioSessionControl_GetState(ses1_ctl2, &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(cap_ctl, &state);
801         ok(hr == S_OK, "GetState failed: %08x\n", hr);
802         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
803
804         ref = IAudioSessionControl_Release(cap_ctl);
805         ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
806
807         ref = IAudioClient_Release(cap_ac);
808         ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
809     }
810
811     ref = IAudioSessionControl_Release(ses1_ctl);
812     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
813
814     ref = IAudioClient_Release(ses1_ac1);
815     ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
816
817     ref = IAudioClient_Release(ses1_ac2);
818     ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
819
820     /* we've released all of our IAudioClient references, so check GetState */
821     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
822     ok(hr == S_OK, "GetState failed: %08x\n", hr);
823     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
824
825     ref = IAudioSessionControl_Release(ses1_ctl2);
826     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
827
828     CoTaskMemFree(pwfx);
829 }
830
831 static void test_streamvolume(void)
832 {
833     IAudioClient *ac;
834     IAudioStreamVolume *asv;
835     WAVEFORMATEX *fmt;
836     UINT32 chans, i;
837     HRESULT hr;
838     float vol, *vols;
839
840     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
841             NULL, (void**)&ac);
842     ok(hr == S_OK, "Activation failed with %08x\n", hr);
843     if(hr != S_OK)
844         return;
845
846     hr = IAudioClient_GetMixFormat(ac, &fmt);
847     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
848
849     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
850             0, fmt, NULL);
851     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
852
853     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
854     ok(hr == S_OK, "GetService failed: %08x\n", hr);
855
856     hr = IAudioStreamVolume_GetChannelCount(asv, NULL);
857     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
858
859     hr = IAudioStreamVolume_GetChannelCount(asv, &chans);
860     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
861     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
862
863     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, NULL);
864     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
865
866     hr = IAudioStreamVolume_GetChannelVolume(asv, fmt->nChannels, &vol);
867     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
868
869     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, NULL);
870     ok(hr == E_POINTER, "GetChannelCount gave wrong error: %08x\n", hr);
871
872     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
873     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
874     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
875
876     hr = IAudioStreamVolume_SetChannelVolume(asv, fmt->nChannels, -1.f);
877     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
878
879     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, -1.f);
880     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
881
882     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 2.f);
883     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
884
885     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
886     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
887
888     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
889     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
890     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
891
892     hr = IAudioStreamVolume_GetAllVolumes(asv, 0, NULL);
893     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
894
895     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, NULL);
896     ok(hr == E_POINTER, "GetAllVolumes gave wrong error: %08x\n", hr);
897
898     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
899     ok(vols != NULL, "HeapAlloc failed\n");
900
901     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels - 1, vols);
902     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
903
904     hr = IAudioStreamVolume_GetAllVolumes(asv, fmt->nChannels, vols);
905     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
906     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
907     for(i = 1; i < fmt->nChannels; ++i)
908         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
909
910     hr = IAudioStreamVolume_SetAllVolumes(asv, 0, NULL);
911     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
912
913     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, NULL);
914     ok(hr == E_POINTER, "SetAllVolumes gave wrong error: %08x\n", hr);
915
916     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels - 1, vols);
917     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
918
919     hr = IAudioStreamVolume_SetAllVolumes(asv, fmt->nChannels, vols);
920     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
921
922     HeapFree(GetProcessHeap(), 0, vols);
923     IAudioStreamVolume_Release(asv);
924     IAudioClient_Release(ac);
925     CoTaskMemFree(fmt);
926 }
927
928 static void test_channelvolume(void)
929 {
930     IAudioClient *ac;
931     IChannelAudioVolume *acv;
932     WAVEFORMATEX *fmt;
933     UINT32 chans, i;
934     HRESULT hr;
935     float vol, *vols;
936
937     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
938             NULL, (void**)&ac);
939     ok(hr == S_OK, "Activation failed with %08x\n", hr);
940     if(hr != S_OK)
941         return;
942
943     hr = IAudioClient_GetMixFormat(ac, &fmt);
944     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
945
946     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
947             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
948     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
949
950     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&acv);
951     ok(hr == S_OK, "GetService failed: %08x\n", hr);
952
953     hr = IChannelAudioVolume_GetChannelCount(acv, NULL);
954     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
955
956     hr = IChannelAudioVolume_GetChannelCount(acv, &chans);
957     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
958     ok(chans == fmt->nChannels, "GetChannelCount gave wrong number of channels: %d\n", chans);
959
960     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, NULL);
961     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
962
963     hr = IChannelAudioVolume_GetChannelVolume(acv, fmt->nChannels, &vol);
964     ok(hr == E_INVALIDARG, "GetChannelCount gave wrong error: %08x\n", hr);
965
966     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, NULL);
967     ok(hr == NULL_PTR_ERR, "GetChannelCount gave wrong error: %08x\n", hr);
968
969     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
970     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
971     ok(vol == 1.f, "Channel volume was not 1: %f\n", vol);
972
973     hr = IChannelAudioVolume_SetChannelVolume(acv, fmt->nChannels, -1.f, NULL);
974     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
975
976     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, -1.f, NULL);
977     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
978
979     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 2.f, NULL);
980     ok(hr == E_INVALIDARG, "SetChannelVolume gave wrong error: %08x\n", hr);
981
982     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 0.2f, NULL);
983     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
984
985     hr = IChannelAudioVolume_GetChannelVolume(acv, 0, &vol);
986     ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
987     ok(fabsf(vol - 0.2f) < 0.05f, "Channel volume wasn't 0.2: %f\n", vol);
988
989     hr = IChannelAudioVolume_GetAllVolumes(acv, 0, NULL);
990     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
991
992     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, NULL);
993     ok(hr == NULL_PTR_ERR, "GetAllVolumes gave wrong error: %08x\n", hr);
994
995     vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
996     ok(vols != NULL, "HeapAlloc failed\n");
997
998     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels - 1, vols);
999     ok(hr == E_INVALIDARG, "GetAllVolumes gave wrong error: %08x\n", hr);
1000
1001     hr = IChannelAudioVolume_GetAllVolumes(acv, fmt->nChannels, vols);
1002     ok(hr == S_OK, "GetAllVolumes failed: %08x\n", hr);
1003     ok(fabsf(vols[0] - 0.2f) < 0.05f, "Channel 0 volume wasn't 0.2: %f\n", vol);
1004     for(i = 1; i < fmt->nChannels; ++i)
1005         ok(vols[i] == 1.f, "Channel %d volume is not 1: %f\n", i, vols[i]);
1006
1007     hr = IChannelAudioVolume_SetAllVolumes(acv, 0, NULL, NULL);
1008     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1009
1010     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, NULL, NULL);
1011     ok(hr == NULL_PTR_ERR, "SetAllVolumes gave wrong error: %08x\n", hr);
1012
1013     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels - 1, vols, NULL);
1014     ok(hr == E_INVALIDARG, "SetAllVolumes gave wrong error: %08x\n", hr);
1015
1016     hr = IChannelAudioVolume_SetAllVolumes(acv, fmt->nChannels, vols, NULL);
1017     ok(hr == S_OK, "SetAllVolumes failed: %08x\n", hr);
1018
1019     hr = IChannelAudioVolume_SetChannelVolume(acv, 0, 1.0f, NULL);
1020     ok(hr == S_OK, "SetChannelVolume failed: %08x\n", hr);
1021
1022     HeapFree(GetProcessHeap(), 0, vols);
1023     IChannelAudioVolume_Release(acv);
1024     IAudioClient_Release(ac);
1025     CoTaskMemFree(fmt);
1026 }
1027
1028 static void test_simplevolume(void)
1029 {
1030     IAudioClient *ac;
1031     ISimpleAudioVolume *sav;
1032     WAVEFORMATEX *fmt;
1033     HRESULT hr;
1034     float vol;
1035     BOOL mute;
1036
1037     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1038             NULL, (void**)&ac);
1039     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1040     if(hr != S_OK)
1041         return;
1042
1043     hr = IAudioClient_GetMixFormat(ac, &fmt);
1044     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1045
1046     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1047             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, NULL);
1048     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1049
1050     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1051     ok(hr == S_OK, "GetService failed: %08x\n", hr);
1052
1053     hr = ISimpleAudioVolume_GetMasterVolume(sav, NULL);
1054     ok(hr == NULL_PTR_ERR, "GetMasterVolume gave wrong error: %08x\n", hr);
1055
1056     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1057     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1058     ok(vol == 1.f, "Master volume wasn't 1: %f\n", vol);
1059
1060     hr = ISimpleAudioVolume_SetMasterVolume(sav, -1.f, NULL);
1061     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1062
1063     hr = ISimpleAudioVolume_SetMasterVolume(sav, 2.f, NULL);
1064     ok(hr == E_INVALIDARG, "SetMasterVolume gave wrong error: %08x\n", hr);
1065
1066     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.2f, NULL);
1067     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1068
1069     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1070     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1071     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1072
1073     hr = ISimpleAudioVolume_GetMute(sav, NULL);
1074     ok(hr == NULL_PTR_ERR, "GetMute gave wrong error: %08x\n", hr);
1075
1076     mute = TRUE;
1077     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1078     todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1079     todo_wine ok(mute == FALSE, "Session is already muted\n");
1080
1081     hr = ISimpleAudioVolume_SetMute(sav, TRUE, NULL);
1082     todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1083
1084     mute = FALSE;
1085     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1086     todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1087     todo_wine ok(mute == TRUE, "Session should have been muted\n");
1088
1089     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1090     ok(hr == S_OK, "GetMasterVolume failed: %08x\n", hr);
1091     ok(fabsf(vol - 0.2f) < 0.05f, "Master volume wasn't 0.2: %f\n", vol);
1092
1093     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1094     ok(hr == S_OK, "SetMasterVolume failed: %08x\n", hr);
1095
1096     mute = FALSE;
1097     hr = ISimpleAudioVolume_GetMute(sav, &mute);
1098     todo_wine ok(hr == S_OK, "GetMute failed: %08x\n", hr);
1099     todo_wine ok(mute == TRUE, "Session should have been muted\n");
1100
1101     hr = ISimpleAudioVolume_SetMute(sav, FALSE, NULL);
1102     todo_wine ok(hr == S_OK, "SetMute failed: %08x\n", hr);
1103
1104     ISimpleAudioVolume_Release(sav);
1105     IAudioClient_Release(ac);
1106     CoTaskMemFree(fmt);
1107 }
1108
1109 static void test_volume_dependence(void)
1110 {
1111     IAudioClient *ac, *ac2;
1112     ISimpleAudioVolume *sav;
1113     IChannelAudioVolume *cav;
1114     IAudioStreamVolume *asv;
1115     WAVEFORMATEX *fmt;
1116     HRESULT hr;
1117     float vol;
1118     GUID session;
1119     UINT32 nch;
1120
1121     hr = CoCreateGuid(&session);
1122     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
1123
1124     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1125             NULL, (void**)&ac);
1126     ok(hr == S_OK, "Activation failed with %08x\n", hr);
1127
1128     hr = IAudioClient_GetMixFormat(ac, &fmt);
1129     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
1130
1131     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
1132             AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1133     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1134
1135     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
1136     ok(hr == S_OK, "GetService (SimpleAudioVolume) failed: %08x\n", hr);
1137
1138     hr = IAudioClient_GetService(ac, &IID_IChannelAudioVolume, (void**)&cav);
1139     ok(hr == S_OK, "GetService (ChannelAudioVolme) failed: %08x\n", hr);
1140
1141     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&asv);
1142     ok(hr == S_OK, "GetService (AudioStreamVolume) failed: %08x\n", hr);
1143
1144     hr = IAudioStreamVolume_SetChannelVolume(asv, 0, 0.2f);
1145     ok(hr == S_OK, "ASV_SetChannelVolume failed: %08x\n", hr);
1146
1147     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 0.4f, NULL);
1148     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1149
1150     hr = ISimpleAudioVolume_SetMasterVolume(sav, 0.6f, NULL);
1151     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1152
1153     hr = IAudioStreamVolume_GetChannelVolume(asv, 0, &vol);
1154     ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1155     ok(fabsf(vol - 0.2) < 0.05f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1156
1157     hr = IChannelAudioVolume_GetChannelVolume(cav, 0, &vol);
1158     ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1159     ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1160
1161     hr = ISimpleAudioVolume_GetMasterVolume(sav, &vol);
1162     ok(hr == S_OK, "SAV_GetMasterVolume failed: %08x\n", hr);
1163     ok(fabsf(vol - 0.6) < 0.05f, "SAV_GetMasterVolume gave wrong volume: %f\n", vol);
1164
1165     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1166             NULL, (void**)&ac2);
1167     if(SUCCEEDED(hr)){
1168         IChannelAudioVolume *cav2;
1169         IAudioStreamVolume *asv2;
1170
1171         hr = IAudioClient_Initialize(ac2, AUDCLNT_SHAREMODE_SHARED,
1172                 AUDCLNT_STREAMFLAGS_NOPERSIST, 5000000, 0, fmt, &session);
1173         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1174
1175         hr = IAudioClient_GetService(ac2, &IID_IChannelAudioVolume, (void**)&cav2);
1176         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1177
1178         hr = IAudioClient_GetService(ac2, &IID_IAudioStreamVolume, (void**)&asv2);
1179         ok(hr == S_OK, "GetService failed: %08x\n", hr);
1180
1181         hr = IChannelAudioVolume_GetChannelVolume(cav2, 0, &vol);
1182         ok(hr == S_OK, "CAV_GetChannelVolume failed: %08x\n", hr);
1183         ok(fabsf(vol - 0.4) < 0.05f, "CAV_GetChannelVolume gave wrong volume: %f\n", vol);
1184
1185         hr = IAudioStreamVolume_GetChannelVolume(asv2, 0, &vol);
1186         ok(hr == S_OK, "ASV_GetChannelVolume failed: %08x\n", hr);
1187         ok(vol == 1.f, "ASV_GetChannelVolume gave wrong volume: %f\n", vol);
1188
1189         hr = IChannelAudioVolume_GetChannelCount(cav2, &nch);
1190         ok(hr == S_OK, "GetChannelCount failed: %08x\n", hr);
1191         ok(nch == fmt->nChannels, "Got wrong channel count, expected %u: %u\n", fmt->nChannels, nch);
1192
1193         hr = IAudioStreamVolume_GetChannelCount(asv2, &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         IAudioStreamVolume_Release(asv2);
1198         IChannelAudioVolume_Release(cav2);
1199         IAudioClient_Release(ac2);
1200     }else
1201         skip("Unable to open the same device twice. Skipping session volume control tests\n");
1202
1203     hr = IChannelAudioVolume_SetChannelVolume(cav, 0, 1.f, NULL);
1204     ok(hr == S_OK, "CAV_SetChannelVolume failed: %08x\n", hr);
1205
1206     hr = ISimpleAudioVolume_SetMasterVolume(sav, 1.f, NULL);
1207     ok(hr == S_OK, "SAV_SetMasterVolume failed: %08x\n", hr);
1208
1209     CoTaskMemFree(fmt);
1210     ISimpleAudioVolume_Release(sav);
1211     IChannelAudioVolume_Release(cav);
1212     IAudioStreamVolume_Release(asv);
1213     IAudioClient_Release(ac);
1214 }
1215
1216 START_TEST(render)
1217 {
1218     HRESULT hr;
1219
1220     CoInitializeEx(NULL, COINIT_MULTITHREADED);
1221     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
1222     if (FAILED(hr))
1223     {
1224         skip("mmdevapi not available: 0x%08x\n", hr);
1225         goto cleanup;
1226     }
1227
1228     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
1229     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
1230     if (hr != S_OK || !dev)
1231     {
1232         if (hr == E_NOTFOUND)
1233             skip("No sound card available\n");
1234         else
1235             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
1236         goto cleanup;
1237     }
1238
1239     test_audioclient();
1240     test_references();
1241     test_event();
1242     test_padding();
1243     test_clock();
1244     test_session();
1245     test_streamvolume();
1246     test_channelvolume();
1247     test_simplevolume();
1248     test_volume_dependence();
1249
1250     IMMDevice_Release(dev);
1251
1252 cleanup:
1253     if (mme)
1254         IMMDeviceEnumerator_Release(mme);
1255     CoUninitialize();
1256 }