mshtml: Added partial IHTMLDocument2::put_designMode implementation.
[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     if (This->event){
1820         OSSpinLockUnlock(&This->lock);
1821         FIXME("called twice\n");
1822         return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
1823     }
1824
1825     This->event = event;
1826
1827     OSSpinLockUnlock(&This->lock);
1828
1829     return S_OK;
1830 }
1831
1832 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1833         void **ppv)
1834 {
1835     ACImpl *This = impl_from_IAudioClient(iface);
1836
1837     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1838
1839     if(!ppv)
1840         return E_POINTER;
1841     *ppv = NULL;
1842
1843     OSSpinLockLock(&This->lock);
1844
1845     if(!This->aqueue){
1846         OSSpinLockUnlock(&This->lock);
1847         return AUDCLNT_E_NOT_INITIALIZED;
1848     }
1849
1850     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1851         if(This->dataflow != eRender){
1852             OSSpinLockUnlock(&This->lock);
1853             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1854         }
1855         IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface);
1856         *ppv = &This->IAudioRenderClient_iface;
1857     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1858         if(This->dataflow != eCapture){
1859             OSSpinLockUnlock(&This->lock);
1860             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1861         }
1862         IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface);
1863         *ppv = &This->IAudioCaptureClient_iface;
1864     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1865         IAudioClock_AddRef(&This->IAudioClock_iface);
1866         *ppv = &This->IAudioClock_iface;
1867     }else if(IsEqualIID(riid, &IID_IAudioStreamVolume)){
1868         IAudioStreamVolume_AddRef(&This->IAudioStreamVolume_iface);
1869         *ppv = &This->IAudioStreamVolume_iface;
1870     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1871         if(!This->session_wrapper){
1872             This->session_wrapper = AudioSessionWrapper_Create(This);
1873             if(!This->session_wrapper){
1874                 OSSpinLockUnlock(&This->lock);
1875                 return E_OUTOFMEMORY;
1876             }
1877         }else
1878             IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface);
1879
1880         *ppv = &This->session_wrapper->IAudioSessionControl2_iface;
1881     }else if(IsEqualIID(riid, &IID_IChannelAudioVolume)){
1882         if(!This->session_wrapper){
1883             This->session_wrapper = AudioSessionWrapper_Create(This);
1884             if(!This->session_wrapper){
1885                 OSSpinLockUnlock(&This->lock);
1886                 return E_OUTOFMEMORY;
1887             }
1888         }else
1889             IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface);
1890
1891         *ppv = &This->session_wrapper->IChannelAudioVolume_iface;
1892     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1893         if(!This->session_wrapper){
1894             This->session_wrapper = AudioSessionWrapper_Create(This);
1895             if(!This->session_wrapper){
1896                 OSSpinLockUnlock(&This->lock);
1897                 return E_OUTOFMEMORY;
1898             }
1899         }else
1900             ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface);
1901
1902         *ppv = &This->session_wrapper->ISimpleAudioVolume_iface;
1903     }
1904
1905     if(*ppv){
1906         OSSpinLockUnlock(&This->lock);
1907         return S_OK;
1908     }
1909
1910     OSSpinLockUnlock(&This->lock);
1911
1912     FIXME("stub %s\n", debugstr_guid(riid));
1913     return E_NOINTERFACE;
1914 }
1915
1916 static const IAudioClientVtbl AudioClient_Vtbl =
1917 {
1918     AudioClient_QueryInterface,
1919     AudioClient_AddRef,
1920     AudioClient_Release,
1921     AudioClient_Initialize,
1922     AudioClient_GetBufferSize,
1923     AudioClient_GetStreamLatency,
1924     AudioClient_GetCurrentPadding,
1925     AudioClient_IsFormatSupported,
1926     AudioClient_GetMixFormat,
1927     AudioClient_GetDevicePeriod,
1928     AudioClient_Start,
1929     AudioClient_Stop,
1930     AudioClient_Reset,
1931     AudioClient_SetEventHandle,
1932     AudioClient_GetService
1933 };
1934
1935 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1936         IAudioRenderClient *iface, REFIID riid, void **ppv)
1937 {
1938     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1939
1940     if(!ppv)
1941         return E_POINTER;
1942     *ppv = NULL;
1943
1944     if(IsEqualIID(riid, &IID_IUnknown) ||
1945             IsEqualIID(riid, &IID_IAudioRenderClient))
1946         *ppv = iface;
1947     if(*ppv){
1948         IUnknown_AddRef((IUnknown*)*ppv);
1949         return S_OK;
1950     }
1951
1952     WARN("Unknown interface %s\n", debugstr_guid(riid));
1953     return E_NOINTERFACE;
1954 }
1955
1956 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1957 {
1958     ACImpl *This = impl_from_IAudioRenderClient(iface);
1959     return AudioClient_AddRef(&This->IAudioClient_iface);
1960 }
1961
1962 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1963 {
1964     ACImpl *This = impl_from_IAudioRenderClient(iface);
1965     return AudioClient_Release(&This->IAudioClient_iface);
1966 }
1967
1968 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1969         UINT32 frames, BYTE **data)
1970 {
1971     ACImpl *This = impl_from_IAudioRenderClient(iface);
1972     AQBuffer *buf;
1973     UINT32 pad, bytes;
1974     HRESULT hr;
1975     OSStatus sc;
1976
1977     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1978
1979     if(!data)
1980         return E_POINTER;
1981     *data = NULL;
1982
1983     OSSpinLockLock(&This->lock);
1984
1985     if(This->getbuf_last){
1986         OSSpinLockUnlock(&This->lock);
1987         return AUDCLNT_E_OUT_OF_ORDER;
1988     }
1989
1990     if(!frames){
1991         OSSpinLockUnlock(&This->lock);
1992         return S_OK;
1993     }
1994
1995     hr = AudioClient_GetCurrentPadding_nolock(This, &pad);
1996     if(FAILED(hr)){
1997         OSSpinLockUnlock(&This->lock);
1998         return hr;
1999     }
2000
2001     if(pad + frames > This->bufsize_frames){
2002         OSSpinLockUnlock(&This->lock);
2003         return AUDCLNT_E_BUFFER_TOO_LARGE;
2004     }
2005
2006     bytes = frames * This->fmt->nBlockAlign;
2007     LIST_FOR_EACH_ENTRY(buf, &This->avail_buffers, AQBuffer, entry){
2008         if(buf->buf->mAudioDataBytesCapacity >= bytes){
2009             This->public_buffer = buf->buf;
2010             list_remove(&buf->entry);
2011             break;
2012         }
2013     }
2014
2015     if(&buf->entry == &This->avail_buffers){
2016         sc = AudioQueueAllocateBuffer(This->aqueue, bytes,
2017                 &This->public_buffer);
2018         if(sc != noErr){
2019             This->public_buffer = NULL;
2020             OSSpinLockUnlock(&This->lock);
2021             WARN("Unable to allocate buffer: %lx\n", sc);
2022             return E_OUTOFMEMORY;
2023         }
2024         buf = HeapAlloc(GetProcessHeap(), 0, sizeof(AQBuffer));
2025         if(!buf){
2026             AudioQueueFreeBuffer(This->aqueue, This->public_buffer);
2027             This->public_buffer = NULL;
2028             OSSpinLockUnlock(&This->lock);
2029             return E_OUTOFMEMORY;
2030         }
2031         buf->used = FALSE;
2032         buf->buf = This->public_buffer;
2033         This->public_buffer->mUserData = buf;
2034     }
2035
2036     This->getbuf_last = frames;
2037     *data = This->public_buffer->mAudioData;
2038
2039     OSSpinLockUnlock(&This->lock);
2040
2041     return S_OK;
2042 }
2043
2044 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
2045         IAudioRenderClient *iface, UINT32 frames, DWORD flags)
2046 {
2047     ACImpl *This = impl_from_IAudioRenderClient(iface);
2048     AQBuffer *buf;
2049     AudioTimeStamp start_time, req_time = {0}, *passed_time = NULL;
2050     OSStatus sc;
2051
2052     TRACE("(%p)->(%u, %x)\n", This, frames, flags);
2053
2054     OSSpinLockLock(&This->lock);
2055
2056     if(!frames){
2057         This->getbuf_last = 0;
2058         if(This->public_buffer){
2059             buf = This->public_buffer->mUserData;
2060             list_add_head(&This->avail_buffers, &buf->entry);
2061             This->public_buffer = NULL;
2062         }
2063         OSSpinLockUnlock(&This->lock);
2064         return S_OK;
2065     }
2066
2067     if(!This->getbuf_last){
2068         OSSpinLockUnlock(&This->lock);
2069         return AUDCLNT_E_OUT_OF_ORDER;
2070     }
2071
2072     if(frames > This->getbuf_last){
2073         OSSpinLockUnlock(&This->lock);
2074         return AUDCLNT_E_INVALID_SIZE;
2075     }
2076
2077     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
2078         WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
2079         if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
2080                 (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
2081                  IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
2082                 This->fmt->wBitsPerSample == 8)
2083             memset(This->public_buffer->mAudioData, 128,
2084                     frames * This->fmt->nBlockAlign);
2085         else
2086             memset(This->public_buffer->mAudioData, 0,
2087                     frames * This->fmt->nBlockAlign);
2088     }
2089
2090     This->public_buffer->mAudioDataByteSize = frames * This->fmt->nBlockAlign;
2091
2092     buf = This->public_buffer->mUserData;
2093     buf->used = TRUE;
2094
2095     if(list_empty(&This->queued_bufinfos)){
2096         sc = AudioQueueGetCurrentTime(This->aqueue, NULL, &req_time, NULL);
2097         if(sc == noErr)
2098             passed_time = &req_time;
2099         else
2100             TRACE("AudioQueueGetCurrentTime failed: %lx\n", sc);
2101     }else{
2102         req_time.mSampleTime = This->next_sampletime;
2103         req_time.mFlags = kAudioTimeStampSampleTimeValid;
2104         passed_time = &req_time;
2105     }
2106
2107     sc = AudioQueueEnqueueBufferWithParameters(This->aqueue,
2108             This->public_buffer, 0, NULL, 0, 0, 0, NULL, passed_time,
2109             &start_time);
2110     if(sc != noErr){
2111         OSSpinLockUnlock(&This->lock);
2112         ERR("Unable to enqueue buffer: %lx\n", sc);
2113         return AUDCLNT_E_DEVICE_INVALIDATED;
2114     }
2115     list_add_tail(&This->queued_buffers, &buf->entry);
2116
2117     if(start_time.mFlags & kAudioTimeStampSampleTimeValid){
2118         QueuedBufInfo *bufinfo;
2119
2120         bufinfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*bufinfo));
2121         bufinfo->start_sampletime = start_time.mSampleTime;
2122         bufinfo->start_pos = This->written_frames;
2123         bufinfo->len_frames = frames;
2124
2125         list_add_tail(&This->queued_bufinfos, &bufinfo->entry);
2126
2127         This->next_sampletime = start_time.mSampleTime + bufinfo->len_frames;
2128     }else
2129         WARN("Start time didn't contain valid SampleTime member\n");
2130
2131     if(This->playing == StateStopped)
2132         AudioQueuePrime(This->aqueue, 0, NULL);
2133
2134     This->public_buffer = NULL;
2135     This->getbuf_last = 0;
2136     This->written_frames += frames;
2137     This->inbuf_frames += frames;
2138
2139     OSSpinLockUnlock(&This->lock);
2140
2141     return S_OK;
2142 }
2143
2144 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
2145     AudioRenderClient_QueryInterface,
2146     AudioRenderClient_AddRef,
2147     AudioRenderClient_Release,
2148     AudioRenderClient_GetBuffer,
2149     AudioRenderClient_ReleaseBuffer
2150 };
2151
2152 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
2153         IAudioCaptureClient *iface, REFIID riid, void **ppv)
2154 {
2155     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2156
2157     if(!ppv)
2158         return E_POINTER;
2159     *ppv = NULL;
2160
2161     if(IsEqualIID(riid, &IID_IUnknown) ||
2162             IsEqualIID(riid, &IID_IAudioCaptureClient))
2163         *ppv = iface;
2164     if(*ppv){
2165         IUnknown_AddRef((IUnknown*)*ppv);
2166         return S_OK;
2167     }
2168
2169     WARN("Unknown interface %s\n", debugstr_guid(riid));
2170     return E_NOINTERFACE;
2171 }
2172
2173 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
2174 {
2175     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2176     return IAudioClient_AddRef(&This->IAudioClient_iface);
2177 }
2178
2179 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
2180 {
2181     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2182     return IAudioClient_Release(&This->IAudioClient_iface);
2183 }
2184
2185 static HRESULT AudioCaptureClient_GetNextPacket(ACImpl *This, UINT32 *frames)
2186 {
2187     AQBuffer *buf;
2188     OSStatus sc;
2189
2190     avail_update(This); /* once, not inside loop */
2191
2192     for(;;){
2193         if(!This->public_buffer){
2194             struct list *head = list_head(&This->avail_buffers);
2195
2196             if(!head){
2197                 *frames = 0;
2198                 return S_OK;
2199             }
2200             buf = LIST_ENTRY(head, AQBuffer, entry);
2201             This->public_buffer = buf->buf;
2202             list_remove(&buf->entry);
2203         }else
2204             buf = This->public_buffer->mUserData;
2205         *frames = This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
2206         if(*frames)
2207             return S_OK;
2208
2209         WARN("empty packet\n");
2210         buf->used = TRUE;
2211         sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer, 0, NULL);
2212         if(sc != noErr){
2213             ERR("Unable to enqueue buffer: %lx\n", sc);
2214             /* Release will free This->public_buffer */
2215             return AUDCLNT_E_DEVICE_INVALIDATED;
2216         }else
2217             list_add_tail(&This->queued_buffers, &buf->entry);
2218         This->public_buffer = NULL;
2219     }
2220 }
2221
2222 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
2223         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
2224         UINT64 *qpcpos)
2225 {
2226     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2227     HRESULT hr;
2228
2229     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
2230             devpos, qpcpos);
2231
2232     if(!data || !frames || !flags)
2233         return E_POINTER;
2234
2235     OSSpinLockLock(&This->lock);
2236
2237     if(This->getbuf_last){
2238         OSSpinLockUnlock(&This->lock);
2239         return AUDCLNT_E_OUT_OF_ORDER;
2240     }
2241
2242     hr = AudioCaptureClient_GetNextPacket(This, frames);
2243     if(FAILED(hr)){
2244         OSSpinLockUnlock(&This->lock);
2245         return hr;
2246     }
2247
2248     if((This->getbuf_last = *frames)){
2249         *flags = 0;
2250         *data = This->public_buffer->mAudioData;
2251
2252         if(devpos)
2253             *devpos = This->written_frames;
2254         if(qpcpos){ /* fixme: qpc of recording time */
2255             LARGE_INTEGER stamp, freq;
2256             QueryPerformanceCounter(&stamp);
2257             QueryPerformanceFrequency(&freq);
2258             *qpcpos = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2259         }
2260     }
2261     OSSpinLockUnlock(&This->lock);
2262
2263     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
2264 }
2265
2266 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
2267         IAudioCaptureClient *iface, UINT32 done)
2268 {
2269     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2270     AQBuffer *buf;
2271     OSStatus sc;
2272
2273     TRACE("(%p)->(%u)\n", This, done);
2274
2275     OSSpinLockLock(&This->lock);
2276
2277     if(!done){
2278         This->getbuf_last = 0;
2279         OSSpinLockUnlock(&This->lock);
2280         return S_OK;
2281     }
2282
2283     if(!This->getbuf_last){
2284         OSSpinLockUnlock(&This->lock);
2285         return AUDCLNT_E_OUT_OF_ORDER;
2286     }
2287
2288     if(This->getbuf_last != done){
2289         OSSpinLockUnlock(&This->lock);
2290         return AUDCLNT_E_INVALID_SIZE;
2291     }
2292
2293     This->written_frames += done;
2294     This->inbuf_frames -= done;
2295     This->getbuf_last = 0;
2296
2297     buf = This->public_buffer->mUserData;
2298     buf->used = TRUE;
2299     sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer, 0, NULL);
2300     if(sc != noErr){
2301         OSSpinLockUnlock(&This->lock);
2302         /* fixme: can't zero public_buffer or we lose memory, but then
2303          * GetBuffer will see that packet again and again. */
2304         ERR("Unable to enqueue buffer: %lx\n", sc);
2305         return AUDCLNT_E_DEVICE_INVALIDATED;
2306     }else
2307         list_add_tail(&This->queued_buffers, &buf->entry);
2308     This->public_buffer = NULL;
2309
2310     OSSpinLockUnlock(&This->lock);
2311
2312     return S_OK;
2313 }
2314
2315 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
2316         IAudioCaptureClient *iface, UINT32 *frames)
2317 {
2318     ACImpl *This = impl_from_IAudioCaptureClient(iface);
2319     HRESULT hr;
2320
2321     TRACE("(%p)->(%p)\n", This, frames);
2322
2323     if(!frames)
2324         return E_POINTER;
2325
2326     OSSpinLockLock(&This->lock);
2327
2328     hr = AudioCaptureClient_GetNextPacket(This, frames);
2329
2330     OSSpinLockUnlock(&This->lock);
2331
2332     return hr;
2333 }
2334
2335 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
2336 {
2337     AudioCaptureClient_QueryInterface,
2338     AudioCaptureClient_AddRef,
2339     AudioCaptureClient_Release,
2340     AudioCaptureClient_GetBuffer,
2341     AudioCaptureClient_ReleaseBuffer,
2342     AudioCaptureClient_GetNextPacketSize
2343 };
2344
2345 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
2346         REFIID riid, void **ppv)
2347 {
2348     ACImpl *This = impl_from_IAudioClock(iface);
2349
2350     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2351
2352     if(!ppv)
2353         return E_POINTER;
2354     *ppv = NULL;
2355
2356     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
2357         *ppv = iface;
2358     else if(IsEqualIID(riid, &IID_IAudioClock2))
2359         *ppv = &This->IAudioClock2_iface;
2360     if(*ppv){
2361         IUnknown_AddRef((IUnknown*)*ppv);
2362         return S_OK;
2363     }
2364
2365     WARN("Unknown interface %s\n", debugstr_guid(riid));
2366     return E_NOINTERFACE;
2367 }
2368
2369 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
2370 {
2371     ACImpl *This = impl_from_IAudioClock(iface);
2372     return IAudioClient_AddRef(&This->IAudioClient_iface);
2373 }
2374
2375 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
2376 {
2377     ACImpl *This = impl_from_IAudioClock(iface);
2378     return IAudioClient_Release(&This->IAudioClient_iface);
2379 }
2380
2381 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
2382 {
2383     ACImpl *This = impl_from_IAudioClock(iface);
2384
2385     TRACE("(%p)->(%p)\n", This, freq);
2386
2387     *freq = This->fmt->nSamplesPerSec;
2388
2389     return S_OK;
2390 }
2391
2392 static HRESULT AudioClock_GetPosition_nolock(ACImpl *This,
2393         UINT64 *pos, UINT64 *qpctime)
2394 {
2395     avail_update(This);
2396
2397     if(This->dataflow == eRender)
2398         *pos = get_current_aqbuffer_position(This, BUFPOS_ABSOLUTE);
2399     else
2400         *pos = This->inbuf_frames + This->written_frames;
2401
2402     if(qpctime){
2403         LARGE_INTEGER stamp, freq;
2404         QueryPerformanceCounter(&stamp);
2405         QueryPerformanceFrequency(&freq);
2406         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2407     }
2408
2409     return S_OK;
2410 }
2411
2412 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2413         UINT64 *qpctime)
2414 {
2415     ACImpl *This = impl_from_IAudioClock(iface);
2416     HRESULT hr;
2417
2418     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2419
2420     if(!pos)
2421         return E_POINTER;
2422
2423     OSSpinLockLock(&This->lock);
2424
2425     hr = AudioClock_GetPosition_nolock(This, pos, qpctime);
2426
2427     OSSpinLockUnlock(&This->lock);
2428
2429     return hr;
2430 }
2431
2432 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2433         DWORD *chars)
2434 {
2435     ACImpl *This = impl_from_IAudioClock(iface);
2436
2437     TRACE("(%p)->(%p)\n", This, chars);
2438
2439     if(!chars)
2440         return E_POINTER;
2441
2442     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2443
2444     return S_OK;
2445 }
2446
2447 static const IAudioClockVtbl AudioClock_Vtbl =
2448 {
2449     AudioClock_QueryInterface,
2450     AudioClock_AddRef,
2451     AudioClock_Release,
2452     AudioClock_GetFrequency,
2453     AudioClock_GetPosition,
2454     AudioClock_GetCharacteristics
2455 };
2456
2457 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2458         REFIID riid, void **ppv)
2459 {
2460     ACImpl *This = impl_from_IAudioClock2(iface);
2461     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2462 }
2463
2464 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2465 {
2466     ACImpl *This = impl_from_IAudioClock2(iface);
2467     return IAudioClient_AddRef(&This->IAudioClient_iface);
2468 }
2469
2470 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2471 {
2472     ACImpl *This = impl_from_IAudioClock2(iface);
2473     return IAudioClient_Release(&This->IAudioClient_iface);
2474 }
2475
2476 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2477         UINT64 *pos, UINT64 *qpctime)
2478 {
2479     ACImpl *This = impl_from_IAudioClock2(iface);
2480
2481     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2482
2483     return E_NOTIMPL;
2484 }
2485
2486 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2487 {
2488     AudioClock2_QueryInterface,
2489     AudioClock2_AddRef,
2490     AudioClock2_Release,
2491     AudioClock2_GetDevicePosition
2492 };
2493
2494 static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client)
2495 {
2496     AudioSessionWrapper *ret;
2497
2498     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2499             sizeof(AudioSessionWrapper));
2500     if(!ret)
2501         return NULL;
2502
2503     ret->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
2504     ret->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
2505     ret->IChannelAudioVolume_iface.lpVtbl = &ChannelAudioVolume_Vtbl;
2506
2507     ret->ref = 1;
2508
2509     ret->client = client;
2510     if(client){
2511         ret->session = client->session;
2512         AudioClient_AddRef(&client->IAudioClient_iface);
2513     }
2514
2515     return ret;
2516 }
2517
2518 static HRESULT WINAPI AudioSessionControl_QueryInterface(
2519         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
2520 {
2521     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2522
2523     if(!ppv)
2524         return E_POINTER;
2525     *ppv = NULL;
2526
2527     if(IsEqualIID(riid, &IID_IUnknown) ||
2528             IsEqualIID(riid, &IID_IAudioSessionControl) ||
2529             IsEqualIID(riid, &IID_IAudioSessionControl2))
2530         *ppv = iface;
2531     if(*ppv){
2532         IUnknown_AddRef((IUnknown*)*ppv);
2533         return S_OK;
2534     }
2535
2536     WARN("Unknown interface %s\n", debugstr_guid(riid));
2537     return E_NOINTERFACE;
2538 }
2539
2540 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
2541 {
2542     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2543     ULONG ref;
2544     ref = InterlockedIncrement(&This->ref);
2545     TRACE("(%p) Refcount now %u\n", This, ref);
2546     return ref;
2547 }
2548
2549 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
2550 {
2551     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2552     ULONG ref;
2553     ref = InterlockedDecrement(&This->ref);
2554     TRACE("(%p) Refcount now %u\n", This, ref);
2555     if(!ref){
2556         if(This->client){
2557             OSSpinLockLock(&This->client->lock);
2558             This->client->session_wrapper = NULL;
2559             OSSpinLockUnlock(&This->client->lock);
2560             AudioClient_Release(&This->client->IAudioClient_iface);
2561         }
2562         HeapFree(GetProcessHeap(), 0, This);
2563     }
2564     return ref;
2565 }
2566
2567 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
2568         AudioSessionState *state)
2569 {
2570     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2571     ACImpl *client;
2572
2573     TRACE("(%p)->(%p)\n", This, state);
2574
2575     if(!state)
2576         return NULL_PTR_ERR;
2577
2578     EnterCriticalSection(&g_sessions_lock);
2579
2580     if(list_empty(&This->session->clients)){
2581         *state = AudioSessionStateExpired;
2582         LeaveCriticalSection(&g_sessions_lock);
2583         return S_OK;
2584     }
2585
2586     LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
2587         OSSpinLockLock(&client->lock);
2588         if(client->playing == StatePlaying ||
2589                 client->playing == StateInTransition){
2590             *state = AudioSessionStateActive;
2591             OSSpinLockUnlock(&client->lock);
2592             LeaveCriticalSection(&g_sessions_lock);
2593             return S_OK;
2594         }
2595         OSSpinLockUnlock(&client->lock);
2596     }
2597
2598     LeaveCriticalSection(&g_sessions_lock);
2599
2600     *state = AudioSessionStateInactive;
2601
2602     return S_OK;
2603 }
2604
2605 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
2606         IAudioSessionControl2 *iface, WCHAR **name)
2607 {
2608     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2609
2610     FIXME("(%p)->(%p) - stub\n", This, name);
2611
2612     return E_NOTIMPL;
2613 }
2614
2615 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
2616         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
2617 {
2618     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2619
2620     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
2621
2622     return E_NOTIMPL;
2623 }
2624
2625 static HRESULT WINAPI AudioSessionControl_GetIconPath(
2626         IAudioSessionControl2 *iface, WCHAR **path)
2627 {
2628     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2629
2630     FIXME("(%p)->(%p) - stub\n", This, path);
2631
2632     return E_NOTIMPL;
2633 }
2634
2635 static HRESULT WINAPI AudioSessionControl_SetIconPath(
2636         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
2637 {
2638     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2639
2640     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
2641
2642     return E_NOTIMPL;
2643 }
2644
2645 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
2646         IAudioSessionControl2 *iface, GUID *group)
2647 {
2648     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2649
2650     FIXME("(%p)->(%p) - stub\n", This, group);
2651
2652     return E_NOTIMPL;
2653 }
2654
2655 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
2656         IAudioSessionControl2 *iface, const GUID *group, const GUID *session)
2657 {
2658     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2659
2660     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
2661             debugstr_guid(session));
2662
2663     return E_NOTIMPL;
2664 }
2665
2666 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
2667         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2668 {
2669     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2670
2671     FIXME("(%p)->(%p) - stub\n", This, events);
2672
2673     return S_OK;
2674 }
2675
2676 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
2677         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
2678 {
2679     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2680
2681     FIXME("(%p)->(%p) - stub\n", This, events);
2682
2683     return S_OK;
2684 }
2685
2686 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
2687         IAudioSessionControl2 *iface, WCHAR **id)
2688 {
2689     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2690
2691     FIXME("(%p)->(%p) - stub\n", This, id);
2692
2693     return E_NOTIMPL;
2694 }
2695
2696 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
2697         IAudioSessionControl2 *iface, WCHAR **id)
2698 {
2699     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2700
2701     FIXME("(%p)->(%p) - stub\n", This, id);
2702
2703     return E_NOTIMPL;
2704 }
2705
2706 static HRESULT WINAPI AudioSessionControl_GetProcessId(
2707         IAudioSessionControl2 *iface, DWORD *pid)
2708 {
2709     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2710
2711     TRACE("(%p)->(%p)\n", This, pid);
2712
2713     if(!pid)
2714         return E_POINTER;
2715
2716     *pid = GetCurrentProcessId();
2717
2718     return S_OK;
2719 }
2720
2721 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
2722         IAudioSessionControl2 *iface)
2723 {
2724     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2725
2726     TRACE("(%p)\n", This);
2727
2728     return S_FALSE;
2729 }
2730
2731 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
2732         IAudioSessionControl2 *iface, BOOL optout)
2733 {
2734     AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface);
2735
2736     TRACE("(%p)->(%d)\n", This, optout);
2737
2738     return S_OK;
2739 }
2740
2741 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
2742 {
2743     AudioSessionControl_QueryInterface,
2744     AudioSessionControl_AddRef,
2745     AudioSessionControl_Release,
2746     AudioSessionControl_GetState,
2747     AudioSessionControl_GetDisplayName,
2748     AudioSessionControl_SetDisplayName,
2749     AudioSessionControl_GetIconPath,
2750     AudioSessionControl_SetIconPath,
2751     AudioSessionControl_GetGroupingParam,
2752     AudioSessionControl_SetGroupingParam,
2753     AudioSessionControl_RegisterAudioSessionNotification,
2754     AudioSessionControl_UnregisterAudioSessionNotification,
2755     AudioSessionControl_GetSessionIdentifier,
2756     AudioSessionControl_GetSessionInstanceIdentifier,
2757     AudioSessionControl_GetProcessId,
2758     AudioSessionControl_IsSystemSoundsSession,
2759     AudioSessionControl_SetDuckingPreference
2760 };
2761
2762 /* index == -1 means set all channels, otherwise sets only the given channel */
2763 static HRESULT ca_setvol(ACImpl *This, UINT32 index)
2764 {
2765     float level;
2766     OSStatus sc;
2767
2768     if(index == (UINT32)-1){
2769         HRESULT ret = S_OK;
2770         UINT32 i;
2771         for(i = 0; i < This->fmt->nChannels; ++i){
2772             HRESULT hr;
2773             hr = ca_setvol(This, i);
2774             if(FAILED(hr))
2775                 ret = hr;
2776         }
2777         return ret;
2778     }
2779
2780     if(This->session->mute)
2781         level = 0;
2782     else
2783         level = This->session->master_vol *
2784             This->session->channel_vols[index] * This->vols[index];
2785
2786     sc = AudioQueueSetParameter(This->aqueue, kAudioQueueParam_Volume, level);
2787     if(sc != noErr)
2788         WARN("Setting _Volume property failed: %lx\n", sc);
2789
2790     return S_OK;
2791 }
2792
2793 static HRESULT ca_session_setvol(AudioSession *session, UINT32 index)
2794 {
2795     HRESULT ret = S_OK;
2796     ACImpl *client;
2797
2798     LIST_FOR_EACH_ENTRY(client, &session->clients, ACImpl, entry){
2799         HRESULT hr;
2800         hr = ca_setvol(client, index);
2801         if(FAILED(hr))
2802             ret = hr;
2803     }
2804
2805     return ret;
2806 }
2807
2808 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
2809         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
2810 {
2811     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2812
2813     if(!ppv)
2814         return E_POINTER;
2815     *ppv = NULL;
2816
2817     if(IsEqualIID(riid, &IID_IUnknown) ||
2818             IsEqualIID(riid, &IID_ISimpleAudioVolume))
2819         *ppv = iface;
2820     if(*ppv){
2821         IUnknown_AddRef((IUnknown*)*ppv);
2822         return S_OK;
2823     }
2824
2825     WARN("Unknown interface %s\n", debugstr_guid(riid));
2826     return E_NOINTERFACE;
2827 }
2828
2829 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
2830 {
2831     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2832     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
2833 }
2834
2835 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
2836 {
2837     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2838     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
2839 }
2840
2841 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
2842         ISimpleAudioVolume *iface, float level, const GUID *context)
2843 {
2844     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2845     AudioSession *session = This->session;
2846     HRESULT ret;
2847
2848     TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
2849
2850     if(level < 0.f || level > 1.f)
2851         return E_INVALIDARG;
2852
2853     if(context)
2854         FIXME("Notifications not supported yet\n");
2855
2856     EnterCriticalSection(&session->lock);
2857
2858     session->master_vol = level;
2859
2860     ret = ca_session_setvol(session, -1);
2861
2862     LeaveCriticalSection(&session->lock);
2863
2864     return ret;
2865 }
2866
2867 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
2868         ISimpleAudioVolume *iface, float *level)
2869 {
2870     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2871     AudioSession *session = This->session;
2872
2873     TRACE("(%p)->(%p)\n", session, level);
2874
2875     if(!level)
2876         return NULL_PTR_ERR;
2877
2878     *level = session->master_vol;
2879
2880     return S_OK;
2881 }
2882
2883 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
2884         BOOL mute, const GUID *context)
2885 {
2886     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2887     AudioSession *session = This->session;
2888
2889     TRACE("(%p)->(%u, %p)\n", session, mute, context);
2890
2891     if(context)
2892         FIXME("Notifications not supported yet\n");
2893
2894     EnterCriticalSection(&session->lock);
2895
2896     session->mute = mute;
2897
2898     ca_session_setvol(session, -1);
2899
2900     LeaveCriticalSection(&session->lock);
2901
2902     return S_OK;
2903 }
2904
2905 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
2906         BOOL *mute)
2907 {
2908     AudioSessionWrapper *This = impl_from_ISimpleAudioVolume(iface);
2909     AudioSession *session = This->session;
2910
2911     TRACE("(%p)->(%p)\n", session, mute);
2912
2913     if(!mute)
2914         return NULL_PTR_ERR;
2915
2916     *mute = session->mute;
2917
2918     return S_OK;
2919 }
2920
2921 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
2922 {
2923     SimpleAudioVolume_QueryInterface,
2924     SimpleAudioVolume_AddRef,
2925     SimpleAudioVolume_Release,
2926     SimpleAudioVolume_SetMasterVolume,
2927     SimpleAudioVolume_GetMasterVolume,
2928     SimpleAudioVolume_SetMute,
2929     SimpleAudioVolume_GetMute
2930 };
2931
2932 static HRESULT WINAPI AudioStreamVolume_QueryInterface(
2933         IAudioStreamVolume *iface, REFIID riid, void **ppv)
2934 {
2935     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
2936
2937     if(!ppv)
2938         return E_POINTER;
2939     *ppv = NULL;
2940
2941     if(IsEqualIID(riid, &IID_IUnknown) ||
2942             IsEqualIID(riid, &IID_IAudioStreamVolume))
2943         *ppv = iface;
2944     if(*ppv){
2945         IUnknown_AddRef((IUnknown*)*ppv);
2946         return S_OK;
2947     }
2948
2949     WARN("Unknown interface %s\n", debugstr_guid(riid));
2950     return E_NOINTERFACE;
2951 }
2952
2953 static ULONG WINAPI AudioStreamVolume_AddRef(IAudioStreamVolume *iface)
2954 {
2955     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2956     return IAudioClient_AddRef(&This->IAudioClient_iface);
2957 }
2958
2959 static ULONG WINAPI AudioStreamVolume_Release(IAudioStreamVolume *iface)
2960 {
2961     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2962     return IAudioClient_Release(&This->IAudioClient_iface);
2963 }
2964
2965 static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
2966         IAudioStreamVolume *iface, UINT32 *out)
2967 {
2968     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2969
2970     TRACE("(%p)->(%p)\n", This, out);
2971
2972     if(!out)
2973         return E_POINTER;
2974
2975     *out = This->fmt->nChannels;
2976
2977     return S_OK;
2978 }
2979
2980 static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
2981         IAudioStreamVolume *iface, UINT32 index, float level)
2982 {
2983     ACImpl *This = impl_from_IAudioStreamVolume(iface);
2984     HRESULT ret;
2985
2986     TRACE("(%p)->(%d, %f)\n", This, index, level);
2987
2988     if(level < 0.f || level > 1.f)
2989         return E_INVALIDARG;
2990
2991     if(index >= This->fmt->nChannels)
2992         return E_INVALIDARG;
2993
2994     OSSpinLockLock(&This->lock);
2995
2996     This->vols[index] = level;
2997
2998     WARN("AudioQueue doesn't support per-channel volume control\n");
2999     ret = ca_setvol(This, index);
3000
3001     OSSpinLockUnlock(&This->lock);
3002
3003     return ret;
3004 }
3005
3006 static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
3007         IAudioStreamVolume *iface, UINT32 index, float *level)
3008 {
3009     ACImpl *This = impl_from_IAudioStreamVolume(iface);
3010
3011     TRACE("(%p)->(%d, %p)\n", This, index, level);
3012
3013     if(!level)
3014         return E_POINTER;
3015
3016     if(index >= This->fmt->nChannels)
3017         return E_INVALIDARG;
3018
3019     *level = This->vols[index];
3020
3021     return S_OK;
3022 }
3023
3024 static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
3025         IAudioStreamVolume *iface, UINT32 count, const float *levels)
3026 {
3027     ACImpl *This = impl_from_IAudioStreamVolume(iface);
3028     int i;
3029     HRESULT ret;
3030
3031     TRACE("(%p)->(%d, %p)\n", This, count, levels);
3032
3033     if(!levels)
3034         return E_POINTER;
3035
3036     if(count != This->fmt->nChannels)
3037         return E_INVALIDARG;
3038
3039     OSSpinLockLock(&This->lock);
3040
3041     for(i = 0; i < count; ++i)
3042         This->vols[i] = levels[i];
3043
3044     ret = ca_setvol(This, -1);
3045
3046     OSSpinLockUnlock(&This->lock);
3047
3048     return ret;
3049 }
3050
3051 static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
3052         IAudioStreamVolume *iface, UINT32 count, float *levels)
3053 {
3054     ACImpl *This = impl_from_IAudioStreamVolume(iface);
3055     int i;
3056
3057     TRACE("(%p)->(%d, %p)\n", This, count, levels);
3058
3059     if(!levels)
3060         return E_POINTER;
3061
3062     if(count != This->fmt->nChannels)
3063         return E_INVALIDARG;
3064
3065     OSSpinLockLock(&This->lock);
3066
3067     for(i = 0; i < count; ++i)
3068         levels[i] = This->vols[i];
3069
3070     OSSpinLockUnlock(&This->lock);
3071
3072     return S_OK;
3073 }
3074
3075 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
3076 {
3077     AudioStreamVolume_QueryInterface,
3078     AudioStreamVolume_AddRef,
3079     AudioStreamVolume_Release,
3080     AudioStreamVolume_GetChannelCount,
3081     AudioStreamVolume_SetChannelVolume,
3082     AudioStreamVolume_GetChannelVolume,
3083     AudioStreamVolume_SetAllVolumes,
3084     AudioStreamVolume_GetAllVolumes
3085 };
3086
3087 static HRESULT WINAPI ChannelAudioVolume_QueryInterface(
3088         IChannelAudioVolume *iface, REFIID riid, void **ppv)
3089 {
3090     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
3091
3092     if(!ppv)
3093         return E_POINTER;
3094     *ppv = NULL;
3095
3096     if(IsEqualIID(riid, &IID_IUnknown) ||
3097             IsEqualIID(riid, &IID_IChannelAudioVolume))
3098         *ppv = iface;
3099     if(*ppv){
3100         IUnknown_AddRef((IUnknown*)*ppv);
3101         return S_OK;
3102     }
3103
3104     WARN("Unknown interface %s\n", debugstr_guid(riid));
3105     return E_NOINTERFACE;
3106 }
3107
3108 static ULONG WINAPI ChannelAudioVolume_AddRef(IChannelAudioVolume *iface)
3109 {
3110     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3111     return AudioSessionControl_AddRef(&This->IAudioSessionControl2_iface);
3112 }
3113
3114 static ULONG WINAPI ChannelAudioVolume_Release(IChannelAudioVolume *iface)
3115 {
3116     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3117     return AudioSessionControl_Release(&This->IAudioSessionControl2_iface);
3118 }
3119
3120 static HRESULT WINAPI ChannelAudioVolume_GetChannelCount(
3121         IChannelAudioVolume *iface, UINT32 *out)
3122 {
3123     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3124     AudioSession *session = This->session;
3125
3126     TRACE("(%p)->(%p)\n", session, out);
3127
3128     if(!out)
3129         return NULL_PTR_ERR;
3130
3131     *out = session->channel_count;
3132
3133     return S_OK;
3134 }
3135
3136 static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
3137         IChannelAudioVolume *iface, UINT32 index, float level,
3138         const GUID *context)
3139 {
3140     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3141     AudioSession *session = This->session;
3142     HRESULT ret;
3143
3144     TRACE("(%p)->(%d, %f, %s)\n", session, index, level,
3145             wine_dbgstr_guid(context));
3146
3147     if(level < 0.f || level > 1.f)
3148         return E_INVALIDARG;
3149
3150     if(index >= session->channel_count)
3151         return E_INVALIDARG;
3152
3153     if(context)
3154         FIXME("Notifications not supported yet\n");
3155
3156     EnterCriticalSection(&session->lock);
3157
3158     session->channel_vols[index] = level;
3159
3160     WARN("AudioQueue doesn't support per-channel volume control\n");
3161     ret = ca_session_setvol(session, index);
3162
3163     LeaveCriticalSection(&session->lock);
3164
3165     return ret;
3166 }
3167
3168 static HRESULT WINAPI ChannelAudioVolume_GetChannelVolume(
3169         IChannelAudioVolume *iface, UINT32 index, float *level)
3170 {
3171     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3172     AudioSession *session = This->session;
3173
3174     TRACE("(%p)->(%d, %p)\n", session, index, level);
3175
3176     if(!level)
3177         return NULL_PTR_ERR;
3178
3179     if(index >= session->channel_count)
3180         return E_INVALIDARG;
3181
3182     *level = session->channel_vols[index];
3183
3184     return S_OK;
3185 }
3186
3187 static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
3188         IChannelAudioVolume *iface, UINT32 count, const float *levels,
3189         const GUID *context)
3190 {
3191     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3192     AudioSession *session = This->session;
3193     int i;
3194     HRESULT ret;
3195
3196     TRACE("(%p)->(%d, %p, %s)\n", session, count, levels,
3197             wine_dbgstr_guid(context));
3198
3199     if(!levels)
3200         return NULL_PTR_ERR;
3201
3202     if(count != session->channel_count)
3203         return E_INVALIDARG;
3204
3205     if(context)
3206         FIXME("Notifications not supported yet\n");
3207
3208     EnterCriticalSection(&session->lock);
3209
3210     for(i = 0; i < count; ++i)
3211         session->channel_vols[i] = levels[i];
3212
3213     ret = ca_session_setvol(session, -1);
3214
3215     LeaveCriticalSection(&session->lock);
3216
3217     return ret;
3218 }
3219
3220 static HRESULT WINAPI ChannelAudioVolume_GetAllVolumes(
3221         IChannelAudioVolume *iface, UINT32 count, float *levels)
3222 {
3223     AudioSessionWrapper *This = impl_from_IChannelAudioVolume(iface);
3224     AudioSession *session = This->session;
3225     int i;
3226
3227     TRACE("(%p)->(%d, %p)\n", session, count, levels);
3228
3229     if(!levels)
3230         return NULL_PTR_ERR;
3231
3232     if(count != session->channel_count)
3233         return E_INVALIDARG;
3234
3235     for(i = 0; i < count; ++i)
3236         levels[i] = session->channel_vols[i];
3237
3238     return S_OK;
3239 }
3240
3241 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
3242 {
3243     ChannelAudioVolume_QueryInterface,
3244     ChannelAudioVolume_AddRef,
3245     ChannelAudioVolume_Release,
3246     ChannelAudioVolume_GetChannelCount,
3247     ChannelAudioVolume_SetChannelVolume,
3248     ChannelAudioVolume_GetChannelVolume,
3249     ChannelAudioVolume_SetAllVolumes,
3250     ChannelAudioVolume_GetAllVolumes
3251 };
3252
3253 static HRESULT WINAPI AudioSessionManager_QueryInterface(IAudioSessionManager2 *iface,
3254         REFIID riid, void **ppv)
3255 {
3256     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
3257
3258     if(!ppv)
3259         return E_POINTER;
3260     *ppv = NULL;
3261
3262     if(IsEqualIID(riid, &IID_IUnknown) ||
3263             IsEqualIID(riid, &IID_IAudioSessionManager) ||
3264             IsEqualIID(riid, &IID_IAudioSessionManager2))
3265         *ppv = iface;
3266     if(*ppv){
3267         IUnknown_AddRef((IUnknown*)*ppv);
3268         return S_OK;
3269     }
3270
3271     WARN("Unknown interface %s\n", debugstr_guid(riid));
3272     return E_NOINTERFACE;
3273 }
3274
3275 static ULONG WINAPI AudioSessionManager_AddRef(IAudioSessionManager2 *iface)
3276 {
3277     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3278     ULONG ref;
3279     ref = InterlockedIncrement(&This->ref);
3280     TRACE("(%p) Refcount now %u\n", This, ref);
3281     return ref;
3282 }
3283
3284 static ULONG WINAPI AudioSessionManager_Release(IAudioSessionManager2 *iface)
3285 {
3286     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3287     ULONG ref;
3288     ref = InterlockedDecrement(&This->ref);
3289     TRACE("(%p) Refcount now %u\n", This, ref);
3290     if(!ref)
3291         HeapFree(GetProcessHeap(), 0, This);
3292     return ref;
3293 }
3294
3295 static HRESULT WINAPI AudioSessionManager_GetAudioSessionControl(
3296         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3297         IAudioSessionControl **out)
3298 {
3299     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3300     AudioSession *session;
3301     AudioSessionWrapper *wrapper;
3302     HRESULT hr;
3303
3304     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3305             flags, out);
3306
3307     hr = get_audio_session(session_guid, This->device, 0, &session);
3308     if(FAILED(hr))
3309         return hr;
3310
3311     wrapper = AudioSessionWrapper_Create(NULL);
3312     if(!wrapper)
3313         return E_OUTOFMEMORY;
3314
3315     wrapper->session = session;
3316
3317     *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface;
3318
3319     return S_OK;
3320 }
3321
3322 static HRESULT WINAPI AudioSessionManager_GetSimpleAudioVolume(
3323         IAudioSessionManager2 *iface, const GUID *session_guid, DWORD flags,
3324         ISimpleAudioVolume **out)
3325 {
3326     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3327     AudioSession *session;
3328     AudioSessionWrapper *wrapper;
3329     HRESULT hr;
3330
3331     TRACE("(%p)->(%s, %x, %p)\n", This, debugstr_guid(session_guid),
3332             flags, out);
3333
3334     hr = get_audio_session(session_guid, This->device, 0, &session);
3335     if(FAILED(hr))
3336         return hr;
3337
3338     wrapper = AudioSessionWrapper_Create(NULL);
3339     if(!wrapper)
3340         return E_OUTOFMEMORY;
3341
3342     wrapper->session = session;
3343
3344     *out = &wrapper->ISimpleAudioVolume_iface;
3345
3346     return S_OK;
3347 }
3348
3349 static HRESULT WINAPI AudioSessionManager_GetSessionEnumerator(
3350         IAudioSessionManager2 *iface, IAudioSessionEnumerator **out)
3351 {
3352     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3353     FIXME("(%p)->(%p) - stub\n", This, out);
3354     return E_NOTIMPL;
3355 }
3356
3357 static HRESULT WINAPI AudioSessionManager_RegisterSessionNotification(
3358         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3359 {
3360     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3361     FIXME("(%p)->(%p) - stub\n", This, notification);
3362     return E_NOTIMPL;
3363 }
3364
3365 static HRESULT WINAPI AudioSessionManager_UnregisterSessionNotification(
3366         IAudioSessionManager2 *iface, IAudioSessionNotification *notification)
3367 {
3368     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3369     FIXME("(%p)->(%p) - stub\n", This, notification);
3370     return E_NOTIMPL;
3371 }
3372
3373 static HRESULT WINAPI AudioSessionManager_RegisterDuckNotification(
3374         IAudioSessionManager2 *iface, const WCHAR *session_id,
3375         IAudioVolumeDuckNotification *notification)
3376 {
3377     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3378     FIXME("(%p)->(%p) - stub\n", This, notification);
3379     return E_NOTIMPL;
3380 }
3381
3382 static HRESULT WINAPI AudioSessionManager_UnregisterDuckNotification(
3383         IAudioSessionManager2 *iface,
3384         IAudioVolumeDuckNotification *notification)
3385 {
3386     SessionMgr *This = impl_from_IAudioSessionManager2(iface);
3387     FIXME("(%p)->(%p) - stub\n", This, notification);
3388     return E_NOTIMPL;
3389 }
3390
3391 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl =
3392 {
3393     AudioSessionManager_QueryInterface,
3394     AudioSessionManager_AddRef,
3395     AudioSessionManager_Release,
3396     AudioSessionManager_GetAudioSessionControl,
3397     AudioSessionManager_GetSimpleAudioVolume,
3398     AudioSessionManager_GetSessionEnumerator,
3399     AudioSessionManager_RegisterSessionNotification,
3400     AudioSessionManager_UnregisterSessionNotification,
3401     AudioSessionManager_RegisterDuckNotification,
3402     AudioSessionManager_UnregisterDuckNotification
3403 };
3404
3405 HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
3406         IAudioSessionManager2 **out)
3407 {
3408     SessionMgr *This;
3409
3410     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SessionMgr));
3411     if(!This)
3412         return E_OUTOFMEMORY;
3413
3414     This->IAudioSessionManager2_iface.lpVtbl = &AudioSessionManager2_Vtbl;
3415     This->device = device;
3416     This->ref = 1;
3417
3418     *out = &This->IAudioSessionManager2_iface;
3419
3420     return S_OK;
3421 }