winealsa.drv: Move IAudioClock closer to its related interfaces.
[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 "wine/test.h"
25
26 #define COBJMACROS
27
28 #ifdef STANDALONE
29 #include "initguid.h"
30 #endif
31
32 #include "unknwn.h"
33 #include "uuids.h"
34 #include "mmdeviceapi.h"
35 #include "audioclient.h"
36 #include "audiopolicy.h"
37
38 #include <stdio.h>
39
40 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
41
42 static IMMDeviceEnumerator *mme = NULL;
43 static IMMDevice *dev = NULL;
44
45 static inline const char *dbgstr_guid( const GUID *id )
46 {
47     static char ret[256];
48     sprintf(ret, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
49                              id->Data1, id->Data2, id->Data3,
50                              id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
51                              id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
52     return ret;
53 }
54
55 static void test_uninitialized(IAudioClient *ac)
56 {
57     HRESULT hr;
58     UINT32 num;
59     REFERENCE_TIME t1;
60
61     HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
62     IUnknown *unk;
63
64     hr = IAudioClient_GetBufferSize(ac, &num);
65     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);
66
67     hr = IAudioClient_GetStreamLatency(ac, &t1);
68     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);
69
70     hr = IAudioClient_GetCurrentPadding(ac, &num);
71     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);
72
73     hr = IAudioClient_Start(ac);
74     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);
75
76     hr = IAudioClient_Stop(ac);
77     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);
78
79     hr = IAudioClient_Reset(ac);
80     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);
81
82     hr = IAudioClient_SetEventHandle(ac, handle);
83     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);
84
85     hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
86     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);
87
88     CloseHandle(handle);
89 }
90
91 static void test_audioclient(void)
92 {
93     IAudioClient *ac;
94     IUnknown *unk;
95     HRESULT hr;
96     ULONG ref;
97     WAVEFORMATEX *pwfx, *pwfx2;
98     REFERENCE_TIME t1, t2;
99     HANDLE handle;
100
101     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
102             NULL, (void**)&ac);
103     ok(hr == S_OK, "Activation failed with %08x\n", hr);
104     if(hr != S_OK)
105         return;
106
107     handle = CreateEventW(NULL, FALSE, FALSE, NULL);
108
109     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
110     ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);
111
112     unk = (void*)(LONG_PTR)0x12345678;
113     hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
114     ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
115     ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);
116
117     hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
118     ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
119     if (unk)
120     {
121         ref = IUnknown_Release(unk);
122         ok(ref == 1, "Released count is %u\n", ref);
123     }
124
125     hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
126     ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
127     if (unk)
128     {
129         ref = IUnknown_Release(unk);
130         ok(ref == 1, "Released count is %u\n", ref);
131     }
132
133     hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
134     ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);
135
136     hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
137     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
138
139     hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
140     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
141
142     hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
143     ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
144     trace("Returned periods: %u.%05u ms %u.%05u ms\n",
145           (UINT)(t1/10000), (UINT)(t1 % 10000),
146           (UINT)(t2/10000), (UINT)(t2 % 10000));
147
148     hr = IAudioClient_GetMixFormat(ac, NULL);
149     ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);
150
151     hr = IAudioClient_GetMixFormat(ac, &pwfx);
152     ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);
153
154     if (hr == S_OK)
155     {
156         trace("pwfx: %p\n", pwfx);
157         trace("Tag: %04x\n", pwfx->wFormatTag);
158         trace("bits: %u\n", pwfx->wBitsPerSample);
159         trace("chan: %u\n", pwfx->nChannels);
160         trace("rate: %u\n", pwfx->nSamplesPerSec);
161         trace("align: %u\n", pwfx->nBlockAlign);
162         trace("extra: %u\n", pwfx->cbSize);
163         ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
164         if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
165         {
166             WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
167             trace("Res: %u\n", pwfxe->Samples.wReserved);
168             trace("Mask: %x\n", pwfxe->dwChannelMask);
169             trace("Alg: %s\n",
170                   IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
171                   (IsEqualGUID(&pwfxe->SubFormat,
172                                &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
173         }
174
175         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
176         ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
177         ok(pwfx2 == NULL, "pwfx2 is non-null\n");
178         CoTaskMemFree(pwfx2);
179
180         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
181         ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);
182
183         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
184         ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);
185
186         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
187         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
188
189         hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
190         ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
191         ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");
192
193         hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
194         ok(hr == E_INVALIDARG ||
195            hr == AUDCLNT_E_UNSUPPORTED_FORMAT,
196            "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
197     }
198
199     test_uninitialized(ac);
200
201     hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
202     ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);
203
204     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
205     ok(hr == E_INVALIDARG, "Initialize with invalid flags returns %08x\n", hr);
206
207     /* It seems that if length > 2s or periodicity != 0 the length is ignored and call succeeds
208      * Since we can only initialize successfully once, skip those tests.
209      */
210     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
211     ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);
212
213     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
214     ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);
215
216     if (hr != S_OK)
217     {
218         skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
219         CoTaskMemFree(pwfx);
220         return;
221     }
222
223     hr = IAudioClient_GetStreamLatency(ac, NULL);
224     ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);
225
226     hr = IAudioClient_GetStreamLatency(ac, &t1);
227     ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
228     trace("Returned latency: %u.%05u ms\n",
229           (UINT)(t1/10000), (UINT)(t1 % 10000));
230
231     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
232     ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);
233
234     hr = IAudioClient_SetEventHandle(ac, NULL);
235     ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
236
237     hr = IAudioClient_SetEventHandle(ac, handle);
238     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
239        broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
240        broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
241        broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
242        , "SetEventHandle returns %08x\n", hr);
243
244     hr = IAudioClient_Reset(ac);
245     ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);
246
247     hr = IAudioClient_Stop(ac);
248     ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);
249
250     hr = IAudioClient_Start(ac);
251     ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);
252
253     IAudioClient_Release(ac);
254
255     CloseHandle(handle);
256     CoTaskMemFree(pwfx);
257 }
258
259 static void test_references(void)
260 {
261     IAudioClient *ac;
262     IAudioRenderClient *rc;
263     ISimpleAudioVolume *sav;
264     IAudioClock *acl;
265     WAVEFORMATEX *pwfx;
266     HRESULT hr;
267     ULONG ref;
268
269     /* IAudioRenderClient */
270     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
271             NULL, (void**)&ac);
272     ok(hr == S_OK, "Activation failed with %08x\n", hr);
273     if(hr != S_OK)
274         return;
275
276     hr = IAudioClient_GetMixFormat(ac, &pwfx);
277     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
278     if(hr != S_OK)
279         return;
280
281     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
282             0, pwfx, NULL);
283     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
284
285     CoTaskMemFree(pwfx);
286
287     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&rc);
288     ok(hr == S_OK, "GetService failed: %08x\n", hr);
289
290     IAudioRenderClient_AddRef(rc);
291     ref = IAudioRenderClient_Release(rc);
292     ok(ref != 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
293
294     ref = IAudioClient_Release(ac);
295     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
296
297     ref = IAudioRenderClient_Release(rc);
298     ok(ref == 0, "RenderClient_Release gave wrong refcount: %u\n", ref);
299
300     /* ISimpleAudioVolume */
301     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
302             NULL, (void**)&ac);
303     ok(hr == S_OK, "Activation failed with %08x\n", hr);
304     if(hr != S_OK)
305         return;
306
307     hr = IAudioClient_GetMixFormat(ac, &pwfx);
308     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
309
310     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
311             0, pwfx, NULL);
312     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
313
314     CoTaskMemFree(pwfx);
315
316     hr = IAudioClient_GetService(ac, &IID_ISimpleAudioVolume, (void**)&sav);
317     ok(hr == S_OK, "GetService failed: %08x\n", hr);
318
319     ISimpleAudioVolume_AddRef(sav);
320     ref = ISimpleAudioVolume_Release(sav);
321     ok(ref != 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
322
323     ref = IAudioClient_Release(ac);
324     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
325
326     ref = ISimpleAudioVolume_Release(sav);
327     ok(ref == 0, "SimpleAudioVolume_Release gave wrong refcount: %u\n", ref);
328
329     /* IAudioClock */
330     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
331             NULL, (void**)&ac);
332     ok(hr == S_OK, "Activation failed with %08x\n", hr);
333     if(hr != S_OK)
334         return;
335
336     hr = IAudioClient_GetMixFormat(ac, &pwfx);
337     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
338
339     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000,
340             0, pwfx, NULL);
341     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
342
343     CoTaskMemFree(pwfx);
344
345     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
346     ok(hr == S_OK, "GetService failed: %08x\n", hr);
347
348     IAudioClock_AddRef(acl);
349     ref = IAudioClock_Release(acl);
350     ok(ref != 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
351
352     ref = IAudioClient_Release(ac);
353     ok(ref != 0, "Client_Release gave wrong refcount: %u\n", ref);
354
355     ref = IAudioClock_Release(acl);
356     ok(ref == 0, "AudioClock_Release gave wrong refcount: %u\n", ref);
357 }
358
359 static void test_event(void)
360 {
361     HANDLE event;
362     HRESULT hr;
363     IAudioClient *ac;
364     WAVEFORMATEX *pwfx;
365
366     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
367             NULL, (void**)&ac);
368     ok(hr == S_OK, "Activation failed with %08x\n", hr);
369     if(hr != S_OK)
370         return;
371
372     hr = IAudioClient_GetMixFormat(ac, &pwfx);
373     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
374     if(hr != S_OK)
375         return;
376
377     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
378             AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
379             0, pwfx, NULL);
380     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
381
382     CoTaskMemFree(pwfx);
383
384     event = CreateEventW(NULL, FALSE, FALSE, NULL);
385     ok(event != NULL, "CreateEvent failed\n");
386
387     hr = IAudioClient_Start(ac);
388     ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start failed: %08x\n", hr);
389
390     hr = IAudioClient_SetEventHandle(ac, event);
391     ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);
392
393     hr = IAudioClient_Start(ac);
394     ok(hr == S_OK, "Start failed: %08x\n", hr);
395
396     hr = IAudioClient_Stop(ac);
397     ok(hr == S_OK, "Start failed: %08x\n", hr);
398
399     /* test releasing a playing stream */
400     hr = IAudioClient_Start(ac);
401     ok(hr == S_OK, "Start failed: %08x\n", hr);
402     IAudioClient_Release(ac);
403
404     CloseHandle(event);
405 }
406
407 static void test_padding(void)
408 {
409     HRESULT hr;
410     IAudioClient *ac;
411     IAudioRenderClient *arc;
412     WAVEFORMATEX *pwfx;
413     REFERENCE_TIME minp, defp;
414     BYTE *buf;
415     UINT32 psize, pad, written;
416
417     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
418             NULL, (void**)&ac);
419     ok(hr == S_OK, "Activation failed with %08x\n", hr);
420     if(hr != S_OK)
421         return;
422
423     hr = IAudioClient_GetMixFormat(ac, &pwfx);
424     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
425     if(hr != S_OK)
426         return;
427
428     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
429             0, 5000000, 0, pwfx, NULL);
430     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
431
432     hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
433     ok(hr == S_OK, "GetDevicePeriod failed: %08x\n", hr);
434     ok(defp != 0, "Default period is 0\n");
435     ok(minp != 0, "Minimum period is 0\n");
436     ok(minp <= defp, "Mininum period is greater than default period\n");
437
438     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
439     ok(hr == S_OK, "GetService failed: %08x\n", hr);
440
441     psize = (defp / 10000000.) * pwfx->nSamplesPerSec * pwfx->nBlockAlign;
442
443     written = 0;
444     hr = IAudioClient_GetCurrentPadding(ac, &pad);
445     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
446     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
447
448     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
449     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
450     ok(buf != NULL, "NULL buffer returned\n");
451
452     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
453             AUDCLNT_BUFFERFLAGS_SILENT);
454     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
455     written += psize;
456
457     hr = IAudioClient_GetCurrentPadding(ac, &pad);
458     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
459     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
460
461     psize = (minp / 10000000.) * pwfx->nSamplesPerSec * pwfx->nBlockAlign;
462
463     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
464     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
465     ok(buf != NULL, "NULL buffer returned\n");
466
467     hr = IAudioRenderClient_ReleaseBuffer(arc, psize,
468             AUDCLNT_BUFFERFLAGS_SILENT);
469     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
470     written += psize;
471
472     hr = IAudioClient_GetCurrentPadding(ac, &pad);
473     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
474     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
475
476     /* overfull buffer. requested 1/2s buffer size, so try
477      * to get a 1/2s buffer, which should fail */
478     psize = pwfx->nSamplesPerSec / 2.;
479     hr = IAudioRenderClient_GetBuffer(arc, psize, &buf);
480     ok(hr == AUDCLNT_E_BUFFER_TOO_LARGE, "GetBuffer gave wrong error: %08x\n", hr);
481
482     hr = IAudioRenderClient_ReleaseBuffer(arc, psize, 0);
483     ok(hr == AUDCLNT_E_OUT_OF_ORDER, "ReleaseBuffer gave wrong error: %08x\n", hr);
484
485     hr = IAudioClient_GetCurrentPadding(ac, &pad);
486     ok(hr == S_OK, "GetCurrentPadding failed: %08x\n", hr);
487     ok(pad == written, "GetCurrentPadding returned %u, should be %u\n", pad, written);
488
489     CoTaskMemFree(pwfx);
490
491     IAudioRenderClient_Release(arc);
492     IAudioClient_Release(ac);
493 }
494
495 static void test_clock(void)
496 {
497     HRESULT hr;
498     IAudioClient *ac;
499     IAudioClock *acl;
500     IAudioRenderClient *arc;
501     UINT64 freq, pos, pcpos, last;
502     BYTE *data;
503     WAVEFORMATEX *pwfx;
504
505     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
506             NULL, (void**)&ac);
507     ok(hr == S_OK, "Activation failed with %08x\n", hr);
508     if(hr != S_OK)
509         return;
510
511     hr = IAudioClient_GetMixFormat(ac, &pwfx);
512     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
513     if(hr != S_OK)
514         return;
515
516     hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
517             0, 5000000, 0, pwfx, NULL);
518     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
519
520     hr = IAudioClient_GetService(ac, &IID_IAudioClock, (void**)&acl);
521     ok(hr == S_OK, "GetService(IAudioClock) failed: %08x\n", hr);
522
523     hr = IAudioClock_GetFrequency(acl, &freq);
524     ok(hr == S_OK, "GetFrequency failed: %08x\n", hr);
525
526     hr = IAudioClock_GetPosition(acl, NULL, NULL);
527     ok(hr == E_POINTER, "GetPosition wrong error: %08x\n", hr);
528
529     pcpos = 0;
530     hr = IAudioClock_GetPosition(acl, &pos, &pcpos);
531     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
532     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
533     ok(pcpos != 0, "GetPosition returned zero pcpos\n");
534     last = pos;
535
536     hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (void**)&arc);
537     ok(hr == S_OK, "GetService(IAudioRenderClient) failed: %08x\n", hr);
538
539     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
540     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
541
542     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
543     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
544
545     hr = IAudioClock_GetPosition(acl, &pos, NULL);
546     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
547     ok(pos == 0, "GetPosition returned non-zero pos before being started\n");
548
549     hr = IAudioClient_Start(ac);
550     ok(hr == S_OK, "Start failed: %08x\n", hr);
551
552     Sleep(100);
553
554     hr = IAudioClock_GetPosition(acl, &pos, NULL);
555     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
556     ok(pos > 0, "Position should have been further along...\n");
557     last = pos;
558
559     hr = IAudioClient_Stop(ac);
560     ok(hr == S_OK, "Stop failed: %08x\n", hr);
561
562     hr = IAudioClock_GetPosition(acl, &pos, NULL);
563     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
564     ok(pos >= last, "Position should have been further along...\n");
565     last = pos;
566
567     hr = IAudioClient_Start(ac);
568     ok(hr == S_OK, "Start failed: %08x\n", hr);
569
570     Sleep(100);
571
572     hr = IAudioClient_Stop(ac);
573     ok(hr == S_OK, "Stop failed: %08x\n", hr);
574
575     hr = IAudioClock_GetPosition(acl, &pos, NULL);
576     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
577     ok(pos >= last, "Position should have been further along...\n");
578     last = pos;
579
580     hr = IAudioClock_GetPosition(acl, &pos, NULL);
581     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
582     ok(pos == last, "Position should have been further along...\n");
583
584     hr = IAudioClient_Reset(ac);
585     ok(hr == S_OK, "Reset failed: %08x\n", hr);
586
587     hr = IAudioClock_GetPosition(acl, &pos, NULL);
588     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
589     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
590     last = pos;
591
592     hr = IAudioRenderClient_GetBuffer(arc, pwfx->nSamplesPerSec / 2., &data);
593     ok(hr == S_OK, "GetBuffer failed: %08x\n", hr);
594
595     hr = IAudioRenderClient_ReleaseBuffer(arc, pwfx->nSamplesPerSec / 2., AUDCLNT_BUFFERFLAGS_SILENT);
596     ok(hr == S_OK, "ReleaseBuffer failed: %08x\n", hr);
597
598     hr = IAudioClock_GetPosition(acl, &pos, NULL);
599     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
600     ok(pos == 0, "GetPosition returned non-zero pos after Reset\n");
601     last = pos;
602
603     hr = IAudioClient_Start(ac);
604     ok(hr == S_OK, "Start failed: %08x\n", hr);
605
606     Sleep(100);
607
608     hr = IAudioClock_GetPosition(acl, &pos, NULL);
609     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
610     ok(pos > last, "Position should have been further along...\n");
611
612     hr = IAudioClient_Stop(ac);
613     ok(hr == S_OK, "Stop failed: %08x\n", hr);
614
615     hr = IAudioClock_GetPosition(acl, &pos, NULL);
616     ok(hr == S_OK, "GetPosition failed: %08x\n", hr);
617     ok(pos >= last, "Position should have been further along...\n");
618
619     IAudioClock_Release(acl);
620     IAudioClient_Release(ac);
621 }
622
623 static void test_session(void)
624 {
625     IAudioClient *ses1_ac1, *ses1_ac2, *cap_ac = NULL;
626     IAudioSessionControl2 *ses1_ctl, *ses1_ctl2, *cap_ctl;
627     IMMDevice *cap_dev;
628     GUID ses1_guid;
629     AudioSessionState state;
630     WAVEFORMATEX *pwfx;
631     ULONG ref;
632     HRESULT hr;
633
634     hr = CoCreateGuid(&ses1_guid);
635     ok(hr == S_OK, "CoCreateGuid failed: %08x\n", hr);
636
637     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
638             NULL, (void**)&ses1_ac1);
639     ok(hr == S_OK, "Activation failed with %08x\n", hr);
640
641     hr = IAudioClient_GetMixFormat(ses1_ac1, &pwfx);
642     ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
643
644     hr = IAudioClient_Initialize(ses1_ac1, AUDCLNT_SHAREMODE_SHARED,
645             0, 5000000, 0, pwfx, &ses1_guid);
646     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
647
648     hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
649             NULL, (void**)&ses1_ac2);
650     ok(hr == S_OK, "Activation failed with %08x\n", hr);
651
652     hr = IAudioClient_Initialize(ses1_ac2, AUDCLNT_SHAREMODE_SHARED,
653             0, 5000000, 0, pwfx, &ses1_guid);
654     ok(hr == S_OK, "Initialize failed: %08x\n", hr);
655
656     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eCapture,
657             eMultimedia, &cap_dev);
658     if(hr == S_OK){
659         WAVEFORMATEX *cap_pwfx;
660
661         hr = IMMDevice_Activate(cap_dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
662                 NULL, (void**)&cap_ac);
663         ok(hr == S_OK, "Activate failed: %08x\n", hr);
664
665         hr = IAudioClient_GetMixFormat(cap_ac, &cap_pwfx);
666         ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
667
668         hr = IAudioClient_Initialize(cap_ac, AUDCLNT_SHAREMODE_SHARED,
669                 0, 5000000, 0, cap_pwfx, &ses1_guid);
670         ok(hr == S_OK, "Initialize failed: %08x\n", hr);
671
672         hr = IAudioClient_GetService(cap_ac, &IID_IAudioSessionControl, (void**)&cap_ctl);
673         ok(hr == S_OK, "GetService failed: %08x\n", hr);
674
675         IMMDevice_Release(cap_dev);
676         CoTaskMemFree(cap_pwfx);
677     }else
678         skip("No capture device available; skipping capture device in render session tests\n");
679
680     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl2, (void**)&ses1_ctl);
681     ok(hr == E_NOINTERFACE, "GetService gave wrong error: %08x\n", hr);
682
683     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl);
684     ok(hr == S_OK, "GetService failed: %08x\n", hr);
685
686     hr = IAudioClient_GetService(ses1_ac1, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
687     ok(hr == S_OK, "GetService failed: %08x\n", hr);
688     ok(ses1_ctl == ses1_ctl2, "Got different controls: %p %p\n", ses1_ctl, ses1_ctl2);
689     ref = IAudioSessionControl_Release(ses1_ctl2);
690     ok(ref != 0, "AudioSessionControl was destroyed\n");
691
692     hr = IAudioClient_GetService(ses1_ac2, &IID_IAudioSessionControl, (void**)&ses1_ctl2);
693     ok(hr == S_OK, "GetService failed: %08x\n", hr);
694
695     hr = IAudioSessionControl_GetState(ses1_ctl, NULL);
696     ok(hr == NULL_PTR_ERR, "GetState gave wrong error: %08x\n", hr);
697
698     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
699     ok(hr == S_OK, "GetState failed: %08x\n", hr);
700     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
701
702     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
703     ok(hr == S_OK, "GetState failed: %08x\n", hr);
704     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
705
706     if(cap_ac){
707         hr = IAudioSessionControl_GetState(cap_ctl, &state);
708         ok(hr == S_OK, "GetState failed: %08x\n", hr);
709         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
710     }
711
712     hr = IAudioClient_Start(ses1_ac1);
713     ok(hr == S_OK, "Start failed: %08x\n", hr);
714
715     hr = IAudioSessionControl_GetState(ses1_ctl, &state);
716     ok(hr == S_OK, "GetState failed: %08x\n", hr);
717     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
718
719     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
720     ok(hr == S_OK, "GetState failed: %08x\n", hr);
721     ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
722
723     if(cap_ac){
724         hr = IAudioSessionControl_GetState(cap_ctl, &state);
725         ok(hr == S_OK, "GetState failed: %08x\n", hr);
726         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
727     }
728
729     hr = IAudioClient_Stop(ses1_ac1);
730     ok(hr == S_OK, "Start failed: %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         hr = IAudioClient_Start(cap_ac);
746         ok(hr == S_OK, "Start failed: %08x\n", hr);
747
748         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
749         ok(hr == S_OK, "GetState failed: %08x\n", hr);
750         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
751
752         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
753         ok(hr == S_OK, "GetState failed: %08x\n", hr);
754         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
755
756         hr = IAudioSessionControl_GetState(cap_ctl, &state);
757         ok(hr == S_OK, "GetState failed: %08x\n", hr);
758         ok(state == AudioSessionStateActive, "Got wrong state: %d\n", state);
759
760         hr = IAudioClient_Stop(cap_ac);
761         ok(hr == S_OK, "Stop failed: %08x\n", hr);
762
763         hr = IAudioSessionControl_GetState(ses1_ctl, &state);
764         ok(hr == S_OK, "GetState failed: %08x\n", hr);
765         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
766
767         hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
768         ok(hr == S_OK, "GetState failed: %08x\n", hr);
769         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
770
771         hr = IAudioSessionControl_GetState(cap_ctl, &state);
772         ok(hr == S_OK, "GetState failed: %08x\n", hr);
773         ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
774
775         ref = IAudioSessionControl_Release(cap_ctl);
776         ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
777
778         ref = IAudioClient_Release(cap_ac);
779         ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
780     }
781
782     ref = IAudioSessionControl_Release(ses1_ctl);
783     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
784
785     ref = IAudioClient_Release(ses1_ac1);
786     ok(ref == 0, "AudioClient wasn't released: %u\n", ref);
787
788     ref = IAudioClient_Release(ses1_ac2);
789     ok(ref == 1, "AudioClient had wrong refcount: %u\n", ref);
790
791     /* we've released all of our IAudioClient references, so check GetState */
792     hr = IAudioSessionControl_GetState(ses1_ctl2, &state);
793     ok(hr == S_OK, "GetState failed: %08x\n", hr);
794     ok(state == AudioSessionStateInactive, "Got wrong state: %d\n", state);
795
796     ref = IAudioSessionControl_Release(ses1_ctl2);
797     ok(ref == 0, "AudioSessionControl wasn't released: %u\n", ref);
798
799     CoTaskMemFree(pwfx);
800 }
801
802 START_TEST(render)
803 {
804     HRESULT hr;
805
806     CoInitializeEx(NULL, COINIT_MULTITHREADED);
807     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&mme);
808     if (FAILED(hr))
809     {
810         skip("mmdevapi not available: 0x%08x\n", hr);
811         goto cleanup;
812     }
813
814     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme, eRender, eMultimedia, &dev);
815     ok(hr == S_OK || hr == E_NOTFOUND, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr);
816     if (hr != S_OK || !dev)
817     {
818         if (hr == E_NOTFOUND)
819             skip("No sound card available\n");
820         else
821             skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr);
822         goto cleanup;
823     }
824
825     test_audioclient();
826     test_references();
827     test_event();
828     test_padding();
829     test_clock();
830     test_session();
831
832     IMMDevice_Release(dev);
833
834 cleanup:
835     if (mme)
836         IMMDeviceEnumerator_Release(mme);
837     CoUninitialize();
838 }