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