winealsa.drv: Properly allocate and free the WAVEFORMATEX returned by IsFormatSupported.
[wine] / dlls / winealsa.drv / mmdevdrv.c
1 /*
2  * Copyright 2010 Maarten Lankhorst for CodeWeavers
3  * Copyright 2011 Andrew Eikum for CodeWeavers
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #define NONAMELESSUNION
21 #define COBJMACROS
22 #define INITGUID
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <math.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "winreg.h"
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34 #include "wine/list.h"
35
36 #include "ole2.h"
37 #include "mmdeviceapi.h"
38 #include "dshow.h"
39 #include "dsound.h"
40 #include "audioclient.h"
41 #include "endpointvolume.h"
42 #include "audiopolicy.h"
43
44 #include "dsdriver.h"
45
46 #include <alsa/asoundlib.h>
47
48 WINE_DEFAULT_DEBUG_CHANNEL(alsa);
49
50 static const REFERENCE_TIME DefaultPeriod = 200000;
51 static const REFERENCE_TIME MinimumPeriod = 100000;
52
53 typedef struct ACImpl {
54     IAudioClient IAudioClient_iface;
55     IAudioRenderClient IAudioRenderClient_iface;
56     IAudioCaptureClient IAudioCaptureClient_iface;
57     IAudioSessionControl2 IAudioSessionControl2_iface;
58     ISimpleAudioVolume ISimpleAudioVolume_iface;
59     IAudioClock IAudioClock_iface;
60     IAudioClock2 IAudioClock2_iface;
61
62     LONG ref;
63
64     snd_pcm_t *pcm_handle;
65     snd_pcm_uframes_t period_alsa, bufsize_alsa;
66     snd_pcm_hw_params_t *hw_params; /* does not hold state between calls */
67
68     IMMDevice *parent;
69
70     EDataFlow dataflow;
71     WAVEFORMATEX *fmt;
72     DWORD flags;
73     AUDCLNT_SHAREMODE share;
74     HANDLE event;
75
76     BOOL initted, started;
77     UINT64 written_frames, held_frames, tmp_buffer_frames;
78     UINT32 bufsize_frames, period_us;
79     UINT32 lcl_offs_frames; /* offs into local_buffer where valid data starts */
80
81     HANDLE timer;
82     BYTE *local_buffer, *tmp_buffer;
83     int buf_state;
84
85     CRITICAL_SECTION lock;
86 } ACImpl;
87
88 enum BufferStates {
89     NOT_LOCKED = 0,
90     LOCKED_NORMAL, /* public buffer piece is from local_buffer */
91     LOCKED_WRAPPED /* public buffer piece is wrapped around, in tmp_buffer */
92 };
93
94 static HANDLE g_timer_q;
95
96 static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
97
98 static const IAudioClientVtbl AudioClient_Vtbl;
99 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
100 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
101 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl;
102 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl;
103 static const IAudioClockVtbl AudioClock_Vtbl;
104 static const IAudioClock2Vtbl AudioClock2_Vtbl;
105
106 int wine_snd_pcm_recover(snd_pcm_t *pcm, int err, int silent);
107
108 static inline ACImpl *impl_from_IAudioClient(IAudioClient *iface)
109 {
110     return CONTAINING_RECORD(iface, ACImpl, IAudioClient_iface);
111 }
112
113 static inline ACImpl *impl_from_IAudioRenderClient(IAudioRenderClient *iface)
114 {
115     return CONTAINING_RECORD(iface, ACImpl, IAudioRenderClient_iface);
116 }
117
118 static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface)
119 {
120     return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface);
121 }
122
123 static inline ACImpl *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
124 {
125     return CONTAINING_RECORD(iface, ACImpl, IAudioSessionControl2_iface);
126 }
127
128 static inline ACImpl *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
129 {
130     return CONTAINING_RECORD(iface, ACImpl, ISimpleAudioVolume_iface);
131 }
132
133 static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface)
134 {
135     return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface);
136 }
137
138 static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface)
139 {
140     return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface);
141 }
142
143 HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, void ***keys,
144         UINT *num, UINT *def_index)
145 {
146     TRACE("%d %p %p %p\n", flow, ids, num, def_index);
147
148     *num = 1;
149     *def_index = 0;
150
151     *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *));
152     if(!*ids)
153         return E_OUTOFMEMORY;
154
155     (*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
156     if(!(*ids)[0]){
157         HeapFree(GetProcessHeap(), 0, *ids);
158         return E_OUTOFMEMORY;
159     }
160
161     lstrcpyW((*ids)[0], defaultW);
162
163     *keys = HeapAlloc(GetProcessHeap(), 0, sizeof(void *));
164     (*keys)[0] = NULL;
165
166     return S_OK;
167 }
168
169 HRESULT WINAPI AUDDRV_GetAudioEndpoint(void *key, IMMDevice *dev,
170         EDataFlow dataflow, IAudioClient **out)
171 {
172     ACImpl *This;
173     int err;
174     snd_pcm_stream_t stream;
175
176     TRACE("%p %p %d %p\n", key, dev, dataflow, out);
177
178     if(!g_timer_q){
179         g_timer_q = CreateTimerQueue();
180         if(!g_timer_q)
181             return E_FAIL;
182     }
183
184     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
185     if(!This)
186         return E_OUTOFMEMORY;
187
188     This->IAudioClient_iface.lpVtbl = &AudioClient_Vtbl;
189     This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
190     This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl;
191     This->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
192     This->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
193     This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl;
194     This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl;
195
196     if(dataflow == eRender)
197         stream = SND_PCM_STREAM_PLAYBACK;
198     else if(dataflow == eCapture)
199         stream = SND_PCM_STREAM_CAPTURE;
200     else{
201         HeapFree(GetProcessHeap(), 0, This);
202         return E_UNEXPECTED;
203     }
204
205     This->dataflow = dataflow;
206     if((err = snd_pcm_open(&This->pcm_handle, "default", stream,
207                     SND_PCM_NONBLOCK)) < 0){
208         HeapFree(GetProcessHeap(), 0, This);
209         WARN("Unable to open PCM \"default\": %d (%s)\n", err,
210                 snd_strerror(err));
211         return E_FAIL;
212     }
213
214     This->hw_params = HeapAlloc(GetProcessHeap(), 0,
215             snd_pcm_hw_params_sizeof());
216     if(!This->hw_params){
217         HeapFree(GetProcessHeap(), 0, This);
218         snd_pcm_close(This->pcm_handle);
219         return E_OUTOFMEMORY;
220     }
221
222     InitializeCriticalSection(&This->lock);
223
224     This->parent = dev;
225     IMMDevice_AddRef(This->parent);
226
227     *out = &This->IAudioClient_iface;
228     IAudioClient_AddRef(&This->IAudioClient_iface);
229
230     return S_OK;
231 }
232
233 static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient *iface,
234         REFIID riid, void **ppv)
235 {
236     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
237
238     if(!ppv)
239         return E_POINTER;
240     *ppv = NULL;
241     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClient))
242         *ppv = iface;
243     if(*ppv){
244         IUnknown_AddRef((IUnknown*)*ppv);
245         return S_OK;
246     }
247     WARN("Unknown interface %s\n", debugstr_guid(riid));
248     return E_NOINTERFACE;
249 }
250
251 static ULONG WINAPI AudioClient_AddRef(IAudioClient *iface)
252 {
253     ACImpl *This = impl_from_IAudioClient(iface);
254     ULONG ref;
255     ref = InterlockedIncrement(&This->ref);
256     TRACE("(%p) Refcount now %u\n", This, ref);
257     return ref;
258 }
259
260 static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
261 {
262     ACImpl *This = impl_from_IAudioClient(iface);
263     ULONG ref;
264     ref = InterlockedDecrement(&This->ref);
265     TRACE("(%p) Refcount now %u\n", This, ref);
266     if(!ref){
267         IAudioClient_Stop(iface);
268         IMMDevice_Release(This->parent);
269         DeleteCriticalSection(&This->lock);
270         snd_pcm_drop(This->pcm_handle);
271         snd_pcm_close(This->pcm_handle);
272         HeapFree(GetProcessHeap(), 0, This->local_buffer);
273         HeapFree(GetProcessHeap(), 0, This->hw_params);
274         CoTaskMemFree(This->fmt);
275         HeapFree(GetProcessHeap(), 0, This);
276     }
277     return ref;
278 }
279
280 static void dump_fmt(const WAVEFORMATEX *fmt)
281 {
282     TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
283     switch(fmt->wFormatTag){
284     case WAVE_FORMAT_PCM:
285         TRACE("WAVE_FORMAT_PCM");
286         break;
287     case WAVE_FORMAT_IEEE_FLOAT:
288         TRACE("WAVE_FORMAT_IEEE_FLOAT");
289         break;
290     case WAVE_FORMAT_EXTENSIBLE:
291         TRACE("WAVE_FORMAT_EXTENSIBLE");
292         break;
293     default:
294         TRACE("Unknown");
295         break;
296     }
297     TRACE(")\n");
298
299     TRACE("nChannels: %u\n", fmt->nChannels);
300     TRACE("nSamplesPerSec: %u\n", fmt->nSamplesPerSec);
301     TRACE("nAvgBytesPerSec: %u\n", fmt->nAvgBytesPerSec);
302     TRACE("nBlockAlign: %u\n", fmt->nBlockAlign);
303     TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample);
304     TRACE("cbSize: %u\n", fmt->cbSize);
305
306     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
307         WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt;
308         TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask);
309         TRACE("Samples: %04x\n", fmtex->Samples.wReserved);
310         TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat));
311     }
312 }
313
314 static WAVEFORMATEX *clone_format(const WAVEFORMATEX *fmt)
315 {
316     WAVEFORMATEX *ret;
317     size_t size;
318
319     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
320         size = sizeof(WAVEFORMATEXTENSIBLE);
321     else
322         size = sizeof(WAVEFORMATEX);
323
324     ret = CoTaskMemAlloc(size);
325     if(!ret)
326         return NULL;
327
328     memcpy(ret, fmt, size);
329
330     ret->cbSize = size - sizeof(WAVEFORMATEX);
331
332     return ret;
333 }
334
335 static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
336         AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
337         REFERENCE_TIME period, const WAVEFORMATEX *fmt,
338         const GUID *sessionguid)
339 {
340     ACImpl *This = impl_from_IAudioClient(iface);
341     snd_pcm_sw_params_t *sw_params = NULL;
342     snd_pcm_format_t format;
343     snd_pcm_uframes_t boundary;
344     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
345     unsigned int time_us, rate;
346     int err;
347     HRESULT hr = S_OK;
348
349     TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
350           wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
351
352     if(!fmt)
353         return E_POINTER;
354
355     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
356         return AUDCLNT_E_NOT_INITIALIZED;
357
358     if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
359                 AUDCLNT_STREAMFLAGS_LOOPBACK |
360                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
361                 AUDCLNT_STREAMFLAGS_NOPERSIST |
362                 AUDCLNT_STREAMFLAGS_RATEADJUST |
363                 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
364                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
365                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)){
366         TRACE("Unknown flags: %08x\n", flags);
367         return E_INVALIDARG;
368     }
369
370     EnterCriticalSection(&This->lock);
371
372     if(This->initted){
373         LeaveCriticalSection(&This->lock);
374         return AUDCLNT_E_ALREADY_INITIALIZED;
375     }
376
377     dump_fmt(fmt);
378
379     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
380         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
381         hr = E_FAIL;
382         goto exit;
383     }
384
385     if((err = snd_pcm_hw_params_set_access(This->pcm_handle, This->hw_params,
386                 SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
387         WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
388         hr = E_FAIL;
389         goto exit;
390     }
391
392     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
393             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
394              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
395         if(fmt->wBitsPerSample == 8)
396             format = SND_PCM_FORMAT_U8;
397         else if(fmt->wBitsPerSample == 16)
398             format = SND_PCM_FORMAT_S16_LE;
399         else if(fmt->wBitsPerSample == 24)
400             format = SND_PCM_FORMAT_S24_3LE;
401         else if(fmt->wBitsPerSample == 32)
402             format = SND_PCM_FORMAT_S32_LE;
403         else{
404             WARN("Unsupported bit depth: %u\n", fmt->wBitsPerSample);
405             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
406             goto exit;
407         }
408     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
409             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
410              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
411         if(fmt->wBitsPerSample != 32){
412             WARN("Unsupported float size: %u\n", fmt->wBitsPerSample);
413             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
414             goto exit;
415         }
416         format = SND_PCM_FORMAT_FLOAT_LE;
417     }else{
418         WARN("Unknown wave format: %04x\n", fmt->wFormatTag);
419         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
420         goto exit;
421     }
422
423     if((err = snd_pcm_hw_params_set_format(This->pcm_handle, This->hw_params,
424                 format)) < 0){
425         WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
426                 snd_strerror(err));
427         hr = E_FAIL;
428         goto exit;
429     }
430
431     rate = fmt->nSamplesPerSec;
432     if((err = snd_pcm_hw_params_set_rate_near(This->pcm_handle, This->hw_params,
433                 &rate, NULL)) < 0){
434         WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
435                 snd_strerror(err));
436         hr = E_FAIL;
437         goto exit;
438     }
439
440     if((err = snd_pcm_hw_params_set_channels(This->pcm_handle, This->hw_params,
441                 fmt->nChannels)) < 0){
442         WARN("Unable to set channels to %u: %d (%s)\n", fmt->nChannels, err,
443                 snd_strerror(err));
444         hr = E_FAIL;
445         goto exit;
446     }
447
448     time_us = MinimumPeriod / 10;
449     if((err = snd_pcm_hw_params_set_period_time_near(This->pcm_handle,
450                 This->hw_params, &time_us, NULL)) < 0){
451         WARN("Unable to set max period time to %u: %d (%s)\n", time_us,
452                 err, snd_strerror(err));
453         hr = E_FAIL;
454         goto exit;
455     }
456
457     if((err = snd_pcm_hw_params(This->pcm_handle, This->hw_params)) < 0){
458         WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
459         hr = E_FAIL;
460         goto exit;
461     }
462
463     sw_params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_sw_params_sizeof());
464     if(!sw_params){
465         hr = E_OUTOFMEMORY;
466         goto exit;
467     }
468
469     if((err = snd_pcm_sw_params_current(This->pcm_handle, sw_params)) < 0){
470         WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
471         hr = E_FAIL;
472         goto exit;
473     }
474
475     This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec);
476     This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
477             This->bufsize_frames * fmt->nBlockAlign);
478     if(!This->local_buffer){
479         hr = E_OUTOFMEMORY;
480         goto exit;
481     }
482     if (fmt->wBitsPerSample == 8)
483         memset(This->local_buffer, 128, This->bufsize_frames * fmt->nBlockAlign);
484     else
485         memset(This->local_buffer, 0, This->bufsize_frames * fmt->nBlockAlign);
486
487     if((err = snd_pcm_sw_params_get_boundary(sw_params, &boundary)) < 0){
488         WARN("Unable to get boundary: %d (%s)\n", err, snd_strerror(err));
489         hr = E_FAIL;
490         goto exit;
491     }
492
493     if((err = snd_pcm_sw_params_set_start_threshold(This->pcm_handle,
494                 sw_params, boundary)) < 0){
495         WARN("Unable to set start threshold to %lx: %d (%s)\n", boundary, err,
496                 snd_strerror(err));
497         hr = E_FAIL;
498         goto exit;
499     }
500
501     if((err = snd_pcm_sw_params_set_stop_threshold(This->pcm_handle,
502                 sw_params, boundary)) < 0){
503         WARN("Unable to set stop threshold to %lx: %d (%s)\n", boundary, err,
504                 snd_strerror(err));
505         hr = E_FAIL;
506         goto exit;
507     }
508
509     if((err = snd_pcm_sw_params_set_avail_min(This->pcm_handle,
510                 sw_params, 0)) < 0){
511         WARN("Unable to set avail min to 0: %d (%s)\n", err, snd_strerror(err));
512         hr = E_FAIL;
513         goto exit;
514     }
515
516     if((err = snd_pcm_sw_params(This->pcm_handle, sw_params)) < 0){
517         WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
518         hr = E_FAIL;
519         goto exit;
520     }
521
522     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
523         WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
524         hr = E_FAIL;
525         goto exit;
526     }
527
528     if((err = snd_pcm_hw_params_get_buffer_size(This->hw_params,
529                     &This->bufsize_alsa)) < 0){
530         WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
531         hr = E_FAIL;
532         goto exit;
533     }
534
535     if((err = snd_pcm_hw_params_get_period_size(This->hw_params,
536                     &This->period_alsa, NULL)) < 0){
537         WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
538         hr = E_FAIL;
539         goto exit;
540     }
541
542     if((err = snd_pcm_hw_params_get_period_time(This->hw_params,
543                     &This->period_us, NULL)) < 0){
544         WARN("Unable to get period time: %d (%s)\n", err, snd_strerror(err));
545         hr = E_FAIL;
546         goto exit;
547     }
548
549     This->fmt = clone_format(fmt);
550     if(!This->fmt){
551         hr = E_OUTOFMEMORY;
552         goto exit;
553     }
554
555     This->initted = TRUE;
556     This->share = mode;
557     This->flags = flags;
558
559 exit:
560     HeapFree(GetProcessHeap(), 0, sw_params);
561     if(FAILED(hr)){
562         if(This->local_buffer){
563             HeapFree(GetProcessHeap(), 0, This->local_buffer);
564             This->local_buffer = NULL;
565         }
566     }
567
568     LeaveCriticalSection(&This->lock);
569
570     return hr;
571 }
572
573 static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface,
574         UINT32 *out)
575 {
576     ACImpl *This = impl_from_IAudioClient(iface);
577
578     TRACE("(%p)->(%p)\n", This, out);
579
580     if(!out)
581         return E_POINTER;
582
583     EnterCriticalSection(&This->lock);
584
585     if(!This->initted){
586         LeaveCriticalSection(&This->lock);
587         return AUDCLNT_E_NOT_INITIALIZED;
588     }
589
590     *out = This->bufsize_frames;
591
592     LeaveCriticalSection(&This->lock);
593
594     return S_OK;
595 }
596
597 static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
598         REFERENCE_TIME *latency)
599 {
600     ACImpl *This = impl_from_IAudioClient(iface);
601
602     TRACE("(%p)->(%p)\n", This, latency);
603
604     if(!latency)
605         return E_POINTER;
606
607     EnterCriticalSection(&This->lock);
608
609     if(!This->initted){
610         LeaveCriticalSection(&This->lock);
611         return AUDCLNT_E_NOT_INITIALIZED;
612     }
613
614     LeaveCriticalSection(&This->lock);
615
616     *latency = 500000;
617
618     return S_OK;
619 }
620
621 static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
622         UINT32 *out)
623 {
624     ACImpl *This = impl_from_IAudioClient(iface);
625
626     TRACE("(%p)->(%p)\n", This, out);
627
628     if(!out)
629         return E_POINTER;
630
631     EnterCriticalSection(&This->lock);
632
633     if(!This->initted){
634         LeaveCriticalSection(&This->lock);
635         return AUDCLNT_E_NOT_INITIALIZED;
636     }
637
638     if(This->dataflow == eRender){
639         snd_pcm_sframes_t avail_frames;
640
641         avail_frames = snd_pcm_avail_update(This->pcm_handle);
642
643         if(This->bufsize_alsa < avail_frames){
644             WARN("Xrun detected\n");
645             *out = This->held_frames;
646         }else
647             *out = This->bufsize_alsa - avail_frames + This->held_frames;
648     }else if(This->dataflow == eCapture){
649         *out = This->held_frames;
650     }else{
651         LeaveCriticalSection(&This->lock);
652         return E_UNEXPECTED;
653     }
654
655     LeaveCriticalSection(&This->lock);
656
657     return S_OK;
658 }
659
660 static DWORD get_channel_mask(unsigned int channels)
661 {
662     switch(channels){
663     case 0:
664         return 0;
665     case 1:
666         return SPEAKER_FRONT_CENTER;
667     case 2:
668         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
669     case 3:
670         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
671             SPEAKER_LOW_FREQUENCY;
672     case 4:
673         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
674             SPEAKER_BACK_RIGHT;
675     case 5:
676         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
677             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
678     case 6:
679         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
680             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER;
681     case 7:
682         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
683             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER |
684             SPEAKER_BACK_CENTER;
685     }
686     FIXME("Unknown speaker configuration: %u\n", channels);
687     return 0;
688 }
689
690 static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
691         AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *fmt,
692         WAVEFORMATEX **out)
693 {
694     ACImpl *This = impl_from_IAudioClient(iface);
695     snd_pcm_format_mask_t *formats = NULL;
696     HRESULT hr = S_OK;
697     WAVEFORMATEX *closest = NULL;
698     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
699     unsigned int max = 0, min = 0;
700     int err;
701
702     TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out);
703
704     if(!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out))
705         return E_POINTER;
706
707     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
708         return E_INVALIDARG;
709
710     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
711             fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
712         return E_INVALIDARG;
713
714     dump_fmt(fmt);
715
716     EnterCriticalSection(&This->lock);
717
718     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
719         hr = E_FAIL;
720         goto exit;
721     }
722
723     formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
724             snd_pcm_format_mask_sizeof());
725     if(!formats){
726         hr = E_OUTOFMEMORY;
727         goto exit;
728     }
729
730     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
731
732     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
733             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
734              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
735         switch(fmt->wBitsPerSample){
736         case 8:
737             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
738                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
739                 goto exit;
740             }
741             break;
742         case 16:
743             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
744                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
745                 goto exit;
746             }
747             break;
748         case 24:
749             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
750                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
751                 goto exit;
752             }
753             break;
754         case 32:
755             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
756                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
757                 goto exit;
758             }
759             break;
760         default:
761             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
762             goto exit;
763         }
764     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
765             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
766              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
767         switch(fmt->wBitsPerSample){
768         case 32:
769             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
770                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
771                 goto exit;
772             }
773             break;
774         case 64:
775             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT64_LE)){
776                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
777                 goto exit;
778             }
779             break;
780         default:
781             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
782             goto exit;
783         }
784     }else{
785         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
786         goto exit;
787     }
788
789     closest = clone_format(fmt);
790     if(!closest){
791         hr = E_OUTOFMEMORY;
792         goto exit;
793     }
794
795     if((err = snd_pcm_hw_params_get_rate_min(This->hw_params, &min, NULL)) < 0){
796         hr = E_FAIL;
797         WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err));
798         goto exit;
799     }
800
801     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max, NULL)) < 0){
802         hr = E_FAIL;
803         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
804         goto exit;
805     }
806
807     if(fmt->nSamplesPerSec < min || fmt->nSamplesPerSec > max ||
808             (fmt->nSamplesPerSec != 48000 &&
809             fmt->nSamplesPerSec != 44100 &&
810             fmt->nSamplesPerSec != 22050 &&
811             fmt->nSamplesPerSec != 11025 &&
812             fmt->nSamplesPerSec != 8000)){
813         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
814         goto exit;
815     }
816
817     if((err = snd_pcm_hw_params_get_channels_min(This->hw_params, &min)) < 0){
818         hr = E_FAIL;
819         WARN("Unable to get min channels: %d (%s)\n", err, snd_strerror(err));
820         goto exit;
821     }
822
823     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params, &max)) < 0){
824         hr = E_FAIL;
825         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
826         goto exit;
827     }
828     if(max > 7)
829         max = 2;
830     if(fmt->nChannels > max){
831         hr = S_FALSE;
832         closest->nChannels = max;
833     }else if(fmt->nChannels < min){
834         hr = S_FALSE;
835         closest->nChannels = min;
836     }
837
838     if(closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
839         DWORD mask = get_channel_mask(closest->nChannels);
840
841         ((WAVEFORMATEXTENSIBLE*)closest)->dwChannelMask = mask;
842
843         if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
844                 fmtex->dwChannelMask != mask)
845             hr = S_FALSE;
846     }
847
848 exit:
849     LeaveCriticalSection(&This->lock);
850     HeapFree(GetProcessHeap(), 0, formats);
851
852     if(hr == S_OK || !out){
853         CoTaskMemFree(closest);
854         if(out)
855             *out = NULL;
856     }else if(closest){
857         closest->nBlockAlign =
858             closest->nChannels * closest->wBitsPerSample / 8;
859         closest->nAvgBytesPerSec =
860             closest->nBlockAlign * closest->nSamplesPerSec;
861         *out = closest;
862     }
863
864     TRACE("returning: %08x\n", hr);
865     return hr;
866 }
867
868 static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface,
869         WAVEFORMATEX **pwfx)
870 {
871     ACImpl *This = impl_from_IAudioClient(iface);
872     WAVEFORMATEXTENSIBLE *fmt;
873     snd_pcm_format_mask_t *formats;
874     unsigned int max_rate, max_channels;
875     int err;
876     HRESULT hr = S_OK;
877
878     TRACE("(%p)->(%p)\n", This, pwfx);
879
880     if(!pwfx)
881         return E_POINTER;
882
883     *pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
884     if(!*pwfx)
885         return E_OUTOFMEMORY;
886
887     fmt = (WAVEFORMATEXTENSIBLE*)*pwfx;
888
889     formats = HeapAlloc(GetProcessHeap(), 0, snd_pcm_format_mask_sizeof());
890     if(!formats){
891         HeapFree(GetProcessHeap(), 0, *pwfx);
892         return E_OUTOFMEMORY;
893     }
894
895     EnterCriticalSection(&This->lock);
896
897     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
898         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
899         hr = E_FAIL;
900         goto exit;
901     }
902
903     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
904
905     fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
906     if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
907         fmt->Format.wBitsPerSample = 32;
908         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
909     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
910         fmt->Format.wBitsPerSample = 16;
911         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
912     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
913         fmt->Format.wBitsPerSample = 8;
914         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
915     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
916         fmt->Format.wBitsPerSample = 32;
917         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
918     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
919         fmt->Format.wBitsPerSample = 24;
920         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
921     }else{
922         ERR("Didn't recognize any available ALSA formats\n");
923         hr = E_FAIL;
924         goto exit;
925     }
926
927     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params,
928                     &max_channels)) < 0){
929         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
930         hr = E_FAIL;
931         goto exit;
932     }
933
934     if(max_channels > 2){
935         FIXME("Don't know what to do with %u channels, pretending there's "
936                 "only 2 channels\n", max_channels);
937         fmt->Format.nChannels = 2;
938     }else
939         fmt->Format.nChannels = max_channels;
940
941     fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
942
943     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max_rate,
944                     NULL)) < 0){
945         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
946         hr = E_FAIL;
947         goto exit;
948     }
949
950     if(max_rate >= 48000)
951         fmt->Format.nSamplesPerSec = 48000;
952     else if(max_rate >= 44100)
953         fmt->Format.nSamplesPerSec = 44100;
954     else if(max_rate >= 22050)
955         fmt->Format.nSamplesPerSec = 22050;
956     else if(max_rate >= 11025)
957         fmt->Format.nSamplesPerSec = 11025;
958     else if(max_rate >= 8000)
959         fmt->Format.nSamplesPerSec = 8000;
960     else{
961         ERR("Unknown max rate: %u\n", max_rate);
962         hr = E_FAIL;
963         goto exit;
964     }
965
966     fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
967             fmt->Format.nChannels) / 8;
968     fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
969         fmt->Format.nBlockAlign;
970
971     fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
972     fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
973
974     dump_fmt((WAVEFORMATEX*)fmt);
975
976 exit:
977     LeaveCriticalSection(&This->lock);
978     if(FAILED(hr))
979         HeapFree(GetProcessHeap(), 0, *pwfx);
980     HeapFree(GetProcessHeap(), 0, formats);
981
982     return hr;
983 }
984
985 static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
986         REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
987 {
988     ACImpl *This = impl_from_IAudioClient(iface);
989
990     TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
991
992     if(!defperiod && !minperiod)
993         return E_POINTER;
994
995     if(defperiod)
996         *defperiod = DefaultPeriod;
997     if(minperiod)
998         *minperiod = MinimumPeriod;
999
1000     return S_OK;
1001 }
1002
1003 static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
1004         snd_pcm_uframes_t frames)
1005 {
1006     snd_pcm_sframes_t written;
1007
1008     written = snd_pcm_writei(handle, buf, frames);
1009     if(written < 0){
1010         int ret;
1011
1012         if(written == -EAGAIN)
1013             /* buffer full */
1014             return 0;
1015
1016         WARN("writei failed, recovering: %ld (%s)\n", written,
1017                 snd_strerror(written));
1018
1019         ret = wine_snd_pcm_recover(handle, written, 0);
1020         if(ret < 0){
1021             WARN("Could not recover: %d (%s)\n", ret, snd_strerror(ret));
1022             return ret;
1023         }
1024
1025         written = snd_pcm_writei(handle, buf, frames);
1026     }
1027
1028     return written;
1029 }
1030
1031 static void alsa_write_data(ACImpl *This)
1032 {
1033     snd_pcm_sframes_t written;
1034     snd_pcm_uframes_t to_write;
1035     BYTE *buf =
1036         This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
1037
1038     if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
1039         to_write = This->bufsize_frames - This->lcl_offs_frames;
1040     else
1041         to_write = This->held_frames;
1042
1043     written = alsa_write_best_effort(This->pcm_handle, buf, to_write);
1044     if(written < 0){
1045         WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1046         return;
1047     }
1048
1049     This->lcl_offs_frames += written;
1050     This->lcl_offs_frames %= This->bufsize_frames;
1051     This->held_frames -= written;
1052
1053     if(written < to_write){
1054         /* ALSA buffer probably full */
1055         return;
1056     }
1057
1058     if(This->held_frames){
1059         /* wrapped and have some data back at the start to write */
1060         written = alsa_write_best_effort(This->pcm_handle, This->local_buffer,
1061                 This->held_frames);
1062         if(written < 0){
1063             WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1064             return;
1065         }
1066
1067         This->lcl_offs_frames += written;
1068         This->lcl_offs_frames %= This->bufsize_frames;
1069         This->held_frames -= written;
1070     }
1071 }
1072
1073 static void alsa_read_data(ACImpl *This)
1074 {
1075     snd_pcm_sframes_t pos, readable, nread;
1076
1077     pos = (This->held_frames + This->lcl_offs_frames) % This->bufsize_frames;
1078     readable = This->bufsize_frames - pos;
1079
1080     nread = snd_pcm_readi(This->pcm_handle,
1081             This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1082     if(nread < 0){
1083         int ret;
1084
1085         WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
1086
1087         ret = wine_snd_pcm_recover(This->pcm_handle, nread, 0);
1088         if(ret < 0){
1089             WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
1090             return;
1091         }
1092
1093         nread = snd_pcm_readi(This->pcm_handle,
1094                 This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1095         if(nread < 0){
1096             WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
1097             return;
1098         }
1099     }
1100
1101     This->held_frames += nread;
1102
1103     if(This->held_frames > This->bufsize_frames){
1104         WARN("Overflow of unread data\n");
1105         This->lcl_offs_frames += This->held_frames;
1106         This->lcl_offs_frames %= This->bufsize_frames;
1107         This->held_frames = This->bufsize_frames;
1108     }
1109 }
1110
1111 static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
1112 {
1113     ACImpl *This = user;
1114
1115     EnterCriticalSection(&This->lock);
1116
1117     if(This->dataflow == eRender && This->held_frames)
1118         alsa_write_data(This);
1119     else if(This->dataflow == eCapture)
1120         alsa_read_data(This);
1121
1122     if(This->event)
1123         SetEvent(This->event);
1124
1125     LeaveCriticalSection(&This->lock);
1126 }
1127
1128 static HRESULT alsa_consider_start(ACImpl *This)
1129 {
1130     snd_pcm_sframes_t avail;
1131     int err;
1132
1133     avail = snd_pcm_avail_update(This->pcm_handle);
1134     if(avail < 0){
1135         WARN("Unable to get avail_update: %ld (%s)\n", avail,
1136                 snd_strerror(avail));
1137         return E_FAIL;
1138     }
1139
1140     if(This->period_alsa < This->bufsize_alsa - avail){
1141         if((err = snd_pcm_start(This->pcm_handle)) < 0){
1142             WARN("Start failed: %d (%s), state: %d\n", err, snd_strerror(err),
1143                     snd_pcm_state(This->pcm_handle));
1144             return E_FAIL;
1145         }
1146
1147         return S_OK;
1148     }
1149
1150     return S_FALSE;
1151 }
1152
1153 static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
1154 {
1155     ACImpl *This = impl_from_IAudioClient(iface);
1156     DWORD period_ms;
1157     HRESULT hr;
1158
1159     TRACE("(%p)\n", This);
1160
1161     EnterCriticalSection(&This->lock);
1162
1163     if(!This->initted){
1164         LeaveCriticalSection(&This->lock);
1165         return AUDCLNT_E_NOT_INITIALIZED;
1166     }
1167
1168     if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
1169         LeaveCriticalSection(&This->lock);
1170         return AUDCLNT_E_EVENTHANDLE_NOT_SET;
1171     }
1172
1173     if(This->started){
1174         LeaveCriticalSection(&This->lock);
1175         return AUDCLNT_E_NOT_STOPPED;
1176     }
1177
1178     hr = alsa_consider_start(This);
1179     if(FAILED(hr)){
1180         LeaveCriticalSection(&This->lock);
1181         return hr;
1182     }
1183
1184     period_ms = This->period_us / 1000;
1185     if(!period_ms)
1186         period_ms = 10;
1187
1188     if(This->dataflow == eCapture){
1189         /* dump any data that might be leftover in the ALSA capture buffer */
1190         snd_pcm_readi(This->pcm_handle, This->local_buffer,
1191                 This->bufsize_frames);
1192     }
1193
1194     if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
1195             This, 0, period_ms, WT_EXECUTEINTIMERTHREAD)){
1196         LeaveCriticalSection(&This->lock);
1197         WARN("Unable to create timer: %u\n", GetLastError());
1198         return E_FAIL;
1199     }
1200
1201     This->started = TRUE;
1202
1203     LeaveCriticalSection(&This->lock);
1204
1205     return S_OK;
1206 }
1207
1208 static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
1209 {
1210     ACImpl *This = impl_from_IAudioClient(iface);
1211     int err;
1212
1213     TRACE("(%p)\n", This);
1214
1215     EnterCriticalSection(&This->lock);
1216
1217     if(!This->initted){
1218         LeaveCriticalSection(&This->lock);
1219         return AUDCLNT_E_NOT_INITIALIZED;
1220     }
1221
1222     if(!This->started){
1223         LeaveCriticalSection(&This->lock);
1224         return S_FALSE;
1225     }
1226
1227     DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE);
1228
1229     if((err = snd_pcm_drop(This->pcm_handle)) < 0){
1230         LeaveCriticalSection(&This->lock);
1231         WARN("Drop failed: %d (%s)\n", err, snd_strerror(err));
1232         return E_FAIL;
1233     }
1234
1235     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
1236         LeaveCriticalSection(&This->lock);
1237         WARN("Prepare failed: %d (%s)\n", err, snd_strerror(err));
1238         return E_FAIL;
1239     }
1240
1241     This->started = FALSE;
1242
1243     LeaveCriticalSection(&This->lock);
1244
1245     return S_OK;
1246 }
1247
1248 static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
1249 {
1250     ACImpl *This = impl_from_IAudioClient(iface);
1251
1252     TRACE("(%p)\n", This);
1253
1254     EnterCriticalSection(&This->lock);
1255
1256     if(!This->initted){
1257         LeaveCriticalSection(&This->lock);
1258         return AUDCLNT_E_NOT_INITIALIZED;
1259     }
1260
1261     if(This->started){
1262         LeaveCriticalSection(&This->lock);
1263         return AUDCLNT_E_NOT_STOPPED;
1264     }
1265
1266     This->held_frames = 0;
1267     This->written_frames = 0;
1268     This->lcl_offs_frames = 0;
1269
1270     LeaveCriticalSection(&This->lock);
1271
1272     return S_OK;
1273 }
1274
1275 static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface,
1276         HANDLE event)
1277 {
1278     ACImpl *This = impl_from_IAudioClient(iface);
1279
1280     TRACE("(%p)->(%p)\n", This, event);
1281
1282     if(!event)
1283         return E_INVALIDARG;
1284
1285     EnterCriticalSection(&This->lock);
1286
1287     if(!This->initted){
1288         LeaveCriticalSection(&This->lock);
1289         return AUDCLNT_E_NOT_INITIALIZED;
1290     }
1291
1292     if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
1293         LeaveCriticalSection(&This->lock);
1294         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
1295     }
1296
1297     This->event = event;
1298
1299     LeaveCriticalSection(&This->lock);
1300
1301     return S_OK;
1302 }
1303
1304 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1305         void **ppv)
1306 {
1307     ACImpl *This = impl_from_IAudioClient(iface);
1308
1309     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1310
1311     if(!ppv)
1312         return E_POINTER;
1313     *ppv = NULL;
1314
1315     EnterCriticalSection(&This->lock);
1316
1317     if(!This->initted){
1318         LeaveCriticalSection(&This->lock);
1319         return AUDCLNT_E_NOT_INITIALIZED;
1320     }
1321
1322     LeaveCriticalSection(&This->lock);
1323
1324     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1325         if(This->dataflow != eRender)
1326             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1327         *ppv = &This->IAudioRenderClient_iface;
1328     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1329         if(This->dataflow != eCapture)
1330             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1331         *ppv = &This->IAudioCaptureClient_iface;
1332     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1333         *ppv = &This->IAudioSessionControl2_iface;
1334     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1335         *ppv = &This->ISimpleAudioVolume_iface;
1336     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1337         *ppv = &This->IAudioClock_iface;
1338     }
1339
1340     if(*ppv){
1341         IUnknown_AddRef((IUnknown*)*ppv);
1342         return S_OK;
1343     }
1344
1345     FIXME("stub %s\n", debugstr_guid(riid));
1346     return E_NOINTERFACE;
1347 }
1348
1349 static const IAudioClientVtbl AudioClient_Vtbl =
1350 {
1351     AudioClient_QueryInterface,
1352     AudioClient_AddRef,
1353     AudioClient_Release,
1354     AudioClient_Initialize,
1355     AudioClient_GetBufferSize,
1356     AudioClient_GetStreamLatency,
1357     AudioClient_GetCurrentPadding,
1358     AudioClient_IsFormatSupported,
1359     AudioClient_GetMixFormat,
1360     AudioClient_GetDevicePeriod,
1361     AudioClient_Start,
1362     AudioClient_Stop,
1363     AudioClient_Reset,
1364     AudioClient_SetEventHandle,
1365     AudioClient_GetService
1366 };
1367
1368 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1369         IAudioRenderClient *iface, REFIID riid, void **ppv)
1370 {
1371     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1372
1373     if(!ppv)
1374         return E_POINTER;
1375     *ppv = NULL;
1376
1377     if(IsEqualIID(riid, &IID_IUnknown) ||
1378             IsEqualIID(riid, &IID_IAudioRenderClient))
1379         *ppv = iface;
1380     if(*ppv){
1381         IUnknown_AddRef((IUnknown*)*ppv);
1382         return S_OK;
1383     }
1384
1385     WARN("Unknown interface %s\n", debugstr_guid(riid));
1386     return E_NOINTERFACE;
1387 }
1388
1389 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1390 {
1391     ACImpl *This = impl_from_IAudioRenderClient(iface);
1392     return AudioClient_AddRef(&This->IAudioClient_iface);
1393 }
1394
1395 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1396 {
1397     ACImpl *This = impl_from_IAudioRenderClient(iface);
1398     return AudioClient_Release(&This->IAudioClient_iface);
1399 }
1400
1401 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1402         UINT32 frames, BYTE **data)
1403 {
1404     ACImpl *This = impl_from_IAudioRenderClient(iface);
1405     UINT32 write_pos;
1406     UINT32 pad;
1407     HRESULT hr;
1408
1409     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1410
1411     if(!data)
1412         return E_POINTER;
1413
1414     EnterCriticalSection(&This->lock);
1415
1416     if(This->buf_state != NOT_LOCKED){
1417         LeaveCriticalSection(&This->lock);
1418         return AUDCLNT_E_OUT_OF_ORDER;
1419     }
1420
1421     if(!frames){
1422         This->buf_state = LOCKED_NORMAL;
1423         LeaveCriticalSection(&This->lock);
1424         return S_OK;
1425     }
1426
1427     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
1428     if(FAILED(hr)){
1429         LeaveCriticalSection(&This->lock);
1430         return hr;
1431     }
1432
1433     if(pad + frames > This->bufsize_frames){
1434         LeaveCriticalSection(&This->lock);
1435         return AUDCLNT_E_BUFFER_TOO_LARGE;
1436     }
1437
1438     write_pos =
1439         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1440     if(write_pos + frames > This->bufsize_frames){
1441         if(This->tmp_buffer_frames < frames){
1442             if(This->tmp_buffer)
1443                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
1444                         This->tmp_buffer, frames * This->fmt->nBlockAlign);
1445             else
1446                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
1447                         frames * This->fmt->nBlockAlign);
1448             if(!This->tmp_buffer){
1449                 LeaveCriticalSection(&This->lock);
1450                 return E_OUTOFMEMORY;
1451             }
1452             This->tmp_buffer_frames = frames;
1453         }
1454         *data = This->tmp_buffer;
1455         This->buf_state = LOCKED_WRAPPED;
1456     }else{
1457         *data = This->local_buffer +
1458             This->lcl_offs_frames * This->fmt->nBlockAlign;
1459         This->buf_state = LOCKED_NORMAL;
1460     }
1461
1462     LeaveCriticalSection(&This->lock);
1463
1464     return S_OK;
1465 }
1466
1467 static void alsa_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_bytes)
1468 {
1469     snd_pcm_uframes_t write_offs_frames =
1470         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1471     UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
1472     snd_pcm_uframes_t chunk_frames = This->bufsize_frames - write_offs_frames;
1473     UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
1474
1475     if(written_bytes < chunk_bytes){
1476         memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
1477     }else{
1478         memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
1479         memcpy(This->local_buffer, buffer + chunk_bytes,
1480                 written_bytes - chunk_bytes);
1481     }
1482 }
1483
1484 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
1485         IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
1486 {
1487     ACImpl *This = impl_from_IAudioRenderClient(iface);
1488     UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
1489     BYTE *buffer;
1490     HRESULT hr;
1491
1492     TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
1493
1494     EnterCriticalSection(&This->lock);
1495
1496     if(This->buf_state == NOT_LOCKED || !written_frames){
1497         This->buf_state = NOT_LOCKED;
1498         LeaveCriticalSection(&This->lock);
1499         return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1500     }
1501
1502     if(This->buf_state == LOCKED_NORMAL)
1503         buffer = This->local_buffer +
1504             This->lcl_offs_frames * This->fmt->nBlockAlign;
1505     else
1506         buffer = This->tmp_buffer;
1507
1508     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
1509         WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
1510         if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
1511                 (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1512                  IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
1513                 This->fmt->wBitsPerSample == 8)
1514             memset(buffer, 128, written_frames * This->fmt->nBlockAlign);
1515         else
1516             memset(buffer, 0, written_frames * This->fmt->nBlockAlign);
1517     }
1518
1519     if(This->held_frames){
1520         if(This->buf_state == LOCKED_WRAPPED)
1521             alsa_wrap_buffer(This, buffer, written_bytes);
1522
1523         This->held_frames += written_frames;
1524     }else{
1525         snd_pcm_sframes_t written;
1526
1527         written = alsa_write_best_effort(This->pcm_handle, buffer,
1528                 written_frames);
1529         if(written < 0){
1530             LeaveCriticalSection(&This->lock);
1531             WARN("write failed: %ld (%s)\n", written, snd_strerror(written));
1532             return E_FAIL;
1533         }
1534
1535         if(written < written_frames){
1536             if(This->buf_state == LOCKED_WRAPPED)
1537                 alsa_wrap_buffer(This,
1538                         This->tmp_buffer + written * This->fmt->nBlockAlign,
1539                         written_frames - written);
1540
1541             This->held_frames = written_frames - written;
1542         }
1543     }
1544
1545     if(This->started &&
1546             snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_PREPARED){
1547         hr = alsa_consider_start(This);
1548         if(FAILED(hr)){
1549             LeaveCriticalSection(&This->lock);
1550             return hr;
1551         }
1552     }
1553
1554     This->written_frames += written_frames;
1555     This->buf_state = NOT_LOCKED;
1556
1557     LeaveCriticalSection(&This->lock);
1558
1559     return S_OK;
1560 }
1561
1562 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
1563     AudioRenderClient_QueryInterface,
1564     AudioRenderClient_AddRef,
1565     AudioRenderClient_Release,
1566     AudioRenderClient_GetBuffer,
1567     AudioRenderClient_ReleaseBuffer
1568 };
1569
1570 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
1571         IAudioCaptureClient *iface, REFIID riid, void **ppv)
1572 {
1573     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1574
1575     if(!ppv)
1576         return E_POINTER;
1577     *ppv = NULL;
1578
1579     if(IsEqualIID(riid, &IID_IUnknown) ||
1580             IsEqualIID(riid, &IID_IAudioCaptureClient))
1581         *ppv = iface;
1582     if(*ppv){
1583         IUnknown_AddRef((IUnknown*)*ppv);
1584         return S_OK;
1585     }
1586
1587     WARN("Unknown interface %s\n", debugstr_guid(riid));
1588     return E_NOINTERFACE;
1589 }
1590
1591 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
1592 {
1593     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1594     return IAudioClient_AddRef(&This->IAudioClient_iface);
1595 }
1596
1597 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
1598 {
1599     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1600     return IAudioClient_Release(&This->IAudioClient_iface);
1601 }
1602
1603 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
1604         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
1605         UINT64 *qpcpos)
1606 {
1607     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1608     HRESULT hr;
1609
1610     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
1611             devpos, qpcpos);
1612
1613     if(!data || !frames || !flags)
1614         return E_POINTER;
1615
1616     EnterCriticalSection(&This->lock);
1617
1618     if(This->buf_state != NOT_LOCKED){
1619         LeaveCriticalSection(&This->lock);
1620         return AUDCLNT_E_OUT_OF_ORDER;
1621     }
1622
1623     hr = IAudioCaptureClient_GetNextPacketSize(iface, frames);
1624     if(FAILED(hr)){
1625         LeaveCriticalSection(&This->lock);
1626         return hr;
1627     }
1628
1629     *flags = 0;
1630
1631     if(This->lcl_offs_frames + *frames > This->bufsize_frames){
1632         UINT32 chunk_bytes, offs_bytes, frames_bytes;
1633         if(This->tmp_buffer_frames < *frames){
1634             if(This->tmp_buffer)
1635                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
1636                         This->tmp_buffer, *frames * This->fmt->nBlockAlign);
1637             else
1638                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
1639                         *frames * This->fmt->nBlockAlign);
1640             if(!This->tmp_buffer){
1641                 LeaveCriticalSection(&This->lock);
1642                 return E_OUTOFMEMORY;
1643             }
1644             This->tmp_buffer_frames = *frames;
1645         }
1646
1647         *data = This->tmp_buffer;
1648         chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
1649             This->fmt->nBlockAlign;
1650         offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
1651         frames_bytes = *frames * This->fmt->nBlockAlign;
1652         memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
1653         memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
1654                 frames_bytes - chunk_bytes);
1655     }else
1656         *data = This->local_buffer +
1657             This->lcl_offs_frames * This->fmt->nBlockAlign;
1658
1659     This->buf_state = LOCKED_NORMAL;
1660
1661     if(devpos || qpcpos)
1662         IAudioClock_GetPosition(&This->IAudioClock_iface, devpos, qpcpos);
1663
1664     LeaveCriticalSection(&This->lock);
1665
1666     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
1667 }
1668
1669 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
1670         IAudioCaptureClient *iface, UINT32 done)
1671 {
1672     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1673
1674     TRACE("(%p)->(%u)\n", This, done);
1675
1676     EnterCriticalSection(&This->lock);
1677
1678     if(This->buf_state == NOT_LOCKED){
1679         LeaveCriticalSection(&This->lock);
1680         return AUDCLNT_E_OUT_OF_ORDER;
1681     }
1682
1683     This->held_frames -= done;
1684     This->lcl_offs_frames += done;
1685     This->lcl_offs_frames %= This->bufsize_frames;
1686
1687     This->buf_state = NOT_LOCKED;
1688
1689     LeaveCriticalSection(&This->lock);
1690
1691     return S_OK;
1692 }
1693
1694 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
1695         IAudioCaptureClient *iface, UINT32 *frames)
1696 {
1697     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1698
1699     TRACE("(%p)->(%p)\n", This, frames);
1700
1701     return AudioClient_GetCurrentPadding(&This->IAudioClient_iface, frames);
1702 }
1703
1704 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
1705 {
1706     AudioCaptureClient_QueryInterface,
1707     AudioCaptureClient_AddRef,
1708     AudioCaptureClient_Release,
1709     AudioCaptureClient_GetBuffer,
1710     AudioCaptureClient_ReleaseBuffer,
1711     AudioCaptureClient_GetNextPacketSize
1712 };
1713
1714 static HRESULT WINAPI AudioSessionControl_QueryInterface(
1715         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
1716 {
1717     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1718
1719     if(!ppv)
1720         return E_POINTER;
1721     *ppv = NULL;
1722
1723     if(IsEqualIID(riid, &IID_IUnknown) ||
1724             IsEqualIID(riid, &IID_IAudioSessionControl) ||
1725             IsEqualIID(riid, &IID_IAudioSessionControl2))
1726         *ppv = iface;
1727     if(*ppv){
1728         IUnknown_AddRef((IUnknown*)*ppv);
1729         return S_OK;
1730     }
1731
1732     WARN("Unknown interface %s\n", debugstr_guid(riid));
1733     return E_NOINTERFACE;
1734 }
1735
1736 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
1737 {
1738     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1739     return IAudioClient_AddRef(&This->IAudioClient_iface);
1740 }
1741
1742 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
1743 {
1744     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1745     return IAudioClient_Release(&This->IAudioClient_iface);
1746 }
1747
1748 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
1749         AudioSessionState *state)
1750 {
1751     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1752
1753     FIXME("(%p)->(%p) - stub\n", This, state);
1754
1755     if(!state)
1756         return E_POINTER;
1757
1758     return E_NOTIMPL;
1759 }
1760
1761 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
1762         IAudioSessionControl2 *iface, WCHAR **name)
1763 {
1764     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1765
1766     FIXME("(%p)->(%p) - stub\n", This, name);
1767
1768     return E_NOTIMPL;
1769 }
1770
1771 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
1772         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
1773 {
1774     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1775
1776     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
1777
1778     return E_NOTIMPL;
1779 }
1780
1781 static HRESULT WINAPI AudioSessionControl_GetIconPath(
1782         IAudioSessionControl2 *iface, WCHAR **path)
1783 {
1784     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1785
1786     FIXME("(%p)->(%p) - stub\n", This, path);
1787
1788     return E_NOTIMPL;
1789 }
1790
1791 static HRESULT WINAPI AudioSessionControl_SetIconPath(
1792         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
1793 {
1794     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1795
1796     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
1797
1798     return E_NOTIMPL;
1799 }
1800
1801 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
1802         IAudioSessionControl2 *iface, GUID *group)
1803 {
1804     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1805
1806     FIXME("(%p)->(%p) - stub\n", This, group);
1807
1808     return E_NOTIMPL;
1809 }
1810
1811 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
1812         IAudioSessionControl2 *iface, GUID *group, const GUID *session)
1813 {
1814     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1815
1816     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
1817             debugstr_guid(session));
1818
1819     return E_NOTIMPL;
1820 }
1821
1822 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
1823         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1824 {
1825     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1826
1827     FIXME("(%p)->(%p) - stub\n", This, events);
1828
1829     return S_OK;
1830 }
1831
1832 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
1833         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1834 {
1835     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1836
1837     FIXME("(%p)->(%p) - stub\n", This, events);
1838
1839     return S_OK;
1840 }
1841
1842 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
1843         IAudioSessionControl2 *iface, WCHAR **id)
1844 {
1845     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1846
1847     FIXME("(%p)->(%p) - stub\n", This, id);
1848
1849     return E_NOTIMPL;
1850 }
1851
1852 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
1853         IAudioSessionControl2 *iface, WCHAR **id)
1854 {
1855     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1856
1857     FIXME("(%p)->(%p) - stub\n", This, id);
1858
1859     return E_NOTIMPL;
1860 }
1861
1862 static HRESULT WINAPI AudioSessionControl_GetProcessId(
1863         IAudioSessionControl2 *iface, DWORD *pid)
1864 {
1865     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1866
1867     TRACE("(%p)->(%p)\n", This, pid);
1868
1869     if(!pid)
1870         return E_POINTER;
1871
1872     *pid = GetCurrentProcessId();
1873
1874     return S_OK;
1875 }
1876
1877 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
1878         IAudioSessionControl2 *iface)
1879 {
1880     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1881
1882     TRACE("(%p)\n", This);
1883
1884     return S_FALSE;
1885 }
1886
1887 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
1888         IAudioSessionControl2 *iface, BOOL optout)
1889 {
1890     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1891
1892     TRACE("(%p)->(%d)\n", This, optout);
1893
1894     return S_OK;
1895 }
1896
1897 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
1898 {
1899     AudioSessionControl_QueryInterface,
1900     AudioSessionControl_AddRef,
1901     AudioSessionControl_Release,
1902     AudioSessionControl_GetState,
1903     AudioSessionControl_GetDisplayName,
1904     AudioSessionControl_SetDisplayName,
1905     AudioSessionControl_GetIconPath,
1906     AudioSessionControl_SetIconPath,
1907     AudioSessionControl_GetGroupingParam,
1908     AudioSessionControl_SetGroupingParam,
1909     AudioSessionControl_RegisterAudioSessionNotification,
1910     AudioSessionControl_UnregisterAudioSessionNotification,
1911     AudioSessionControl_GetSessionIdentifier,
1912     AudioSessionControl_GetSessionInstanceIdentifier,
1913     AudioSessionControl_GetProcessId,
1914     AudioSessionControl_IsSystemSoundsSession,
1915     AudioSessionControl_SetDuckingPreference
1916 };
1917
1918 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
1919         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
1920 {
1921     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1922
1923     if(!ppv)
1924         return E_POINTER;
1925     *ppv = NULL;
1926
1927     if(IsEqualIID(riid, &IID_IUnknown) ||
1928             IsEqualIID(riid, &IID_ISimpleAudioVolume))
1929         *ppv = iface;
1930     if(*ppv){
1931         IUnknown_AddRef((IUnknown*)*ppv);
1932         return S_OK;
1933     }
1934
1935     WARN("Unknown interface %s\n", debugstr_guid(riid));
1936     return E_NOINTERFACE;
1937 }
1938
1939 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
1940 {
1941     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1942     return IAudioClient_AddRef(&This->IAudioClient_iface);
1943 }
1944
1945 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
1946 {
1947     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1948     return IAudioClient_Release(&This->IAudioClient_iface);
1949 }
1950
1951 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
1952         ISimpleAudioVolume *iface, float level, const GUID *context)
1953 {
1954     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1955
1956     FIXME("(%p)->(%f, %p) - stub\n", This, level, context);
1957
1958     return E_NOTIMPL;
1959 }
1960
1961 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
1962         ISimpleAudioVolume *iface, float *level)
1963 {
1964     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1965
1966     FIXME("(%p)->(%p) - stub\n", This, level);
1967
1968     return E_NOTIMPL;
1969 }
1970
1971 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
1972         BOOL mute, const GUID *context)
1973 {
1974     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1975
1976     FIXME("(%p)->(%u, %p) - stub\n", This, mute, context);
1977
1978     return E_NOTIMPL;
1979 }
1980
1981 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
1982         BOOL *mute)
1983 {
1984     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1985
1986     FIXME("(%p)->(%p) - stub\n", This, mute);
1987
1988     return E_NOTIMPL;
1989 }
1990
1991 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
1992 {
1993     SimpleAudioVolume_QueryInterface,
1994     SimpleAudioVolume_AddRef,
1995     SimpleAudioVolume_Release,
1996     SimpleAudioVolume_SetMasterVolume,
1997     SimpleAudioVolume_GetMasterVolume,
1998     SimpleAudioVolume_SetMute,
1999     SimpleAudioVolume_GetMute
2000 };
2001
2002 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
2003         REFIID riid, void **ppv)
2004 {
2005     ACImpl *This = impl_from_IAudioClock(iface);
2006
2007     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2008
2009     if(!ppv)
2010         return E_POINTER;
2011     *ppv = NULL;
2012
2013     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
2014         *ppv = iface;
2015     else if(IsEqualIID(riid, &IID_IAudioClock2))
2016         *ppv = &This->IAudioClock2_iface;
2017     if(*ppv){
2018         IUnknown_AddRef((IUnknown*)*ppv);
2019         return S_OK;
2020     }
2021
2022     WARN("Unknown interface %s\n", debugstr_guid(riid));
2023     return E_NOINTERFACE;
2024 }
2025
2026 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
2027 {
2028     ACImpl *This = impl_from_IAudioClock(iface);
2029     return IAudioClient_AddRef(&This->IAudioClient_iface);
2030 }
2031
2032 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
2033 {
2034     ACImpl *This = impl_from_IAudioClock(iface);
2035     return IAudioClient_Release(&This->IAudioClient_iface);
2036 }
2037
2038 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
2039 {
2040     ACImpl *This = impl_from_IAudioClock(iface);
2041
2042     TRACE("(%p)->(%p)\n", This, freq);
2043
2044     *freq = This->fmt->nSamplesPerSec;
2045
2046     return S_OK;
2047 }
2048
2049 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2050         UINT64 *qpctime)
2051 {
2052     ACImpl *This = impl_from_IAudioClock(iface);
2053     UINT32 pad;
2054     HRESULT hr;
2055
2056     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2057
2058     if(!pos)
2059         return E_POINTER;
2060
2061     EnterCriticalSection(&This->lock);
2062
2063     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
2064     if(FAILED(hr)){
2065         LeaveCriticalSection(&This->lock);
2066         return hr;
2067     }
2068
2069     if(This->dataflow == eRender)
2070         *pos = This->written_frames - pad;
2071     else if(This->dataflow == eCapture)
2072         *pos = This->written_frames + pad;
2073
2074     LeaveCriticalSection(&This->lock);
2075
2076     if(qpctime){
2077         LARGE_INTEGER stamp, freq;
2078         QueryPerformanceCounter(&stamp);
2079         QueryPerformanceFrequency(&freq);
2080         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2081     }
2082
2083     return S_OK;
2084 }
2085
2086 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2087         DWORD *chars)
2088 {
2089     ACImpl *This = impl_from_IAudioClock(iface);
2090
2091     TRACE("(%p)->(%p)\n", This, chars);
2092
2093     if(!chars)
2094         return E_POINTER;
2095
2096     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2097
2098     return S_OK;
2099 }
2100
2101 static const IAudioClockVtbl AudioClock_Vtbl =
2102 {
2103     AudioClock_QueryInterface,
2104     AudioClock_AddRef,
2105     AudioClock_Release,
2106     AudioClock_GetFrequency,
2107     AudioClock_GetPosition,
2108     AudioClock_GetCharacteristics
2109 };
2110
2111 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2112         REFIID riid, void **ppv)
2113 {
2114     ACImpl *This = impl_from_IAudioClock2(iface);
2115     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2116 }
2117
2118 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2119 {
2120     ACImpl *This = impl_from_IAudioClock2(iface);
2121     return IAudioClient_AddRef(&This->IAudioClient_iface);
2122 }
2123
2124 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2125 {
2126     ACImpl *This = impl_from_IAudioClock2(iface);
2127     return IAudioClient_Release(&This->IAudioClient_iface);
2128 }
2129
2130 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2131         UINT64 *pos, UINT64 *qpctime)
2132 {
2133     ACImpl *This = impl_from_IAudioClock2(iface);
2134
2135     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2136
2137     return E_NOTIMPL;
2138 }
2139
2140 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2141 {
2142     AudioClock2_QueryInterface,
2143     AudioClock2_AddRef,
2144     AudioClock2_Release,
2145     AudioClock2_GetDevicePosition
2146 };