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