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