d3dx9_36: Implemented ID3DXConstantTable_SetFloatArray and ID3DXConstantTable_SetFloat.
[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     IMMDevice *device;
64
65     float master_vol;
66     UINT32 channel_count;
67     float *channel_vols;
68     BOOL mute;
69
70     CRITICAL_SECTION lock;
71
72     struct list entry;
73 } AudioSession;
74
75 typedef struct _AudioSessionWrapper {
76     IAudioSessionControl2 IAudioSessionControl2_iface;
77     IChannelAudioVolume IChannelAudioVolume_iface;
78     ISimpleAudioVolume ISimpleAudioVolume_iface;
79
80     LONG ref;
81
82     ACImpl *client;
83     AudioSession *session;
84 } AudioSessionWrapper;
85
86 struct ACImpl {
87     IAudioClient IAudioClient_iface;
88     IAudioRenderClient IAudioRenderClient_iface;
89     IAudioCaptureClient IAudioCaptureClient_iface;
90     IAudioClock IAudioClock_iface;
91     IAudioClock2 IAudioClock2_iface;
92     IAudioStreamVolume IAudioStreamVolume_iface;
93
94     LONG ref;
95
96     snd_pcm_t *pcm_handle;
97     snd_pcm_uframes_t period_alsa, bufsize_alsa;
98     snd_pcm_hw_params_t *hw_params; /* does not hold state between calls */
99     snd_pcm_format_t alsa_format;
100
101     IMMDevice *parent;
102
103     EDataFlow dataflow;
104     WAVEFORMATEX *fmt;
105     DWORD flags;
106     AUDCLNT_SHAREMODE share;
107     HANDLE event;
108     float *vols;
109
110     BOOL initted, started;
111     UINT64 written_frames, held_frames, tmp_buffer_frames;
112     UINT32 bufsize_frames, period_us;
113     UINT32 lcl_offs_frames; /* offs into local_buffer where valid data starts */
114
115     HANDLE timer;
116     BYTE *local_buffer, *tmp_buffer;
117     int buf_state;
118
119     CRITICAL_SECTION lock;
120
121     AudioSession *session;
122     AudioSessionWrapper *session_wrapper;
123
124     struct list entry;
125 };
126
127 enum BufferStates {
128     NOT_LOCKED = 0,
129     LOCKED_NORMAL, /* public buffer piece is from local_buffer */
130     LOCKED_WRAPPED /* public buffer piece is wrapped around, in tmp_buffer */
131 };
132
133 typedef struct _SessionMgr {
134     IAudioSessionManager2 IAudioSessionManager2_iface;
135
136     LONG ref;
137
138     IMMDevice *device;
139 } SessionMgr;
140
141 static HANDLE g_timer_q;
142
143 static CRITICAL_SECTION g_sessions_lock;
144 static struct list g_sessions = LIST_INIT(g_sessions);
145
146 static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
147 static const char defname[] = "default";
148
149 static const IAudioClientVtbl AudioClient_Vtbl;
150 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
151 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
152 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl;
153 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl;
154 static const IAudioClockVtbl AudioClock_Vtbl;
155 static const IAudioClock2Vtbl AudioClock2_Vtbl;
156 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl;
157 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl;
158 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl;
159
160 int wine_snd_pcm_recover(snd_pcm_t *pcm, int err, int silent);
161 static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client);
162
163 static inline ACImpl *impl_from_IAudioClient(IAudioClient *iface)
164 {
165     return CONTAINING_RECORD(iface, ACImpl, IAudioClient_iface);
166 }
167
168 static inline ACImpl *impl_from_IAudioRenderClient(IAudioRenderClient *iface)
169 {
170     return CONTAINING_RECORD(iface, ACImpl, IAudioRenderClient_iface);
171 }
172
173 static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface)
174 {
175     return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface);
176 }
177
178 static inline AudioSessionWrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
179 {
180     return CONTAINING_RECORD(iface, AudioSessionWrapper, IAudioSessionControl2_iface);
181 }
182
183 static inline AudioSessionWrapper *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
184 {
185     return CONTAINING_RECORD(iface, AudioSessionWrapper, ISimpleAudioVolume_iface);
186 }
187
188 static inline AudioSessionWrapper *impl_from_IChannelAudioVolume(IChannelAudioVolume *iface)
189 {
190     return CONTAINING_RECORD(iface, AudioSessionWrapper, IChannelAudioVolume_iface);
191 }
192
193 static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface)
194 {
195     return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface);
196 }
197
198 static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface)
199 {
200     return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface);
201 }
202
203 static inline ACImpl *impl_from_IAudioStreamVolume(IAudioStreamVolume *iface)
204 {
205     return CONTAINING_RECORD(iface, ACImpl, IAudioStreamVolume_iface);
206 }
207
208 static inline SessionMgr *impl_from_IAudioSessionManager2(IAudioSessionManager2 *iface)
209 {
210     return CONTAINING_RECORD(iface, SessionMgr, IAudioSessionManager2_iface);
211 }
212
213 BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
214 {
215     if(reason == DLL_PROCESS_ATTACH){
216         g_timer_q = CreateTimerQueue();
217         if(!g_timer_q)
218             return FALSE;
219
220         InitializeCriticalSection(&g_sessions_lock);
221     }
222
223     return TRUE;
224 }
225
226 static HRESULT alsa_get_card_devices(EDataFlow flow, WCHAR **ids, char **keys,
227         UINT *num, snd_ctl_t *ctl, int card, const WCHAR *cardnameW)
228 {
229     static const WCHAR dashW[] = {' ','-',' ',0};
230     int err, device;
231     snd_pcm_info_t *info;
232
233     info = HeapAlloc(GetProcessHeap(), 0, snd_pcm_info_sizeof());
234     if(!info)
235         return E_OUTOFMEMORY;
236
237     snd_pcm_info_set_subdevice(info, 0);
238     snd_pcm_info_set_stream(info,
239             flow == eRender ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE);
240
241     device = -1;
242     for(err = snd_ctl_pcm_next_device(ctl, &device); device != -1 && err >= 0;
243             err = snd_ctl_pcm_next_device(ctl, &device)){
244         const char *devname;
245
246         snd_pcm_info_set_device(info, device);
247
248         if((err = snd_ctl_pcm_info(ctl, info)) < 0){
249             if(err == -ENOENT)
250                 /* This device doesn't have the right stream direction */
251                 continue;
252
253             WARN("Failed to get info for card %d, device %d: %d (%s)\n",
254                     card, device, err, snd_strerror(err));
255             continue;
256         }
257
258         if(ids && keys){
259             DWORD len, cardlen;
260
261             devname = snd_pcm_info_get_name(info);
262             if(!devname){
263                 WARN("Unable to get device name for card %d, device %d\n", card,
264                         device);
265                 continue;
266             }
267
268             cardlen = lstrlenW(cardnameW);
269             len = MultiByteToWideChar(CP_UNIXCP, 0, devname, -1, NULL, 0);
270             len += lstrlenW(dashW);
271             len += cardlen;
272             ids[*num] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
273             if(!ids[*num]){
274                 HeapFree(GetProcessHeap(), 0, info);
275                 return E_OUTOFMEMORY;
276             }
277             memcpy(ids[*num], cardnameW, cardlen * sizeof(WCHAR));
278             memcpy(ids[*num] + cardlen, dashW, lstrlenW(dashW) * sizeof(WCHAR));
279             cardlen += lstrlenW(dashW);
280             MultiByteToWideChar(CP_UNIXCP, 0, devname, -1, ids[*num] + cardlen,
281                     len - cardlen);
282
283             keys[*num] = HeapAlloc(GetProcessHeap(), 0, 32);
284             if(!keys[*num]){
285                 HeapFree(GetProcessHeap(), 0, info);
286                 HeapFree(GetProcessHeap(), 0, ids[*num]);
287                 return E_OUTOFMEMORY;
288             }
289             sprintf(keys[*num], "hw:%d,%d", card, device);
290         }
291
292         ++(*num);
293     }
294
295     HeapFree(GetProcessHeap(), 0, info);
296
297     if(err != 0)
298         WARN("Got a failure during device enumeration on card %d: %d (%s)\n",
299                 card, err, snd_strerror(err));
300
301     return S_OK;
302 }
303
304 static HRESULT alsa_enum_devices(EDataFlow flow, WCHAR **ids, char **keys,
305         UINT *num)
306 {
307     int err, card;
308
309     card = -1;
310     *num = 0;
311     for(err = snd_card_next(&card); card != -1 && err >= 0;
312             err = snd_card_next(&card)){
313         char cardpath[64];
314         const char *cardname;
315         WCHAR *cardnameW;
316         snd_ctl_t *ctl;
317         DWORD len;
318
319         sprintf(cardpath, "hw:%u", card);
320
321         if((err = snd_ctl_open(&ctl, cardpath, 0)) < 0){
322             WARN("Unable to open ctl for ALSA device %s: %d (%s)\n", cardpath,
323                     err, snd_strerror(err));
324             continue;
325         }
326
327         if((err = snd_card_get_name(card, (char **)&cardname)) < 0){
328             WARN("Unable to get card name for ALSA device %s: %d (%s)\n",
329                     cardpath, err, snd_strerror(err));
330             /* FIXME: Should be localized */
331             cardname = "Unknown soundcard";
332         }
333
334         len = MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, NULL, 0);
335         cardnameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
336         if(!cardnameW){
337             snd_ctl_close(ctl);
338             return E_OUTOFMEMORY;
339         }
340         MultiByteToWideChar(CP_UNIXCP, 0, cardname, -1, cardnameW, len);
341
342         alsa_get_card_devices(flow, ids, keys, num, ctl, card, cardnameW);
343
344         HeapFree(GetProcessHeap(), 0, cardnameW);
345
346         snd_ctl_close(ctl);
347     }
348
349     if(err != 0)
350         WARN("Got a failure during card enumeration: %d (%s)\n",
351                 err, snd_strerror(err));
352
353     return S_OK;
354 }
355
356 HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, char ***keys,
357         UINT *num, UINT *def_index)
358 {
359     HRESULT hr;
360
361     TRACE("%d %p %p %p %p\n", flow, ids, keys, num, def_index);
362
363     hr = alsa_enum_devices(flow, NULL, NULL, num);
364     if(FAILED(hr))
365         return hr;
366
367     *ids = HeapAlloc(GetProcessHeap(), 0, (*num + 1) * sizeof(WCHAR *));
368     *keys = HeapAlloc(GetProcessHeap(), 0, (*num + 1) * sizeof(char *));
369     if(!*ids || !*keys){
370         HeapFree(GetProcessHeap(), 0, *ids);
371         HeapFree(GetProcessHeap(), 0, *keys);
372         return E_OUTOFMEMORY;
373     }
374
375     (*ids)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
376     memcpy((*ids)[0], defaultW, sizeof(defaultW));
377     (*keys)[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(defname));
378     memcpy((*keys)[0], defname, sizeof(defname));
379     *def_index = 0;
380
381     hr = alsa_enum_devices(flow, (*ids) + 1, (*keys) + 1, num);
382     if(FAILED(hr)){
383         int i;
384         for(i = 0; i < *num; ++i){
385             HeapFree(GetProcessHeap(), 0, (*ids)[i]);
386             HeapFree(GetProcessHeap(), 0, (*keys)[i]);
387         }
388         HeapFree(GetProcessHeap(), 0, *ids);
389         HeapFree(GetProcessHeap(), 0, *keys);
390         return E_OUTOFMEMORY;
391     }
392
393     ++(*num); /* for default device */
394
395     return S_OK;
396 }
397
398 HRESULT WINAPI AUDDRV_GetAudioEndpoint(const char *key, IMMDevice *dev,
399         EDataFlow dataflow, IAudioClient **out)
400 {
401     ACImpl *This;
402     int err;
403     snd_pcm_stream_t stream;
404
405     TRACE("\"%s\" %p %d %p\n", key, dev, dataflow, out);
406
407     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
408     if(!This)
409         return E_OUTOFMEMORY;
410
411     This->IAudioClient_iface.lpVtbl = &AudioClient_Vtbl;
412     This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
413     This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl;
414     This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl;
415     This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl;
416     This->IAudioStreamVolume_iface.lpVtbl = &AudioStreamVolume_Vtbl;
417
418     if(dataflow == eRender)
419         stream = SND_PCM_STREAM_PLAYBACK;
420     else if(dataflow == eCapture)
421         stream = SND_PCM_STREAM_CAPTURE;
422     else{
423         HeapFree(GetProcessHeap(), 0, This);
424         return E_UNEXPECTED;
425     }
426
427     This->dataflow = dataflow;
428     if((err = snd_pcm_open(&This->pcm_handle, key, stream,
429                     SND_PCM_NONBLOCK)) < 0){
430         HeapFree(GetProcessHeap(), 0, This);
431         WARN("Unable to open PCM \"%s\": %d (%s)\n", key, err,
432                 snd_strerror(err));
433         return E_FAIL;
434     }
435
436     This->hw_params = HeapAlloc(GetProcessHeap(), 0,
437             snd_pcm_hw_params_sizeof());
438     if(!This->hw_params){
439         HeapFree(GetProcessHeap(), 0, This);
440         snd_pcm_close(This->pcm_handle);
441         return E_OUTOFMEMORY;
442     }
443
444     InitializeCriticalSection(&This->lock);
445
446     This->parent = dev;
447     IMMDevice_AddRef(This->parent);
448
449     *out = &This->IAudioClient_iface;
450     IAudioClient_AddRef(&This->IAudioClient_iface);
451
452     return S_OK;
453 }
454
455 static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient *iface,
456         REFIID riid, void **ppv)
457 {
458     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
459
460     if(!ppv)
461         return E_POINTER;
462     *ppv = NULL;
463     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClient))
464         *ppv = iface;
465     if(*ppv){
466         IUnknown_AddRef((IUnknown*)*ppv);
467         return S_OK;
468     }
469     WARN("Unknown interface %s\n", debugstr_guid(riid));
470     return E_NOINTERFACE;
471 }
472
473 static ULONG WINAPI AudioClient_AddRef(IAudioClient *iface)
474 {
475     ACImpl *This = impl_from_IAudioClient(iface);
476     ULONG ref;
477     ref = InterlockedIncrement(&This->ref);
478     TRACE("(%p) Refcount now %u\n", This, ref);
479     return ref;
480 }
481
482 static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
483 {
484     ACImpl *This = impl_from_IAudioClient(iface);
485     ULONG ref;
486     ref = InterlockedDecrement(&This->ref);
487     TRACE("(%p) Refcount now %u\n", This, ref);
488     if(!ref){
489         IAudioClient_Stop(iface);
490         IMMDevice_Release(This->parent);
491         DeleteCriticalSection(&This->lock);
492         snd_pcm_drop(This->pcm_handle);
493         snd_pcm_close(This->pcm_handle);
494         if(This->initted){
495             EnterCriticalSection(&g_sessions_lock);
496             list_remove(&This->entry);
497             LeaveCriticalSection(&g_sessions_lock);
498         }
499         HeapFree(GetProcessHeap(), 0, This->vols);
500         HeapFree(GetProcessHeap(), 0, This->local_buffer);
501         HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
502         HeapFree(GetProcessHeap(), 0, This->hw_params);
503         CoTaskMemFree(This->fmt);
504         HeapFree(GetProcessHeap(), 0, This);
505     }
506     return ref;
507 }
508
509 static void dump_fmt(const WAVEFORMATEX *fmt)
510 {
511     TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
512     switch(fmt->wFormatTag){
513     case WAVE_FORMAT_PCM:
514         TRACE("WAVE_FORMAT_PCM");
515         break;
516     case WAVE_FORMAT_IEEE_FLOAT:
517         TRACE("WAVE_FORMAT_IEEE_FLOAT");
518         break;
519     case WAVE_FORMAT_EXTENSIBLE:
520         TRACE("WAVE_FORMAT_EXTENSIBLE");
521         break;
522     default:
523         TRACE("Unknown");
524         break;
525     }
526     TRACE(")\n");
527
528     TRACE("nChannels: %u\n", fmt->nChannels);
529     TRACE("nSamplesPerSec: %u\n", fmt->nSamplesPerSec);
530     TRACE("nAvgBytesPerSec: %u\n", fmt->nAvgBytesPerSec);
531     TRACE("nBlockAlign: %u\n", fmt->nBlockAlign);
532     TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample);
533     TRACE("cbSize: %u\n", fmt->cbSize);
534
535     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
536         WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt;
537         TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask);
538         TRACE("Samples: %04x\n", fmtex->Samples.wReserved);
539         TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat));
540     }
541 }
542
543 static WAVEFORMATEX *clone_format(const WAVEFORMATEX *fmt)
544 {
545     WAVEFORMATEX *ret;
546     size_t size;
547
548     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
549         size = sizeof(WAVEFORMATEXTENSIBLE);
550     else
551         size = sizeof(WAVEFORMATEX);
552
553     ret = CoTaskMemAlloc(size);
554     if(!ret)
555         return NULL;
556
557     memcpy(ret, fmt, size);
558
559     ret->cbSize = size - sizeof(WAVEFORMATEX);
560
561     return ret;
562 }
563
564 static void session_init_vols(AudioSession *session, UINT channels)
565 {
566     if(session->channel_count < channels){
567         UINT i;
568
569         if(session->channel_vols)
570             session->channel_vols = HeapReAlloc(GetProcessHeap(), 0,
571                     session->channel_vols, sizeof(float) * channels);
572         else
573             session->channel_vols = HeapAlloc(GetProcessHeap(), 0,
574                     sizeof(float) * channels);
575         if(!session->channel_vols)
576             return;
577
578         for(i = session->channel_count; i < channels; ++i)
579             session->channel_vols[i] = 1.f;
580
581         session->channel_count = channels;
582     }
583 }
584
585 static AudioSession *create_session(const GUID *guid, IMMDevice *device,
586         UINT num_channels)
587 {
588     AudioSession *ret;
589
590     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AudioSession));
591     if(!ret)
592         return NULL;
593
594     memcpy(&ret->guid, guid, sizeof(GUID));
595
596     ret->device = device;
597
598     list_init(&ret->clients);
599
600     list_add_head(&g_sessions, &ret->entry);
601
602     InitializeCriticalSection(&ret->lock);
603
604     session_init_vols(ret, num_channels);
605
606     ret->master_vol = 1.f;
607
608     return ret;
609 }
610
611 /* if channels == 0, then this will return or create a session with
612  * matching dataflow and GUID. otherwise, channels must also match */
613 static HRESULT get_audio_session(const GUID *sessionguid,
614         IMMDevice *device, UINT channels, AudioSession **out)
615 {
616     AudioSession *session;
617
618     if(!sessionguid || IsEqualGUID(sessionguid, &GUID_NULL)){
619         *out = create_session(&GUID_NULL, device, channels);
620         if(!*out)
621             return E_OUTOFMEMORY;
622
623         return S_OK;
624     }
625
626     *out = NULL;
627     LIST_FOR_EACH_ENTRY(session, &g_sessions, AudioSession, entry){
628         if(session->device == device &&
629                 IsEqualGUID(sessionguid, &session->guid)){
630             session_init_vols(session, channels);
631             *out = session;
632             break;
633         }
634     }
635
636     if(!*out){
637         *out = create_session(sessionguid, device, channels);
638         if(!*out)
639             return E_OUTOFMEMORY;
640     }
641
642     return S_OK;
643 }
644
645 static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
646         AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
647         REFERENCE_TIME period, const WAVEFORMATEX *fmt,
648         const GUID *sessionguid)
649 {
650     ACImpl *This = impl_from_IAudioClient(iface);
651     snd_pcm_sw_params_t *sw_params = NULL;
652     snd_pcm_format_t format;
653     snd_pcm_uframes_t boundary;
654     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
655     unsigned int time_us, rate;
656     int err, i;
657     HRESULT hr = S_OK;
658
659     TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
660           wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
661
662     if(!fmt)
663         return E_POINTER;
664
665     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
666         return AUDCLNT_E_NOT_INITIALIZED;
667
668     if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
669                 AUDCLNT_STREAMFLAGS_LOOPBACK |
670                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
671                 AUDCLNT_STREAMFLAGS_NOPERSIST |
672                 AUDCLNT_STREAMFLAGS_RATEADJUST |
673                 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
674                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
675                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)){
676         TRACE("Unknown flags: %08x\n", flags);
677         return E_INVALIDARG;
678     }
679
680     EnterCriticalSection(&This->lock);
681
682     if(This->initted){
683         LeaveCriticalSection(&This->lock);
684         return AUDCLNT_E_ALREADY_INITIALIZED;
685     }
686
687     dump_fmt(fmt);
688
689     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
690         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
691         hr = E_FAIL;
692         goto exit;
693     }
694
695     if((err = snd_pcm_hw_params_set_access(This->pcm_handle, This->hw_params,
696                 SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
697         WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
698         hr = E_FAIL;
699         goto exit;
700     }
701
702     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
703             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
704              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
705         if(fmt->wBitsPerSample == 8)
706             format = SND_PCM_FORMAT_U8;
707         else if(fmt->wBitsPerSample == 16)
708             format = SND_PCM_FORMAT_S16_LE;
709         else if(fmt->wBitsPerSample == 24)
710             format = SND_PCM_FORMAT_S24_3LE;
711         else if(fmt->wBitsPerSample == 32)
712             format = SND_PCM_FORMAT_S32_LE;
713         else{
714             WARN("Unsupported bit depth: %u\n", fmt->wBitsPerSample);
715             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
716             goto exit;
717         }
718     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
719             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
720              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
721         if(fmt->wBitsPerSample == 32)
722             format = SND_PCM_FORMAT_FLOAT_LE;
723         else if(fmt->wBitsPerSample == 64)
724             format = SND_PCM_FORMAT_FLOAT64_LE;
725         else{
726             WARN("Unsupported float size: %u\n", fmt->wBitsPerSample);
727             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
728             goto exit;
729         }
730     }else{
731         WARN("Unknown wave format: %04x\n", fmt->wFormatTag);
732         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
733         goto exit;
734     }
735
736     if((err = snd_pcm_hw_params_set_format(This->pcm_handle, This->hw_params,
737                 format)) < 0){
738         WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
739                 snd_strerror(err));
740         hr = E_FAIL;
741         goto exit;
742     }
743
744     This->alsa_format = format;
745
746     rate = fmt->nSamplesPerSec;
747     if((err = snd_pcm_hw_params_set_rate_near(This->pcm_handle, This->hw_params,
748                 &rate, NULL)) < 0){
749         WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
750                 snd_strerror(err));
751         hr = E_FAIL;
752         goto exit;
753     }
754
755     if((err = snd_pcm_hw_params_set_channels(This->pcm_handle, This->hw_params,
756                 fmt->nChannels)) < 0){
757         WARN("Unable to set channels to %u: %d (%s)\n", fmt->nChannels, err,
758                 snd_strerror(err));
759         hr = E_FAIL;
760         goto exit;
761     }
762
763     time_us = MinimumPeriod / 10;
764     if((err = snd_pcm_hw_params_set_period_time_near(This->pcm_handle,
765                 This->hw_params, &time_us, NULL)) < 0){
766         WARN("Unable to set max period time to %u: %d (%s)\n", time_us,
767                 err, snd_strerror(err));
768         hr = E_FAIL;
769         goto exit;
770     }
771
772     if((err = snd_pcm_hw_params(This->pcm_handle, This->hw_params)) < 0){
773         WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
774         hr = E_FAIL;
775         goto exit;
776     }
777
778     sw_params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_sw_params_sizeof());
779     if(!sw_params){
780         hr = E_OUTOFMEMORY;
781         goto exit;
782     }
783
784     if((err = snd_pcm_sw_params_current(This->pcm_handle, sw_params)) < 0){
785         WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
786         hr = E_FAIL;
787         goto exit;
788     }
789
790     This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec);
791     This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
792             This->bufsize_frames * fmt->nBlockAlign);
793     if(!This->local_buffer){
794         hr = E_OUTOFMEMORY;
795         goto exit;
796     }
797     if (fmt->wBitsPerSample == 8)
798         memset(This->local_buffer, 128, This->bufsize_frames * fmt->nBlockAlign);
799     else
800         memset(This->local_buffer, 0, This->bufsize_frames * fmt->nBlockAlign);
801
802     if((err = snd_pcm_sw_params_get_boundary(sw_params, &boundary)) < 0){
803         WARN("Unable to get boundary: %d (%s)\n", err, snd_strerror(err));
804         hr = E_FAIL;
805         goto exit;
806     }
807
808     if((err = snd_pcm_sw_params_set_start_threshold(This->pcm_handle,
809                 sw_params, boundary)) < 0){
810         WARN("Unable to set start threshold to %lx: %d (%s)\n", boundary, err,
811                 snd_strerror(err));
812         hr = E_FAIL;
813         goto exit;
814     }
815
816     if((err = snd_pcm_sw_params_set_stop_threshold(This->pcm_handle,
817                 sw_params, boundary)) < 0){
818         WARN("Unable to set stop threshold to %lx: %d (%s)\n", boundary, err,
819                 snd_strerror(err));
820         hr = E_FAIL;
821         goto exit;
822     }
823
824     if((err = snd_pcm_sw_params_set_avail_min(This->pcm_handle,
825                 sw_params, 0)) < 0){
826         WARN("Unable to set avail min to 0: %d (%s)\n", err, snd_strerror(err));
827         hr = E_FAIL;
828         goto exit;
829     }
830
831     if((err = snd_pcm_sw_params(This->pcm_handle, sw_params)) < 0){
832         WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
833         hr = E_FAIL;
834         goto exit;
835     }
836
837     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
838         WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
839         hr = E_FAIL;
840         goto exit;
841     }
842
843     if((err = snd_pcm_hw_params_get_buffer_size(This->hw_params,
844                     &This->bufsize_alsa)) < 0){
845         WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
846         hr = E_FAIL;
847         goto exit;
848     }
849
850     if((err = snd_pcm_hw_params_get_period_size(This->hw_params,
851                     &This->period_alsa, NULL)) < 0){
852         WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
853         hr = E_FAIL;
854         goto exit;
855     }
856
857     if((err = snd_pcm_hw_params_get_period_time(This->hw_params,
858                     &This->period_us, NULL)) < 0){
859         WARN("Unable to get period time: %d (%s)\n", err, snd_strerror(err));
860         hr = E_FAIL;
861         goto exit;
862     }
863
864     This->fmt = clone_format(fmt);
865     if(!This->fmt){
866         hr = E_OUTOFMEMORY;
867         goto exit;
868     }
869
870     This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
871     if(!This->vols){
872         hr = E_OUTOFMEMORY;
873         goto exit;
874     }
875
876     for(i = 0; i < fmt->nChannels; ++i)
877         This->vols[i] = 1.f;
878
879     This->share = mode;
880     This->flags = flags;
881
882     EnterCriticalSection(&g_sessions_lock);
883
884     hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
885             &This->session);
886     if(FAILED(hr)){
887         LeaveCriticalSection(&g_sessions_lock);
888         goto exit;
889     }
890
891     list_add_tail(&This->session->clients, &This->entry);
892
893     LeaveCriticalSection(&g_sessions_lock);
894
895     This->initted = TRUE;
896
897 exit:
898     HeapFree(GetProcessHeap(), 0, sw_params);
899     if(FAILED(hr)){
900         if(This->local_buffer){
901             HeapFree(GetProcessHeap(), 0, This->local_buffer);
902             This->local_buffer = NULL;
903         }
904         if(This->fmt){
905             CoTaskMemFree(This->fmt);
906             This->fmt = NULL;
907         }
908         if(This->vols){
909             HeapFree(GetProcessHeap(), 0, This->vols);
910             This->vols = NULL;
911         }
912     }
913
914     LeaveCriticalSection(&This->lock);
915
916     return hr;
917 }
918
919 static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface,
920         UINT32 *out)
921 {
922     ACImpl *This = impl_from_IAudioClient(iface);
923
924     TRACE("(%p)->(%p)\n", This, out);
925
926     if(!out)
927         return E_POINTER;
928
929     EnterCriticalSection(&This->lock);
930
931     if(!This->initted){
932         LeaveCriticalSection(&This->lock);
933         return AUDCLNT_E_NOT_INITIALIZED;
934     }
935
936     *out = This->bufsize_frames;
937
938     LeaveCriticalSection(&This->lock);
939
940     return S_OK;
941 }
942
943 static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
944         REFERENCE_TIME *latency)
945 {
946     ACImpl *This = impl_from_IAudioClient(iface);
947
948     TRACE("(%p)->(%p)\n", This, latency);
949
950     if(!latency)
951         return E_POINTER;
952
953     EnterCriticalSection(&This->lock);
954
955     if(!This->initted){
956         LeaveCriticalSection(&This->lock);
957         return AUDCLNT_E_NOT_INITIALIZED;
958     }
959
960     LeaveCriticalSection(&This->lock);
961
962     *latency = 500000;
963
964     return S_OK;
965 }
966
967 static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
968         UINT32 *out)
969 {
970     ACImpl *This = impl_from_IAudioClient(iface);
971
972     TRACE("(%p)->(%p)\n", This, out);
973
974     if(!out)
975         return E_POINTER;
976
977     EnterCriticalSection(&This->lock);
978
979     if(!This->initted){
980         LeaveCriticalSection(&This->lock);
981         return AUDCLNT_E_NOT_INITIALIZED;
982     }
983
984     if(This->dataflow == eRender){
985         snd_pcm_sframes_t avail_frames;
986
987         avail_frames = snd_pcm_avail_update(This->pcm_handle);
988
989         if(This->bufsize_alsa < avail_frames){
990             WARN("Xrun detected\n");
991             *out = This->held_frames;
992         }else
993             *out = This->bufsize_alsa - avail_frames + This->held_frames;
994     }else if(This->dataflow == eCapture){
995         *out = This->held_frames;
996     }else{
997         LeaveCriticalSection(&This->lock);
998         return E_UNEXPECTED;
999     }
1000
1001     LeaveCriticalSection(&This->lock);
1002
1003     return S_OK;
1004 }
1005
1006 static DWORD get_channel_mask(unsigned int channels)
1007 {
1008     switch(channels){
1009     case 0:
1010         return 0;
1011     case 1:
1012         return SPEAKER_FRONT_CENTER;
1013     case 2:
1014         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1015     case 3:
1016         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
1017             SPEAKER_LOW_FREQUENCY;
1018     case 4:
1019         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
1020             SPEAKER_BACK_RIGHT;
1021     case 5:
1022         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
1023             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
1024     case 6:
1025         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
1026             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER;
1027     case 7:
1028         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
1029             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER |
1030             SPEAKER_BACK_CENTER;
1031     }
1032     FIXME("Unknown speaker configuration: %u\n", channels);
1033     return 0;
1034 }
1035
1036 static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
1037         AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *fmt,
1038         WAVEFORMATEX **out)
1039 {
1040     ACImpl *This = impl_from_IAudioClient(iface);
1041     snd_pcm_format_mask_t *formats = NULL;
1042     HRESULT hr = S_OK;
1043     WAVEFORMATEX *closest = NULL;
1044     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
1045     unsigned int max = 0, min = 0;
1046     int err;
1047
1048     TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out);
1049
1050     if(!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out))
1051         return E_POINTER;
1052
1053     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
1054         return E_INVALIDARG;
1055
1056     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1057             fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
1058         return E_INVALIDARG;
1059
1060     dump_fmt(fmt);
1061
1062     EnterCriticalSection(&This->lock);
1063
1064     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
1065         hr = E_FAIL;
1066         goto exit;
1067     }
1068
1069     formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1070             snd_pcm_format_mask_sizeof());
1071     if(!formats){
1072         hr = E_OUTOFMEMORY;
1073         goto exit;
1074     }
1075
1076     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
1077
1078     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
1079             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1080              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
1081         switch(fmt->wBitsPerSample){
1082         case 8:
1083             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
1084                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1085                 goto exit;
1086             }
1087             break;
1088         case 16:
1089             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
1090                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1091                 goto exit;
1092             }
1093             break;
1094         case 24:
1095             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
1096                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1097                 goto exit;
1098             }
1099             break;
1100         case 32:
1101             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
1102                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1103                 goto exit;
1104             }
1105             break;
1106         default:
1107             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1108             goto exit;
1109         }
1110     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
1111             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1112              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
1113         switch(fmt->wBitsPerSample){
1114         case 32:
1115             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
1116                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1117                 goto exit;
1118             }
1119             break;
1120         case 64:
1121             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT64_LE)){
1122                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1123                 goto exit;
1124             }
1125             break;
1126         default:
1127             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1128             goto exit;
1129         }
1130     }else{
1131         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1132         goto exit;
1133     }
1134
1135     closest = clone_format(fmt);
1136     if(!closest){
1137         hr = E_OUTOFMEMORY;
1138         goto exit;
1139     }
1140
1141     if((err = snd_pcm_hw_params_get_rate_min(This->hw_params, &min, NULL)) < 0){
1142         hr = E_FAIL;
1143         WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err));
1144         goto exit;
1145     }
1146
1147     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max, NULL)) < 0){
1148         hr = E_FAIL;
1149         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
1150         goto exit;
1151     }
1152
1153     if(fmt->nSamplesPerSec < min || fmt->nSamplesPerSec > max){
1154         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1155         goto exit;
1156     }
1157
1158     if((err = snd_pcm_hw_params_get_channels_min(This->hw_params, &min)) < 0){
1159         hr = E_FAIL;
1160         WARN("Unable to get min channels: %d (%s)\n", err, snd_strerror(err));
1161         goto exit;
1162     }
1163
1164     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params, &max)) < 0){
1165         hr = E_FAIL;
1166         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
1167         goto exit;
1168     }
1169     if(max > 7)
1170         max = 2;
1171     if(fmt->nChannels > max){
1172         hr = S_FALSE;
1173         closest->nChannels = max;
1174     }else if(fmt->nChannels < min){
1175         hr = S_FALSE;
1176         closest->nChannels = min;
1177     }
1178
1179     if(closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
1180         DWORD mask = get_channel_mask(closest->nChannels);
1181
1182         ((WAVEFORMATEXTENSIBLE*)closest)->dwChannelMask = mask;
1183
1184         if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1185                 fmtex->dwChannelMask != mask)
1186             hr = S_FALSE;
1187     }
1188
1189 exit:
1190     LeaveCriticalSection(&This->lock);
1191     HeapFree(GetProcessHeap(), 0, formats);
1192
1193     if(hr == S_OK || !out){
1194         CoTaskMemFree(closest);
1195         if(out)
1196             *out = NULL;
1197     }else if(closest){
1198         closest->nBlockAlign =
1199             closest->nChannels * closest->wBitsPerSample / 8;
1200         closest->nAvgBytesPerSec =
1201             closest->nBlockAlign * closest->nSamplesPerSec;
1202         *out = closest;
1203     }
1204
1205     TRACE("returning: %08x\n", hr);
1206     return hr;
1207 }
1208
1209 static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface,
1210         WAVEFORMATEX **pwfx)
1211 {
1212     ACImpl *This = impl_from_IAudioClient(iface);
1213     WAVEFORMATEXTENSIBLE *fmt;
1214     snd_pcm_format_mask_t *formats;
1215     unsigned int max_rate, max_channels;
1216     int err;
1217     HRESULT hr = S_OK;
1218
1219     TRACE("(%p)->(%p)\n", This, pwfx);
1220
1221     if(!pwfx)
1222         return E_POINTER;
1223     *pwfx = NULL;
1224
1225     fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
1226     if(!fmt)
1227         return E_OUTOFMEMORY;
1228
1229     formats = HeapAlloc(GetProcessHeap(), 0, snd_pcm_format_mask_sizeof());
1230     if(!formats){
1231         CoTaskMemFree(fmt);
1232         return E_OUTOFMEMORY;
1233     }
1234
1235     EnterCriticalSection(&This->lock);
1236
1237     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
1238         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
1239         hr = E_FAIL;
1240         goto exit;
1241     }
1242
1243     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
1244
1245     fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1246     if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
1247         fmt->Format.wBitsPerSample = 32;
1248         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
1249     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
1250         fmt->Format.wBitsPerSample = 16;
1251         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1252     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
1253         fmt->Format.wBitsPerSample = 8;
1254         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1255     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
1256         fmt->Format.wBitsPerSample = 32;
1257         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1258     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
1259         fmt->Format.wBitsPerSample = 24;
1260         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1261     }else{
1262         ERR("Didn't recognize any available ALSA formats\n");
1263         hr = E_FAIL;
1264         goto exit;
1265     }
1266
1267     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params,
1268                     &max_channels)) < 0){
1269         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
1270         hr = E_FAIL;
1271         goto exit;
1272     }
1273
1274     if(max_channels > 2){
1275         FIXME("Don't know what to do with %u channels, pretending there's "
1276                 "only 2 channels\n", max_channels);
1277         fmt->Format.nChannels = 2;
1278     }else
1279         fmt->Format.nChannels = max_channels;
1280
1281     fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
1282
1283     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max_rate,
1284                     NULL)) < 0){
1285         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
1286         hr = E_FAIL;
1287         goto exit;
1288     }
1289
1290     if(max_rate >= 48000)
1291         fmt->Format.nSamplesPerSec = 48000;
1292     else if(max_rate >= 44100)
1293         fmt->Format.nSamplesPerSec = 44100;
1294     else if(max_rate >= 22050)
1295         fmt->Format.nSamplesPerSec = 22050;
1296     else if(max_rate >= 11025)
1297         fmt->Format.nSamplesPerSec = 11025;
1298     else if(max_rate >= 8000)
1299         fmt->Format.nSamplesPerSec = 8000;
1300     else{
1301         ERR("Unknown max rate: %u\n", max_rate);
1302         hr = E_FAIL;
1303         goto exit;
1304     }
1305
1306     fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
1307             fmt->Format.nChannels) / 8;
1308     fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
1309         fmt->Format.nBlockAlign;
1310
1311     fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
1312     fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1313
1314     dump_fmt((WAVEFORMATEX*)fmt);
1315     *pwfx = (WAVEFORMATEX*)fmt;
1316
1317 exit:
1318     LeaveCriticalSection(&This->lock);
1319     if(FAILED(hr))
1320         CoTaskMemFree(fmt);
1321     HeapFree(GetProcessHeap(), 0, formats);
1322
1323     return hr;
1324 }
1325
1326 static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
1327         REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
1328 {
1329     ACImpl *This = impl_from_IAudioClient(iface);
1330
1331     TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
1332
1333     if(!defperiod && !minperiod)
1334         return E_POINTER;
1335
1336     if(defperiod)
1337         *defperiod = DefaultPeriod;
1338     if(minperiod)
1339         *minperiod = MinimumPeriod;
1340
1341     return S_OK;
1342 }
1343
1344 static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
1345         snd_pcm_uframes_t frames, ACImpl *This)
1346 {
1347     snd_pcm_sframes_t written;
1348
1349     if(This->session->mute){
1350         int err;
1351         if((err = snd_pcm_format_set_silence(This->alsa_format, buf,
1352                         frames * This->fmt->nChannels)) < 0)
1353             WARN("Setting buffer to silence failed: %d (%s)\n", err,
1354                     snd_strerror(err));
1355     }
1356
1357     written = snd_pcm_writei(handle, buf, frames);
1358     if(written < 0){
1359         int ret;
1360
1361         if(written == -EAGAIN)
1362             /* buffer full */
1363             return 0;
1364
1365         WARN("writei failed, recovering: %ld (%s)\n", written,
1366                 snd_strerror(written));
1367
1368         ret = wine_snd_pcm_recover(handle, written, 0);
1369         if(ret < 0){
1370             WARN("Could not recover: %d (%s)\n", ret, snd_strerror(ret));
1371             return ret;
1372         }
1373
1374         written = snd_pcm_writei(handle, buf, frames);
1375     }
1376
1377     return written;
1378 }
1379
1380 static void alsa_write_data(ACImpl *This)
1381 {
1382     snd_pcm_sframes_t written;
1383     snd_pcm_uframes_t to_write;
1384     BYTE *buf =
1385         This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
1386
1387     if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
1388         to_write = This->bufsize_frames - This->lcl_offs_frames;
1389     else
1390         to_write = This->held_frames;
1391
1392     written = alsa_write_best_effort(This->pcm_handle, buf, to_write, This);
1393     if(written < 0){
1394         WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1395         return;
1396     }
1397
1398     This->lcl_offs_frames += written;
1399     This->lcl_offs_frames %= This->bufsize_frames;
1400     This->held_frames -= written;
1401
1402     if(written < to_write){
1403         /* ALSA buffer probably full */
1404         return;
1405     }
1406
1407     if(This->held_frames){
1408         /* wrapped and have some data back at the start to write */
1409         written = alsa_write_best_effort(This->pcm_handle, This->local_buffer,
1410                 This->held_frames, This);
1411         if(written < 0){
1412             WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1413             return;
1414         }
1415
1416         This->lcl_offs_frames += written;
1417         This->lcl_offs_frames %= This->bufsize_frames;
1418         This->held_frames -= written;
1419     }
1420 }
1421
1422 static void alsa_read_data(ACImpl *This)
1423 {
1424     snd_pcm_sframes_t pos, readable, nread;
1425
1426     pos = (This->held_frames + This->lcl_offs_frames) % This->bufsize_frames;
1427     readable = This->bufsize_frames - pos;
1428
1429     nread = snd_pcm_readi(This->pcm_handle,
1430             This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1431     if(nread < 0){
1432         int ret;
1433
1434         WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
1435
1436         ret = wine_snd_pcm_recover(This->pcm_handle, nread, 0);
1437         if(ret < 0){
1438             WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
1439             return;
1440         }
1441
1442         nread = snd_pcm_readi(This->pcm_handle,
1443                 This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1444         if(nread < 0){
1445             WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
1446             return;
1447         }
1448     }
1449
1450     if(This->session->mute){
1451         int err;
1452         if((err = snd_pcm_format_set_silence(This->alsa_format,
1453                         This->local_buffer + pos * This->fmt->nBlockAlign,
1454                         nread)) < 0)
1455             WARN("Setting buffer to silence failed: %d (%s)\n", err,
1456                     snd_strerror(err));
1457     }
1458
1459     This->held_frames += nread;
1460
1461     if(This->held_frames > This->bufsize_frames){
1462         WARN("Overflow of unread data\n");
1463         This->lcl_offs_frames += This->held_frames;
1464         This->lcl_offs_frames %= This->bufsize_frames;
1465         This->held_frames = This->bufsize_frames;
1466     }
1467 }
1468
1469 static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
1470 {
1471     ACImpl *This = user;
1472
1473     EnterCriticalSection(&This->lock);
1474
1475     if(This->started){
1476         if(This->dataflow == eRender && This->held_frames)
1477             alsa_write_data(This);
1478         else if(This->dataflow == eCapture)
1479             alsa_read_data(This);
1480
1481         if(This->event)
1482             SetEvent(This->event);
1483     }
1484
1485     LeaveCriticalSection(&This->lock);
1486 }
1487
1488 static HRESULT alsa_consider_start(ACImpl *This)
1489 {
1490     snd_pcm_sframes_t avail;
1491     int err;
1492
1493     avail = snd_pcm_avail_update(This->pcm_handle);
1494     if(avail < 0){
1495         WARN("Unable to get avail_update: %ld (%s)\n", avail,
1496                 snd_strerror(avail));
1497         return E_FAIL;
1498     }
1499
1500     if(This->period_alsa < This->bufsize_alsa - avail){
1501         if((err = snd_pcm_start(This->pcm_handle)) < 0){
1502             WARN("Start failed: %d (%s), state: %d\n", err, snd_strerror(err),
1503                     snd_pcm_state(This->pcm_handle));
1504             return E_FAIL;
1505         }
1506
1507         return S_OK;
1508     }
1509
1510     return S_FALSE;
1511 }
1512
1513 static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
1514 {
1515     ACImpl *This = impl_from_IAudioClient(iface);
1516     DWORD period_ms;
1517     HRESULT hr;
1518
1519     TRACE("(%p)\n", This);
1520
1521     EnterCriticalSection(&This->lock);
1522
1523     if(!This->initted){
1524         LeaveCriticalSection(&This->lock);
1525         return AUDCLNT_E_NOT_INITIALIZED;
1526     }
1527
1528     if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
1529         LeaveCriticalSection(&This->lock);
1530         return AUDCLNT_E_EVENTHANDLE_NOT_SET;
1531     }
1532
1533     if(This->started){
1534         LeaveCriticalSection(&This->lock);
1535         return AUDCLNT_E_NOT_STOPPED;
1536     }
1537
1538     hr = alsa_consider_start(This);
1539     if(FAILED(hr)){
1540         LeaveCriticalSection(&This->lock);
1541         return hr;
1542     }
1543
1544     period_ms = This->period_us / 1000;
1545     if(!period_ms)
1546         period_ms = 10;
1547
1548     if(This->dataflow == eCapture){
1549         /* dump any data that might be leftover in the ALSA capture buffer */
1550         snd_pcm_readi(This->pcm_handle, This->local_buffer,
1551                 This->bufsize_frames);
1552     }
1553
1554     if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
1555             This, 0, period_ms, WT_EXECUTEINTIMERTHREAD)){
1556         LeaveCriticalSection(&This->lock);
1557         WARN("Unable to create timer: %u\n", GetLastError());
1558         return E_FAIL;
1559     }
1560
1561     This->started = TRUE;
1562
1563     LeaveCriticalSection(&This->lock);
1564
1565     return S_OK;
1566 }
1567
1568 static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
1569 {
1570     ACImpl *This = impl_from_IAudioClient(iface);
1571     int err;
1572     HANDLE event;
1573     BOOL wait;
1574
1575     TRACE("(%p)\n", This);
1576
1577     EnterCriticalSection(&This->lock);
1578
1579     if(!This->initted){
1580         LeaveCriticalSection(&This->lock);
1581         return AUDCLNT_E_NOT_INITIALIZED;
1582     }
1583
1584     if(!This->started){
1585         LeaveCriticalSection(&This->lock);
1586         return S_FALSE;
1587     }
1588
1589     event = CreateEventW(NULL, TRUE, FALSE, NULL);
1590     wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event);
1591     if(wait)
1592         WARN("DeleteTimerQueueTimer error %u\n", GetLastError());
1593     wait = wait && GetLastError() == ERROR_IO_PENDING;
1594
1595     if((err = snd_pcm_drop(This->pcm_handle)) < 0){
1596         LeaveCriticalSection(&This->lock);
1597         WARN("Drop failed: %d (%s)\n", err, snd_strerror(err));
1598         return E_FAIL;
1599     }
1600
1601     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
1602         LeaveCriticalSection(&This->lock);
1603         WARN("Prepare failed: %d (%s)\n", err, snd_strerror(err));
1604         return E_FAIL;
1605     }
1606
1607     This->started = FALSE;
1608
1609     LeaveCriticalSection(&This->lock);
1610
1611     if(event && wait)
1612         WaitForSingleObject(event, INFINITE);
1613     CloseHandle(event);
1614
1615     return S_OK;
1616 }
1617
1618 static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
1619 {
1620     ACImpl *This = impl_from_IAudioClient(iface);
1621
1622     TRACE("(%p)\n", This);
1623
1624     EnterCriticalSection(&This->lock);
1625
1626     if(!This->initted){
1627         LeaveCriticalSection(&This->lock);
1628         return AUDCLNT_E_NOT_INITIALIZED;
1629     }
1630
1631     if(This->started){
1632         LeaveCriticalSection(&This->lock);
1633         return AUDCLNT_E_NOT_STOPPED;
1634     }
1635
1636     This->held_frames = 0;
1637     This->written_frames = 0;
1638     This->lcl_offs_frames = 0;
1639
1640     LeaveCriticalSection(&This->lock);
1641
1642     return S_OK;
1643 }
1644
1645 static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface,
1646         HANDLE event)
1647 {
1648     ACImpl *This = impl_from_IAudioClient(iface);
1649
1650     TRACE("(%p)->(%p)\n", This, event);
1651
1652     if(!event)
1653         return E_INVALIDARG;
1654
1655     EnterCriticalSection(&This->lock);
1656
1657     if(!This->initted){
1658         LeaveCriticalSection(&This->lock);
1659         return AUDCLNT_E_NOT_INITIALIZED;
1660     }
1661
1662     if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
1663         LeaveCriticalSection(&This->lock);
1664         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
1665     }
1666
1667     This->event = event;
1668
1669     LeaveCriticalSection(&This->lock);
1670
1671     return S_OK;
1672 }
1673
1674 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1675         void **ppv)
1676 {
1677     ACImpl *This = impl_from_IAudioClient(iface);
1678
1679     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1680
1681     if(!ppv)
1682         return E_POINTER;
1683     *ppv = NULL;
1684
1685     EnterCriticalSection(&This->lock);
1686
1687     if(!This->initted){
1688         LeaveCriticalSection(&This->lock);
1689         return AUDCLNT_E_NOT_INITIALIZED;
1690     }
1691
1692     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1693         if(This->dataflow != eRender){
1694             LeaveCriticalSection(&This->lock);
1695             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1696         }
1697         IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
1698         *ppv = &This->IAudioRenderClient_iface;
1699     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1700         if(This->dataflow != eCapture){
1701             LeaveCriticalSection(&This->lock);
1702             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1703         }
1704         IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
1705         *ppv = &This->IAudioCaptureClient_iface;
1706     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1707         IAudioClock_AddRef(&This->IAudioClock_iface);
1708         *ppv = &This->IAudioClock_iface;
1709     }else if(IsEqualIID(riid, &IID_IAudioStreamVolume)){
1710         IAudioStreamVolume_AddRef(&This->IAudioStreamVolume_iface);
1711         *ppv = &This->IAudioStreamVolume_iface;
1712     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1713         if(!This->session_wrapper){
1714             This->session_wrapper = AudioSessionWrapper_Create(This);
1715             if(!This->session_wrapper){
1716                 LeaveCriticalSection(&This->lock);
1717                 return E_OUTOFMEMORY;
1718             }
1719         }else
1720             IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
1721
1722         *ppv = &This->session_wrapper->IAudioSessionControl2_iface;
1723     }else if(IsEqualIID(riid, &IID_IChannelAudioVolume)){
1724         if(!This->session_wrapper){
1725             This->session_wrapper = AudioSessionWrapper_Create(This);
1726             if(!This->session_wrapper){
1727                 LeaveCriticalSection(&This->lock);
1728                 return E_OUTOFMEMORY;
1729             }
1730         }else
1731             IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
1732
1733         *ppv = &This->session_wrapper->IChannelAudioVolume_iface;
1734     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1735         if(!This->session_wrapper){
1736             This->session_wrapper = AudioSessionWrapper_Create(This);
1737             if(!This->session_wrapper){
1738                 LeaveCriticalSection(&This->lock);
1739                 return E_OUTOFMEMORY;
1740             }
1741         }else
1742             ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
1743
1744         *ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
1745     }
1746
1747     if(*ppv){
1748         LeaveCriticalSection(&This->lock);
1749         return S_OK;
1750     }
1751
1752     LeaveCriticalSection(&This->lock);
1753
1754     FIXME("stub %s\n", debugstr_guid(riid));
1755     return E_NOINTERFACE;
1756 }
1757
1758 static const IAudioClientVtbl AudioClient_Vtbl =
1759 {
1760     AudioClient_QueryInterface,
1761     AudioClient_AddRef,
1762     AudioClient_Release,
1763     AudioClient_Initialize,
1764     AudioClient_GetBufferSize,
1765     AudioClient_GetStreamLatency,
1766     AudioClient_GetCurrentPadding,
1767     AudioClient_IsFormatSupported,
1768     AudioClient_GetMixFormat,
1769     AudioClient_GetDevicePeriod,
1770     AudioClient_Start,
1771     AudioClient_Stop,
1772     AudioClient_Reset,
1773     AudioClient_SetEventHandle,
1774     AudioClient_GetService
1775 };
1776
1777 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1778         IAudioRenderClient *iface, REFIID riid, void **ppv)
1779 {
1780     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1781
1782     if(!ppv)
1783         return E_POINTER;
1784     *ppv = NULL;
1785
1786     if(IsEqualIID(riid, &IID_IUnknown) ||
1787             IsEqualIID(riid, &IID_IAudioRenderClient))
1788         *ppv = iface;
1789     if(*ppv){
1790         IUnknown_AddRef((IUnknown*)*ppv);
1791         return S_OK;
1792     }
1793
1794     WARN("Unknown interface %s\n", debugstr_guid(riid));
1795     return E_NOINTERFACE;
1796 }
1797
1798 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1799 {
1800     ACImpl *This = impl_from_IAudioRenderClient(iface);
1801     return AudioClient_AddRef(&This->IAudioClient_iface);
1802 }
1803
1804 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1805 {
1806     ACImpl *This = impl_from_IAudioRenderClient(iface);
1807     return AudioClient_Release(&This->IAudioClient_iface);
1808 }
1809
1810 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1811         UINT32 frames, BYTE **data)
1812 {
1813     ACImpl *This = impl_from_IAudioRenderClient(iface);
1814     UINT32 write_pos;
1815     UINT32 pad;
1816     HRESULT hr;
1817
1818     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1819
1820     if(!data)
1821         return E_POINTER;
1822
1823     EnterCriticalSection(&This->lock);
1824
1825     if(This->buf_state != NOT_LOCKED){
1826         LeaveCriticalSection(&This->lock);
1827         return AUDCLNT_E_OUT_OF_ORDER;
1828     }
1829
1830     if(!frames){
1831         This->buf_state = LOCKED_NORMAL;
1832         LeaveCriticalSection(&This->lock);
1833         return S_OK;
1834     }
1835
1836     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
1837     if(FAILED(hr)){
1838         LeaveCriticalSection(&This->lock);
1839         return hr;
1840     }
1841
1842     if(pad + frames > This->bufsize_frames){
1843         LeaveCriticalSection(&This->lock);
1844         return AUDCLNT_E_BUFFER_TOO_LARGE;
1845     }
1846
1847     write_pos =
1848         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1849     if(write_pos + frames > This->bufsize_frames){
1850         if(This->tmp_buffer_frames < frames){
1851             if(This->tmp_buffer)
1852                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
1853                         This->tmp_buffer, frames * This->fmt->nBlockAlign);
1854             else
1855                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
1856                         frames * This->fmt->nBlockAlign);
1857             if(!This->tmp_buffer){
1858                 LeaveCriticalSection(&This->lock);
1859                 return E_OUTOFMEMORY;
1860             }
1861             This->tmp_buffer_frames = frames;
1862         }
1863         *data = This->tmp_buffer;
1864         This->buf_state = LOCKED_WRAPPED;
1865     }else{
1866         *data = This->local_buffer +
1867             This->lcl_offs_frames * This->fmt->nBlockAlign;
1868         This->buf_state = LOCKED_NORMAL;
1869     }
1870
1871     LeaveCriticalSection(&This->lock);
1872
1873     return S_OK;
1874 }
1875
1876 static void alsa_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_bytes)
1877 {
1878     snd_pcm_uframes_t write_offs_frames =
1879         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
1880     UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
1881     snd_pcm_uframes_t chunk_frames = This->bufsize_frames - write_offs_frames;
1882     UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
1883
1884     if(written_bytes < chunk_bytes){
1885         memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
1886     }else{
1887         memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
1888         memcpy(This->local_buffer, buffer + chunk_bytes,
1889                 written_bytes - chunk_bytes);
1890     }
1891 }
1892
1893 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
1894         IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
1895 {
1896     ACImpl *This = impl_from_IAudioRenderClient(iface);
1897     UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
1898     BYTE *buffer;
1899     HRESULT hr;
1900
1901     TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
1902
1903     EnterCriticalSection(&This->lock);
1904
1905     if(This->buf_state == NOT_LOCKED || !written_frames){
1906         This->buf_state = NOT_LOCKED;
1907         LeaveCriticalSection(&This->lock);
1908         return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
1909     }
1910
1911     if(This->buf_state == LOCKED_NORMAL)
1912         buffer = This->local_buffer +
1913             This->lcl_offs_frames * This->fmt->nBlockAlign;
1914     else
1915         buffer = This->tmp_buffer;
1916
1917     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
1918         WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
1919         if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
1920                 (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1921                  IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
1922                 This->fmt->wBitsPerSample == 8)
1923             memset(buffer, 128, written_frames * This->fmt->nBlockAlign);
1924         else
1925             memset(buffer, 0, written_frames * This->fmt->nBlockAlign);
1926     }
1927
1928     if(This->held_frames){
1929         if(This->buf_state == LOCKED_WRAPPED)
1930             alsa_wrap_buffer(This, buffer, written_bytes);
1931
1932         This->held_frames += written_frames;
1933     }else{
1934         snd_pcm_sframes_t written;
1935
1936         written = alsa_write_best_effort(This->pcm_handle, buffer,
1937                 written_frames, This);
1938         if(written < 0){
1939             LeaveCriticalSection(&This->lock);
1940             WARN("write failed: %ld (%s)\n", written, snd_strerror(written));
1941             return E_FAIL;
1942         }
1943
1944         if(written < written_frames){
1945             if(This->buf_state == LOCKED_WRAPPED)
1946                 alsa_wrap_buffer(This,
1947                         This->tmp_buffer + written * This->fmt->nBlockAlign,
1948                         written_frames - written);
1949
1950             This->held_frames = written_frames - written;
1951         }
1952     }
1953
1954     if(This->started &&
1955             snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_PREPARED){
1956         hr = alsa_consider_start(This);
1957         if(FAILED(hr)){
1958             LeaveCriticalSection(&This->lock);
1959             return hr;
1960         }
1961     }
1962
1963     This->written_frames += written_frames;
1964     This->buf_state = NOT_LOCKED;
1965
1966     LeaveCriticalSection(&This->lock);
1967
1968     return S_OK;
1969 }
1970
1971 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
1972     AudioRenderClient_QueryInterface,
1973     AudioRenderClient_AddRef,
1974     AudioRenderClient_Release,
1975     AudioRenderClient_GetBuffer,
1976     AudioRenderClient_ReleaseBuffer
1977 };
1978
1979 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
1980         IAudioCaptureClient *iface, REFIID riid, void **ppv)
1981 {
1982     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1983
1984     if(!ppv)
1985         return E_POINTER;
1986     *ppv = NULL;
1987
1988     if(IsEqualIID(riid, &IID_IUnknown) ||
1989             IsEqualIID(riid, &IID_IAudioCaptureClient))
1990         *ppv = iface;
1991     if(*ppv){
1992         IUnknown_AddRef((IUnknown*)*ppv);
1993         return S_OK;
1994     }
1995
1996     WARN("Unknown interface %s\n", debugstr_guid(riid));
1997     return E_NOINTERFACE;
1998 }
1999
2000 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
2001 {
2002     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2003     return IAudioClient_AddRef(&This->IAudioClient_iface);
2004 }
2005
2006 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
2007 {
2008     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2009     return IAudioClient_Release(&This->IAudioClient_iface);
2010 }
2011
2012 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
2013         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
2014         UINT64 *qpcpos)
2015 {
2016     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2017     HRESULT hr;
2018
2019     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
2020             devpos, qpcpos);
2021
2022     if(!data || !frames || !flags)
2023         return E_POINTER;
2024
2025     EnterCriticalSection(&This->lock);
2026
2027     if(This->buf_state != NOT_LOCKED){
2028         LeaveCriticalSection(&This->lock);
2029         return AUDCLNT_E_OUT_OF_ORDER;
2030     }
2031
2032     hr = IAudioCaptureClient_GetNextPacketSize(iface, frames);
2033     if(FAILED(hr)){
2034         LeaveCriticalSection(&This->lock);
2035         return hr;
2036     }
2037
2038     *flags = 0;
2039
2040     if(This->lcl_offs_frames + *frames > This->bufsize_frames){
2041         UINT32 chunk_bytes, offs_bytes, frames_bytes;
2042         if(This->tmp_buffer_frames < *frames){
2043             if(This->tmp_buffer)
2044                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
2045                         This->tmp_buffer, *frames * This->fmt->nBlockAlign);
2046             else
2047                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
2048                         *frames * This->fmt->nBlockAlign);
2049             if(!This->tmp_buffer){
2050                 LeaveCriticalSection(&This->lock);
2051                 return E_OUTOFMEMORY;
2052             }
2053             This->tmp_buffer_frames = *frames;
2054         }
2055
2056         *data = This->tmp_buffer;
2057         chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
2058             This->fmt->nBlockAlign;
2059         offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
2060         frames_bytes = *frames * This->fmt->nBlockAlign;
2061         memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
2062         memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
2063                 frames_bytes - chunk_bytes);
2064     }else
2065         *data = This->local_buffer +
2066             This->lcl_offs_frames * This->fmt->nBlockAlign;
2067
2068     This->buf_state = LOCKED_NORMAL;
2069
2070     if(devpos || qpcpos)
2071         IAudioClock_GetPosition(&This->IAudioClock_iface, devpos, qpcpos);
2072
2073     LeaveCriticalSection(&This->lock);
2074
2075     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2076 }
2077
2078 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
2079         IAudioCaptureClient *iface, UINT32 done)
2080 {
2081     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2082
2083     TRACE("(%p)->(%u)\n", This, done);
2084
2085     EnterCriticalSection(&This->lock);
2086
2087     if(This->buf_state == NOT_LOCKED){
2088         LeaveCriticalSection(&This->lock);
2089         return AUDCLNT_E_OUT_OF_ORDER;
2090     }
2091
2092     This->held_frames -= done;
2093     This->lcl_offs_frames += done;
2094     This->lcl_offs_frames %= This->bufsize_frames;
2095
2096     This->buf_state = NOT_LOCKED;
2097
2098     LeaveCriticalSection(&This->lock);
2099
2100     return S_OK;
2101 }
2102
2103 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
2104         IAudioCaptureClient *iface, UINT32 *frames)
2105 {
2106     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2107
2108     TRACE("(%p)->(%p)\n", This, frames);
2109
2110     return AudioClient_GetCurrentPadding(&This->IAudioClient_iface, frames);
2111 }
2112
2113 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
2114 {
2115     AudioCaptureClient_QueryInterface,
2116     AudioCaptureClient_AddRef,
2117     AudioCaptureClient_Release,
2118     AudioCaptureClient_GetBuffer,
2119     AudioCaptureClient_ReleaseBuffer,
2120     AudioCaptureClient_GetNextPacketSize
2121 };
2122
2123 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
2124         REFIID riid, void **ppv)
2125 {
2126     ACImpl *This = impl_from_IAudioClock(iface);
2127
2128     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2129
2130     if(!ppv)
2131         return E_POINTER;
2132     *ppv = NULL;
2133
2134     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
2135         *ppv = iface;
2136     else if(IsEqualIID(riid, &IID_IAudioClock2))
2137         *ppv = &This->IAudioClock2_iface;
2138     if(*ppv){
2139         IUnknown_AddRef((IUnknown*)*ppv);
2140         return S_OK;
2141     }
2142
2143     WARN("Unknown interface %s\n", debugstr_guid(riid));
2144     return E_NOINTERFACE;
2145 }
2146
2147 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
2148 {
2149     ACImpl *This = impl_from_IAudioClock(iface);
2150     return IAudioClient_AddRef(&This->IAudioClient_iface);
2151 }
2152
2153 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
2154 {
2155     ACImpl *This = impl_from_IAudioClock(iface);
2156     return IAudioClient_Release(&This->IAudioClient_iface);
2157 }
2158
2159 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
2160 {
2161     ACImpl *This = impl_from_IAudioClock(iface);
2162
2163     TRACE("(%p)->(%p)\n", This, freq);
2164
2165     *freq = This->fmt->nSamplesPerSec;
2166
2167     return S_OK;
2168 }
2169
2170 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2171         UINT64 *qpctime)
2172 {
2173     ACImpl *This = impl_from_IAudioClock(iface);
2174     UINT32 pad;
2175     HRESULT hr;
2176
2177     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2178
2179     if(!pos)
2180         return E_POINTER;
2181
2182     EnterCriticalSection(&This->lock);
2183
2184     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
2185     if(FAILED(hr)){
2186         LeaveCriticalSection(&This->lock);
2187         return hr;
2188     }
2189
2190     if(This->dataflow == eRender)
2191         *pos = This->written_frames - pad;
2192     else if(This->dataflow == eCapture)
2193         *pos = This->written_frames + pad;
2194
2195     LeaveCriticalSection(&This->lock);
2196
2197     if(qpctime){
2198         LARGE_INTEGER stamp, freq;
2199         QueryPerformanceCounter(&stamp);
2200         QueryPerformanceFrequency(&freq);
2201         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2202     }
2203
2204     return S_OK;
2205 }
2206
2207 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2208         DWORD *chars)
2209 {
2210     ACImpl *This = impl_from_IAudioClock(iface);
2211
2212     TRACE("(%p)->(%p)\n", This, chars);
2213
2214     if(!chars)
2215         return E_POINTER;
2216
2217     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2218
2219     return S_OK;
2220 }
2221
2222 static const IAudioClockVtbl AudioClock_Vtbl =
2223 {
2224     AudioClock_QueryInterface,
2225     AudioClock_AddRef,
2226     AudioClock_Release,
2227     AudioClock_GetFrequency,
2228     AudioClock_GetPosition,
2229     AudioClock_GetCharacteristics
2230 };
2231
2232 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2233         REFIID riid, void **ppv)
2234 {
2235     ACImpl *This = impl_from_IAudioClock2(iface);
2236     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2237 }
2238
2239 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2240 {
2241     ACImpl *This = impl_from_IAudioClock2(iface);
2242     return IAudioClient_AddRef(&This->IAudioClient_iface);
2243 }
2244
2245 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2246 {
2247     ACImpl *This = impl_from_IAudioClock2(iface);
2248     return IAudioClient_Release(&This->IAudioClient_iface);
2249 }
2250
2251 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2252         UINT64 *pos, UINT64 *qpctime)
2253 {
2254     ACImpl *This = impl_from_IAudioClock2(iface);
2255
2256     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2257
2258     return E_NOTIMPL;
2259 }
2260
2261 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2262 {
2263     AudioClock2_QueryInterface,
2264     AudioClock2_AddRef,
2265     AudioClock2_Release,
2266     AudioClock2_GetDevicePosition
2267 };
2268
2269 static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client)
2270 {
2271     AudioSessionWrapper *ret;
2272
2273     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2274             sizeof(AudioSessionWrapper));
2275     if(!ret)
2276         return NULL;
2277
2278     ret->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
2279     ret->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
2280     ret->IChannelAudioVolume_iface.lpVtbl = &ChannelAudioVolume_Vtbl;
2281
2282     ret->ref = 1;
2283
2284     ret->client = client;
2285     if(client){
2286         ret->session = client->session;
2287         AudioClient_AddRef(&client->IAudioClient_iface);
2288     }
2289
2290     return ret;
2291 }
2292
2293 static HRESULT WINAPI AudioSessionControl_QueryInterface(
2294         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
2295 {
2296     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2297
2298     if(!ppv)
2299         return E_POINTER;
2300     *ppv = NULL;
2301
2302     if(IsEqualIID(riid, &IID_IUnknown) ||
2303             IsEqualIID(riid, &IID_IAudioSessionControl) ||
2304             IsEqualIID(riid, &IID_IAudioSessionControl2))
2305         *ppv = iface;
2306     if(*ppv){
2307         IUnknown_AddRef((IUnknown*)*ppv);
2308         return S_OK;
2309     }
2310
2311     WARN("Unknown interface %s\n", debugstr_guid(riid));
2312     return E_NOINTERFACE;
2313 }
2314
2315 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
2316 {
2317     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2318     ULONG ref;
2319     ref = InterlockedIncrement(&This->ref);
2320     TRACE("(%p) Refcount now %u\n", This, ref);
2321     return ref;
2322 }
2323
2324 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
2325 {
2326     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2327     ULONG ref;
2328     ref = InterlockedDecrement(&This->ref);
2329     TRACE("(%p) Refcount now %u\n", This, ref);
2330     if(!ref){
2331         if(This->client){
2332             EnterCriticalSection(&This->client->lock);
2333             This->client->session_wrapper = NULL;
2334             LeaveCriticalSection(&This->client->lock);
2335             AudioClient_Release(&This->client->IAudioClient_iface);
2336         }
2337         HeapFree(GetProcessHeap(), 0, This);
2338     }
2339     return ref;
2340 }
2341
2342 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
2343         AudioSessionState *state)
2344 {
2345     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2346     ACImpl *client;
2347
2348     TRACE("(%p)->(%p)\n", This, state);
2349
2350     if(!state)
2351         return NULL_PTR_ERR;
2352
2353     EnterCriticalSection(&g_sessions_lock);
2354
2355     if(list_empty(&This->session->clients)){
2356         *state = AudioSessionStateExpired;
2357         LeaveCriticalSection(&g_sessions_lock);
2358         return S_OK;
2359     }
2360
2361     LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
2362         EnterCriticalSection(&client->lock);
2363         if(client->started){
2364             *state = AudioSessionStateActive;
2365             LeaveCriticalSection(&client->lock);
2366             LeaveCriticalSection(&g_sessions_lock);
2367             return S_OK;
2368         }
2369         LeaveCriticalSection(&client->lock);
2370     }
2371
2372     LeaveCriticalSection(&g_sessions_lock);
2373
2374     *state = AudioSessionStateInactive;
2375
2376     return S_OK;
2377 }
2378
2379 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
2380         IAudioSessionControl2 *iface, WCHAR **name)
2381 {
2382     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2383
2384     FIXME("(%p)->(%p) - stub\n", This, name);
2385
2386     return E_NOTIMPL;
2387 }
2388
2389 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
2390         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
2391 {
2392     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2393
2394     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
2395
2396     return E_NOTIMPL;
2397 }
2398
2399 static HRESULT WINAPI AudioSessionControl_GetIconPath(
2400         IAudioSessionControl2 *iface, WCHAR **path)
2401 {
2402     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2403
2404     FIXME("(%p)->(%p) - stub\n", This, path);
2405
2406     return E_NOTIMPL;
2407 }
2408
2409 static HRESULT WINAPI AudioSessionControl_SetIconPath(
2410         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
2411 {
2412     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2413
2414     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
2415
2416     return E_NOTIMPL;
2417 }
2418
2419 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
2420         IAudioSessionControl2 *iface, GUID *group)
2421 {
2422     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2423
2424     FIXME("(%p)->(%p) - stub\n", This, group);
2425
2426     return E_NOTIMPL;
2427 }
2428
2429 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
2430         IAudioSessionControl2 *iface, GUID *group, const GUID *session)
2431 {
2432     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2433
2434     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
2435             debugstr_guid(session));
2436
2437     return E_NOTIMPL;
2438 }
2439
2440 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
2441         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2442 {
2443     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2444
2445     FIXME("(%p)->(%p) - stub\n", This, events);
2446
2447     return S_OK;
2448 }
2449
2450 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
2451         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2452 {
2453     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2454
2455     FIXME("(%p)->(%p) - stub\n", This, events);
2456
2457     return S_OK;
2458 }
2459
2460 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
2461         IAudioSessionControl2 *iface, WCHAR **id)
2462 {
2463     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2464
2465     FIXME("(%p)->(%p) - stub\n", This, id);
2466
2467     return E_NOTIMPL;
2468 }
2469
2470 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
2471         IAudioSessionControl2 *iface, WCHAR **id)
2472 {
2473     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2474
2475     FIXME("(%p)->(%p) - stub\n", This, id);
2476
2477     return E_NOTIMPL;
2478 }
2479
2480 static HRESULT WINAPI AudioSessionControl_GetProcessId(
2481         IAudioSessionControl2 *iface, DWORD *pid)
2482 {
2483     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2484
2485     TRACE("(%p)->(%p)\n", This, pid);
2486
2487     if(!pid)
2488         return E_POINTER;
2489
2490     *pid = GetCurrentProcessId();
2491
2492     return S_OK;
2493 }
2494
2495 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
2496         IAudioSessionControl2 *iface)
2497 {
2498     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2499
2500     TRACE("(%p)\n", This);
2501
2502     return S_FALSE;
2503 }
2504
2505 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
2506         IAudioSessionControl2 *iface, BOOL optout)
2507 {
2508     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2509
2510     TRACE("(%p)->(%d)\n", This, optout);
2511
2512     return S_OK;
2513 }
2514
2515 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
2516 {
2517     AudioSessionControl_QueryInterface,
2518     AudioSessionControl_AddRef,
2519     AudioSessionControl_Release,
2520     AudioSessionControl_GetState,
2521     AudioSessionControl_GetDisplayName,
2522     AudioSessionControl_SetDisplayName,
2523     AudioSessionControl_GetIconPath,
2524     AudioSessionControl_SetIconPath,
2525     AudioSessionControl_GetGroupingParam,
2526     AudioSessionControl_SetGroupingParam,
2527     AudioSessionControl_RegisterAudioSessionNotification,
2528     AudioSessionControl_UnregisterAudioSessionNotification,
2529     AudioSessionControl_GetSessionIdentifier,
2530     AudioSessionControl_GetSessionInstanceIdentifier,
2531     AudioSessionControl_GetProcessId,
2532     AudioSessionControl_IsSystemSoundsSession,
2533     AudioSessionControl_SetDuckingPreference
2534 };
2535
2536 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
2537         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
2538 {
2539     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2540
2541     if(!ppv)
2542         return E_POINTER;
2543     *ppv = NULL;
2544
2545     if(IsEqualIID(riid, &IID_IUnknown) ||
2546             IsEqualIID(riid, &IID_ISimpleAudioVolume))
2547         *ppv = iface;
2548     if(*ppv){
2549         IUnknown_AddRef((IUnknown*)*ppv);
2550         return S_OK;
2551     }
2552
2553     WARN("Unknown interface %s\n", debugstr_guid(riid));
2554     return E_NOINTERFACE;
2555 }
2556
2557 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
2558 {
2559     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2560     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
2561 }
2562
2563 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
2564 {
2565     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2566     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
2567 }
2568
2569 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
2570         ISimpleAudioVolume *iface, float level, const GUID *context)
2571 {
2572     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2573     AudioSession *session = This->session;
2574
2575     TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
2576
2577     if(level < 0.f || level > 1.f)
2578         return E_INVALIDARG;
2579
2580     if(context)
2581         FIXME("Notifications not supported yet\n");
2582
2583     TRACE("ALSA does not support volume control\n");
2584
2585     EnterCriticalSection(&session->lock);
2586
2587     session->master_vol = level;
2588
2589     LeaveCriticalSection(&session->lock);
2590
2591     return S_OK;
2592 }
2593
2594 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
2595         ISimpleAudioVolume *iface, float *level)
2596 {
2597     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2598     AudioSession *session = This->session;
2599
2600     TRACE("(%p)->(%p)\n", session, level);
2601
2602     if(!level)
2603         return NULL_PTR_ERR;
2604
2605     *level = session->master_vol;
2606
2607     return S_OK;
2608 }
2609
2610 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
2611         BOOL mute, const GUID *context)
2612 {
2613     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2614     AudioSession *session = This->session;
2615
2616     TRACE("(%p)->(%u, %p)\n", session, mute, context);
2617
2618     if(context)
2619         FIXME("Notifications not supported yet\n");
2620
2621     session->mute = mute;
2622
2623     return S_OK;
2624 }
2625
2626 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
2627         BOOL *mute)
2628 {
2629     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2630     AudioSession *session = This->session;
2631
2632     TRACE("(%p)->(%p)\n", session, mute);
2633
2634     if(!mute)
2635         return NULL_PTR_ERR;
2636
2637     *mute = session->mute;
2638
2639     return S_OK;
2640 }
2641
2642 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
2643 {
2644     SimpleAudioVolume_QueryInterface,
2645     SimpleAudioVolume_AddRef,
2646     SimpleAudioVolume_Release,
2647     SimpleAudioVolume_SetMasterVolume,
2648     SimpleAudioVolume_GetMasterVolume,
2649     SimpleAudioVolume_SetMute,
2650     SimpleAudioVolume_GetMute
2651 };
2652
2653 static HRESULT WINAPI AudioStreamVolume_QueryInterface(
2654         IAudioStreamVolume *iface, REFIID riid, void **ppv)
2655 {
2656     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2657
2658     if(!ppv)
2659         return E_POINTER;
2660     *ppv = NULL;
2661
2662     if(IsEqualIID(riid, &IID_IUnknown) ||
2663             IsEqualIID(riid, &IID_IAudioStreamVolume))
2664         *ppv = iface;
2665     if(*ppv){
2666         IUnknown_AddRef((IUnknown*)*ppv);
2667         return S_OK;
2668     }
2669
2670     WARN("Unknown interface %s\n", debugstr_guid(riid));
2671     return E_NOINTERFACE;
2672 }
2673
2674 static ULONG WINAPI AudioStreamVolume_AddRef(IAudioStreamVolume *iface)
2675 {
2676     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2677     return IAudioClient_AddRef(&This->IAudioClient_iface);
2678 }
2679
2680 static ULONG WINAPI AudioStreamVolume_Release(IAudioStreamVolume *iface)
2681 {
2682     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2683     return IAudioClient_Release(&This->IAudioClient_iface);
2684 }
2685
2686 static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
2687         IAudioStreamVolume *iface, UINT32 *out)
2688 {
2689     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2690
2691     TRACE("(%p)->(%p)\n", This, out);
2692
2693     if(!out)
2694         return E_POINTER;
2695
2696     *out = This->fmt->nChannels;
2697
2698     return S_OK;
2699 }
2700
2701 static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
2702         IAudioStreamVolume *iface, UINT32 index, float level)
2703 {
2704     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2705
2706     TRACE("(%p)->(%d, %f)\n", This, index, level);
2707
2708     if(level < 0.f || level > 1.f)
2709         return E_INVALIDARG;
2710
2711     if(index >= This->fmt->nChannels)
2712         return E_INVALIDARG;
2713
2714     TRACE("ALSA does not support volume control\n");
2715
2716     EnterCriticalSection(&This->lock);
2717
2718     This->vols[index] = level;
2719
2720     LeaveCriticalSection(&This->lock);
2721
2722     return S_OK;
2723 }
2724
2725 static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
2726         IAudioStreamVolume *iface, UINT32 index, float *level)
2727 {
2728     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2729
2730     TRACE("(%p)->(%d, %p)\n", This, index, level);
2731
2732     if(!level)
2733         return E_POINTER;
2734
2735     if(index >= This->fmt->nChannels)
2736         return E_INVALIDARG;
2737
2738     *level = This->vols[index];
2739
2740     return S_OK;
2741 }
2742
2743 static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
2744         IAudioStreamVolume *iface, UINT32 count, const float *levels)
2745 {
2746     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2747     int i;
2748
2749     TRACE("(%p)->(%d, %p)\n", This, count, levels);
2750
2751     if(!levels)
2752         return E_POINTER;
2753
2754     if(count != This->fmt->nChannels)
2755         return E_INVALIDARG;
2756
2757     TRACE("ALSA does not support volume control\n");
2758
2759     EnterCriticalSection(&This->lock);
2760
2761     for(i = 0; i < count; ++i)
2762         This->vols[i] = levels[i];
2763
2764     LeaveCriticalSection(&This->lock);
2765
2766     return S_OK;
2767 }
2768
2769 static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
2770         IAudioStreamVolume *iface, UINT32 count, float *levels)
2771 {
2772     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2773     int i;
2774
2775     TRACE("(%p)->(%d, %p)\n", This, count, levels);
2776
2777     if(!levels)
2778         return E_POINTER;
2779
2780     if(count != This->fmt->nChannels)
2781         return E_INVALIDARG;
2782
2783     EnterCriticalSection(&This->lock);
2784
2785     for(i = 0; i < count; ++i)
2786         levels[i] = This->vols[i];
2787
2788     LeaveCriticalSection(&This->lock);
2789
2790     return S_OK;
2791 }
2792
2793 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
2794 {
2795     AudioStreamVolume_QueryInterface,
2796     AudioStreamVolume_AddRef,
2797     AudioStreamVolume_Release,
2798     AudioStreamVolume_GetChannelCount,
2799     AudioStreamVolume_SetChannelVolume,
2800     AudioStreamVolume_GetChannelVolume,
2801     AudioStreamVolume_SetAllVolumes,
2802     AudioStreamVolume_GetAllVolumes
2803 };
2804
2805 static HRESULT WINAPI ChannelAudioVolume_QueryInterface(
2806         IChannelAudioVolume *iface, REFIID riid, void **ppv)
2807 {
2808     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2809
2810     if(!ppv)
2811         return E_POINTER;
2812     *ppv = NULL;
2813
2814     if(IsEqualIID(riid, &IID_IUnknown) ||
2815             IsEqualIID(riid, &IID_IChannelAudioVolume))
2816         *ppv = iface;
2817     if(*ppv){
2818         IUnknown_AddRef((IUnknown*)*ppv);
2819         return S_OK;
2820     }
2821
2822     WARN("Unknown interface %s\n", debugstr_guid(riid));
2823     return E_NOINTERFACE;
2824 }
2825
2826 static ULONG WINAPI ChannelAudioVolume_AddRef(IChannelAudioVolume *iface)
2827 {
2828     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2829     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
2830 }
2831
2832 static ULONG WINAPI ChannelAudioVolume_Release(IChannelAudioVolume *iface)
2833 {
2834     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2835     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
2836 }
2837
2838 static HRESULT WINAPI ChannelAudioVolume_GetChannelCount(
2839         IChannelAudioVolume *iface, UINT32 *out)
2840 {
2841     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2842     AudioSession *session = This->session;
2843
2844     TRACE("(%p)->(%p)\n", session, out);
2845
2846     if(!out)
2847         return NULL_PTR_ERR;
2848
2849     *out = session->channel_count;
2850
2851     return S_OK;
2852 }
2853
2854 static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
2855         IChannelAudioVolume *iface, UINT32 index, float level,
2856         const GUID *context)
2857 {
2858     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2859     AudioSession *session = This->session;
2860
2861     TRACE("(%p)->(%d, %f, %s)\n", session, index, level,
2862             wine_dbgstr_guid(context));
2863
2864     if(level < 0.f || level > 1.f)
2865         return E_INVALIDARG;
2866
2867     if(index >= session->channel_count)
2868         return E_INVALIDARG;
2869
2870     if(context)
2871         FIXME("Notifications not supported yet\n");
2872
2873     TRACE("ALSA does not support volume control\n");
2874
2875     EnterCriticalSection(&session->lock);
2876
2877     session->channel_vols[index] = level;
2878
2879     LeaveCriticalSection(&session->lock);
2880
2881     return S_OK;
2882 }
2883
2884 static HRESULT WINAPI ChannelAudioVolume_GetChannelVolume(
2885         IChannelAudioVolume *iface, UINT32 index, float *level)
2886 {
2887     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2888     AudioSession *session = This->session;
2889
2890     TRACE("(%p)->(%d, %p)\n", session, index, level);
2891
2892     if(!level)
2893         return NULL_PTR_ERR;
2894
2895     if(index >= session->channel_count)
2896         return E_INVALIDARG;
2897
2898     *level = session->channel_vols[index];
2899
2900     return S_OK;
2901 }
2902
2903 static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
2904         IChannelAudioVolume *iface, UINT32 count, const float *levels,
2905         const GUID *context)
2906 {
2907     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2908     AudioSession *session = This->session;
2909     int i;
2910
2911     TRACE("(%p)->(%d, %p, %s)\n", session, count, levels,
2912             wine_dbgstr_guid(context));
2913
2914     if(!levels)
2915         return NULL_PTR_ERR;
2916
2917     if(count != session->channel_count)
2918         return E_INVALIDARG;
2919
2920     if(context)
2921         FIXME("Notifications not supported yet\n");
2922
2923     TRACE("ALSA does not support volume control\n");
2924
2925     EnterCriticalSection(&session->lock);
2926
2927     for(i = 0; i < count; ++i)
2928         session->channel_vols[i] = levels[i];
2929
2930     LeaveCriticalSection(&session->lock);
2931
2932     return S_OK;
2933 }
2934
2935 static HRESULT WINAPI ChannelAudioVolume_GetAllVolumes(
2936         IChannelAudioVolume *iface, UINT32 count, float *levels)
2937 {
2938     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2939     AudioSession *session = This->session;
2940     int i;
2941
2942     TRACE("(%p)->(%d, %p)\n", session, count, levels);
2943
2944     if(!levels)
2945         return NULL_PTR_ERR;
2946
2947     if(count != session->channel_count)
2948         return E_INVALIDARG;
2949
2950     for(i = 0; i < count; ++i)
2951         levels[i] = session->channel_vols[i];
2952
2953     return S_OK;
2954 }
2955
2956 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
2957 {
2958     ChannelAudioVolume_QueryInterface,
2959     ChannelAudioVolume_AddRef,
2960     ChannelAudioVolume_Release,
2961     ChannelAudioVolume_GetChannelCount,
2962     ChannelAudioVolume_SetChannelVolume,
2963     ChannelAudioVolume_GetChannelVolume,
2964     ChannelAudioVolume_SetAllVolumes,
2965     ChannelAudioVolume_GetAllVolumes
2966 };
2967
2968 HRESULT WINAPI AudioSessionManager_QueryInterface(IAudioSessionManager2 *iface,
2969         REFIID riid, void **ppv)
2970 {
2971     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2972
2973     if(!ppv)
2974         return E_POINTER;
2975     *ppv = NULL;
2976
2977     if(IsEqualIID(riid, &IID_IUnknown) ||
2978             IsEqualIID(riid, &IID_IAudioSessionManager) ||
2979             IsEqualIID(riid, &IID_IAudioSessionManager2))
2980         *ppv = iface;
2981     if(*ppv){
2982         IUnknown_AddRef((IUnknown*)*ppv);
2983         return S_OK;
2984     }
2985
2986     WARN("Unknown interface %s\n", debugstr_guid(riid));
2987     return E_NOINTERFACE;
2988 }
2989
2990 ULONG WINAPI AudioSessionManager_AddRef(IAudioSessionManager2 *iface)
2991 {
2992     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
2993     ULONG ref;
2994     ref = InterlockedIncrement(&This->ref);
2995     TRACE("(%p) Refcount now %u\n", This, ref);
2996     return ref;
2997 }
2998
2999 ULONG WINAPI AudioSessionManager_Release(IAudioSessionManager2 *iface)
3000 {
3001     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3002     ULONG ref;
3003     ref = InterlockedDecrement(&This->ref);
3004     TRACE("(%p) Refcount now %u\n", This, ref);
3005     if(!ref)
3006         HeapFree(GetProcessHeap(), 0, This);
3007     return ref;
3008 }
3009
3010 HRESULT WINAPI AudioSessionManager_GetAudioSessionControl(
3011         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3012         IAudioSessionControl **out)
3013 {
3014     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3015     AudioSession *session;
3016     AudioSessionWrapper *wrapper;
3017     HRESULT hr;
3018
3019     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3020             flags, out);
3021
3022     hr = get_audio_session(session_guid, This->device, 0, &session);
3023     if(FAILED(hr))
3024         return hr;
3025
3026     wrapper = AudioSessionWrapper_Create(NULL);
3027     if(!wrapper)
3028         return E_OUTOFMEMORY;
3029
3030     wrapper->session = session;
3031
3032     *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface;
3033
3034     return S_OK;
3035 }
3036
3037 HRESULT WINAPI AudioSessionManager_GetSimpleAudioVolume(
3038         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3039         ISimpleAudioVolume **out)
3040 {
3041     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3042     AudioSession *session;
3043     AudioSessionWrapper *wrapper;
3044     HRESULT hr;
3045
3046     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3047             flags, out);
3048
3049     hr = get_audio_session(session_guid, This->device, 0, &session);
3050     if(FAILED(hr))
3051         return hr;
3052
3053     wrapper = AudioSessionWrapper_Create(NULL);
3054     if(!wrapper)
3055         return E_OUTOFMEMORY;
3056
3057     wrapper->session = session;
3058
3059     *out = &wrapper->ISimpleAudioVolume_iface;
3060
3061     return S_OK;
3062 }
3063
3064 HRESULT WINAPI AudioSessionManager_GetSessionEnumerator(
3065         IAudioSessionManager2 *iface, IAudioSessionEnumerator **out)
3066 {
3067     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3068     FIXME("(%p)->(%p) - stub\n", This, out);
3069     return E_NOTIMPL;
3070 }
3071
3072 HRESULT WINAPI AudioSessionManager_RegisterSessionNotification(
3073         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3074 {
3075     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3076     FIXME("(%p)->(%p) - stub\n", This, notification);
3077     return E_NOTIMPL;
3078 }
3079
3080 HRESULT WINAPI AudioSessionManager_UnregisterSessionNotification(
3081         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3082 {
3083     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3084     FIXME("(%p)->(%p) - stub\n", This, notification);
3085     return E_NOTIMPL;
3086 }
3087
3088 HRESULT WINAPI AudioSessionManager_RegisterDuckNotification(
3089         IAudioSessionManager2 *iface, const WCHAR *session_id,
3090         IAudioVolumeDuckNotification *notification)
3091 {
3092     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3093     FIXME("(%p)->(%p) - stub\n", This, notification);
3094     return E_NOTIMPL;
3095 }
3096
3097 HRESULT WINAPI AudioSessionManager_UnregisterDuckNotification(
3098         IAudioSessionManager2 *iface,
3099         IAudioVolumeDuckNotification *notification)
3100 {
3101     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3102     FIXME("(%p)->(%p) - stub\n", This, notification);
3103     return E_NOTIMPL;
3104 }
3105
3106 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl =
3107 {
3108     AudioSessionManager_QueryInterface,
3109     AudioSessionManager_AddRef,
3110     AudioSessionManager_Release,
3111     AudioSessionManager_GetAudioSessionControl,
3112     AudioSessionManager_GetSimpleAudioVolume,
3113     AudioSessionManager_GetSessionEnumerator,
3114     AudioSessionManager_RegisterSessionNotification,
3115     AudioSessionManager_UnregisterSessionNotification,
3116     AudioSessionManager_RegisterDuckNotification,
3117     AudioSessionManager_UnregisterDuckNotification
3118 };
3119
3120 HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
3121         IAudioSessionManager2 **out)
3122 {
3123     SessionMgr *This;
3124
3125     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SessionMgr));
3126     if(!This)
3127         return E_OUTOFMEMORY;
3128
3129     This->IAudioSessionManager2_iface.lpVtbl = &AudioSessionManager2_Vtbl;
3130     This->device = device;
3131     This->ref = 1;
3132
3133     *out = &This->IAudioSessionManager2_iface;
3134
3135     return S_OK;
3136 }