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