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