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