msxml3: Skip leading space characters when loading from BSTR.
[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;
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;
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     snd_pcm_uframes_t alsa_period_frames;
812     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
813     unsigned int rate, mmdev_period_frames, alsa_period_us;
814     int err, i;
815     HRESULT hr = S_OK;
816
817     TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
818           wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
819
820     if(!fmt)
821         return E_POINTER;
822
823     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
824         return AUDCLNT_E_NOT_INITIALIZED;
825
826     if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
827                 AUDCLNT_STREAMFLAGS_LOOPBACK |
828                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
829                 AUDCLNT_STREAMFLAGS_NOPERSIST |
830                 AUDCLNT_STREAMFLAGS_RATEADJUST |
831                 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
832                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
833                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)){
834         TRACE("Unknown flags: %08x\n", flags);
835         return E_INVALIDARG;
836     }
837
838     if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE && flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){
839         FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
840         return AUDCLNT_E_DEVICE_IN_USE;
841     }
842
843     if(!duration)
844         duration = 300000; /* 0.03s */
845
846     EnterCriticalSection(&This->lock);
847
848     if(This->initted){
849         LeaveCriticalSection(&This->lock);
850         return AUDCLNT_E_ALREADY_INITIALIZED;
851     }
852
853     dump_fmt(fmt);
854
855     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
856         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
857         hr = E_FAIL;
858         goto exit;
859     }
860
861     if((err = snd_pcm_hw_params_set_access(This->pcm_handle, This->hw_params,
862                 SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
863         WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
864         hr = E_FAIL;
865         goto exit;
866     }
867
868     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
869             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
870              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
871         if(fmt->wBitsPerSample == 8)
872             format = SND_PCM_FORMAT_U8;
873         else if(fmt->wBitsPerSample == 16)
874             format = SND_PCM_FORMAT_S16_LE;
875         else if(fmt->wBitsPerSample == 24)
876             format = SND_PCM_FORMAT_S24_3LE;
877         else if(fmt->wBitsPerSample == 32)
878             format = SND_PCM_FORMAT_S32_LE;
879         else{
880             WARN("Unsupported bit depth: %u\n", fmt->wBitsPerSample);
881             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
882             goto exit;
883         }
884     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
885             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
886              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
887         if(fmt->wBitsPerSample == 32)
888             format = SND_PCM_FORMAT_FLOAT_LE;
889         else if(fmt->wBitsPerSample == 64)
890             format = SND_PCM_FORMAT_FLOAT64_LE;
891         else{
892             WARN("Unsupported float size: %u\n", fmt->wBitsPerSample);
893             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
894             goto exit;
895         }
896     }else{
897         WARN("Unknown wave format: %04x\n", fmt->wFormatTag);
898         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
899         goto exit;
900     }
901
902     if((err = snd_pcm_hw_params_set_format(This->pcm_handle, This->hw_params,
903                 format)) < 0){
904         WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
905                 snd_strerror(err));
906         hr = E_FAIL;
907         goto exit;
908     }
909
910     This->alsa_format = format;
911
912     rate = fmt->nSamplesPerSec;
913     if((err = snd_pcm_hw_params_set_rate_near(This->pcm_handle, This->hw_params,
914                 &rate, NULL)) < 0){
915         WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
916                 snd_strerror(err));
917         hr = E_FAIL;
918         goto exit;
919     }
920
921     if((err = snd_pcm_hw_params_set_channels(This->pcm_handle, This->hw_params,
922                 fmt->nChannels)) < 0){
923         WARN("Unable to set channels to %u: %d (%s)\n", fmt->nChannels, err,
924                 snd_strerror(err));
925         hr = E_FAIL;
926         goto exit;
927     }
928
929     alsa_period_us = duration / 100; /* duration / 10 converted to us */
930     if((err = snd_pcm_hw_params_set_period_time_near(This->pcm_handle,
931                 This->hw_params, &alsa_period_us, NULL)) < 0){
932         WARN("Unable to set period time near %u: %d (%s)\n", alsa_period_us,
933                 err, snd_strerror(err));
934         hr = E_FAIL;
935         goto exit;
936     }
937
938     if((err = snd_pcm_hw_params(This->pcm_handle, This->hw_params)) < 0){
939         WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
940         hr = E_FAIL;
941         goto exit;
942     }
943
944     if((err = snd_pcm_hw_params_current(This->pcm_handle, This->hw_params)) < 0){
945         WARN("Unable to get current hw params: %d (%s)\n", err, snd_strerror(err));
946         hr = E_FAIL;
947         goto exit;
948     }
949
950     if((err = snd_pcm_hw_params_get_period_size(This->hw_params,
951                     &alsa_period_frames, NULL)) < 0){
952         WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
953         hr = E_FAIL;
954         goto exit;
955     }
956     TRACE("alsa_period_frames: %lu\n", alsa_period_frames);
957
958     if((err = snd_pcm_hw_params_get_buffer_size(This->hw_params,
959                     &This->alsa_bufsize_frames)) < 0){
960         WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
961         hr = E_FAIL;
962         goto exit;
963     }
964
965     sw_params = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_sw_params_sizeof());
966     if(!sw_params){
967         hr = E_OUTOFMEMORY;
968         goto exit;
969     }
970
971     if((err = snd_pcm_sw_params_current(This->pcm_handle, sw_params)) < 0){
972         WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
973         hr = E_FAIL;
974         goto exit;
975     }
976
977     if((err = snd_pcm_sw_params_set_start_threshold(This->pcm_handle,
978                     sw_params, 1)) < 0){
979         WARN("Unable set start threshold to 0: %d (%s)\n", err, snd_strerror(err));
980         hr = E_FAIL;
981         goto exit;
982     }
983
984     if((err = snd_pcm_sw_params_set_stop_threshold(This->pcm_handle,
985                     sw_params, This->alsa_bufsize_frames)) < 0){
986         WARN("Unable set stop threshold to %lu: %d (%s)\n",
987                 This->alsa_bufsize_frames, err, snd_strerror(err));
988         hr = E_FAIL;
989         goto exit;
990     }
991
992     if((err = snd_pcm_sw_params(This->pcm_handle, sw_params)) < 0){
993         WARN("Unable set sw params: %d (%s)\n", err, snd_strerror(err));
994         hr = E_FAIL;
995         goto exit;
996     }
997
998     if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
999         WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
1000         hr = E_FAIL;
1001         goto exit;
1002     }
1003
1004     if(period)
1005         This->mmdev_period_rt = period;
1006     else
1007         This->mmdev_period_rt = DefaultPeriod;
1008
1009     /* Check if the ALSA buffer is so small that it will run out before
1010      * the next MMDevAPI period tick occurs. Allow a little wiggle room
1011      * with 120% of the period time. */
1012     mmdev_period_frames = fmt->nSamplesPerSec * (This->mmdev_period_rt / 10000000.);
1013     if(This->alsa_bufsize_frames < 1.2 * mmdev_period_frames)
1014         FIXME("ALSA buffer time is smaller than our period time. Expect underruns. (%lu < %u)\n",
1015                 This->alsa_bufsize_frames, mmdev_period_frames);
1016
1017     This->bufsize_frames = ceil((duration / 10000000.) * fmt->nSamplesPerSec);
1018     This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
1019             This->bufsize_frames * fmt->nBlockAlign);
1020     if(!This->local_buffer){
1021         hr = E_OUTOFMEMORY;
1022         goto exit;
1023     }
1024     if (fmt->wBitsPerSample == 8)
1025         memset(This->local_buffer, 128, This->bufsize_frames * fmt->nBlockAlign);
1026     else
1027         memset(This->local_buffer, 0, This->bufsize_frames * fmt->nBlockAlign);
1028
1029     This->fmt = clone_format(fmt);
1030     if(!This->fmt){
1031         hr = E_OUTOFMEMORY;
1032         goto exit;
1033     }
1034
1035     This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
1036     if(!This->vols){
1037         hr = E_OUTOFMEMORY;
1038         goto exit;
1039     }
1040
1041     for(i = 0; i < fmt->nChannels; ++i)
1042         This->vols[i] = 1.f;
1043
1044     This->share = mode;
1045     This->flags = flags;
1046
1047     EnterCriticalSection(&g_sessions_lock);
1048
1049     hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
1050             &This->session);
1051     if(FAILED(hr)){
1052         LeaveCriticalSection(&g_sessions_lock);
1053         goto exit;
1054     }
1055
1056     list_add_tail(&This->session->clients, &This->entry);
1057
1058     LeaveCriticalSection(&g_sessions_lock);
1059
1060     This->initted = TRUE;
1061
1062 exit:
1063     HeapFree(GetProcessHeap(), 0, sw_params);
1064     if(FAILED(hr)){
1065         HeapFree(GetProcessHeap(), 0, This->local_buffer);
1066         This->local_buffer = NULL;
1067         CoTaskMemFree(This->fmt);
1068         This->fmt = NULL;
1069         HeapFree(GetProcessHeap(), 0, This->vols);
1070         This->vols = NULL;
1071     }
1072
1073     LeaveCriticalSection(&This->lock);
1074
1075     return hr;
1076 }
1077
1078 static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface,
1079         UINT32 *out)
1080 {
1081     ACImpl *This = impl_from_IAudioClient(iface);
1082
1083     TRACE("(%p)->(%p)\n", This, out);
1084
1085     if(!out)
1086         return E_POINTER;
1087
1088     EnterCriticalSection(&This->lock);
1089
1090     if(!This->initted){
1091         LeaveCriticalSection(&This->lock);
1092         return AUDCLNT_E_NOT_INITIALIZED;
1093     }
1094
1095     *out = This->bufsize_frames;
1096
1097     LeaveCriticalSection(&This->lock);
1098
1099     return S_OK;
1100 }
1101
1102 static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
1103         REFERENCE_TIME *latency)
1104 {
1105     ACImpl *This = impl_from_IAudioClient(iface);
1106
1107     TRACE("(%p)->(%p)\n", This, latency);
1108
1109     if(!latency)
1110         return E_POINTER;
1111
1112     EnterCriticalSection(&This->lock);
1113
1114     if(!This->initted){
1115         LeaveCriticalSection(&This->lock);
1116         return AUDCLNT_E_NOT_INITIALIZED;
1117     }
1118
1119     LeaveCriticalSection(&This->lock);
1120
1121     *latency = 500000;
1122
1123     return S_OK;
1124 }
1125
1126 static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
1127         UINT32 *out)
1128 {
1129     ACImpl *This = impl_from_IAudioClient(iface);
1130
1131     TRACE("(%p)->(%p)\n", This, out);
1132
1133     if(!out)
1134         return E_POINTER;
1135
1136     EnterCriticalSection(&This->lock);
1137
1138     if(!This->initted){
1139         LeaveCriticalSection(&This->lock);
1140         return AUDCLNT_E_NOT_INITIALIZED;
1141     }
1142
1143     if(This->dataflow == eRender){
1144         snd_pcm_sframes_t avail_frames;
1145
1146         avail_frames = snd_pcm_avail_update(This->pcm_handle);
1147         if(This->alsa_bufsize_frames < avail_frames ||
1148                 snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_XRUN)
1149             *out = This->held_frames;
1150         else
1151             *out = This->alsa_bufsize_frames - avail_frames + This->held_frames;
1152         TRACE("PCM state: %u, avail: %ld, pad: %u\n",
1153                 snd_pcm_state(This->pcm_handle), avail_frames, *out);
1154     }else if(This->dataflow == eCapture){
1155         *out = This->held_frames;
1156     }else{
1157         LeaveCriticalSection(&This->lock);
1158         return E_UNEXPECTED;
1159     }
1160
1161     LeaveCriticalSection(&This->lock);
1162
1163     return S_OK;
1164 }
1165
1166 static DWORD get_channel_mask(unsigned int channels)
1167 {
1168     switch(channels){
1169     case 0:
1170         return 0;
1171     case 1:
1172         return KSAUDIO_SPEAKER_MONO;
1173     case 2:
1174         return KSAUDIO_SPEAKER_STEREO;
1175     case 3:
1176         return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
1177     case 4:
1178         return KSAUDIO_SPEAKER_QUAD;    /* not _SURROUND */
1179     case 5:
1180         return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
1181     case 6:
1182         return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
1183     case 7:
1184         return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
1185     case 8:
1186         return KSAUDIO_SPEAKER_7POINT1; /* not 7POINT1_SURROUND */
1187     }
1188     FIXME("Unknown speaker configuration: %u\n", channels);
1189     return 0;
1190 }
1191
1192 static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
1193         AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *fmt,
1194         WAVEFORMATEX **out)
1195 {
1196     ACImpl *This = impl_from_IAudioClient(iface);
1197     snd_pcm_format_mask_t *formats = NULL;
1198     HRESULT hr = S_OK;
1199     WAVEFORMATEX *closest = NULL;
1200     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
1201     unsigned int max = 0, min = 0;
1202     int err;
1203
1204     TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out);
1205
1206     if(!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out))
1207         return E_POINTER;
1208
1209     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
1210         return E_INVALIDARG;
1211
1212     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1213             fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
1214         return E_INVALIDARG;
1215
1216     dump_fmt(fmt);
1217
1218     if(out){
1219         *out = NULL;
1220         if(mode != AUDCLNT_SHAREMODE_SHARED)
1221             out = NULL;
1222     }
1223
1224     EnterCriticalSection(&This->lock);
1225
1226     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
1227         hr = E_FAIL;
1228         goto exit;
1229     }
1230
1231     formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1232             snd_pcm_format_mask_sizeof());
1233     if(!formats){
1234         hr = E_OUTOFMEMORY;
1235         goto exit;
1236     }
1237
1238     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
1239
1240     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
1241             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1242              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
1243         switch(fmt->wBitsPerSample){
1244         case 8:
1245             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
1246                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1247                 goto exit;
1248             }
1249             break;
1250         case 16:
1251             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
1252                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1253                 goto exit;
1254             }
1255             break;
1256         case 24:
1257             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
1258                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1259                 goto exit;
1260             }
1261             break;
1262         case 32:
1263             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
1264                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1265                 goto exit;
1266             }
1267             break;
1268         default:
1269             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1270             goto exit;
1271         }
1272     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
1273             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1274              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
1275         switch(fmt->wBitsPerSample){
1276         case 32:
1277             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
1278                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1279                 goto exit;
1280             }
1281             break;
1282         case 64:
1283             if(!snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT64_LE)){
1284                 hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1285                 goto exit;
1286             }
1287             break;
1288         default:
1289             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1290             goto exit;
1291         }
1292     }else{
1293         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1294         goto exit;
1295     }
1296
1297     closest = clone_format(fmt);
1298     if(!closest){
1299         hr = E_OUTOFMEMORY;
1300         goto exit;
1301     }
1302
1303     if((err = snd_pcm_hw_params_get_rate_min(This->hw_params, &min, NULL)) < 0){
1304         hr = E_FAIL;
1305         WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err));
1306         goto exit;
1307     }
1308
1309     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max, NULL)) < 0){
1310         hr = E_FAIL;
1311         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
1312         goto exit;
1313     }
1314
1315     if(fmt->nSamplesPerSec < min || fmt->nSamplesPerSec > max){
1316         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1317         goto exit;
1318     }
1319
1320     if((err = snd_pcm_hw_params_get_channels_min(This->hw_params, &min)) < 0){
1321         hr = E_FAIL;
1322         WARN("Unable to get min channels: %d (%s)\n", err, snd_strerror(err));
1323         goto exit;
1324     }
1325
1326     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params, &max)) < 0){
1327         hr = E_FAIL;
1328         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
1329         goto exit;
1330     }
1331     if(max > 8)
1332         max = 2;
1333     if(fmt->nChannels > max){
1334         hr = S_FALSE;
1335         closest->nChannels = max;
1336     }else if(fmt->nChannels < min){
1337         hr = S_FALSE;
1338         closest->nChannels = min;
1339     }
1340
1341     if(closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
1342         DWORD mask = get_channel_mask(closest->nChannels);
1343
1344         ((WAVEFORMATEXTENSIBLE*)closest)->dwChannelMask = mask;
1345
1346         if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1347                 fmtex->dwChannelMask != 0 &&
1348                 fmtex->dwChannelMask != mask)
1349             hr = S_FALSE;
1350     }
1351
1352 exit:
1353     LeaveCriticalSection(&This->lock);
1354     HeapFree(GetProcessHeap(), 0, formats);
1355
1356     if(hr == S_FALSE && !out)
1357         hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
1358
1359     if(hr == S_FALSE && out) {
1360         closest->nBlockAlign =
1361             closest->nChannels * closest->wBitsPerSample / 8;
1362         closest->nAvgBytesPerSec =
1363             closest->nBlockAlign * closest->nSamplesPerSec;
1364         *out = closest;
1365     } else
1366         CoTaskMemFree(closest);
1367
1368     TRACE("returning: %08x\n", hr);
1369     return hr;
1370 }
1371
1372 static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface,
1373         WAVEFORMATEX **pwfx)
1374 {
1375     ACImpl *This = impl_from_IAudioClient(iface);
1376     WAVEFORMATEXTENSIBLE *fmt;
1377     snd_pcm_format_mask_t *formats;
1378     unsigned int max_rate, max_channels;
1379     int err;
1380     HRESULT hr = S_OK;
1381
1382     TRACE("(%p)->(%p)\n", This, pwfx);
1383
1384     if(!pwfx)
1385         return E_POINTER;
1386     *pwfx = NULL;
1387
1388     fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
1389     if(!fmt)
1390         return E_OUTOFMEMORY;
1391
1392     formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof());
1393     if(!formats){
1394         CoTaskMemFree(fmt);
1395         return E_OUTOFMEMORY;
1396     }
1397
1398     EnterCriticalSection(&This->lock);
1399
1400     if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
1401         WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
1402         hr = E_FAIL;
1403         goto exit;
1404     }
1405
1406     snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
1407
1408     fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
1409     if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
1410         fmt->Format.wBitsPerSample = 32;
1411         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
1412     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S16_LE)){
1413         fmt->Format.wBitsPerSample = 16;
1414         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1415     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_U8)){
1416         fmt->Format.wBitsPerSample = 8;
1417         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1418     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S32_LE)){
1419         fmt->Format.wBitsPerSample = 32;
1420         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1421     }else if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_S24_3LE)){
1422         fmt->Format.wBitsPerSample = 24;
1423         fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1424     }else{
1425         ERR("Didn't recognize any available ALSA formats\n");
1426         hr = E_FAIL;
1427         goto exit;
1428     }
1429
1430     if((err = snd_pcm_hw_params_get_channels_max(This->hw_params,
1431                     &max_channels)) < 0){
1432         WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
1433         hr = E_FAIL;
1434         goto exit;
1435     }
1436
1437     if(max_channels > 2){
1438         FIXME("Don't know what to do with %u channels, pretending there's "
1439                 "only 2 channels\n", max_channels);
1440         fmt->Format.nChannels = 2;
1441     }else
1442         fmt->Format.nChannels = max_channels;
1443
1444     fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
1445
1446     if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max_rate,
1447                     NULL)) < 0){
1448         WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
1449         hr = E_FAIL;
1450         goto exit;
1451     }
1452
1453     if(max_rate >= 48000)
1454         fmt->Format.nSamplesPerSec = 48000;
1455     else if(max_rate >= 44100)
1456         fmt->Format.nSamplesPerSec = 44100;
1457     else if(max_rate >= 22050)
1458         fmt->Format.nSamplesPerSec = 22050;
1459     else if(max_rate >= 11025)
1460         fmt->Format.nSamplesPerSec = 11025;
1461     else if(max_rate >= 8000)
1462         fmt->Format.nSamplesPerSec = 8000;
1463     else{
1464         ERR("Unknown max rate: %u\n", max_rate);
1465         hr = E_FAIL;
1466         goto exit;
1467     }
1468
1469     fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
1470             fmt->Format.nChannels) / 8;
1471     fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
1472         fmt->Format.nBlockAlign;
1473
1474     fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
1475     fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1476
1477     dump_fmt((WAVEFORMATEX*)fmt);
1478     *pwfx = (WAVEFORMATEX*)fmt;
1479
1480 exit:
1481     LeaveCriticalSection(&This->lock);
1482     if(FAILED(hr))
1483         CoTaskMemFree(fmt);
1484     HeapFree(GetProcessHeap(), 0, formats);
1485
1486     return hr;
1487 }
1488
1489 static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
1490         REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
1491 {
1492     ACImpl *This = impl_from_IAudioClient(iface);
1493
1494     TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
1495
1496     if(!defperiod && !minperiod)
1497         return E_POINTER;
1498
1499     if(defperiod)
1500         *defperiod = DefaultPeriod;
1501     if(minperiod)
1502         *minperiod = MinimumPeriod;
1503
1504     return S_OK;
1505 }
1506
1507 static snd_pcm_sframes_t alsa_write_best_effort(snd_pcm_t *handle, BYTE *buf,
1508         snd_pcm_uframes_t frames, ACImpl *This)
1509 {
1510     snd_pcm_sframes_t written;
1511
1512     if(This->session->mute){
1513         int err;
1514         if((err = snd_pcm_format_set_silence(This->alsa_format, buf,
1515                         frames * This->fmt->nChannels)) < 0)
1516             WARN("Setting buffer to silence failed: %d (%s)\n", err,
1517                     snd_strerror(err));
1518     }
1519
1520     written = snd_pcm_writei(handle, buf, frames);
1521     if(written < 0){
1522         int ret;
1523
1524         if(written == -EAGAIN)
1525             /* buffer full */
1526             return 0;
1527
1528         WARN("writei failed, recovering: %ld (%s)\n", written,
1529                 snd_strerror(written));
1530
1531         ret = snd_pcm_recover(handle, written, 0);
1532         if(ret < 0){
1533             WARN("Could not recover: %d (%s)\n", ret, snd_strerror(ret));
1534             return ret;
1535         }
1536
1537         written = snd_pcm_writei(handle, buf, frames);
1538     }
1539
1540     return written;
1541 }
1542
1543 static void alsa_write_data(ACImpl *This)
1544 {
1545     snd_pcm_sframes_t written;
1546     snd_pcm_uframes_t to_write, avail;
1547     int err;
1548     BYTE *buf =
1549         This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
1550
1551     /* this call seems to be required to get an accurate snd_pcm_state() */
1552     avail = snd_pcm_avail_update(This->pcm_handle);
1553
1554     if(snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_XRUN ||
1555             avail > This->alsa_bufsize_frames){
1556         TRACE("XRun state, recovering\n");
1557
1558         if((err = snd_pcm_recover(This->pcm_handle, -EPIPE, 1)) < 0)
1559             WARN("snd_pcm_recover failed: %d (%s)\n", err, snd_strerror(err));
1560
1561         if((err = snd_pcm_reset(This->pcm_handle)) < 0)
1562             WARN("snd_pcm_reset failed: %d (%s)\n", err, snd_strerror(err));
1563
1564         if((err = snd_pcm_prepare(This->pcm_handle)) < 0)
1565             WARN("snd_pcm_prepare failed: %d (%s)\n", err, snd_strerror(err));
1566     }
1567
1568     if(This->held_frames == 0)
1569         return;
1570
1571     if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
1572         to_write = This->bufsize_frames - This->lcl_offs_frames;
1573     else
1574         to_write = This->held_frames;
1575
1576     written = alsa_write_best_effort(This->pcm_handle, buf, to_write, This);
1577     if(written < 0){
1578         WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1579         return;
1580     }
1581
1582     This->lcl_offs_frames += written;
1583     This->lcl_offs_frames %= This->bufsize_frames;
1584     This->held_frames -= written;
1585
1586     if(written < to_write){
1587         /* ALSA buffer probably full */
1588         return;
1589     }
1590
1591     if(This->held_frames){
1592         /* wrapped and have some data back at the start to write */
1593         written = alsa_write_best_effort(This->pcm_handle, This->local_buffer,
1594                 This->held_frames, This);
1595         if(written < 0){
1596             WARN("Couldn't write: %ld (%s)\n", written, snd_strerror(written));
1597             return;
1598         }
1599
1600         This->lcl_offs_frames += written;
1601         This->lcl_offs_frames %= This->bufsize_frames;
1602         This->held_frames -= written;
1603     }
1604 }
1605
1606 static void alsa_read_data(ACImpl *This)
1607 {
1608     snd_pcm_sframes_t pos, readable, nread;
1609
1610     pos = (This->held_frames + This->lcl_offs_frames) % This->bufsize_frames;
1611     readable = This->bufsize_frames - pos;
1612
1613     nread = snd_pcm_readi(This->pcm_handle,
1614             This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1615     if(nread < 0){
1616         int ret;
1617
1618         WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
1619
1620         ret = snd_pcm_recover(This->pcm_handle, nread, 0);
1621         if(ret < 0){
1622             WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
1623             return;
1624         }
1625
1626         nread = snd_pcm_readi(This->pcm_handle,
1627                 This->local_buffer + pos * This->fmt->nBlockAlign, readable);
1628         if(nread < 0){
1629             WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
1630             return;
1631         }
1632     }
1633
1634     if(This->session->mute){
1635         int err;
1636         if((err = snd_pcm_format_set_silence(This->alsa_format,
1637                         This->local_buffer + pos * This->fmt->nBlockAlign,
1638                         nread)) < 0)
1639             WARN("Setting buffer to silence failed: %d (%s)\n", err,
1640                     snd_strerror(err));
1641     }
1642
1643     This->held_frames += nread;
1644
1645     if(This->held_frames > This->bufsize_frames){
1646         WARN("Overflow of unread data\n");
1647         This->lcl_offs_frames += This->held_frames;
1648         This->lcl_offs_frames %= This->bufsize_frames;
1649         This->held_frames = This->bufsize_frames;
1650     }
1651 }
1652
1653 static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
1654 {
1655     ACImpl *This = user;
1656
1657     EnterCriticalSection(&This->lock);
1658
1659     if(This->started){
1660         if(This->dataflow == eRender)
1661             alsa_write_data(This);
1662         else if(This->dataflow == eCapture)
1663             alsa_read_data(This);
1664
1665         if(This->event)
1666             SetEvent(This->event);
1667     }
1668
1669     LeaveCriticalSection(&This->lock);
1670 }
1671
1672 static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
1673 {
1674     ACImpl *This = impl_from_IAudioClient(iface);
1675
1676     TRACE("(%p)\n", This);
1677
1678     EnterCriticalSection(&This->lock);
1679
1680     if(!This->initted){
1681         LeaveCriticalSection(&This->lock);
1682         return AUDCLNT_E_NOT_INITIALIZED;
1683     }
1684
1685     if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
1686         LeaveCriticalSection(&This->lock);
1687         return AUDCLNT_E_EVENTHANDLE_NOT_SET;
1688     }
1689
1690     if(This->started){
1691         LeaveCriticalSection(&This->lock);
1692         return AUDCLNT_E_NOT_STOPPED;
1693     }
1694
1695     if(This->dataflow == eCapture){
1696         /* dump any data that might be leftover in the ALSA capture buffer */
1697         snd_pcm_readi(This->pcm_handle, This->local_buffer,
1698                 This->bufsize_frames);
1699     }
1700
1701     if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
1702             This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
1703         LeaveCriticalSection(&This->lock);
1704         WARN("Unable to create timer: %u\n", GetLastError());
1705         return E_FAIL;
1706     }
1707
1708     This->started = TRUE;
1709
1710     LeaveCriticalSection(&This->lock);
1711
1712     return S_OK;
1713 }
1714
1715 static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
1716 {
1717     ACImpl *This = impl_from_IAudioClient(iface);
1718     HANDLE event;
1719     BOOL wait;
1720
1721     TRACE("(%p)\n", This);
1722
1723     EnterCriticalSection(&This->lock);
1724
1725     if(!This->initted){
1726         LeaveCriticalSection(&This->lock);
1727         return AUDCLNT_E_NOT_INITIALIZED;
1728     }
1729
1730     if(!This->started){
1731         LeaveCriticalSection(&This->lock);
1732         return S_FALSE;
1733     }
1734
1735     if(snd_pcm_drop(This->pcm_handle) < 0)
1736         WARN("snd_pcm_drop failed\n");
1737
1738     if(snd_pcm_reset(This->pcm_handle) < 0)
1739         WARN("snd_pcm_reset failed\n");
1740
1741     if(snd_pcm_prepare(This->pcm_handle) < 0)
1742         WARN("snd_pcm_prepare failed\n");
1743
1744     event = CreateEventW(NULL, TRUE, FALSE, NULL);
1745     wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event);
1746     if(wait)
1747         WARN("DeleteTimerQueueTimer error %u\n", GetLastError());
1748     wait = wait && GetLastError() == ERROR_IO_PENDING;
1749
1750     This->started = FALSE;
1751
1752     LeaveCriticalSection(&This->lock);
1753
1754     if(event && wait)
1755         WaitForSingleObject(event, INFINITE);
1756     CloseHandle(event);
1757
1758     return S_OK;
1759 }
1760
1761 static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
1762 {
1763     ACImpl *This = impl_from_IAudioClient(iface);
1764
1765     TRACE("(%p)\n", This);
1766
1767     EnterCriticalSection(&This->lock);
1768
1769     if(!This->initted){
1770         LeaveCriticalSection(&This->lock);
1771         return AUDCLNT_E_NOT_INITIALIZED;
1772     }
1773
1774     if(This->started){
1775         LeaveCriticalSection(&This->lock);
1776         return AUDCLNT_E_NOT_STOPPED;
1777     }
1778
1779     if(This->buf_state != NOT_LOCKED){
1780         LeaveCriticalSection(&This->lock);
1781         return AUDCLNT_E_BUFFER_OPERATION_PENDING;
1782     }
1783
1784     if(snd_pcm_drop(This->pcm_handle) < 0)
1785         WARN("snd_pcm_drop failed\n");
1786
1787     if(snd_pcm_reset(This->pcm_handle) < 0)
1788         WARN("snd_pcm_reset failed\n");
1789
1790     if(snd_pcm_prepare(This->pcm_handle) < 0)
1791         WARN("snd_pcm_prepare failed\n");
1792
1793     This->last_pos_frames = 0;
1794     This->held_frames = 0;
1795     This->written_frames = 0;
1796     This->lcl_offs_frames = 0;
1797
1798     LeaveCriticalSection(&This->lock);
1799
1800     return S_OK;
1801 }
1802
1803 static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface,
1804         HANDLE event)
1805 {
1806     ACImpl *This = impl_from_IAudioClient(iface);
1807
1808     TRACE("(%p)->(%p)\n", This, event);
1809
1810     if(!event)
1811         return E_INVALIDARG;
1812
1813     EnterCriticalSection(&This->lock);
1814
1815     if(!This->initted){
1816         LeaveCriticalSection(&This->lock);
1817         return AUDCLNT_E_NOT_INITIALIZED;
1818     }
1819
1820     if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
1821         LeaveCriticalSection(&This->lock);
1822         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
1823     }
1824
1825     This->event = event;
1826
1827     LeaveCriticalSection(&This->lock);
1828
1829     return S_OK;
1830 }
1831
1832 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1833         void **ppv)
1834 {
1835     ACImpl *This = impl_from_IAudioClient(iface);
1836
1837     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1838
1839     if(!ppv)
1840         return E_POINTER;
1841     *ppv = NULL;
1842
1843     EnterCriticalSection(&This->lock);
1844
1845     if(!This->initted){
1846         LeaveCriticalSection(&This->lock);
1847         return AUDCLNT_E_NOT_INITIALIZED;
1848     }
1849
1850     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1851         if(This->dataflow != eRender){
1852             LeaveCriticalSection(&This->lock);
1853             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1854         }
1855         IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
1856         *ppv = &This->IAudioRenderClient_iface;
1857     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1858         if(This->dataflow != eCapture){
1859             LeaveCriticalSection(&This->lock);
1860             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1861         }
1862         IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
1863         *ppv = &This->IAudioCaptureClient_iface;
1864     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1865         IAudioClock_AddRef(&This->IAudioClock_iface);
1866         *ppv = &This->IAudioClock_iface;
1867     }else if(IsEqualIID(riid, &IID_IAudioStreamVolume)){
1868         IAudioStreamVolume_AddRef(&This->IAudioStreamVolume_iface);
1869         *ppv = &This->IAudioStreamVolume_iface;
1870     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1871         if(!This->session_wrapper){
1872             This->session_wrapper = AudioSessionWrapper_Create(This);
1873             if(!This->session_wrapper){
1874                 LeaveCriticalSection(&This->lock);
1875                 return E_OUTOFMEMORY;
1876             }
1877         }else
1878             IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
1879
1880         *ppv = &This->session_wrapper->IAudioSessionControl2_iface;
1881     }else if(IsEqualIID(riid, &IID_IChannelAudioVolume)){
1882         if(!This->session_wrapper){
1883             This->session_wrapper = AudioSessionWrapper_Create(This);
1884             if(!This->session_wrapper){
1885                 LeaveCriticalSection(&This->lock);
1886                 return E_OUTOFMEMORY;
1887             }
1888         }else
1889             IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
1890
1891         *ppv = &This->session_wrapper->IChannelAudioVolume_iface;
1892     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1893         if(!This->session_wrapper){
1894             This->session_wrapper = AudioSessionWrapper_Create(This);
1895             if(!This->session_wrapper){
1896                 LeaveCriticalSection(&This->lock);
1897                 return E_OUTOFMEMORY;
1898             }
1899         }else
1900             ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
1901
1902         *ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
1903     }
1904
1905     if(*ppv){
1906         LeaveCriticalSection(&This->lock);
1907         return S_OK;
1908     }
1909
1910     LeaveCriticalSection(&This->lock);
1911
1912     FIXME("stub %s\n", debugstr_guid(riid));
1913     return E_NOINTERFACE;
1914 }
1915
1916 static const IAudioClientVtbl AudioClient_Vtbl =
1917 {
1918     AudioClient_QueryInterface,
1919     AudioClient_AddRef,
1920     AudioClient_Release,
1921     AudioClient_Initialize,
1922     AudioClient_GetBufferSize,
1923     AudioClient_GetStreamLatency,
1924     AudioClient_GetCurrentPadding,
1925     AudioClient_IsFormatSupported,
1926     AudioClient_GetMixFormat,
1927     AudioClient_GetDevicePeriod,
1928     AudioClient_Start,
1929     AudioClient_Stop,
1930     AudioClient_Reset,
1931     AudioClient_SetEventHandle,
1932     AudioClient_GetService
1933 };
1934
1935 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1936         IAudioRenderClient *iface, REFIID riid, void **ppv)
1937 {
1938     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1939
1940     if(!ppv)
1941         return E_POINTER;
1942     *ppv = NULL;
1943
1944     if(IsEqualIID(riid, &IID_IUnknown) ||
1945             IsEqualIID(riid, &IID_IAudioRenderClient))
1946         *ppv = iface;
1947     if(*ppv){
1948         IUnknown_AddRef((IUnknown*)*ppv);
1949         return S_OK;
1950     }
1951
1952     WARN("Unknown interface %s\n", debugstr_guid(riid));
1953     return E_NOINTERFACE;
1954 }
1955
1956 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1957 {
1958     ACImpl *This = impl_from_IAudioRenderClient(iface);
1959     return AudioClient_AddRef(&This->IAudioClient_iface);
1960 }
1961
1962 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1963 {
1964     ACImpl *This = impl_from_IAudioRenderClient(iface);
1965     return AudioClient_Release(&This->IAudioClient_iface);
1966 }
1967
1968 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1969         UINT32 frames, BYTE **data)
1970 {
1971     ACImpl *This = impl_from_IAudioRenderClient(iface);
1972     UINT32 write_pos;
1973     UINT32 pad;
1974     HRESULT hr;
1975
1976     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1977
1978     if(!data)
1979         return E_POINTER;
1980
1981     EnterCriticalSection(&This->lock);
1982
1983     if(This->buf_state != NOT_LOCKED){
1984         LeaveCriticalSection(&This->lock);
1985         return AUDCLNT_E_OUT_OF_ORDER;
1986     }
1987
1988     if(!frames){
1989         This->buf_state = LOCKED_NORMAL;
1990         LeaveCriticalSection(&This->lock);
1991         return S_OK;
1992     }
1993
1994     hr = IAudioClient_GetCurrentPadding(&This->IAudioClient_iface, &pad);
1995     if(FAILED(hr)){
1996         LeaveCriticalSection(&This->lock);
1997         return hr;
1998     }
1999
2000     if(pad + frames > This->bufsize_frames){
2001         LeaveCriticalSection(&This->lock);
2002         return AUDCLNT_E_BUFFER_TOO_LARGE;
2003     }
2004
2005     write_pos =
2006         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
2007     if(write_pos + frames > This->bufsize_frames){
2008         if(This->tmp_buffer_frames < frames){
2009             if(This->tmp_buffer)
2010                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
2011                         This->tmp_buffer, frames * This->fmt->nBlockAlign);
2012             else
2013                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
2014                         frames * This->fmt->nBlockAlign);
2015             if(!This->tmp_buffer){
2016                 LeaveCriticalSection(&This->lock);
2017                 return E_OUTOFMEMORY;
2018             }
2019             This->tmp_buffer_frames = frames;
2020         }
2021         *data = This->tmp_buffer;
2022         This->buf_state = LOCKED_WRAPPED;
2023     }else{
2024         *data = This->local_buffer + write_pos * This->fmt->nBlockAlign;
2025         This->buf_state = LOCKED_NORMAL;
2026     }
2027
2028     LeaveCriticalSection(&This->lock);
2029
2030     return S_OK;
2031 }
2032
2033 static void alsa_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_frames)
2034 {
2035     snd_pcm_uframes_t write_offs_frames =
2036         (This->lcl_offs_frames + This->held_frames) % This->bufsize_frames;
2037     UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
2038     snd_pcm_uframes_t chunk_frames = This->bufsize_frames - write_offs_frames;
2039     UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
2040     UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
2041
2042     if(written_bytes <= chunk_bytes){
2043         memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
2044     }else{
2045         memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
2046         memcpy(This->local_buffer, buffer + chunk_bytes,
2047                 written_bytes - chunk_bytes);
2048     }
2049 }
2050
2051 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
2052         IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
2053 {
2054     ACImpl *This = impl_from_IAudioRenderClient(iface);
2055     BYTE *buffer;
2056
2057     TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
2058
2059     EnterCriticalSection(&This->lock);
2060
2061     if(This->buf_state == NOT_LOCKED || !written_frames){
2062         This->buf_state = NOT_LOCKED;
2063         LeaveCriticalSection(&This->lock);
2064         return written_frames ? AUDCLNT_E_OUT_OF_ORDER : S_OK;
2065     }
2066
2067     if(This->buf_state == LOCKED_NORMAL)
2068         buffer = This->local_buffer + This->fmt->nBlockAlign *
2069           ((This->lcl_offs_frames + This->held_frames) % This->bufsize_frames);
2070     else
2071         buffer = This->tmp_buffer;
2072
2073     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
2074         if(This->fmt->wBitsPerSample == 8)
2075             memset(buffer, 128, written_frames * This->fmt->nBlockAlign);
2076         else
2077             memset(buffer, 0, written_frames * This->fmt->nBlockAlign);
2078     }
2079
2080     if(This->buf_state == LOCKED_WRAPPED)
2081         alsa_wrap_buffer(This, buffer, written_frames);
2082
2083     This->held_frames += written_frames;
2084     This->written_frames += written_frames;
2085     This->buf_state = NOT_LOCKED;
2086
2087     LeaveCriticalSection(&This->lock);
2088
2089     return S_OK;
2090 }
2091
2092 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
2093     AudioRenderClient_QueryInterface,
2094     AudioRenderClient_AddRef,
2095     AudioRenderClient_Release,
2096     AudioRenderClient_GetBuffer,
2097     AudioRenderClient_ReleaseBuffer
2098 };
2099
2100 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
2101         IAudioCaptureClient *iface, REFIID riid, void **ppv)
2102 {
2103     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2104
2105     if(!ppv)
2106         return E_POINTER;
2107     *ppv = NULL;
2108
2109     if(IsEqualIID(riid, &IID_IUnknown) ||
2110             IsEqualIID(riid, &IID_IAudioCaptureClient))
2111         *ppv = iface;
2112     if(*ppv){
2113         IUnknown_AddRef((IUnknown*)*ppv);
2114         return S_OK;
2115     }
2116
2117     WARN("Unknown interface %s\n", debugstr_guid(riid));
2118     return E_NOINTERFACE;
2119 }
2120
2121 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
2122 {
2123     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2124     return IAudioClient_AddRef(&This->IAudioClient_iface);
2125 }
2126
2127 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
2128 {
2129     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2130     return IAudioClient_Release(&This->IAudioClient_iface);
2131 }
2132
2133 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
2134         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
2135         UINT64 *qpcpos)
2136 {
2137     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2138     HRESULT hr;
2139
2140     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
2141             devpos, qpcpos);
2142
2143     if(!data || !frames || !flags)
2144         return E_POINTER;
2145
2146     EnterCriticalSection(&This->lock);
2147
2148     if(This->buf_state != NOT_LOCKED){
2149         LeaveCriticalSection(&This->lock);
2150         return AUDCLNT_E_OUT_OF_ORDER;
2151     }
2152
2153     hr = IAudioCaptureClient_GetNextPacketSize(iface, frames);
2154     if(FAILED(hr)){
2155         LeaveCriticalSection(&This->lock);
2156         return hr;
2157     }
2158
2159     *flags = 0;
2160
2161     if(This->lcl_offs_frames + *frames > This->bufsize_frames){
2162         UINT32 chunk_bytes, offs_bytes, frames_bytes;
2163         if(This->tmp_buffer_frames < *frames){
2164             if(This->tmp_buffer)
2165                 This->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0,
2166                         This->tmp_buffer, *frames * This->fmt->nBlockAlign);
2167             else
2168                 This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
2169                         *frames * This->fmt->nBlockAlign);
2170             if(!This->tmp_buffer){
2171                 LeaveCriticalSection(&This->lock);
2172                 return E_OUTOFMEMORY;
2173             }
2174             This->tmp_buffer_frames = *frames;
2175         }
2176
2177         *data = This->tmp_buffer;
2178         chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
2179             This->fmt->nBlockAlign;
2180         offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
2181         frames_bytes = *frames * This->fmt->nBlockAlign;
2182         memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
2183         memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
2184                 frames_bytes - chunk_bytes);
2185     }else
2186         *data = This->local_buffer +
2187             This->lcl_offs_frames * This->fmt->nBlockAlign;
2188
2189     This->buf_state = LOCKED_NORMAL;
2190
2191     if(devpos || qpcpos)
2192         IAudioClock_GetPosition(&This->IAudioClock_iface, devpos, qpcpos);
2193
2194     LeaveCriticalSection(&This->lock);
2195
2196     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2197 }
2198
2199 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
2200         IAudioCaptureClient *iface, UINT32 done)
2201 {
2202     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2203
2204     TRACE("(%p)->(%u)\n", This, done);
2205
2206     EnterCriticalSection(&This->lock);
2207
2208     if(This->buf_state == NOT_LOCKED){
2209         LeaveCriticalSection(&This->lock);
2210         return AUDCLNT_E_OUT_OF_ORDER;
2211     }
2212
2213     This->held_frames -= done;
2214     This->lcl_offs_frames += done;
2215     This->lcl_offs_frames %= This->bufsize_frames;
2216
2217     This->buf_state = NOT_LOCKED;
2218
2219     LeaveCriticalSection(&This->lock);
2220
2221     return S_OK;
2222 }
2223
2224 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
2225         IAudioCaptureClient *iface, UINT32 *frames)
2226 {
2227     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2228
2229     TRACE("(%p)->(%p)\n", This, frames);
2230
2231     return AudioClient_GetCurrentPadding(&This->IAudioClient_iface, frames);
2232 }
2233
2234 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
2235 {
2236     AudioCaptureClient_QueryInterface,
2237     AudioCaptureClient_AddRef,
2238     AudioCaptureClient_Release,
2239     AudioCaptureClient_GetBuffer,
2240     AudioCaptureClient_ReleaseBuffer,
2241     AudioCaptureClient_GetNextPacketSize
2242 };
2243
2244 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
2245         REFIID riid, void **ppv)
2246 {
2247     ACImpl *This = impl_from_IAudioClock(iface);
2248
2249     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2250
2251     if(!ppv)
2252         return E_POINTER;
2253     *ppv = NULL;
2254
2255     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
2256         *ppv = iface;
2257     else if(IsEqualIID(riid, &IID_IAudioClock2))
2258         *ppv = &This->IAudioClock2_iface;
2259     if(*ppv){
2260         IUnknown_AddRef((IUnknown*)*ppv);
2261         return S_OK;
2262     }
2263
2264     WARN("Unknown interface %s\n", debugstr_guid(riid));
2265     return E_NOINTERFACE;
2266 }
2267
2268 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
2269 {
2270     ACImpl *This = impl_from_IAudioClock(iface);
2271     return IAudioClient_AddRef(&This->IAudioClient_iface);
2272 }
2273
2274 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
2275 {
2276     ACImpl *This = impl_from_IAudioClock(iface);
2277     return IAudioClient_Release(&This->IAudioClient_iface);
2278 }
2279
2280 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
2281 {
2282     ACImpl *This = impl_from_IAudioClock(iface);
2283
2284     TRACE("(%p)->(%p)\n", This, freq);
2285
2286     *freq = This->fmt->nSamplesPerSec;
2287
2288     return S_OK;
2289 }
2290
2291 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2292         UINT64 *qpctime)
2293 {
2294     ACImpl *This = impl_from_IAudioClock(iface);
2295     UINT64 written_frames, position;
2296     UINT32 held_frames;
2297     int err;
2298     snd_pcm_state_t alsa_state;
2299     snd_pcm_uframes_t avail_frames;
2300     snd_pcm_sframes_t delay_frames;
2301
2302     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2303
2304     if(!pos)
2305         return E_POINTER;
2306
2307     EnterCriticalSection(&This->lock);
2308
2309     /* call required to get accurate snd_pcm_state() */
2310     avail_frames = snd_pcm_avail_update(This->pcm_handle);
2311     alsa_state = snd_pcm_state(This->pcm_handle);
2312     written_frames = This->written_frames;
2313     held_frames = This->held_frames;
2314
2315     err = snd_pcm_delay(This->pcm_handle, &delay_frames);
2316     if(err < 0){
2317         /* old Pulse, shortly after start */
2318         WARN("snd_pcm_delay failed in state %u: %d (%s)\n", alsa_state, err, snd_strerror(err));
2319     }
2320
2321     if(This->dataflow == eRender){
2322         position = written_frames - held_frames; /* maximum */
2323         if(!This->started || alsa_state > SND_PCM_STATE_RUNNING)
2324             ; /* mmdevapi stopped or ALSA underrun: pretend everything was played */
2325         else if(err<0 || delay_frames > position - This->last_pos_frames)
2326             /* Pulse bug: past underrun, despite recovery, avail_frames & delay
2327              * may be larger than alsa_bufsize_frames, as if cumulating frames. */
2328             /* Pulse bug: EIO(-5) shortly after starting: nothing played */
2329             position = This->last_pos_frames;
2330         else if(delay_frames > 0)
2331             position -= delay_frames;
2332     }else
2333         position = written_frames + held_frames;
2334
2335     /* ensure monotic growth */
2336     This->last_pos_frames = position;
2337
2338     LeaveCriticalSection(&This->lock);
2339
2340     TRACE("frames written: %u, held: %u, avail: %ld, delay: %ld state %d, pos: %u\n",
2341           (UINT32)(written_frames%1000000000), held_frames,
2342           avail_frames, delay_frames, alsa_state, (UINT32)(position%1000000000));
2343     *pos = position;
2344
2345     if(qpctime){
2346         LARGE_INTEGER stamp, freq;
2347         QueryPerformanceCounter(&stamp);
2348         QueryPerformanceFrequency(&freq);
2349         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2350     }
2351
2352     return S_OK;
2353 }
2354
2355 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2356         DWORD *chars)
2357 {
2358     ACImpl *This = impl_from_IAudioClock(iface);
2359
2360     TRACE("(%p)->(%p)\n", This, chars);
2361
2362     if(!chars)
2363         return E_POINTER;
2364
2365     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2366
2367     return S_OK;
2368 }
2369
2370 static const IAudioClockVtbl AudioClock_Vtbl =
2371 {
2372     AudioClock_QueryInterface,
2373     AudioClock_AddRef,
2374     AudioClock_Release,
2375     AudioClock_GetFrequency,
2376     AudioClock_GetPosition,
2377     AudioClock_GetCharacteristics
2378 };
2379
2380 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2381         REFIID riid, void **ppv)
2382 {
2383     ACImpl *This = impl_from_IAudioClock2(iface);
2384     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2385 }
2386
2387 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2388 {
2389     ACImpl *This = impl_from_IAudioClock2(iface);
2390     return IAudioClient_AddRef(&This->IAudioClient_iface);
2391 }
2392
2393 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2394 {
2395     ACImpl *This = impl_from_IAudioClock2(iface);
2396     return IAudioClient_Release(&This->IAudioClient_iface);
2397 }
2398
2399 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2400         UINT64 *pos, UINT64 *qpctime)
2401 {
2402     ACImpl *This = impl_from_IAudioClock2(iface);
2403
2404     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2405
2406     return E_NOTIMPL;
2407 }
2408
2409 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2410 {
2411     AudioClock2_QueryInterface,
2412     AudioClock2_AddRef,
2413     AudioClock2_Release,
2414     AudioClock2_GetDevicePosition
2415 };
2416
2417 static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client)
2418 {
2419     AudioSessionWrapper *ret;
2420
2421     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2422             sizeof(AudioSessionWrapper));
2423     if(!ret)
2424         return NULL;
2425
2426     ret->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
2427     ret->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
2428     ret->IChannelAudioVolume_iface.lpVtbl = &ChannelAudioVolume_Vtbl;
2429
2430     ret->ref = 1;
2431
2432     ret->client = client;
2433     if(client){
2434         ret->session = client->session;
2435         AudioClient_AddRef(&client->IAudioClient_iface);
2436     }
2437
2438     return ret;
2439 }
2440
2441 static HRESULT WINAPI AudioSessionControl_QueryInterface(
2442         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
2443 {
2444     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2445
2446     if(!ppv)
2447         return E_POINTER;
2448     *ppv = NULL;
2449
2450     if(IsEqualIID(riid, &IID_IUnknown) ||
2451             IsEqualIID(riid, &IID_IAudioSessionControl) ||
2452             IsEqualIID(riid, &IID_IAudioSessionControl2))
2453         *ppv = iface;
2454     if(*ppv){
2455         IUnknown_AddRef((IUnknown*)*ppv);
2456         return S_OK;
2457     }
2458
2459     WARN("Unknown interface %s\n", debugstr_guid(riid));
2460     return E_NOINTERFACE;
2461 }
2462
2463 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
2464 {
2465     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2466     ULONG ref;
2467     ref = InterlockedIncrement(&This->ref);
2468     TRACE("(%p) Refcount now %u\n", This, ref);
2469     return ref;
2470 }
2471
2472 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
2473 {
2474     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2475     ULONG ref;
2476     ref = InterlockedDecrement(&This->ref);
2477     TRACE("(%p) Refcount now %u\n", This, ref);
2478     if(!ref){
2479         if(This->client){
2480             EnterCriticalSection(&This->client->lock);
2481             This->client->session_wrapper = NULL;
2482             LeaveCriticalSection(&This->client->lock);
2483             AudioClient_Release(&This->client->IAudioClient_iface);
2484         }
2485         HeapFree(GetProcessHeap(), 0, This);
2486     }
2487     return ref;
2488 }
2489
2490 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
2491         AudioSessionState *state)
2492 {
2493     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2494     ACImpl *client;
2495
2496     TRACE("(%p)->(%p)\n", This, state);
2497
2498     if(!state)
2499         return NULL_PTR_ERR;
2500
2501     EnterCriticalSection(&g_sessions_lock);
2502
2503     if(list_empty(&This->session->clients)){
2504         *state = AudioSessionStateExpired;
2505         LeaveCriticalSection(&g_sessions_lock);
2506         return S_OK;
2507     }
2508
2509     LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
2510         EnterCriticalSection(&client->lock);
2511         if(client->started){
2512             *state = AudioSessionStateActive;
2513             LeaveCriticalSection(&client->lock);
2514             LeaveCriticalSection(&g_sessions_lock);
2515             return S_OK;
2516         }
2517         LeaveCriticalSection(&client->lock);
2518     }
2519
2520     LeaveCriticalSection(&g_sessions_lock);
2521
2522     *state = AudioSessionStateInactive;
2523
2524     return S_OK;
2525 }
2526
2527 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
2528         IAudioSessionControl2 *iface, WCHAR **name)
2529 {
2530     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2531
2532     FIXME("(%p)->(%p) - stub\n", This, name);
2533
2534     return E_NOTIMPL;
2535 }
2536
2537 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
2538         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
2539 {
2540     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2541
2542     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
2543
2544     return E_NOTIMPL;
2545 }
2546
2547 static HRESULT WINAPI AudioSessionControl_GetIconPath(
2548         IAudioSessionControl2 *iface, WCHAR **path)
2549 {
2550     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2551
2552     FIXME("(%p)->(%p) - stub\n", This, path);
2553
2554     return E_NOTIMPL;
2555 }
2556
2557 static HRESULT WINAPI AudioSessionControl_SetIconPath(
2558         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
2559 {
2560     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2561
2562     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
2563
2564     return E_NOTIMPL;
2565 }
2566
2567 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
2568         IAudioSessionControl2 *iface, GUID *group)
2569 {
2570     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2571
2572     FIXME("(%p)->(%p) - stub\n", This, group);
2573
2574     return E_NOTIMPL;
2575 }
2576
2577 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
2578         IAudioSessionControl2 *iface, const GUID *group, const GUID *session)
2579 {
2580     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2581
2582     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
2583             debugstr_guid(session));
2584
2585     return E_NOTIMPL;
2586 }
2587
2588 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
2589         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2590 {
2591     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2592
2593     FIXME("(%p)->(%p) - stub\n", This, events);
2594
2595     return S_OK;
2596 }
2597
2598 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
2599         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2600 {
2601     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2602
2603     FIXME("(%p)->(%p) - stub\n", This, events);
2604
2605     return S_OK;
2606 }
2607
2608 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
2609         IAudioSessionControl2 *iface, WCHAR **id)
2610 {
2611     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2612
2613     FIXME("(%p)->(%p) - stub\n", This, id);
2614
2615     return E_NOTIMPL;
2616 }
2617
2618 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
2619         IAudioSessionControl2 *iface, WCHAR **id)
2620 {
2621     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2622
2623     FIXME("(%p)->(%p) - stub\n", This, id);
2624
2625     return E_NOTIMPL;
2626 }
2627
2628 static HRESULT WINAPI AudioSessionControl_GetProcessId(
2629         IAudioSessionControl2 *iface, DWORD *pid)
2630 {
2631     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2632
2633     TRACE("(%p)->(%p)\n", This, pid);
2634
2635     if(!pid)
2636         return E_POINTER;
2637
2638     *pid = GetCurrentProcessId();
2639
2640     return S_OK;
2641 }
2642
2643 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
2644         IAudioSessionControl2 *iface)
2645 {
2646     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2647
2648     TRACE("(%p)\n", This);
2649
2650     return S_FALSE;
2651 }
2652
2653 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
2654         IAudioSessionControl2 *iface, BOOL optout)
2655 {
2656     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2657
2658     TRACE("(%p)->(%d)\n", This, optout);
2659
2660     return S_OK;
2661 }
2662
2663 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
2664 {
2665     AudioSessionControl_QueryInterface,
2666     AudioSessionControl_AddRef,
2667     AudioSessionControl_Release,
2668     AudioSessionControl_GetState,
2669     AudioSessionControl_GetDisplayName,
2670     AudioSessionControl_SetDisplayName,
2671     AudioSessionControl_GetIconPath,
2672     AudioSessionControl_SetIconPath,
2673     AudioSessionControl_GetGroupingParam,
2674     AudioSessionControl_SetGroupingParam,
2675     AudioSessionControl_RegisterAudioSessionNotification,
2676     AudioSessionControl_UnregisterAudioSessionNotification,
2677     AudioSessionControl_GetSessionIdentifier,
2678     AudioSessionControl_GetSessionInstanceIdentifier,
2679     AudioSessionControl_GetProcessId,
2680     AudioSessionControl_IsSystemSoundsSession,
2681     AudioSessionControl_SetDuckingPreference
2682 };
2683
2684 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
2685         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
2686 {
2687     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2688
2689     if(!ppv)
2690         return E_POINTER;
2691     *ppv = NULL;
2692
2693     if(IsEqualIID(riid, &IID_IUnknown) ||
2694             IsEqualIID(riid, &IID_ISimpleAudioVolume))
2695         *ppv = iface;
2696     if(*ppv){
2697         IUnknown_AddRef((IUnknown*)*ppv);
2698         return S_OK;
2699     }
2700
2701     WARN("Unknown interface %s\n", debugstr_guid(riid));
2702     return E_NOINTERFACE;
2703 }
2704
2705 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
2706 {
2707     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2708     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
2709 }
2710
2711 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
2712 {
2713     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2714     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
2715 }
2716
2717 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
2718         ISimpleAudioVolume *iface, float level, const GUID *context)
2719 {
2720     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2721     AudioSession *session = This->session;
2722
2723     TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
2724
2725     if(level < 0.f || level > 1.f)
2726         return E_INVALIDARG;
2727
2728     if(context)
2729         FIXME("Notifications not supported yet\n");
2730
2731     TRACE("ALSA does not support volume control\n");
2732
2733     EnterCriticalSection(&session->lock);
2734
2735     session->master_vol = level;
2736
2737     LeaveCriticalSection(&session->lock);
2738
2739     return S_OK;
2740 }
2741
2742 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
2743         ISimpleAudioVolume *iface, float *level)
2744 {
2745     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2746     AudioSession *session = This->session;
2747
2748     TRACE("(%p)->(%p)\n", session, level);
2749
2750     if(!level)
2751         return NULL_PTR_ERR;
2752
2753     *level = session->master_vol;
2754
2755     return S_OK;
2756 }
2757
2758 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
2759         BOOL mute, const GUID *context)
2760 {
2761     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2762     AudioSession *session = This->session;
2763
2764     TRACE("(%p)->(%u, %p)\n", session, mute, context);
2765
2766     if(context)
2767         FIXME("Notifications not supported yet\n");
2768
2769     session->mute = mute;
2770
2771     return S_OK;
2772 }
2773
2774 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
2775         BOOL *mute)
2776 {
2777     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2778     AudioSession *session = This->session;
2779
2780     TRACE("(%p)->(%p)\n", session, mute);
2781
2782     if(!mute)
2783         return NULL_PTR_ERR;
2784
2785     *mute = session->mute;
2786
2787     return S_OK;
2788 }
2789
2790 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
2791 {
2792     SimpleAudioVolume_QueryInterface,
2793     SimpleAudioVolume_AddRef,
2794     SimpleAudioVolume_Release,
2795     SimpleAudioVolume_SetMasterVolume,
2796     SimpleAudioVolume_GetMasterVolume,
2797     SimpleAudioVolume_SetMute,
2798     SimpleAudioVolume_GetMute
2799 };
2800
2801 static HRESULT WINAPI AudioStreamVolume_QueryInterface(
2802         IAudioStreamVolume *iface, REFIID riid, void **ppv)
2803 {
2804     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2805
2806     if(!ppv)
2807         return E_POINTER;
2808     *ppv = NULL;
2809
2810     if(IsEqualIID(riid, &IID_IUnknown) ||
2811             IsEqualIID(riid, &IID_IAudioStreamVolume))
2812         *ppv = iface;
2813     if(*ppv){
2814         IUnknown_AddRef((IUnknown*)*ppv);
2815         return S_OK;
2816     }
2817
2818     WARN("Unknown interface %s\n", debugstr_guid(riid));
2819     return E_NOINTERFACE;
2820 }
2821
2822 static ULONG WINAPI AudioStreamVolume_AddRef(IAudioStreamVolume *iface)
2823 {
2824     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2825     return IAudioClient_AddRef(&This->IAudioClient_iface);
2826 }
2827
2828 static ULONG WINAPI AudioStreamVolume_Release(IAudioStreamVolume *iface)
2829 {
2830     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2831     return IAudioClient_Release(&This->IAudioClient_iface);
2832 }
2833
2834 static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
2835         IAudioStreamVolume *iface, UINT32 *out)
2836 {
2837     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2838
2839     TRACE("(%p)->(%p)\n", This, out);
2840
2841     if(!out)
2842         return E_POINTER;
2843
2844     *out = This->fmt->nChannels;
2845
2846     return S_OK;
2847 }
2848
2849 static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
2850         IAudioStreamVolume *iface, UINT32 index, float level)
2851 {
2852     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2853
2854     TRACE("(%p)->(%d, %f)\n", This, index, level);
2855
2856     if(level < 0.f || level > 1.f)
2857         return E_INVALIDARG;
2858
2859     if(index >= This->fmt->nChannels)
2860         return E_INVALIDARG;
2861
2862     TRACE("ALSA does not support volume control\n");
2863
2864     EnterCriticalSection(&This->lock);
2865
2866     This->vols[index] = level;
2867
2868     LeaveCriticalSection(&This->lock);
2869
2870     return S_OK;
2871 }
2872
2873 static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
2874         IAudioStreamVolume *iface, UINT32 index, float *level)
2875 {
2876     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2877
2878     TRACE("(%p)->(%d, %p)\n", This, index, level);
2879
2880     if(!level)
2881         return E_POINTER;
2882
2883     if(index >= This->fmt->nChannels)
2884         return E_INVALIDARG;
2885
2886     *level = This->vols[index];
2887
2888     return S_OK;
2889 }
2890
2891 static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
2892         IAudioStreamVolume *iface, UINT32 count, const float *levels)
2893 {
2894     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2895     int i;
2896
2897     TRACE("(%p)->(%d, %p)\n", This, count, levels);
2898
2899     if(!levels)
2900         return E_POINTER;
2901
2902     if(count != This->fmt->nChannels)
2903         return E_INVALIDARG;
2904
2905     TRACE("ALSA does not support volume control\n");
2906
2907     EnterCriticalSection(&This->lock);
2908
2909     for(i = 0; i < count; ++i)
2910         This->vols[i] = levels[i];
2911
2912     LeaveCriticalSection(&This->lock);
2913
2914     return S_OK;
2915 }
2916
2917 static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
2918         IAudioStreamVolume *iface, UINT32 count, float *levels)
2919 {
2920     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2921     int i;
2922
2923     TRACE("(%p)->(%d, %p)\n", This, count, levels);
2924
2925     if(!levels)
2926         return E_POINTER;
2927
2928     if(count != This->fmt->nChannels)
2929         return E_INVALIDARG;
2930
2931     EnterCriticalSection(&This->lock);
2932
2933     for(i = 0; i < count; ++i)
2934         levels[i] = This->vols[i];
2935
2936     LeaveCriticalSection(&This->lock);
2937
2938     return S_OK;
2939 }
2940
2941 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
2942 {
2943     AudioStreamVolume_QueryInterface,
2944     AudioStreamVolume_AddRef,
2945     AudioStreamVolume_Release,
2946     AudioStreamVolume_GetChannelCount,
2947     AudioStreamVolume_SetChannelVolume,
2948     AudioStreamVolume_GetChannelVolume,
2949     AudioStreamVolume_SetAllVolumes,
2950     AudioStreamVolume_GetAllVolumes
2951 };
2952
2953 static HRESULT WINAPI ChannelAudioVolume_QueryInterface(
2954         IChannelAudioVolume *iface, REFIID riid, void **ppv)
2955 {
2956     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2957
2958     if(!ppv)
2959         return E_POINTER;
2960     *ppv = NULL;
2961
2962     if(IsEqualIID(riid, &IID_IUnknown) ||
2963             IsEqualIID(riid, &IID_IChannelAudioVolume))
2964         *ppv = iface;
2965     if(*ppv){
2966         IUnknown_AddRef((IUnknown*)*ppv);
2967         return S_OK;
2968     }
2969
2970     WARN("Unknown interface %s\n", debugstr_guid(riid));
2971     return E_NOINTERFACE;
2972 }
2973
2974 static ULONG WINAPI ChannelAudioVolume_AddRef(IChannelAudioVolume *iface)
2975 {
2976     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2977     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
2978 }
2979
2980 static ULONG WINAPI ChannelAudioVolume_Release(IChannelAudioVolume *iface)
2981 {
2982     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2983     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
2984 }
2985
2986 static HRESULT WINAPI ChannelAudioVolume_GetChannelCount(
2987         IChannelAudioVolume *iface, UINT32 *out)
2988 {
2989     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
2990     AudioSession *session = This->session;
2991
2992     TRACE("(%p)->(%p)\n", session, out);
2993
2994     if(!out)
2995         return NULL_PTR_ERR;
2996
2997     *out = session->channel_count;
2998
2999     return S_OK;
3000 }
3001
3002 static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
3003         IChannelAudioVolume *iface, UINT32 index, float level,
3004         const GUID *context)
3005 {
3006     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3007     AudioSession *session = This->session;
3008
3009     TRACE("(%p)->(%d, %f, %s)\n", session, index, level,
3010             wine_dbgstr_guid(context));
3011
3012     if(level < 0.f || level > 1.f)
3013         return E_INVALIDARG;
3014
3015     if(index >= session->channel_count)
3016         return E_INVALIDARG;
3017
3018     if(context)
3019         FIXME("Notifications not supported yet\n");
3020
3021     TRACE("ALSA does not support volume control\n");
3022
3023     EnterCriticalSection(&session->lock);
3024
3025     session->channel_vols[index] = level;
3026
3027     LeaveCriticalSection(&session->lock);
3028
3029     return S_OK;
3030 }
3031
3032 static HRESULT WINAPI ChannelAudioVolume_GetChannelVolume(
3033         IChannelAudioVolume *iface, UINT32 index, float *level)
3034 {
3035     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3036     AudioSession *session = This->session;
3037
3038     TRACE("(%p)->(%d, %p)\n", session, index, level);
3039
3040     if(!level)
3041         return NULL_PTR_ERR;
3042
3043     if(index >= session->channel_count)
3044         return E_INVALIDARG;
3045
3046     *level = session->channel_vols[index];
3047
3048     return S_OK;
3049 }
3050
3051 static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
3052         IChannelAudioVolume *iface, UINT32 count, const float *levels,
3053         const GUID *context)
3054 {
3055     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3056     AudioSession *session = This->session;
3057     int i;
3058
3059     TRACE("(%p)->(%d, %p, %s)\n", session, count, levels,
3060             wine_dbgstr_guid(context));
3061
3062     if(!levels)
3063         return NULL_PTR_ERR;
3064
3065     if(count != session->channel_count)
3066         return E_INVALIDARG;
3067
3068     if(context)
3069         FIXME("Notifications not supported yet\n");
3070
3071     TRACE("ALSA does not support volume control\n");
3072
3073     EnterCriticalSection(&session->lock);
3074
3075     for(i = 0; i < count; ++i)
3076         session->channel_vols[i] = levels[i];
3077
3078     LeaveCriticalSection(&session->lock);
3079
3080     return S_OK;
3081 }
3082
3083 static HRESULT WINAPI ChannelAudioVolume_GetAllVolumes(
3084         IChannelAudioVolume *iface, UINT32 count, float *levels)
3085 {
3086     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3087     AudioSession *session = This->session;
3088     int i;
3089
3090     TRACE("(%p)->(%d, %p)\n", session, count, levels);
3091
3092     if(!levels)
3093         return NULL_PTR_ERR;
3094
3095     if(count != session->channel_count)
3096         return E_INVALIDARG;
3097
3098     for(i = 0; i < count; ++i)
3099         levels[i] = session->channel_vols[i];
3100
3101     return S_OK;
3102 }
3103
3104 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
3105 {
3106     ChannelAudioVolume_QueryInterface,
3107     ChannelAudioVolume_AddRef,
3108     ChannelAudioVolume_Release,
3109     ChannelAudioVolume_GetChannelCount,
3110     ChannelAudioVolume_SetChannelVolume,
3111     ChannelAudioVolume_GetChannelVolume,
3112     ChannelAudioVolume_SetAllVolumes,
3113     ChannelAudioVolume_GetAllVolumes
3114 };
3115
3116 static HRESULT WINAPI AudioSessionManager_QueryInterface(IAudioSessionManager2 *iface,
3117         REFIID riid, void **ppv)
3118 {
3119     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
3120
3121     if(!ppv)
3122         return E_POINTER;
3123     *ppv = NULL;
3124
3125     if(IsEqualIID(riid, &IID_IUnknown) ||
3126             IsEqualIID(riid, &IID_IAudioSessionManager) ||
3127             IsEqualIID(riid, &IID_IAudioSessionManager2))
3128         *ppv = iface;
3129     if(*ppv){
3130         IUnknown_AddRef((IUnknown*)*ppv);
3131         return S_OK;
3132     }
3133
3134     WARN("Unknown interface %s\n", debugstr_guid(riid));
3135     return E_NOINTERFACE;
3136 }
3137
3138 static ULONG WINAPI AudioSessionManager_AddRef(IAudioSessionManager2 *iface)
3139 {
3140     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3141     ULONG ref;
3142     ref = InterlockedIncrement(&This->ref);
3143     TRACE("(%p) Refcount now %u\n", This, ref);
3144     return ref;
3145 }
3146
3147 static ULONG WINAPI AudioSessionManager_Release(IAudioSessionManager2 *iface)
3148 {
3149     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3150     ULONG ref;
3151     ref = InterlockedDecrement(&This->ref);
3152     TRACE("(%p) Refcount now %u\n", This, ref);
3153     if(!ref)
3154         HeapFree(GetProcessHeap(), 0, This);
3155     return ref;
3156 }
3157
3158 static HRESULT WINAPI AudioSessionManager_GetAudioSessionControl(
3159         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3160         IAudioSessionControl **out)
3161 {
3162     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3163     AudioSession *session;
3164     AudioSessionWrapper *wrapper;
3165     HRESULT hr;
3166
3167     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3168             flags, out);
3169
3170     hr = get_audio_session(session_guid, This->device, 0, &session);
3171     if(FAILED(hr))
3172         return hr;
3173
3174     wrapper = AudioSessionWrapper_Create(NULL);
3175     if(!wrapper)
3176         return E_OUTOFMEMORY;
3177
3178     wrapper->session = session;
3179
3180     *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface;
3181
3182     return S_OK;
3183 }
3184
3185 static HRESULT WINAPI AudioSessionManager_GetSimpleAudioVolume(
3186         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3187         ISimpleAudioVolume **out)
3188 {
3189     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3190     AudioSession *session;
3191     AudioSessionWrapper *wrapper;
3192     HRESULT hr;
3193
3194     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3195             flags, out);
3196
3197     hr = get_audio_session(session_guid, This->device, 0, &session);
3198     if(FAILED(hr))
3199         return hr;
3200
3201     wrapper = AudioSessionWrapper_Create(NULL);
3202     if(!wrapper)
3203         return E_OUTOFMEMORY;
3204
3205     wrapper->session = session;
3206
3207     *out = &wrapper->ISimpleAudioVolume_iface;
3208
3209     return S_OK;
3210 }
3211
3212 static HRESULT WINAPI AudioSessionManager_GetSessionEnumerator(
3213         IAudioSessionManager2 *iface, IAudioSessionEnumerator **out)
3214 {
3215     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3216     FIXME("(%p)->(%p) - stub\n", This, out);
3217     return E_NOTIMPL;
3218 }
3219
3220 static HRESULT WINAPI AudioSessionManager_RegisterSessionNotification(
3221         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3222 {
3223     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3224     FIXME("(%p)->(%p) - stub\n", This, notification);
3225     return E_NOTIMPL;
3226 }
3227
3228 static HRESULT WINAPI AudioSessionManager_UnregisterSessionNotification(
3229         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3230 {
3231     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3232     FIXME("(%p)->(%p) - stub\n", This, notification);
3233     return E_NOTIMPL;
3234 }
3235
3236 static HRESULT WINAPI AudioSessionManager_RegisterDuckNotification(
3237         IAudioSessionManager2 *iface, const WCHAR *session_id,
3238         IAudioVolumeDuckNotification *notification)
3239 {
3240     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3241     FIXME("(%p)->(%p) - stub\n", This, notification);
3242     return E_NOTIMPL;
3243 }
3244
3245 static HRESULT WINAPI AudioSessionManager_UnregisterDuckNotification(
3246         IAudioSessionManager2 *iface,
3247         IAudioVolumeDuckNotification *notification)
3248 {
3249     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3250     FIXME("(%p)->(%p) - stub\n", This, notification);
3251     return E_NOTIMPL;
3252 }
3253
3254 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl =
3255 {
3256     AudioSessionManager_QueryInterface,
3257     AudioSessionManager_AddRef,
3258     AudioSessionManager_Release,
3259     AudioSessionManager_GetAudioSessionControl,
3260     AudioSessionManager_GetSimpleAudioVolume,
3261     AudioSessionManager_GetSessionEnumerator,
3262     AudioSessionManager_RegisterSessionNotification,
3263     AudioSessionManager_UnregisterSessionNotification,
3264     AudioSessionManager_RegisterDuckNotification,
3265     AudioSessionManager_UnregisterDuckNotification
3266 };
3267
3268 HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
3269         IAudioSessionManager2 **out)
3270 {
3271     SessionMgr *This;
3272
3273     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SessionMgr));
3274     if(!This)
3275         return E_OUTOFMEMORY;
3276
3277     This->IAudioSessionManager2_iface.lpVtbl = &AudioSessionManager2_Vtbl;
3278     This->device = device;
3279     This->ref = 1;
3280
3281     *out = &This->IAudioSessionManager2_iface;
3282
3283     return S_OK;
3284 }