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