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