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