winealsa.drv: Add mmdevapi driver.
[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         HeapFree(GetProcessHeap(), 0, 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 = HeapAlloc(GetProcessHeap(), 0, 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
483     if((err = snd_pcm_sw_params_get_boundary(sw_params, &boundary)) < 0){
484         WARN("Unable to get boundary: %d (%s)\n", err, snd_strerror(err));
485         hr = E_FAIL;
486         goto exit;
487     }
488
489     if((err = snd_pcm_sw_params_set_start_threshold(This->pcm_handle,
490                 sw_params, boundary)) < 0){
491         WARN("Unable to set start threshold to %lx: %d (%s)\n", boundary, err,
492                 snd_strerror(err));
493         hr = E_FAIL;
494         goto exit;
495     }
496
497     if((err = snd_pcm_sw_params_set_stop_threshold(This->pcm_handle,
498                 sw_params, boundary)) < 0){
499         WARN("Unable to set stop threshold to %lx: %d (%s)\n", boundary, err,
500                 snd_strerror(err));
501         hr = E_FAIL;
502         goto exit;
503     }
504
505     if((err = snd_pcm_sw_params_set_avail_min(This->pcm_handle,
506                 sw_params, 0)) < 0){
507         WARN("Unable to set avail min to 0: %d (%s)\n", err, snd_strerror(err));
508         hr = E_FAIL;
509         goto exit;
510     }
511
512     if((err = snd_pcm_sw_params(This->pcm_handle, sw_params)) < 0){
513         WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
514         hr = E_FAIL;
515         goto exit;
516     }
517
518     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
519         WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
520         hr = E_FAIL;
521         goto exit;
522     }
523
524     if((err = snd_pcm_hw_params_get_buffer_size(This->hw_params,
525                     &This->bufsize_alsa)) < 0){
526         WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
527         hr = E_FAIL;
528         goto exit;
529     }
530
531     if((err = snd_pcm_hw_params_get_period_size(This->hw_params,
532                     &This->period_alsa, NULL)) < 0){
533         WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
534         hr = E_FAIL;
535         goto exit;
536     }
537
538     if((err = snd_pcm_hw_params_get_period_time(This->hw_params,
539                     &This->period_us, NULL)) < 0){
540         WARN("Unable to get period time: %d (%s)\n", err, snd_strerror(err));
541         hr = E_FAIL;
542         goto exit;
543     }
544
545     This->fmt = clone_format(fmt);
546     if(!This->fmt){
547         hr = E_OUTOFMEMORY;
548         goto exit;
549     }
550
551     This->initted = TRUE;
552     This->share = mode;
553     This->flags = flags;
554
555 exit:
556     HeapFree(GetProcessHeap(), 0, sw_params);
557     if(FAILED(hr)){
558         if(This->local_buffer){
559             HeapFree(GetProcessHeap(), 0, This->local_buffer);
560             This->local_buffer = NULL;
561         }
562     }
563
564     LeaveCriticalSection(&This->lock);
565
566     return hr;
567 }
568
569 static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface,
570         UINT32 *out)
571 {
572     ACImpl *This = impl_from_IAudioClient(iface);
573
574     TRACE("(%p)->(%p)\n", This, out);
575
576     if(!out)
577         return E_POINTER;
578
579     EnterCriticalSection(&This->lock);
580
581     if(!This->initted){
582         LeaveCriticalSection(&This->lock);
583         return AUDCLNT_E_NOT_INITIALIZED;
584     }
585
586     *out = This->bufsize_frames;
587
588     LeaveCriticalSection(&This->lock);
589
590     return S_OK;
591 }
592
593 static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
594         REFERENCE_TIME *latency)
595 {
596     ACImpl *This = impl_from_IAudioClient(iface);
597
598     TRACE("(%p)->(%p)\n", This, latency);
599
600     if(!latency)
601         return E_POINTER;
602
603     EnterCriticalSection(&This->lock);
604
605     if(!This->initted){
606         LeaveCriticalSection(&This->lock);
607         return AUDCLNT_E_NOT_INITIALIZED;
608     }
609
610     LeaveCriticalSection(&This->lock);
611
612     *latency = 500000;
613
614     return S_OK;
615 }
616
617 static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
618         UINT32 *out)
619 {
620     ACImpl *This = impl_from_IAudioClient(iface);
621
622     TRACE("(%p)->(%p)\n", This, out);
623
624     if(!out)
625         return E_POINTER;
626
627     EnterCriticalSection(&This->lock);
628
629     if(!This->initted){
630         LeaveCriticalSection(&This->lock);
631         return AUDCLNT_E_NOT_INITIALIZED;
632     }
633
634     if(This->dataflow == eRender){
635         snd_pcm_sframes_t avail_frames;
636
637         avail_frames = snd_pcm_avail_update(This->pcm_handle);
638
639         if(This->bufsize_alsa < avail_frames){
640             WARN("Xrun detected\n");
641             *out = This->held_frames;
642         }else
643             *out = This->bufsize_alsa - avail_frames + This->held_frames;
644     }else if(This->dataflow == eCapture){
645         *out = This->held_frames;
646     }else{
647         LeaveCriticalSection(&This->lock);
648         return E_UNEXPECTED;
649     }
650
651     LeaveCriticalSection(&This->lock);
652
653     return S_OK;
654 }
655
656 static DWORD get_channel_mask(unsigned int channels)
657 {
658     switch(channels){
659     case 0:
660         return 0;
661     case 1:
662         return SPEAKER_FRONT_CENTER;
663     case 2:
664         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
665     case 3:
666         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
667             SPEAKER_LOW_FREQUENCY;
668     case 4:
669         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
670             SPEAKER_BACK_RIGHT;
671     case 5:
672         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
673             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
674     case 6:
675         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
676             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER;
677     case 7:
678         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
679             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER |
680             SPEAKER_BACK_CENTER;
681     }
682     FIXME("Unknown speaker configuration: %u\n", channels);
683     return 0;
684 }
685
686 static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
687         AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *fmt,
688         WAVEFORMATEX **out)
689 {
690     ACImpl *This = impl_from_IAudioClient(iface);
691     snd_pcm_format_mask_t *formats = NULL;
692     HRESULT hr = S_OK;
693     WAVEFORMATEX *closest = NULL;
694     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
695     unsigned int max = 0, min = 0;
696     int err;
697
698     TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out);
699
700     if(!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out))
701         return E_POINTER;
702
703     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
704         return E_INVALIDARG;
705
706     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
707             fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
708         return E_INVALIDARG;
709
710     dump_fmt(fmt);
711
712     EnterCriticalSection(&This->lock);
713
714     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
715         hr = E_FAIL;
716         goto exit;
717     }
718
719     formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
720             snd_pcm_format_mask_sizeof());
721     if(!formats){
722         hr = E_OUTOFMEMORY;
723         goto exit;
724     }
725
726     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
727
728     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
729             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
730              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
731         switch(fmt->wBitsPerSample){
732         case 8:
733             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
734                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
735                 goto exit;
736             }
737             break;
738         case 16:
739             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
740                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
741                 goto exit;
742             }
743             break;
744         case 24:
745             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
746                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
747                 goto exit;
748             }
749             break;
750         case 32:
751             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
752                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
753                 goto exit;
754             }
755             break;
756         default:
757             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
758             goto exit;
759         }
760     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
761             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
762              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
763         switch(fmt->wBitsPerSample){
764         case 32:
765             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
766                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
767                 goto exit;
768             }
769             break;
770         case 64:
771             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT64_LE)){
772                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
773                 goto exit;
774             }
775             break;
776         default:
777             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
778             goto exit;
779         }
780     }else{
781         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
782         goto exit;
783     }
784
785     closest = clone_format(fmt);
786     if(!closest){
787         hr = E_OUTOFMEMORY;
788         goto exit;
789     }
790
791     if((err = snd_pcm_hw_params_get_rate_min(This->hw_params, &min, NULL)) < 0){
792         hr = E_FAIL;
793         WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err));
794         goto exit;
795     }
796
797     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max, NULL)) < 0){
798         hr = E_FAIL;
799         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
800         goto exit;
801     }
802
803     if(fmt->nSamplesPerSec < min || fmt->nSamplesPerSec > max ||
804             (fmt->nSamplesPerSec != 48000 &&
805             fmt->nSamplesPerSec != 41100 &&
806             fmt->nSamplesPerSec != 22050 &&
807             fmt->nSamplesPerSec != 11025 &&
808             fmt->nSamplesPerSec != 8000)){
809         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
810         goto exit;
811     }
812
813     if((err = snd_pcm_hw_params_get_channels_min(This->hw_params, &min)) < 0){
814         hr = E_FAIL;
815         WARN("Unable to get min channels: %d (%s)\n", err, snd_strerror(err));
816         goto exit;
817     }
818
819     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params, &max)) < 0){
820         hr = E_FAIL;
821         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
822         goto exit;
823     }
824     if(max > 7)
825         max = 2;
826     if(fmt->nChannels > max){
827         hr = S_FALSE;
828         closest->nChannels = max;
829     }else if(fmt->nChannels < min){
830         hr = S_FALSE;
831         closest->nChannels = min;
832     }
833
834     if(closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
835         DWORD mask = get_channel_mask(closest->nChannels);
836
837         ((WAVEFORMATEXTENSIBLE*)closest)->dwChannelMask = mask;
838
839         if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
840                 fmtex->dwChannelMask != mask)
841             hr = S_FALSE;
842     }
843
844 exit:
845     LeaveCriticalSection(&This->lock);
846     HeapFree(GetProcessHeap(), 0, formats);
847
848     if(hr == S_OK || !out){
849         HeapFree(GetProcessHeap(), 0, closest);
850         if(out)
851             *out = NULL;
852     }else if(closest){
853         closest->nBlockAlign =
854             closest->nChannels * closest->wBitsPerSample / 8;
855         closest->nAvgBytesPerSec =
856             closest->nBlockAlign * closest->nSamplesPerSec;
857         *out = closest;
858     }
859
860     TRACE("returning: %08x\n", hr);
861     return hr;
862 }
863
864 static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface,
865         WAVEFORMATEX **pwfx)
866 {
867     ACImpl *This = impl_from_IAudioClient(iface);
868     WAVEFORMATEXTENSIBLE *fmt;
869     snd_pcm_format_mask_t *formats;
870     unsigned int max_rate, max_channels;
871     int err;
872     HRESULT hr = S_OK;
873
874     TRACE("(%p)->(%p)\n", This, pwfx);
875
876     if(!pwfx)
877         return E_POINTER;
878
879     *pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
880     if(!*pwfx)
881         return E_OUTOFMEMORY;
882
883     fmt = (WAVEFORMATEXTENSIBLE*)*pwfx;
884
885     formats = HeapAlloc(GetProcessHeap(), 0, snd_pcm_format_mask_sizeof());
886     if(!formats){
887         HeapFree(GetProcessHeap(), 0, *pwfx);
888         return E_OUTOFMEMORY;
889     }
890
891     EnterCriticalSection(&This->lock);
892
893     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
894         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
895         hr = E_FAIL;
896         goto exit;
897     }
898
899     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
900
901     fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
902     if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
903         fmt->Format.wBitsPerSample = 32;
904         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
905     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
906         fmt->Format.wBitsPerSample = 16;
907         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
908     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
909         fmt->Format.wBitsPerSample = 8;
910         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
911     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
912         fmt->Format.wBitsPerSample = 32;
913         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
914     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
915         fmt->Format.wBitsPerSample = 24;
916         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
917     }else{
918         ERR("Didn't recognize any available ALSA formats\n");
919         hr = E_FAIL;
920         goto exit;
921     }
922
923     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params,
924                     &max_channels)) < 0){
925         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
926         hr = E_FAIL;
927         goto exit;
928     }
929
930     if(max_channels > 2){
931         FIXME("Don't know what to do with %u channels, pretending there's "
932                 "only 2 channels\n", max_channels);
933         fmt->Format.nChannels = 2;
934     }else
935         fmt->Format.nChannels = max_channels;
936
937     fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
938
939     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max_rate,
940                     NULL)) < 0){
941         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
942         hr = E_FAIL;
943         goto exit;
944     }
945
946     if(max_rate >= 48000)
947         fmt->Format.nSamplesPerSec = 48000;
948     else if(max_rate >= 41100)
949         fmt->Format.nSamplesPerSec = 41100;
950     else if(max_rate >= 22050)
951         fmt->Format.nSamplesPerSec = 22050;
952     else if(max_rate >= 11025)
953         fmt->Format.nSamplesPerSec = 11025;
954     else if(max_rate >= 8000)
955         fmt->Format.nSamplesPerSec = 8000;
956     else{
957         ERR("Unknown max rate: %u\n", max_rate);
958         hr = E_FAIL;
959         goto exit;
960     }
961
962     fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
963             fmt->Format.nChannels) / 8;
964     fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
965         fmt->Format.nBlockAlign;
966
967     fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
968     fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
969
970     dump_fmt((WAVEFORMATEX*)fmt);
971
972 exit:
973     LeaveCriticalSection(&This->lock);
974     if(FAILED(hr))
975         HeapFree(GetProcessHeap(), 0, *pwfx);
976     HeapFree(GetProcessHeap(), 0, formats);
977
978     return hr;
979 }
980
981 static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
982         REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
983 {
984     ACImpl *This = impl_from_IAudioClient(iface);
985
986     TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
987
988     if(!defperiod && !minperiod)
989         return E_POINTER;
990
991     if(defperiod)
992         *defperiod = DefaultPeriod;
993     if(minperiod)
994         *minperiod = MinimumPeriod;
995
996     return S_OK;
997 }
998
999 static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
1000         snd_pcm_uframes_t frames)
1001 {
1002     snd_pcm_sframes_t written;
1003
1004     written = snd_pcm_writei(handle, buf, frames);
1005     if(written < 0){
1006         int ret;
1007
1008         if(written == -EAGAIN)
1009             /* buffer full */
1010             return 0;
1011
1012         WARN("writei failed, recovering: %ld (%s)\n", written,
1013                 snd_strerror(written));
1014
1015         ret = wine_snd_pcm_recover(handle, written, 0);
1016         if(ret < 0){
1017             WARN("Could not recover: %d (%s)\n", ret, snd_strerror(ret));
1018             return ret;
1019         }
1020
1021         written = snd_pcm_writei(handle, buf, frames);
1022     }
1023
1024     return written;
1025 }
1026
1027 static void alsa_write_data(ACImpl *This)
1028 {
1029     snd_pcm_sframes_t written;
1030     snd_pcm_uframes_t to_write;
1031     BYTE *buf =
1032         This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
1033
1034     if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
1035         to_write = This->bufsize_frames - This->lcl_offs_frames;
1036     else
1037         to_write = This->held_frames;
1038
1039     written = alsa_write_best_effort(This->pcm_handle, buf, to_write);
1040     if(written < 0){
1041         WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1042         return;
1043     }
1044
1045     This->lcl_offs_frames += written;
1046     This->lcl_offs_frames %= This->bufsize_frames;
1047     This->held_frames -= written;
1048
1049     if(written < to_write){
1050         /* ALSA buffer probably full */
1051         return;
1052     }
1053
1054     if(This->held_frames){
1055         /* wrapped and have some data back at the start to write */
1056         written = alsa_write_best_effort(This->pcm_handle, This->local_buffer,
1057                 This->held_frames);
1058         if(written < 0){
1059             WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1060             return;
1061         }
1062
1063         This->lcl_offs_frames += written;
1064         This->lcl_offs_frames %= This->bufsize_frames;
1065         This->held_frames -= written;
1066     }
1067 }
1068
1069 static void alsa_read_data(ACImpl *This)
1070 {
1071     snd_pcm_sframes_t pos, readable, nread;
1072
1073     pos = (This->held_frames + This->lcl_offs_frames) % This->bufsize_frames;
1074     readable = This->bufsize_frames - pos;
1075
1076     nread = snd_pcm_readi(This->pcm_handle,
1077             This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1078     if(nread < 0){
1079         int ret;
1080
1081         WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
1082
1083         ret = wine_snd_pcm_recover(This->pcm_handle, nread, 0);
1084         if(ret < 0){
1085             WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
1086             return;
1087         }
1088
1089         nread = snd_pcm_readi(This->pcm_handle,
1090                 This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1091         if(nread < 0){
1092             WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
1093             return;
1094         }
1095     }
1096
1097     This->held_frames += nread;
1098
1099     if(This->held_frames > This->bufsize_frames){
1100         WARN("Overflow of unread data\n");
1101         This->lcl_offs_frames += This->held_frames;
1102         This->lcl_offs_frames %= This->bufsize_frames;
1103         This->held_frames = This->bufsize_frames;
1104     }
1105 }
1106
1107 static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
1108 {
1109     ACImpl *This = user;
1110
1111     EnterCriticalSection(&This->lock);
1112
1113     if(This->dataflow == eRender)
1114         alsa_write_data(This);
1115     else if(This->dataflow == eCapture)
1116         alsa_read_data(This);
1117
1118     if(This->event)
1119         SetEvent(This->event);
1120
1121     LeaveCriticalSection(&This->lock);
1122 }
1123
1124 static HRESULT alsa_consider_start(ACImpl *This)
1125 {
1126     snd_pcm_sframes_t avail;
1127     int err;
1128
1129     avail = snd_pcm_avail_update(This->pcm_handle);
1130     if(avail < 0){
1131         WARN("Unable to get avail_update: %ld (%s)\n", avail,
1132                 snd_strerror(avail));
1133         return E_FAIL;
1134     }
1135
1136     if(This->period_alsa < This->bufsize_alsa - avail){
1137         if((err = snd_pcm_start(This->pcm_handle)) < 0){
1138             WARN("Start failed: %d (%s), state: %d\n", err, snd_strerror(err),
1139                     snd_pcm_state(This->pcm_handle));
1140             return E_FAIL;
1141         }
1142
1143         return S_OK;
1144     }
1145
1146     return S_FALSE;
1147 }
1148
1149 static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
1150 {
1151     ACImpl *This = impl_from_IAudioClient(iface);
1152     DWORD period_ms;
1153     HRESULT hr;
1154
1155     TRACE("(%p)\n", This);
1156
1157     EnterCriticalSection(&This->lock);
1158
1159     if(!This->initted){
1160         LeaveCriticalSection(&This->lock);
1161         return AUDCLNT_E_NOT_INITIALIZED;
1162     }
1163
1164     if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
1165         LeaveCriticalSection(&This->lock);
1166         return AUDCLNT_E_EVENTHANDLE_NOT_SET;
1167     }
1168
1169     if(This->started){
1170         LeaveCriticalSection(&This->lock);
1171         return AUDCLNT_E_NOT_STOPPED;
1172     }
1173
1174     hr = alsa_consider_start(This);
1175     if(FAILED(hr)){
1176         LeaveCriticalSection(&This->lock);
1177         return hr;
1178     }
1179
1180     period_ms = This->period_us / 1000;
1181     if(!period_ms)
1182         period_ms = 10;
1183
1184     if(This->dataflow == eCapture){
1185         /* dump any data that might be leftover in the ALSA capture buffer */
1186         snd_pcm_readi(This->pcm_handle, This->local_buffer,
1187                 This->bufsize_frames);
1188     }
1189
1190     if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
1191             This, 0, period_ms, WT_EXECUTEINTIMERTHREAD)){
1192         LeaveCriticalSection(&This->lock);
1193         WARN("Unable to create timer: %u\n", GetLastError());
1194         return E_FAIL;
1195     }
1196
1197     This->started = TRUE;
1198
1199     LeaveCriticalSection(&This->lock);
1200
1201     return S_OK;
1202 }
1203
1204 static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
1205 {
1206     ACImpl *This = impl_from_IAudioClient(iface);
1207     int err;
1208
1209     TRACE("(%p)\n", This);
1210
1211     EnterCriticalSection(&This->lock);
1212
1213     if(!This->initted){
1214         LeaveCriticalSection(&This->lock);
1215         return AUDCLNT_E_NOT_INITIALIZED;
1216     }
1217
1218     if(!This->started){
1219         LeaveCriticalSection(&This->lock);
1220         return S_FALSE;
1221     }
1222
1223     DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE);
1224
1225     if((err = snd_pcm_drop(This->pcm_handle)) < 0){
1226         LeaveCriticalSection(&This->lock);
1227         WARN("Drop failed: %d (%s)\n", err, snd_strerror(err));
1228         return E_FAIL;
1229     }
1230
1231     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
1232         LeaveCriticalSection(&This->lock);
1233         WARN("Prepare failed: %d (%s)\n", err, snd_strerror(err));
1234         return E_FAIL;
1235     }
1236
1237     This->started = FALSE;
1238
1239     LeaveCriticalSection(&This->lock);
1240
1241     return S_OK;
1242 }
1243
1244 static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
1245 {
1246     ACImpl *This = impl_from_IAudioClient(iface);
1247
1248     TRACE("(%p)\n", This);
1249
1250     EnterCriticalSection(&This->lock);
1251
1252     if(!This->initted){
1253         LeaveCriticalSection(&This->lock);
1254         return AUDCLNT_E_NOT_INITIALIZED;
1255     }
1256
1257     if(This->started){
1258         LeaveCriticalSection(&This->lock);
1259         return AUDCLNT_E_NOT_STOPPED;
1260     }
1261
1262     This->held_frames = 0;
1263     This->written_frames = 0;
1264     This->lcl_offs_frames = 0;
1265
1266     LeaveCriticalSection(&This->lock);
1267
1268     return S_OK;
1269 }
1270
1271 static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface,
1272         HANDLE event)
1273 {
1274     ACImpl *This = impl_from_IAudioClient(iface);
1275
1276     TRACE("(%p)->(%p)\n", This, event);
1277
1278     if(!event)
1279         return E_INVALIDARG;
1280
1281     EnterCriticalSection(&This->lock);
1282
1283     if(!This->initted){
1284         LeaveCriticalSection(&This->lock);
1285         return AUDCLNT_E_NOT_INITIALIZED;
1286     }
1287
1288     if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
1289         LeaveCriticalSection(&This->lock);
1290         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
1291     }
1292
1293     This->event = event;
1294
1295     LeaveCriticalSection(&This->lock);
1296
1297     return S_OK;
1298 }
1299
1300 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1301         void **ppv)
1302 {
1303     ACImpl *This = impl_from_IAudioClient(iface);
1304
1305     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1306
1307     if(!ppv)
1308         return E_POINTER;
1309     *ppv = NULL;
1310
1311     EnterCriticalSection(&This->lock);
1312
1313     if(!This->initted){
1314         LeaveCriticalSection(&This->lock);
1315         return AUDCLNT_E_NOT_INITIALIZED;
1316     }
1317
1318     LeaveCriticalSection(&This->lock);
1319
1320     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1321         if(This->dataflow != eRender)
1322             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1323         *ppv = &This->IAudioRenderClient_iface;
1324     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1325         if(This->dataflow != eCapture)
1326             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1327         *ppv = &This->IAudioCaptureClient_iface;
1328     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1329         *ppv = &This->IAudioSessionControl2_iface;
1330     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1331         *ppv = &This->ISimpleAudioVolume_iface;
1332     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1333         *ppv = &This->IAudioClock_iface;
1334     }
1335
1336     if(*ppv){
1337         IUnknown_AddRef((IUnknown*)*ppv);
1338         return S_OK;
1339     }
1340
1341     FIXME("stub %s\n", debugstr_guid(riid));
1342     return E_NOINTERFACE;
1343 }
1344
1345 static const IAudioClientVtbl AudioClient_Vtbl =
1346 {
1347     AudioClient_QueryInterface,
1348     AudioClient_AddRef,
1349     AudioClient_Release,
1350     AudioClient_Initialize,
1351     AudioClient_GetBufferSize,
1352     AudioClient_GetStreamLatency,
1353     AudioClient_GetCurrentPadding,
1354     AudioClient_IsFormatSupported,
1355     AudioClient_GetMixFormat,
1356     AudioClient_GetDevicePeriod,
1357     AudioClient_Start,
1358     AudioClient_Stop,
1359     AudioClient_Reset,
1360     AudioClient_SetEventHandle,
1361     AudioClient_GetService
1362 };
1363
1364 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1365         IAudioRenderClient *iface, REFIID riid, void **ppv)
1366 {
1367     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1368
1369     if(!ppv)
1370         return E_POINTER;
1371     *ppv = NULL;
1372
1373     if(IsEqualIID(riid, &IID_IUnknown) ||
1374             IsEqualIID(riid, &IID_IAudioRenderClient))
1375         *ppv = iface;
1376     if(*ppv){
1377         IUnknown_AddRef((IUnknown*)*ppv);
1378         return S_OK;
1379     }
1380
1381     WARN("Unknown interface %s\n", debugstr_guid(riid));
1382     return E_NOINTERFACE;
1383 }
1384
1385 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1386 {
1387     ACImpl *This = impl_from_IAudioRenderClient(iface);
1388     return AudioClient_AddRef(&This->IAudioClient_iface);
1389 }
1390
1391 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1392 {
1393     ACImpl *This = impl_from_IAudioRenderClient(iface);
1394     return AudioClient_Release(&This->IAudioClient_iface);
1395 }
1396
1397 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1398         UINT32 frames, BYTE **data)
1399 {
1400     ACImpl *This = impl_from_IAudioRenderClient(iface);
1401     UINT32 write_pos;
1402     UINT32 pad;
1403     HRESULT hr;
1404
1405     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1406
1407     if(!data)
1408         return E_POINTER;
1409
1410     EnterCriticalSection(&This->lock);
1411
1412     if(This->buf_state != NOT_LOCKED){
1413         LeaveCriticalSection(&This->lock);
1414         return AUDCLNT_E_OUT_OF_ORDER;
1415     }
1416
1417     if(!frames){
1418         This->buf_state = LOCKED_NORMAL;
1419         LeaveCriticalSection(&This->lock);
1420         return S_OK;
1421     }
1422
1423     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
1424     if(FAILED(hr)){
1425         LeaveCriticalSection(&This->lock);
1426         return hr;
1427     }
1428
1429     if(pad + frames > This->bufsize_frames){
1430         LeaveCriticalSection(&This->lock);
1431         return AUDCLNT_E_BUFFER_TOO_LARGE;
1432     }
1433
1434     write_pos =
1435         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1436     if(write_pos + frames > This->bufsize_frames){
1437         if(This->tmp_buffer_frames < frames){
1438             if(This->tmp_buffer)
1439                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
1440                         This->tmp_buffer, frames * This->fmt->nBlockAlign);
1441             else
1442                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
1443                         frames * This->fmt->nBlockAlign);
1444             if(!This->tmp_buffer){
1445                 LeaveCriticalSection(&This->lock);
1446                 return E_OUTOFMEMORY;
1447             }
1448             This->tmp_buffer_frames = frames;
1449         }
1450         *data = This->tmp_buffer;
1451         This->buf_state = LOCKED_WRAPPED;
1452     }else{
1453         *data = This->local_buffer +
1454             This->lcl_offs_frames * This->fmt->nBlockAlign;
1455         This->buf_state = LOCKED_NORMAL;
1456     }
1457
1458     LeaveCriticalSection(&This->lock);
1459
1460     return S_OK;
1461 }
1462
1463 static void alsa_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_bytes)
1464 {
1465     snd_pcm_uframes_t write_offs_frames =
1466         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1467     UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
1468     snd_pcm_uframes_t chunk_frames = This->bufsize_frames - write_offs_frames;
1469     UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
1470
1471     if(written_bytes < chunk_bytes){
1472         memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
1473     }else{
1474         memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
1475         memcpy(This->local_buffer, buffer + chunk_bytes,
1476                 written_bytes - chunk_bytes);
1477     }
1478 }
1479
1480 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
1481         IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
1482 {
1483     ACImpl *This = impl_from_IAudioRenderClient(iface);
1484     UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
1485     BYTE *buffer;
1486     HRESULT hr;
1487
1488     TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
1489
1490     EnterCriticalSection(&This->lock);
1491
1492     if(This->buf_state == NOT_LOCKED || !written_frames){
1493         This->buf_state = NOT_LOCKED;
1494         LeaveCriticalSection(&This->lock);
1495         return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1496     }
1497
1498     if(This->buf_state == LOCKED_NORMAL)
1499         buffer = This->local_buffer +
1500             This->lcl_offs_frames * This->fmt->nBlockAlign;
1501     else
1502         buffer = This->tmp_buffer;
1503
1504     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
1505         WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
1506         if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
1507                 (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1508                  IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
1509                 This->fmt->wBitsPerSample == 8)
1510             memset(buffer, 128, written_frames * This->fmt->nBlockAlign);
1511         else
1512             memset(buffer, 0, written_frames * This->fmt->nBlockAlign);
1513     }
1514
1515     if(This->held_frames){
1516         if(This->buf_state == LOCKED_WRAPPED)
1517             alsa_wrap_buffer(This, buffer, written_bytes);
1518
1519         This->held_frames += written_frames;
1520     }else{
1521         snd_pcm_sframes_t written;
1522
1523         written = alsa_write_best_effort(This->pcm_handle, buffer,
1524                 written_frames);
1525         if(written < 0){
1526             LeaveCriticalSection(&This->lock);
1527             WARN("write failed: %ld (%s)\n", written, snd_strerror(written));
1528             return E_FAIL;
1529         }
1530
1531         if(written < written_frames){
1532             if(This->buf_state == LOCKED_WRAPPED)
1533                 alsa_wrap_buffer(This,
1534                         This->tmp_buffer + written * This->fmt->nBlockAlign,
1535                         written_frames - written);
1536
1537             This->held_frames = written_frames - written;
1538         }
1539     }
1540
1541     if(This->started &&
1542             snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_PREPARED){
1543         hr = alsa_consider_start(This);
1544         if(FAILED(hr)){
1545             LeaveCriticalSection(&This->lock);
1546             return hr;
1547         }
1548     }
1549
1550     This->written_frames += written_frames;
1551     This->buf_state = NOT_LOCKED;
1552
1553     LeaveCriticalSection(&This->lock);
1554
1555     return S_OK;
1556 }
1557
1558 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
1559     AudioRenderClient_QueryInterface,
1560     AudioRenderClient_AddRef,
1561     AudioRenderClient_Release,
1562     AudioRenderClient_GetBuffer,
1563     AudioRenderClient_ReleaseBuffer
1564 };
1565
1566 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
1567         IAudioCaptureClient *iface, REFIID riid, void **ppv)
1568 {
1569     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1570
1571     if(!ppv)
1572         return E_POINTER;
1573     *ppv = NULL;
1574
1575     if(IsEqualIID(riid, &IID_IUnknown) ||
1576             IsEqualIID(riid, &IID_IAudioCaptureClient))
1577         *ppv = iface;
1578     if(*ppv){
1579         IUnknown_AddRef((IUnknown*)*ppv);
1580         return S_OK;
1581     }
1582
1583     WARN("Unknown interface %s\n", debugstr_guid(riid));
1584     return E_NOINTERFACE;
1585 }
1586
1587 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
1588 {
1589     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1590     return IAudioClient_AddRef(&This->IAudioClient_iface);
1591 }
1592
1593 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
1594 {
1595     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1596     return IAudioClient_Release(&This->IAudioClient_iface);
1597 }
1598
1599 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
1600         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
1601         UINT64 *qpcpos)
1602 {
1603     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1604     HRESULT hr;
1605
1606     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
1607             devpos, qpcpos);
1608
1609     if(!data || !frames || !flags)
1610         return E_POINTER;
1611
1612     EnterCriticalSection(&This->lock);
1613
1614     if(This->buf_state != NOT_LOCKED){
1615         LeaveCriticalSection(&This->lock);
1616         return AUDCLNT_E_OUT_OF_ORDER;
1617     }
1618
1619     hr = IAudioCaptureClient_GetNextPacketSize(iface, frames);
1620     if(FAILED(hr)){
1621         LeaveCriticalSection(&This->lock);
1622         return hr;
1623     }
1624
1625     *flags = 0;
1626
1627     if(This->lcl_offs_frames + *frames > This->bufsize_frames){
1628         UINT32 chunk_bytes, offs_bytes, frames_bytes;
1629         if(This->tmp_buffer_frames < *frames){
1630             if(This->tmp_buffer)
1631                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
1632                         This->tmp_buffer, *frames * This->fmt->nBlockAlign);
1633             else
1634                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
1635                         *frames * This->fmt->nBlockAlign);
1636             if(!This->tmp_buffer){
1637                 LeaveCriticalSection(&This->lock);
1638                 return E_OUTOFMEMORY;
1639             }
1640             This->tmp_buffer_frames = *frames;
1641         }
1642
1643         *data = This->tmp_buffer;
1644         chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
1645             This->fmt->nBlockAlign;
1646         offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
1647         frames_bytes = *frames * This->fmt->nBlockAlign;
1648         memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
1649         memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
1650                 frames_bytes - chunk_bytes);
1651     }else
1652         *data = This->local_buffer +
1653             This->lcl_offs_frames * This->fmt->nBlockAlign;
1654
1655     This->buf_state = LOCKED_NORMAL;
1656
1657     if(devpos || qpcpos)
1658         IAudioClock_GetPosition(&This->IAudioClock_iface, devpos, qpcpos);
1659
1660     LeaveCriticalSection(&This->lock);
1661
1662     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
1663 }
1664
1665 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
1666         IAudioCaptureClient *iface, UINT32 done)
1667 {
1668     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1669
1670     TRACE("(%p)->(%u)\n", This, done);
1671
1672     EnterCriticalSection(&This->lock);
1673
1674     if(This->buf_state == NOT_LOCKED){
1675         LeaveCriticalSection(&This->lock);
1676         return AUDCLNT_E_OUT_OF_ORDER;
1677     }
1678
1679     This->held_frames -= done;
1680     This->lcl_offs_frames += done;
1681     This->lcl_offs_frames %= This->bufsize_frames;
1682
1683     This->buf_state = NOT_LOCKED;
1684
1685     LeaveCriticalSection(&This->lock);
1686
1687     return S_OK;
1688 }
1689
1690 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
1691         IAudioCaptureClient *iface, UINT32 *frames)
1692 {
1693     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1694
1695     TRACE("(%p)->(%p)\n", This, frames);
1696
1697     return AudioClient_GetCurrentPadding(&This->IAudioClient_iface, frames);
1698 }
1699
1700 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
1701 {
1702     AudioCaptureClient_QueryInterface,
1703     AudioCaptureClient_AddRef,
1704     AudioCaptureClient_Release,
1705     AudioCaptureClient_GetBuffer,
1706     AudioCaptureClient_ReleaseBuffer,
1707     AudioCaptureClient_GetNextPacketSize
1708 };
1709
1710 static HRESULT WINAPI AudioSessionControl_QueryInterface(
1711         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
1712 {
1713     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1714
1715     if(!ppv)
1716         return E_POINTER;
1717     *ppv = NULL;
1718
1719     if(IsEqualIID(riid, &IID_IUnknown) ||
1720             IsEqualIID(riid, &IID_IAudioSessionControl) ||
1721             IsEqualIID(riid, &IID_IAudioSessionControl2))
1722         *ppv = iface;
1723     if(*ppv){
1724         IUnknown_AddRef((IUnknown*)*ppv);
1725         return S_OK;
1726     }
1727
1728     WARN("Unknown interface %s\n", debugstr_guid(riid));
1729     return E_NOINTERFACE;
1730 }
1731
1732 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
1733 {
1734     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1735     return IAudioClient_AddRef(&This->IAudioClient_iface);
1736 }
1737
1738 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
1739 {
1740     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1741     return IAudioClient_Release(&This->IAudioClient_iface);
1742 }
1743
1744 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
1745         AudioSessionState *state)
1746 {
1747     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1748
1749     FIXME("(%p)->(%p) - stub\n", This, state);
1750
1751     if(!state)
1752         return E_POINTER;
1753
1754     return E_NOTIMPL;
1755 }
1756
1757 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
1758         IAudioSessionControl2 *iface, WCHAR **name)
1759 {
1760     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1761
1762     FIXME("(%p)->(%p) - stub\n", This, name);
1763
1764     return E_NOTIMPL;
1765 }
1766
1767 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
1768         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
1769 {
1770     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1771
1772     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
1773
1774     return E_NOTIMPL;
1775 }
1776
1777 static HRESULT WINAPI AudioSessionControl_GetIconPath(
1778         IAudioSessionControl2 *iface, WCHAR **path)
1779 {
1780     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1781
1782     FIXME("(%p)->(%p) - stub\n", This, path);
1783
1784     return E_NOTIMPL;
1785 }
1786
1787 static HRESULT WINAPI AudioSessionControl_SetIconPath(
1788         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
1789 {
1790     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1791
1792     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
1793
1794     return E_NOTIMPL;
1795 }
1796
1797 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
1798         IAudioSessionControl2 *iface, GUID *group)
1799 {
1800     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1801
1802     FIXME("(%p)->(%p) - stub\n", This, group);
1803
1804     return E_NOTIMPL;
1805 }
1806
1807 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
1808         IAudioSessionControl2 *iface, GUID *group, const GUID *session)
1809 {
1810     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1811
1812     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
1813             debugstr_guid(session));
1814
1815     return E_NOTIMPL;
1816 }
1817
1818 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
1819         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1820 {
1821     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1822
1823     FIXME("(%p)->(%p) - stub\n", This, events);
1824
1825     return S_OK;
1826 }
1827
1828 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
1829         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1830 {
1831     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1832
1833     FIXME("(%p)->(%p) - stub\n", This, events);
1834
1835     return S_OK;
1836 }
1837
1838 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
1839         IAudioSessionControl2 *iface, WCHAR **id)
1840 {
1841     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1842
1843     FIXME("(%p)->(%p) - stub\n", This, id);
1844
1845     return E_NOTIMPL;
1846 }
1847
1848 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
1849         IAudioSessionControl2 *iface, WCHAR **id)
1850 {
1851     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1852
1853     FIXME("(%p)->(%p) - stub\n", This, id);
1854
1855     return E_NOTIMPL;
1856 }
1857
1858 static HRESULT WINAPI AudioSessionControl_GetProcessId(
1859         IAudioSessionControl2 *iface, DWORD *pid)
1860 {
1861     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1862
1863     TRACE("(%p)->(%p)\n", This, pid);
1864
1865     if(!pid)
1866         return E_POINTER;
1867
1868     *pid = GetCurrentProcessId();
1869
1870     return S_OK;
1871 }
1872
1873 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
1874         IAudioSessionControl2 *iface)
1875 {
1876     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1877
1878     TRACE("(%p)\n", This);
1879
1880     return S_FALSE;
1881 }
1882
1883 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
1884         IAudioSessionControl2 *iface, BOOL optout)
1885 {
1886     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1887
1888     TRACE("(%p)->(%d)\n", This, optout);
1889
1890     return S_OK;
1891 }
1892
1893 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
1894 {
1895     AudioSessionControl_QueryInterface,
1896     AudioSessionControl_AddRef,
1897     AudioSessionControl_Release,
1898     AudioSessionControl_GetState,
1899     AudioSessionControl_GetDisplayName,
1900     AudioSessionControl_SetDisplayName,
1901     AudioSessionControl_GetIconPath,
1902     AudioSessionControl_SetIconPath,
1903     AudioSessionControl_GetGroupingParam,
1904     AudioSessionControl_SetGroupingParam,
1905     AudioSessionControl_RegisterAudioSessionNotification,
1906     AudioSessionControl_UnregisterAudioSessionNotification,
1907     AudioSessionControl_GetSessionIdentifier,
1908     AudioSessionControl_GetSessionInstanceIdentifier,
1909     AudioSessionControl_GetProcessId,
1910     AudioSessionControl_IsSystemSoundsSession,
1911     AudioSessionControl_SetDuckingPreference
1912 };
1913
1914 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
1915         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
1916 {
1917     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1918
1919     if(!ppv)
1920         return E_POINTER;
1921     *ppv = NULL;
1922
1923     if(IsEqualIID(riid, &IID_IUnknown) ||
1924             IsEqualIID(riid, &IID_ISimpleAudioVolume))
1925         *ppv = iface;
1926     if(*ppv){
1927         IUnknown_AddRef((IUnknown*)*ppv);
1928         return S_OK;
1929     }
1930
1931     WARN("Unknown interface %s\n", debugstr_guid(riid));
1932     return E_NOINTERFACE;
1933 }
1934
1935 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
1936 {
1937     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1938     return IAudioClient_AddRef(&This->IAudioClient_iface);
1939 }
1940
1941 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
1942 {
1943     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1944     return IAudioClient_Release(&This->IAudioClient_iface);
1945 }
1946
1947 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
1948         ISimpleAudioVolume *iface, float level, const GUID *context)
1949 {
1950     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1951
1952     FIXME("(%p)->(%f, %p) - stub\n", This, level, context);
1953
1954     return E_NOTIMPL;
1955 }
1956
1957 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
1958         ISimpleAudioVolume *iface, float *level)
1959 {
1960     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1961
1962     FIXME("(%p)->(%p) - stub\n", This, level);
1963
1964     return E_NOTIMPL;
1965 }
1966
1967 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
1968         BOOL mute, const GUID *context)
1969 {
1970     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1971
1972     FIXME("(%p)->(%u, %p) - stub\n", This, mute, context);
1973
1974     return E_NOTIMPL;
1975 }
1976
1977 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
1978         BOOL *mute)
1979 {
1980     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1981
1982     FIXME("(%p)->(%p) - stub\n", This, mute);
1983
1984     return E_NOTIMPL;
1985 }
1986
1987 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
1988 {
1989     SimpleAudioVolume_QueryInterface,
1990     SimpleAudioVolume_AddRef,
1991     SimpleAudioVolume_Release,
1992     SimpleAudioVolume_SetMasterVolume,
1993     SimpleAudioVolume_GetMasterVolume,
1994     SimpleAudioVolume_SetMute,
1995     SimpleAudioVolume_GetMute
1996 };
1997
1998 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
1999         REFIID riid, void **ppv)
2000 {
2001     ACImpl *This = impl_from_IAudioClock(iface);
2002
2003     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2004
2005     if(!ppv)
2006         return E_POINTER;
2007     *ppv = NULL;
2008
2009     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
2010         *ppv = iface;
2011     else if(IsEqualIID(riid, &IID_IAudioClock2))
2012         *ppv = &This->IAudioClock2_iface;
2013     if(*ppv){
2014         IUnknown_AddRef((IUnknown*)*ppv);
2015         return S_OK;
2016     }
2017
2018     WARN("Unknown interface %s\n", debugstr_guid(riid));
2019     return E_NOINTERFACE;
2020 }
2021
2022 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
2023 {
2024     ACImpl *This = impl_from_IAudioClock(iface);
2025     return IAudioClient_AddRef(&This->IAudioClient_iface);
2026 }
2027
2028 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
2029 {
2030     ACImpl *This = impl_from_IAudioClock(iface);
2031     return IAudioClient_Release(&This->IAudioClient_iface);
2032 }
2033
2034 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
2035 {
2036     ACImpl *This = impl_from_IAudioClock(iface);
2037
2038     TRACE("(%p)->(%p)\n", This, freq);
2039
2040     *freq = This->fmt->nSamplesPerSec;
2041
2042     return S_OK;
2043 }
2044
2045 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2046         UINT64 *qpctime)
2047 {
2048     ACImpl *This = impl_from_IAudioClock(iface);
2049     UINT32 pad;
2050     HRESULT hr;
2051
2052     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2053
2054     if(!pos)
2055         return E_POINTER;
2056
2057     EnterCriticalSection(&This->lock);
2058
2059     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
2060     if(FAILED(hr)){
2061         LeaveCriticalSection(&This->lock);
2062         return hr;
2063     }
2064
2065     if(This->dataflow == eRender)
2066         *pos = This->written_frames - pad;
2067     else if(This->dataflow == eCapture)
2068         *pos = This->written_frames + pad;
2069
2070     LeaveCriticalSection(&This->lock);
2071
2072     if(qpctime){
2073         LARGE_INTEGER stamp, freq;
2074         QueryPerformanceCounter(&stamp);
2075         QueryPerformanceFrequency(&freq);
2076         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2077     }
2078
2079     return S_OK;
2080 }
2081
2082 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2083         DWORD *chars)
2084 {
2085     ACImpl *This = impl_from_IAudioClock(iface);
2086
2087     TRACE("(%p)->(%p)\n", This, chars);
2088
2089     if(!chars)
2090         return E_POINTER;
2091
2092     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2093
2094     return S_OK;
2095 }
2096
2097 static const IAudioClockVtbl AudioClock_Vtbl =
2098 {
2099     AudioClock_QueryInterface,
2100     AudioClock_AddRef,
2101     AudioClock_Release,
2102     AudioClock_GetFrequency,
2103     AudioClock_GetPosition,
2104     AudioClock_GetCharacteristics
2105 };
2106
2107 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2108         REFIID riid, void **ppv)
2109 {
2110     ACImpl *This = impl_from_IAudioClock2(iface);
2111     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2112 }
2113
2114 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2115 {
2116     ACImpl *This = impl_from_IAudioClock2(iface);
2117     return IAudioClient_AddRef(&This->IAudioClient_iface);
2118 }
2119
2120 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2121 {
2122     ACImpl *This = impl_from_IAudioClock2(iface);
2123     return IAudioClient_Release(&This->IAudioClient_iface);
2124 }
2125
2126 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2127         UINT64 *pos, UINT64 *qpctime)
2128 {
2129     ACImpl *This = impl_from_IAudioClock2(iface);
2130
2131     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2132
2133     return E_NOTIMPL;
2134 }
2135
2136 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2137 {
2138     AudioClock2_QueryInterface,
2139     AudioClock2_AddRef,
2140     AudioClock2_Release,
2141     AudioClock2_GetDevicePosition
2142 };