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