mmdevapi/tests: Add tests for IAudioClient::GetCurrentPadding.
[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 #define INITGUID
22 #include "config.h"
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "wine/debug.h"
31 #include "wine/unicode.h"
32 #include "wine/list.h"
33
34 #include "ole2.h"
35 #include "mmdeviceapi.h"
36 #include "devpkey.h"
37 #include "dshow.h"
38 #include "dsound.h"
39 #include "audioclient.h"
40 #include "endpointvolume.h"
41 #include "audiopolicy.h"
42
43 #include <errno.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <sys/ioctl.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53
54 #include <libkern/OSAtomic.h>
55 #include <CoreAudio/CoreAudio.h>
56 #include <AudioToolbox/AudioQueue.h>
57
58 WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
59
60 #define CAPTURE_BUFFERS 5
61
62 static const REFERENCE_TIME DefaultPeriod = 200000;
63 static const REFERENCE_TIME MinimumPeriod = 100000;
64
65 typedef struct _AQBuffer {
66     AudioQueueBufferRef buf;
67     struct list entry;
68 } AQBuffer;
69
70 typedef struct ACImpl {
71     IAudioClient IAudioClient_iface;
72     IAudioRenderClient IAudioRenderClient_iface;
73     IAudioCaptureClient IAudioCaptureClient_iface;
74     IAudioSessionControl2 IAudioSessionControl2_iface;
75     ISimpleAudioVolume ISimpleAudioVolume_iface;
76     IAudioClock IAudioClock_iface;
77     IAudioClock2 IAudioClock2_iface;
78
79     LONG ref;
80
81     IMMDevice *parent;
82
83     WAVEFORMATEX *fmt;
84
85     EDataFlow dataflow;
86     DWORD flags;
87     AUDCLNT_SHAREMODE share;
88     HANDLE event;
89
90     AudioDeviceID adevid;
91     AudioQueueRef aqueue;
92     HANDLE timer;
93     UINT32 period_ms, bufsize_frames, inbuf_frames, written_frames;
94     UINT64 last_time;
95     AudioQueueBufferRef public_buffer;
96     BOOL getbuf_last;
97     int playing;
98
99     struct list avail_buffers;
100
101     /* We can't use debug printing or {Enter,Leave}CriticalSection from
102      * OSX callback threads, so we use OSX's OSSpinLock for synchronization
103      * instead. OSSpinLock is not a recursive lock, so don't call
104      * synchronized functions while holding the lock. */
105     OSSpinLock lock;
106 } ACImpl;
107
108 enum PlayingStates {
109     StateStopped = 0,
110     StatePlaying,
111     StateInTransition
112 };
113
114 static const IAudioClientVtbl AudioClient_Vtbl;
115 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
116 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
117 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl;
118 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl;
119 static const IAudioClockVtbl AudioClock_Vtbl;
120 static const IAudioClock2Vtbl AudioClock2_Vtbl;
121
122 static HANDLE g_timer_q;
123
124 static HRESULT AudioClock_GetPosition_nolock(ACImpl *This, UINT64 *pos,
125         UINT64 *qpctime, BOOL raw);
126
127 static inline ACImpl *impl_from_IAudioClient(IAudioClient *iface)
128 {
129     return CONTAINING_RECORD(iface, ACImpl, IAudioClient_iface);
130 }
131
132 static inline ACImpl *impl_from_IAudioRenderClient(IAudioRenderClient *iface)
133 {
134     return CONTAINING_RECORD(iface, ACImpl, IAudioRenderClient_iface);
135 }
136
137 static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface)
138 {
139     return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface);
140 }
141
142 static inline ACImpl *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
143 {
144     return CONTAINING_RECORD(iface, ACImpl, IAudioSessionControl2_iface);
145 }
146
147 static inline ACImpl *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
148 {
149     return CONTAINING_RECORD(iface, ACImpl, ISimpleAudioVolume_iface);
150 }
151
152 static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface)
153 {
154     return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface);
155 }
156
157 static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface)
158 {
159     return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface);
160 }
161
162 HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids,
163         AudioDeviceID ***keys, UINT *num, UINT *def_index)
164 {
165     UInt32 devsize, size;
166     AudioDeviceID *devices;
167     AudioDeviceID default_id;
168     AudioObjectPropertyAddress addr;
169     OSStatus sc;
170     int i, ndevices;
171
172     TRACE("%d %p %p %p\n", flow, ids, num, def_index);
173
174     addr.mScope = kAudioObjectPropertyScopeGlobal;
175     addr.mElement = kAudioObjectPropertyElementMaster;
176     if(flow == eRender)
177         addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
178     else if(flow == eCapture)
179         addr.mSelector = kAudioHardwarePropertyDefaultInputDevice;
180     else
181         return E_INVALIDARG;
182
183     size = sizeof(default_id);
184     sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0,
185             NULL, &size, &default_id);
186     if(sc != noErr){
187         WARN("Getting _DefaultInputDevice property failed: %lx\n", sc);
188         default_id = -1;
189     }
190
191     addr.mSelector = kAudioHardwarePropertyDevices;
192     sc = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, 0,
193             NULL, &devsize);
194     if(sc != noErr){
195         WARN("Getting _Devices property size failed: %lx\n", sc);
196         return E_FAIL;
197     }
198
199     devices = HeapAlloc(GetProcessHeap(), 0, devsize);
200     if(!devices)
201         return E_OUTOFMEMORY;
202
203     sc = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL,
204             &devsize, devices);
205     if(sc != noErr){
206         WARN("Getting _Devices property failed: %lx\n", sc);
207         HeapFree(GetProcessHeap(), 0, devices);
208         return E_FAIL;
209     }
210
211     ndevices = devsize / sizeof(AudioDeviceID);
212
213     *ids = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(WCHAR *));
214     if(!*ids){
215         HeapFree(GetProcessHeap(), 0, devices);
216         return E_OUTOFMEMORY;
217     }
218
219     *keys = HeapAlloc(GetProcessHeap(), 0, ndevices * sizeof(AudioDeviceID *));
220     if(!*ids){
221         HeapFree(GetProcessHeap(), 0, *ids);
222         HeapFree(GetProcessHeap(), 0, devices);
223         return E_OUTOFMEMORY;
224     }
225
226     *num = 0;
227     *def_index = (UINT)-1;
228     for(i = 0; i < ndevices; ++i){
229         AudioBufferList *buffers;
230         CFStringRef name;
231         SIZE_T len;
232         char nameA[256];
233         int j;
234
235         addr.mSelector = kAudioDevicePropertyStreamConfiguration;
236         if(flow == eRender)
237             addr.mScope = kAudioDevicePropertyScopeOutput;
238         else
239             addr.mScope = kAudioDevicePropertyScopeInput;
240         addr.mElement = 0;
241         sc = AudioObjectGetPropertyDataSize(devices[i], &addr, 0, NULL, &size);
242         if(sc != noErr){
243             WARN("Unable to get _StreamConfiguration property size for "
244                     "device %lu: %lx\n", devices[i], sc);
245             continue;
246         }
247
248         buffers = HeapAlloc(GetProcessHeap(), 0, size);
249         if(!buffers){
250             HeapFree(GetProcessHeap(), 0, devices);
251             for(j = 0; j < *num; ++j)
252                 HeapFree(GetProcessHeap(), 0, (*ids)[j]);
253             HeapFree(GetProcessHeap(), 0, *keys);
254             HeapFree(GetProcessHeap(), 0, *ids);
255             return E_OUTOFMEMORY;
256         }
257
258         sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
259                 &size, buffers);
260         if(sc != noErr){
261             WARN("Unable to get _StreamConfiguration property for "
262                     "device %lu: %lx\n", devices[i], sc);
263             HeapFree(GetProcessHeap(), 0, buffers);
264             continue;
265         }
266
267         /* check that there's at least one channel in this device before
268          * we claim it as usable */
269         for(j = 0; j < buffers->mNumberBuffers; ++j)
270             if(buffers->mBuffers[j].mNumberChannels > 0)
271                 break;
272         if(j >= buffers->mNumberBuffers){
273             HeapFree(GetProcessHeap(), 0, buffers);
274             continue;
275         }
276
277         HeapFree(GetProcessHeap(), 0, buffers);
278
279         size = sizeof(name);
280         addr.mSelector = kAudioObjectPropertyName;
281         sc = AudioObjectGetPropertyData(devices[i], &addr, 0, NULL,
282                 &size, &name);
283         if(sc != noErr){
284             WARN("Unable to get _Name property for device %lu: %lx\n",
285                     devices[i], sc);
286             continue;
287         }
288
289         if(!CFStringGetCString(name, nameA, sizeof(nameA),
290                     kCFStringEncodingUTF8)){
291             WARN("Error converting string to UTF8\n");
292             CFRelease(name);
293             continue;
294         }
295
296         CFRelease(name);
297
298         len = MultiByteToWideChar(CP_UNIXCP, 0, nameA, -1, NULL, 0);
299         (*ids)[*num] = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
300         if(!(*ids)[*num]){
301             HeapFree(GetProcessHeap(), 0, devices);
302             for(j = 0; j < *num; ++j){
303                 HeapFree(GetProcessHeap(), 0, (*ids)[j]);
304                 HeapFree(GetProcessHeap(), 0, (*keys)[j]);
305             }
306             HeapFree(GetProcessHeap(), 0, *ids);
307             HeapFree(GetProcessHeap(), 0, *keys);
308             return E_OUTOFMEMORY;
309         }
310         MultiByteToWideChar(CP_UNIXCP, 0, nameA, -1, (*ids)[*num], len);
311
312         (*keys)[*num] = HeapAlloc(GetProcessHeap(), 0, sizeof(AudioDeviceID));
313         if(!(*ids)[*num]){
314             HeapFree(GetProcessHeap(), 0, devices);
315             HeapFree(GetProcessHeap(), 0, (*ids)[*num]);
316             for(j = 0; j < *num; ++j){
317                 HeapFree(GetProcessHeap(), 0, (*ids)[j]);
318                 HeapFree(GetProcessHeap(), 0, (*keys)[j]);
319             }
320             HeapFree(GetProcessHeap(), 0, *ids);
321             HeapFree(GetProcessHeap(), 0, *keys);
322             return E_OUTOFMEMORY;
323         }
324         *(*keys)[*num] = devices[i];
325
326         if(*def_index == (UINT)-1 && devices[i] == default_id)
327             *def_index = *num;
328
329         (*num)++;
330     }
331
332     if(*def_index == (UINT)-1)
333         *def_index = 0;
334
335     HeapFree(GetProcessHeap(), 0, devices);
336
337     return S_OK;
338 }
339
340 HRESULT WINAPI AUDDRV_GetAudioEndpoint(AudioDeviceID *adevid, IMMDevice *dev,
341         EDataFlow dataflow, IAudioClient **out)
342 {
343     ACImpl *This;
344
345     TRACE("%p %d %p\n", dev, dataflow, out);
346
347     if(!g_timer_q){
348         g_timer_q = CreateTimerQueue();
349         if(!g_timer_q)
350             return E_FAIL;
351     }
352
353     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
354     if(!This)
355         return E_OUTOFMEMORY;
356
357     This->IAudioClient_iface.lpVtbl = &AudioClient_Vtbl;
358     This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
359     This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl;
360     This->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl;
361     This->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl;
362     This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl;
363     This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl;
364
365     This->dataflow = dataflow;
366
367     This->lock = 0;
368
369     This->parent = dev;
370     IMMDevice_AddRef(This->parent);
371
372     list_init(&This->avail_buffers);
373
374     This->adevid = *adevid;
375
376     *out = &This->IAudioClient_iface;
377     IAudioClient_AddRef(&This->IAudioClient_iface);
378
379     return S_OK;
380 }
381
382 static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient *iface,
383         REFIID riid, void **ppv)
384 {
385     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
386
387     if(!ppv)
388         return E_POINTER;
389     *ppv = NULL;
390     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClient))
391         *ppv = iface;
392     if(*ppv){
393         IUnknown_AddRef((IUnknown*)*ppv);
394         return S_OK;
395     }
396     WARN("Unknown interface %s\n", debugstr_guid(riid));
397     return E_NOINTERFACE;
398 }
399
400 static ULONG WINAPI AudioClient_AddRef(IAudioClient *iface)
401 {
402     ACImpl *This = impl_from_IAudioClient(iface);
403     ULONG ref;
404     ref = InterlockedIncrement(&This->ref);
405     TRACE("(%p) Refcount now %u\n", This, ref);
406     return ref;
407 }
408
409 static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
410 {
411     ACImpl *This = impl_from_IAudioClient(iface);
412     ULONG ref;
413     ref = InterlockedDecrement(&This->ref);
414     TRACE("(%p) Refcount now %u\n", This, ref);
415     if(!ref){
416         IAudioClient_Stop(iface);
417         if(This->aqueue)
418             AudioQueueDispose(This->aqueue, 1);
419         HeapFree(GetProcessHeap(), 0, This->public_buffer);
420         HeapFree(GetProcessHeap(), 0, This->fmt);
421         IMMDevice_Release(This->parent);
422         HeapFree(GetProcessHeap(), 0, This);
423     }
424     return ref;
425 }
426
427 static void dump_fmt(const WAVEFORMATEX *fmt)
428 {
429     TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
430     switch(fmt->wFormatTag){
431     case WAVE_FORMAT_PCM:
432         TRACE("WAVE_FORMAT_PCM");
433         break;
434     case WAVE_FORMAT_IEEE_FLOAT:
435         TRACE("WAVE_FORMAT_IEEE_FLOAT");
436         break;
437     case WAVE_FORMAT_EXTENSIBLE:
438         TRACE("WAVE_FORMAT_EXTENSIBLE");
439         break;
440     default:
441         TRACE("Unknown");
442         break;
443     }
444     TRACE(")\n");
445
446     TRACE("nChannels: %u\n", fmt->nChannels);
447     TRACE("nSamplesPerSec: %u\n", fmt->nSamplesPerSec);
448     TRACE("nAvgBytesPerSec: %u\n", fmt->nAvgBytesPerSec);
449     TRACE("nBlockAlign: %u\n", fmt->nBlockAlign);
450     TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample);
451     TRACE("cbSize: %u\n", fmt->cbSize);
452
453     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
454         WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt;
455         TRACE("dwChannelMask: %08x\n", fmtex->dwChannelMask);
456         TRACE("Samples: %04x\n", fmtex->Samples.wReserved);
457         TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat));
458     }
459 }
460
461 static DWORD get_channel_mask(unsigned int channels)
462 {
463     switch(channels){
464     case 0:
465         return 0;
466     case 1:
467         return SPEAKER_FRONT_CENTER;
468     case 2:
469         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
470     case 3:
471         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |
472             SPEAKER_LOW_FREQUENCY;
473     case 4:
474         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
475             SPEAKER_BACK_RIGHT;
476     case 5:
477         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
478             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
479     case 6:
480         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
481             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER;
482     case 7:
483         return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
484             SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_FRONT_CENTER |
485             SPEAKER_BACK_CENTER;
486     }
487     FIXME("Unknown speaker configuration: %u\n", channels);
488     return 0;
489 }
490
491 static WAVEFORMATEX *clone_format(const WAVEFORMATEX *fmt)
492 {
493     WAVEFORMATEX *ret;
494     size_t size;
495
496     if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
497         size = sizeof(WAVEFORMATEXTENSIBLE);
498     else
499         size = sizeof(WAVEFORMATEX);
500
501     ret = HeapAlloc(GetProcessHeap(), 0, size);
502     if(!ret)
503         return NULL;
504
505     memcpy(ret, fmt, size);
506
507     ret->cbSize = size - sizeof(WAVEFORMATEX);
508
509     return ret;
510 }
511
512 static HRESULT ca_get_audiodesc(AudioStreamBasicDescription *desc,
513         const WAVEFORMATEX *fmt)
514 {
515     const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
516
517     if(fmt->wFormatTag == WAVE_FORMAT_PCM ||
518             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
519              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
520         desc->mFormatID = kAudioFormatLinearPCM;
521         if(fmt->wBitsPerSample > 8)
522             desc->mFormatFlags = kAudioFormatFlagIsSignedInteger;
523     }else if(fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
524             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
525              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
526         desc->mFormatID = kAudioFormatLinearPCM;
527         desc->mFormatFlags = kAudioFormatFlagIsFloat;
528     }else if(fmt->wFormatTag == WAVE_FORMAT_MULAW ||
529             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
530              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_MULAW))){
531         desc->mFormatID = kAudioFormatULaw;
532     }else if(fmt->wFormatTag == WAVE_FORMAT_ALAW ||
533             (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
534              IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_ALAW))){
535         desc->mFormatID = kAudioFormatALaw;
536     }else
537         return AUDCLNT_E_UNSUPPORTED_FORMAT;
538
539     desc->mSampleRate = fmt->nSamplesPerSec;
540     desc->mBytesPerPacket = fmt->nBlockAlign;
541     desc->mFramesPerPacket = 1;
542     desc->mBytesPerFrame = fmt->nBlockAlign;
543     desc->mChannelsPerFrame = fmt->nChannels;
544     desc->mBitsPerChannel = fmt->wBitsPerSample;
545     desc->mReserved = 0;
546
547     return S_OK;
548 }
549
550 static void ca_out_buffer_cb(void *user, AudioQueueRef aqueue,
551         AudioQueueBufferRef buffer)
552 {
553     ACImpl *This = user;
554     AQBuffer *buf = buffer->mUserData;
555
556     OSSpinLockLock(&This->lock);
557     list_add_tail(&This->avail_buffers, &buf->entry);
558     This->inbuf_frames -= buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
559     OSSpinLockUnlock(&This->lock);
560 }
561
562 static void ca_in_buffer_cb(void *user, AudioQueueRef aqueue,
563         AudioQueueBufferRef buffer, const AudioTimeStamp *start,
564         UInt32 ndesc, const AudioStreamPacketDescription *descs)
565 {
566     ACImpl *This = user;
567     AQBuffer *buf = buffer->mUserData;
568
569     OSSpinLockLock(&This->lock);
570     list_add_tail(&This->avail_buffers, &buf->entry);
571     This->inbuf_frames += buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
572     OSSpinLockUnlock(&This->lock);
573 }
574
575 static HRESULT ca_setup_aqueue(AudioDeviceID did, EDataFlow flow,
576         const WAVEFORMATEX *fmt, void *user, AudioQueueRef *aqueue)
577 {
578     AudioStreamBasicDescription desc;
579     AudioObjectPropertyAddress addr;
580     CFStringRef uid;
581     OSStatus sc;
582     HRESULT hr;
583     UInt32 size;
584
585     addr.mScope = kAudioObjectPropertyScopeGlobal;
586     addr.mElement = 0;
587     addr.mSelector = kAudioDevicePropertyDeviceUID;
588
589     size = sizeof(uid);
590     sc = AudioObjectGetPropertyData(did, &addr, 0, NULL, &size, &uid);
591     if(sc != noErr){
592         WARN("Unable to get _DeviceUID property: %lx\n", sc);
593         return E_FAIL;
594     }
595
596     hr = ca_get_audiodesc(&desc, fmt);
597     if(FAILED(hr)){
598         CFRelease(uid);
599         return hr;
600     }
601
602     if(flow == eRender)
603         sc = AudioQueueNewOutput(&desc, ca_out_buffer_cb, user, NULL, NULL, 0,
604                 aqueue);
605     else if(flow == eCapture)
606         sc = AudioQueueNewInput(&desc, ca_in_buffer_cb, user, NULL, NULL, 0,
607                 aqueue);
608     else{
609         CFRelease(uid);
610         return E_UNEXPECTED;
611     }
612     if(sc != noErr){
613         WARN("Unable to create AudioQueue: %lx\n", sc);
614         CFRelease(uid);
615         return E_FAIL;
616     }
617
618     sc = AudioQueueSetProperty(*aqueue, kAudioQueueProperty_CurrentDevice,
619             &uid, sizeof(uid));
620     if(sc != noErr){
621         CFRelease(uid);
622         return E_FAIL;
623     }
624
625     CFRelease(uid);
626
627     return S_OK;
628 }
629
630 static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
631         AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
632         REFERENCE_TIME period, const WAVEFORMATEX *fmt,
633         const GUID *sessionguid)
634 {
635     ACImpl *This = impl_from_IAudioClient(iface);
636     HRESULT hr;
637     OSStatus sc;
638
639     TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
640           wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
641
642     if(!fmt)
643         return E_POINTER;
644
645     dump_fmt(fmt);
646
647     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
648         return AUDCLNT_E_NOT_INITIALIZED;
649
650     if(flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS |
651                 AUDCLNT_STREAMFLAGS_LOOPBACK |
652                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
653                 AUDCLNT_STREAMFLAGS_NOPERSIST |
654                 AUDCLNT_STREAMFLAGS_RATEADJUST |
655                 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED |
656                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE |
657                 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)){
658         TRACE("Unknown flags: %08x\n", flags);
659         return E_INVALIDARG;
660     }
661
662     OSSpinLockLock(&This->lock);
663
664     if(This->aqueue){
665         OSSpinLockUnlock(&This->lock);
666         return AUDCLNT_E_ALREADY_INITIALIZED;
667     }
668
669     hr = ca_setup_aqueue(This->adevid, This->dataflow, fmt, This, &This->aqueue);
670     if(FAILED(hr)){
671         OSSpinLockUnlock(&This->lock);
672         return hr;
673     }
674
675     This->fmt = clone_format(fmt);
676     if(!This->fmt){
677         AudioQueueDispose(This->aqueue, 1);
678         This->aqueue = NULL;
679         OSSpinLockUnlock(&This->lock);
680         return E_OUTOFMEMORY;
681     }
682
683     if(period){
684         This->period_ms = period / 10000;
685         if(This->period_ms == 0)
686             This->period_ms = 1;
687     }else
688         This->period_ms = MinimumPeriod / 10000;
689
690     This->bufsize_frames = ceil(fmt->nSamplesPerSec * (duration / 10000000.));
691
692     if(This->dataflow == eCapture){
693         int i;
694         UInt32 bsize = ceil((This->bufsize_frames / (double)CAPTURE_BUFFERS) *
695                 This->fmt->nBlockAlign);
696         for(i = 0; i < CAPTURE_BUFFERS; ++i){
697             AQBuffer *buf;
698
699             buf = HeapAlloc(GetProcessHeap(), 0, sizeof(AQBuffer));
700             if(!buf){
701                 AudioQueueDispose(This->aqueue, 1);
702                 This->aqueue = NULL;
703                 OSSpinLockUnlock(&This->lock);
704                 return E_OUTOFMEMORY;
705             }
706
707             sc = AudioQueueAllocateBuffer(This->aqueue, bsize, &buf->buf);
708             if(sc != noErr){
709                 AudioQueueDispose(This->aqueue, 1);
710                 This->aqueue = NULL;
711                 OSSpinLockUnlock(&This->lock);
712                 WARN("Couldn't allocate buffer: %lx\n", sc);
713                 return E_FAIL;
714             }
715
716             buf->buf->mUserData = buf;
717
718             sc = AudioQueueEnqueueBuffer(This->aqueue, buf->buf, 0, NULL);
719             if(sc != noErr){
720                 ERR("Couldn't enqueue buffer: %lx\n", sc);
721                 break;
722             }
723         }
724     }
725
726     This->share = mode;
727     This->flags = flags;
728
729     OSSpinLockUnlock(&This->lock);
730
731     return S_OK;
732 }
733
734 static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient *iface,
735         UINT32 *frames)
736 {
737     ACImpl *This = impl_from_IAudioClient(iface);
738
739     TRACE("(%p)->(%p)\n", This, frames);
740
741     if(!frames)
742         return E_POINTER;
743
744     OSSpinLockLock(&This->lock);
745
746     if(!This->aqueue){
747         OSSpinLockUnlock(&This->lock);
748         return AUDCLNT_E_NOT_INITIALIZED;
749     }
750
751     *frames = This->bufsize_frames;
752
753     OSSpinLockUnlock(&This->lock);
754
755     return S_OK;
756 }
757
758 static HRESULT ca_get_max_stream_latency(ACImpl *This, UInt32 *max)
759 {
760     AudioObjectPropertyAddress addr;
761     AudioStreamID *ids;
762     UInt32 size;
763     OSStatus sc;
764     int nstreams, i;
765
766     if(This->dataflow == eRender)
767         addr.mScope = kAudioDevicePropertyScopeOutput;
768     else if(This->dataflow == eCapture)
769         addr.mScope = kAudioDevicePropertyScopeInput;
770     else
771         return E_UNEXPECTED;
772     addr.mElement = 0;
773     addr.mSelector = kAudioDevicePropertyStreams;
774
775     sc = AudioObjectGetPropertyDataSize(This->adevid, &addr, 0, NULL,
776             &size);
777     if(sc != noErr){
778         WARN("Unable to get size for _Streams property: %lx\n", sc);
779         return E_FAIL;
780     }
781
782     ids = HeapAlloc(GetProcessHeap(), 0, size);
783     if(!ids)
784         return E_OUTOFMEMORY;
785
786     sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, &size, ids);
787     if(sc != noErr){
788         WARN("Unable to get _Streams property: %lx\n", sc);
789         HeapFree(GetProcessHeap(), 0, ids);
790         return E_FAIL;
791     }
792
793     nstreams = size / sizeof(AudioStreamID);
794     *max = 0;
795
796     addr.mSelector = kAudioStreamPropertyLatency;
797     for(i = 0; i < nstreams; ++i){
798         UInt32 latency;
799
800         size = sizeof(latency);
801         sc = AudioObjectGetPropertyData(ids[i], &addr, 0, NULL,
802                 &size, &latency);
803         if(sc != noErr){
804             WARN("Unable to get _Latency property: %lx\n", sc);
805             continue;
806         }
807
808         if(latency > *max)
809             *max = latency;
810     }
811
812     HeapFree(GetProcessHeap(), 0, ids);
813
814     return S_OK;
815 }
816
817 static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient *iface,
818         REFERENCE_TIME *out)
819 {
820     ACImpl *This = impl_from_IAudioClient(iface);
821     UInt32 latency, stream_latency, size;
822     AudioObjectPropertyAddress addr;
823     OSStatus sc;
824     HRESULT hr;
825
826     TRACE("(%p)->(%p)\n", This, out);
827
828     if(!out)
829         return E_POINTER;
830
831     OSSpinLockLock(&This->lock);
832
833     if(!This->aqueue){
834         OSSpinLockUnlock(&This->lock);
835         return AUDCLNT_E_NOT_INITIALIZED;
836     }
837
838     if(This->dataflow == eRender)
839         addr.mScope = kAudioDevicePropertyScopeOutput;
840     else if(This->dataflow == eCapture)
841         addr.mScope = kAudioDevicePropertyScopeInput;
842     else{
843         OSSpinLockUnlock(&This->lock);
844         return E_UNEXPECTED;
845     }
846     addr.mSelector = kAudioDevicePropertyLatency;
847     addr.mElement = 0;
848
849     size = sizeof(latency);
850     sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL,
851             &size, &latency);
852     if(sc != noErr){
853         WARN("Couldn't get _Latency property: %lx\n", sc);
854         OSSpinLockUnlock(&This->lock);
855         return E_FAIL;
856     }
857
858     hr = ca_get_max_stream_latency(This, &stream_latency);
859     if(FAILED(hr)){
860         OSSpinLockUnlock(&This->lock);
861         return hr;
862     }
863
864     latency += stream_latency;
865     *out = (latency / (double)This->fmt->nSamplesPerSec) * 10000000;
866
867     OSSpinLockUnlock(&This->lock);
868
869     return S_OK;
870 }
871
872 static HRESULT AudioClient_GetCurrentPadding_nolock(ACImpl *This,
873         UINT32 *numpad)
874 {
875     if(!This->aqueue)
876         return AUDCLNT_E_NOT_INITIALIZED;
877
878     *numpad = This->inbuf_frames;
879
880     return S_OK;
881 }
882
883 static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient *iface,
884         UINT32 *numpad)
885 {
886     ACImpl *This = impl_from_IAudioClient(iface);
887     HRESULT hr;
888
889     TRACE("(%p)->(%p)\n", This, numpad);
890
891     if(!numpad)
892         return E_POINTER;
893
894     OSSpinLockLock(&This->lock);
895
896     hr = AudioClient_GetCurrentPadding_nolock(This, numpad);
897
898     OSSpinLockUnlock(&This->lock);
899
900     return hr;
901 }
902
903 static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
904         AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *pwfx,
905         WAVEFORMATEX **outpwfx)
906 {
907     ACImpl *This = impl_from_IAudioClient(iface);
908     AudioQueueRef aqueue;
909     HRESULT hr;
910
911     TRACE("(%p)->(%x, %p, %p)\n", This, mode, pwfx, outpwfx);
912
913     if(!pwfx || (mode == AUDCLNT_SHAREMODE_SHARED && !outpwfx))
914         return E_POINTER;
915
916     if(mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
917         return E_INVALIDARG;
918
919     if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
920             pwfx->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
921         return E_INVALIDARG;
922
923     dump_fmt(pwfx);
924
925     OSSpinLockLock(&This->lock);
926
927     hr = ca_setup_aqueue(This->adevid, This->dataflow, pwfx, NULL, &aqueue);
928     if(SUCCEEDED(hr)){
929         AudioQueueDispose(aqueue, 1);
930         OSSpinLockUnlock(&This->lock);
931         if(outpwfx)
932             *outpwfx = NULL;
933         TRACE("returning %08x\n", S_OK);
934         return S_OK;
935     }
936
937     OSSpinLockUnlock(&This->lock);
938
939     if(outpwfx)
940         *outpwfx = NULL;
941
942     TRACE("returning %08x\n", AUDCLNT_E_UNSUPPORTED_FORMAT);
943     return AUDCLNT_E_UNSUPPORTED_FORMAT;
944 }
945
946 static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient *iface,
947         WAVEFORMATEX **pwfx)
948 {
949     ACImpl *This = impl_from_IAudioClient(iface);
950     WAVEFORMATEXTENSIBLE *fmt;
951     OSStatus sc;
952     UInt32 size;
953     Float64 rate;
954     AudioBufferList *buffers;
955     AudioObjectPropertyAddress addr;
956     int i;
957
958     TRACE("(%p)->(%p)\n", This, pwfx);
959
960     if(!pwfx)
961         return E_POINTER;
962
963     *pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
964     if(!*pwfx)
965         return E_OUTOFMEMORY;
966
967     fmt = (WAVEFORMATEXTENSIBLE*)*pwfx;
968
969     fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
970
971     if(This->dataflow == eRender)
972         addr.mScope = kAudioDevicePropertyScopeOutput;
973     else if(This->dataflow == eCapture)
974         addr.mScope = kAudioDevicePropertyScopeInput;
975     else{
976         OSSpinLockUnlock(&This->lock);
977         return E_UNEXPECTED;
978     }
979     addr.mElement = 0;
980     addr.mSelector = kAudioDevicePropertyStreamConfiguration;
981
982     sc = AudioObjectGetPropertyDataSize(This->adevid, &addr, 0, NULL, &size);
983     if(sc != noErr){
984         HeapFree(GetProcessHeap(), 0, fmt);
985         WARN("Unable to get size for _StreamConfiguration property: %lx\n", sc);
986         return E_FAIL;
987     }
988
989     buffers = HeapAlloc(GetProcessHeap(), 0, size);
990     if(!buffers){
991         HeapFree(GetProcessHeap(), 0, fmt);
992         return E_OUTOFMEMORY;
993     }
994
995     sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL,
996             &size, buffers);
997     if(sc != noErr){
998         HeapFree(GetProcessHeap(), 0, fmt);
999         HeapFree(GetProcessHeap(), 0, buffers);
1000         WARN("Unable to get _StreamConfiguration property: %lx\n", sc);
1001         return E_FAIL;
1002     }
1003
1004     fmt->Format.nChannels = 0;
1005     for(i = 0; i < buffers->mNumberBuffers; ++i)
1006         fmt->Format.nChannels += buffers->mBuffers[i].mNumberChannels;
1007
1008     HeapFree(GetProcessHeap(), 0, buffers);
1009
1010     fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
1011
1012     addr.mSelector = kAudioDevicePropertyNominalSampleRate;
1013     size = sizeof(Float64);
1014     sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, &size, &rate);
1015     if(sc != noErr){
1016         HeapFree(GetProcessHeap(), 0, fmt);
1017         WARN("Unable to get _NominalSampleRate property: %lx\n", sc);
1018         return E_FAIL;
1019     }
1020     fmt->Format.nSamplesPerSec = rate;
1021
1022     /* CoreAudio doesn't seem to give a device format preference, so just
1023      * choose a common format... */
1024     fmt->Format.wBitsPerSample = 16;
1025     fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
1026
1027     fmt->Format.nBlockAlign = (fmt->Format.wBitsPerSample *
1028             fmt->Format.nChannels) / 8;
1029     fmt->Format.nAvgBytesPerSec = fmt->Format.nSamplesPerSec *
1030         fmt->Format.nBlockAlign;
1031
1032     fmt->Samples.wValidBitsPerSample = fmt->Format.wBitsPerSample;
1033     fmt->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
1034
1035     dump_fmt(*pwfx);
1036
1037     return S_OK;
1038 }
1039
1040 static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient *iface,
1041         REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
1042 {
1043     ACImpl *This = impl_from_IAudioClient(iface);
1044
1045     TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod);
1046
1047     if(!defperiod && !minperiod)
1048         return E_POINTER;
1049
1050     OSSpinLockLock(&This->lock);
1051
1052     if(This->period_ms){
1053         if(defperiod)
1054             *defperiod = This->period_ms * 10000;
1055         if(minperiod)
1056             *minperiod = This->period_ms * 10000;
1057     }else{
1058         if(defperiod)
1059             *defperiod = DefaultPeriod;
1060         if(minperiod)
1061             *minperiod = MinimumPeriod;
1062     }
1063
1064     OSSpinLockUnlock(&This->lock);
1065
1066     return S_OK;
1067 }
1068
1069 void CALLBACK ca_period_cb(void *user, BOOLEAN timer)
1070 {
1071     ACImpl *This = user;
1072
1073     OSSpinLockLock(&This->lock);
1074     if(This->event)
1075         SetEvent(This->event);
1076     OSSpinLockUnlock(&This->lock);
1077 }
1078
1079 static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
1080 {
1081     ACImpl *This = impl_from_IAudioClient(iface);
1082     OSStatus sc;
1083
1084     TRACE("(%p)\n", This);
1085
1086     OSSpinLockLock(&This->lock);
1087
1088     if(!This->aqueue){
1089         OSSpinLockUnlock(&This->lock);
1090         return AUDCLNT_E_NOT_INITIALIZED;
1091     }
1092
1093     if(This->playing != StateStopped){
1094         OSSpinLockUnlock(&This->lock);
1095         return AUDCLNT_E_NOT_STOPPED;
1096     }
1097
1098     if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
1099         OSSpinLockUnlock(&This->lock);
1100         return AUDCLNT_E_EVENTHANDLE_NOT_SET;
1101     }
1102
1103     if(This->event)
1104         if(!CreateTimerQueueTimer(&This->timer, g_timer_q,
1105                     ca_period_cb, This, 0, This->period_ms, 0))
1106             ERR("Unable to create timer: %u\n", GetLastError());
1107
1108     This->playing = StateInTransition;
1109
1110     OSSpinLockUnlock(&This->lock);
1111
1112     sc = AudioQueueStart(This->aqueue, NULL);
1113     if(sc != noErr){
1114         WARN("Unable to start audio queue: %lx\n", sc);
1115         return E_FAIL;
1116     }
1117
1118     OSSpinLockLock(&This->lock);
1119
1120     This->playing = StatePlaying;
1121
1122     OSSpinLockUnlock(&This->lock);
1123
1124     return S_OK;
1125 }
1126
1127 static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
1128 {
1129     ACImpl *This = impl_from_IAudioClient(iface);
1130     OSStatus sc;
1131
1132     TRACE("(%p)\n", This);
1133
1134     OSSpinLockLock(&This->lock);
1135
1136     if(!This->aqueue){
1137         OSSpinLockUnlock(&This->lock);
1138         return AUDCLNT_E_NOT_INITIALIZED;
1139     }
1140
1141     if(This->playing == StateStopped){
1142         OSSpinLockUnlock(&This->lock);
1143         return S_FALSE;
1144     }
1145
1146     if(This->playing == StateInTransition){
1147         OSSpinLockUnlock(&This->lock);
1148         return S_OK;
1149     }
1150
1151     if(This->timer && This->timer != INVALID_HANDLE_VALUE){
1152         DeleteTimerQueueTimer(g_timer_q, This->timer, INVALID_HANDLE_VALUE);
1153         This->timer = NULL;
1154     }
1155
1156     This->playing = StateInTransition;
1157
1158     OSSpinLockUnlock(&This->lock);
1159
1160     sc = AudioQueueFlush(This->aqueue);
1161     if(sc != noErr)
1162         WARN("Unable to flush audio queue: %lx\n", sc);
1163
1164     sc = AudioQueuePause(This->aqueue);
1165     if(sc != noErr){
1166         WARN("Unable to pause audio queue: %lx\n", sc);
1167         return E_FAIL;
1168     }
1169
1170     OSSpinLockLock(&This->lock);
1171
1172     This->playing = StateStopped;
1173
1174     OSSpinLockUnlock(&This->lock);
1175
1176     return S_OK;
1177 }
1178
1179 static HRESULT WINAPI AudioClient_Reset(IAudioClient *iface)
1180 {
1181     ACImpl *This = impl_from_IAudioClient(iface);
1182     HRESULT hr;
1183     OSStatus sc;
1184
1185     TRACE("(%p)\n", This);
1186
1187     OSSpinLockLock(&This->lock);
1188
1189     if(!This->aqueue){
1190         OSSpinLockUnlock(&This->lock);
1191         return AUDCLNT_E_NOT_INITIALIZED;
1192     }
1193
1194     if(This->playing != StateStopped){
1195         OSSpinLockUnlock(&This->lock);
1196         return AUDCLNT_E_NOT_STOPPED;
1197     }
1198
1199     This->written_frames = 0;
1200
1201     hr = AudioClock_GetPosition_nolock(This, &This->last_time, NULL, TRUE);
1202     if(FAILED(hr)){
1203         OSSpinLockUnlock(&This->lock);
1204         return hr;
1205     }
1206
1207     OSSpinLockUnlock(&This->lock);
1208
1209     sc = AudioQueueReset(This->aqueue);
1210     if(sc != noErr){
1211         WARN("Unable to reset audio queue: %lx\n", sc);
1212         return E_FAIL;
1213     }
1214
1215     return S_OK;
1216 }
1217
1218 static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient *iface,
1219         HANDLE event)
1220 {
1221     ACImpl *This = impl_from_IAudioClient(iface);
1222
1223     TRACE("(%p)->(%p)\n", This, event);
1224
1225     if(!event)
1226         return E_INVALIDARG;
1227
1228     OSSpinLockLock(&This->lock);
1229
1230     if(!This->aqueue){
1231         OSSpinLockUnlock(&This->lock);
1232         return AUDCLNT_E_NOT_INITIALIZED;
1233     }
1234
1235     if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
1236         OSSpinLockUnlock(&This->lock);
1237         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
1238     }
1239
1240     This->event = event;
1241
1242     OSSpinLockUnlock(&This->lock);
1243
1244     return S_OK;
1245 }
1246
1247 static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
1248         void **ppv)
1249 {
1250     ACImpl *This = impl_from_IAudioClient(iface);
1251
1252     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
1253
1254     if(!ppv)
1255         return E_POINTER;
1256     *ppv = NULL;
1257
1258     OSSpinLockLock(&This->lock);
1259
1260     if(!This->aqueue){
1261         OSSpinLockUnlock(&This->lock);
1262         return AUDCLNT_E_NOT_INITIALIZED;
1263     }
1264
1265     OSSpinLockUnlock(&This->lock);
1266
1267     if(IsEqualIID(riid, &IID_IAudioRenderClient)){
1268         if(This->dataflow != eRender)
1269             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1270         *ppv = &This->IAudioRenderClient_iface;
1271     }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){
1272         if(This->dataflow != eCapture)
1273             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
1274         *ppv = &This->IAudioCaptureClient_iface;
1275     }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){
1276         *ppv = &This->IAudioSessionControl2_iface;
1277     }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){
1278         *ppv = &This->ISimpleAudioVolume_iface;
1279     }else if(IsEqualIID(riid, &IID_IAudioClock)){
1280         *ppv = &This->IAudioClock_iface;
1281     }
1282
1283     if(*ppv){
1284         IUnknown_AddRef((IUnknown*)*ppv);
1285         return S_OK;
1286     }
1287
1288     FIXME("stub %s\n", debugstr_guid(riid));
1289     return E_NOINTERFACE;
1290 }
1291
1292 static const IAudioClientVtbl AudioClient_Vtbl =
1293 {
1294     AudioClient_QueryInterface,
1295     AudioClient_AddRef,
1296     AudioClient_Release,
1297     AudioClient_Initialize,
1298     AudioClient_GetBufferSize,
1299     AudioClient_GetStreamLatency,
1300     AudioClient_GetCurrentPadding,
1301     AudioClient_IsFormatSupported,
1302     AudioClient_GetMixFormat,
1303     AudioClient_GetDevicePeriod,
1304     AudioClient_Start,
1305     AudioClient_Stop,
1306     AudioClient_Reset,
1307     AudioClient_SetEventHandle,
1308     AudioClient_GetService
1309 };
1310
1311 static HRESULT WINAPI AudioRenderClient_QueryInterface(
1312         IAudioRenderClient *iface, REFIID riid, void **ppv)
1313 {
1314     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1315
1316     if(!ppv)
1317         return E_POINTER;
1318     *ppv = NULL;
1319
1320     if(IsEqualIID(riid, &IID_IUnknown) ||
1321             IsEqualIID(riid, &IID_IAudioRenderClient))
1322         *ppv = iface;
1323     if(*ppv){
1324         IUnknown_AddRef((IUnknown*)*ppv);
1325         return S_OK;
1326     }
1327
1328     WARN("Unknown interface %s\n", debugstr_guid(riid));
1329     return E_NOINTERFACE;
1330 }
1331
1332 static ULONG WINAPI AudioRenderClient_AddRef(IAudioRenderClient *iface)
1333 {
1334     ACImpl *This = impl_from_IAudioRenderClient(iface);
1335     return AudioClient_AddRef(&This->IAudioClient_iface);
1336 }
1337
1338 static ULONG WINAPI AudioRenderClient_Release(IAudioRenderClient *iface)
1339 {
1340     ACImpl *This = impl_from_IAudioRenderClient(iface);
1341     return AudioClient_Release(&This->IAudioClient_iface);
1342 }
1343
1344 static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
1345         UINT32 frames, BYTE **data)
1346 {
1347     ACImpl *This = impl_from_IAudioRenderClient(iface);
1348     AQBuffer *buf;
1349     UINT32 pad, bytes = frames * This->fmt->nBlockAlign;
1350     HRESULT hr;
1351     OSStatus sc;
1352
1353     TRACE("(%p)->(%u, %p)\n", This, frames, data);
1354
1355     if(!data)
1356         return E_POINTER;
1357
1358     OSSpinLockLock(&This->lock);
1359
1360     if(This->getbuf_last){
1361         OSSpinLockUnlock(&This->lock);
1362         return AUDCLNT_E_OUT_OF_ORDER;
1363     }
1364
1365     if(!frames){
1366         This->getbuf_last = TRUE;
1367         OSSpinLockUnlock(&This->lock);
1368         return S_OK;
1369     }
1370
1371     hr = AudioClient_GetCurrentPadding_nolock(This, &pad);
1372     if(FAILED(hr)){
1373         OSSpinLockUnlock(&This->lock);
1374         return hr;
1375     }
1376
1377     if(pad + frames > This->bufsize_frames){
1378         OSSpinLockUnlock(&This->lock);
1379         return AUDCLNT_E_BUFFER_TOO_LARGE;
1380     }
1381
1382     LIST_FOR_EACH_ENTRY(buf, &This->avail_buffers, AQBuffer, entry){
1383         if(buf->buf->mAudioDataBytesCapacity >= bytes){
1384             This->public_buffer = buf->buf;
1385             list_remove(&buf->entry);
1386             break;
1387         }
1388     }
1389
1390     if(&buf->entry == &This->avail_buffers){
1391         sc = AudioQueueAllocateBuffer(This->aqueue, bytes,
1392                 &This->public_buffer);
1393         if(sc != noErr){
1394             OSSpinLockUnlock(&This->lock);
1395             WARN("Unable to allocate buffer: %lx\n", sc);
1396             return E_FAIL;
1397         }
1398         buf = HeapAlloc(GetProcessHeap(), 0, sizeof(AQBuffer));
1399         if(!buf){
1400             AudioQueueFreeBuffer(This->aqueue, This->public_buffer);
1401             This->public_buffer = NULL;
1402             OSSpinLockUnlock(&This->lock);
1403             return E_OUTOFMEMORY;
1404         }
1405         buf->buf = This->public_buffer;
1406         This->public_buffer->mUserData = buf;
1407     }
1408
1409     *data = This->public_buffer->mAudioData;
1410
1411     This->getbuf_last = TRUE;
1412
1413     OSSpinLockUnlock(&This->lock);
1414
1415     return S_OK;
1416 }
1417
1418 static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
1419         IAudioRenderClient *iface, UINT32 frames, DWORD flags)
1420 {
1421     ACImpl *This = impl_from_IAudioRenderClient(iface);
1422     OSStatus sc;
1423
1424     TRACE("(%p)->(%u, %x)\n", This, frames, flags);
1425
1426     OSSpinLockLock(&This->lock);
1427
1428     if(!This->getbuf_last){
1429         OSSpinLockUnlock(&This->lock);
1430         return AUDCLNT_E_OUT_OF_ORDER;
1431     }
1432
1433     if(flags & AUDCLNT_BUFFERFLAGS_SILENT){
1434         WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
1435         if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
1436                 (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
1437                  IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
1438                 This->fmt->wBitsPerSample == 8)
1439             memset(This->public_buffer->mAudioData, 128,
1440                     frames * This->fmt->nBlockAlign);
1441         else
1442             memset(This->public_buffer->mAudioData, 0,
1443                     frames * This->fmt->nBlockAlign);
1444     }
1445
1446     This->public_buffer->mAudioDataByteSize = frames * This->fmt->nBlockAlign;
1447
1448     sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer, 0, NULL);
1449     if(sc != noErr){
1450         OSSpinLockUnlock(&This->lock);
1451         WARN("Unable to enqueue buffer: %lx\n", sc);
1452         return E_FAIL;
1453     }
1454
1455     if(This->playing == StateStopped)
1456         AudioQueuePrime(This->aqueue, 0, NULL);
1457
1458     This->public_buffer = NULL;
1459     This->getbuf_last = FALSE;
1460     This->written_frames += frames;
1461     This->inbuf_frames += frames;
1462
1463     OSSpinLockUnlock(&This->lock);
1464
1465     return S_OK;
1466 }
1467
1468 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl = {
1469     AudioRenderClient_QueryInterface,
1470     AudioRenderClient_AddRef,
1471     AudioRenderClient_Release,
1472     AudioRenderClient_GetBuffer,
1473     AudioRenderClient_ReleaseBuffer
1474 };
1475
1476 static HRESULT WINAPI AudioCaptureClient_QueryInterface(
1477         IAudioCaptureClient *iface, REFIID riid, void **ppv)
1478 {
1479     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1480
1481     if(!ppv)
1482         return E_POINTER;
1483     *ppv = NULL;
1484
1485     if(IsEqualIID(riid, &IID_IUnknown) ||
1486             IsEqualIID(riid, &IID_IAudioCaptureClient))
1487         *ppv = iface;
1488     if(*ppv){
1489         IUnknown_AddRef((IUnknown*)*ppv);
1490         return S_OK;
1491     }
1492
1493     WARN("Unknown interface %s\n", debugstr_guid(riid));
1494     return E_NOINTERFACE;
1495 }
1496
1497 static ULONG WINAPI AudioCaptureClient_AddRef(IAudioCaptureClient *iface)
1498 {
1499     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1500     return IAudioClient_AddRef(&This->IAudioClient_iface);
1501 }
1502
1503 static ULONG WINAPI AudioCaptureClient_Release(IAudioCaptureClient *iface)
1504 {
1505     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1506     return IAudioClient_Release(&This->IAudioClient_iface);
1507 }
1508
1509 static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
1510         BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos,
1511         UINT64 *qpcpos)
1512 {
1513     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1514
1515     TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
1516             devpos, qpcpos);
1517
1518     if(!data || !frames || !flags)
1519         return E_POINTER;
1520
1521     OSSpinLockLock(&This->lock);
1522
1523     if(This->getbuf_last){
1524         OSSpinLockUnlock(&This->lock);
1525         return AUDCLNT_E_OUT_OF_ORDER;
1526     }
1527
1528     if(This->public_buffer){
1529         *data = This->public_buffer->mAudioData;
1530         *frames =
1531             This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
1532     }else{
1533         struct list *head = list_head(&This->avail_buffers);
1534         if(!head){
1535             *data = NULL;
1536             *frames = 0;
1537         }else{
1538             AQBuffer *buf = LIST_ENTRY(head, AQBuffer, entry);
1539             This->public_buffer = buf->buf;
1540             *data = This->public_buffer->mAudioData;
1541             *frames =
1542                 This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
1543             list_remove(&buf->entry);
1544         }
1545     }
1546
1547     *flags = 0;
1548     This->written_frames += *frames;
1549     This->inbuf_frames -= *frames;
1550     This->getbuf_last = TRUE;
1551
1552     if(devpos || qpcpos)
1553         AudioClock_GetPosition_nolock(This, devpos, qpcpos, FALSE);
1554
1555     OSSpinLockUnlock(&This->lock);
1556
1557     return *frames ? S_OK : AUDCLNT_S_BUFFER_EMPTY;
1558 }
1559
1560 static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
1561         IAudioCaptureClient *iface, UINT32 done)
1562 {
1563     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1564     UINT32 pbuf_frames =
1565         This->public_buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
1566     OSStatus sc;
1567
1568     TRACE("(%p)->(%u)\n", This, done);
1569
1570     OSSpinLockLock(&This->lock);
1571
1572     if(!This->getbuf_last){
1573         OSSpinLockUnlock(&This->lock);
1574         return AUDCLNT_E_OUT_OF_ORDER;
1575     }
1576
1577     if(done != 0 && done != pbuf_frames){
1578         OSSpinLockUnlock(&This->lock);
1579         return AUDCLNT_E_INVALID_SIZE;
1580     }
1581
1582     if(done){
1583         sc = AudioQueueEnqueueBuffer(This->aqueue, This->public_buffer,
1584                 0, NULL);
1585         if(sc != noErr)
1586             WARN("Unable to enqueue buffer: %lx\n", sc);
1587         This->public_buffer = NULL;
1588     }
1589
1590     This->getbuf_last = FALSE;
1591
1592     OSSpinLockUnlock(&This->lock);
1593
1594     return S_OK;
1595 }
1596
1597 static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
1598         IAudioCaptureClient *iface, UINT32 *frames)
1599 {
1600     ACImpl *This = impl_from_IAudioCaptureClient(iface);
1601     struct list *head;
1602     AQBuffer *buf;
1603
1604     TRACE("(%p)->(%p)\n", This, frames);
1605
1606     if(!frames)
1607         return E_POINTER;
1608
1609     OSSpinLockLock(&This->lock);
1610
1611     head = list_head(&This->avail_buffers);
1612
1613     if(!head){
1614         *frames = This->bufsize_frames / CAPTURE_BUFFERS;
1615         OSSpinLockUnlock(&This->lock);
1616         return S_OK;
1617     }
1618
1619     buf = LIST_ENTRY(head, AQBuffer, entry);
1620     *frames = buf->buf->mAudioDataByteSize / This->fmt->nBlockAlign;
1621
1622     OSSpinLockUnlock(&This->lock);
1623
1624     return S_OK;
1625 }
1626
1627 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
1628 {
1629     AudioCaptureClient_QueryInterface,
1630     AudioCaptureClient_AddRef,
1631     AudioCaptureClient_Release,
1632     AudioCaptureClient_GetBuffer,
1633     AudioCaptureClient_ReleaseBuffer,
1634     AudioCaptureClient_GetNextPacketSize
1635 };
1636
1637 static HRESULT WINAPI AudioSessionControl_QueryInterface(
1638         IAudioSessionControl2 *iface, REFIID riid, void **ppv)
1639 {
1640     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1641
1642     if(!ppv)
1643         return E_POINTER;
1644     *ppv = NULL;
1645
1646     if(IsEqualIID(riid, &IID_IUnknown) ||
1647             IsEqualIID(riid, &IID_IAudioSessionControl) ||
1648             IsEqualIID(riid, &IID_IAudioSessionControl2))
1649         *ppv = iface;
1650     if(*ppv){
1651         IUnknown_AddRef((IUnknown*)*ppv);
1652         return S_OK;
1653     }
1654
1655     WARN("Unknown interface %s\n", debugstr_guid(riid));
1656     return E_NOINTERFACE;
1657 }
1658
1659 static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface)
1660 {
1661     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1662     return IAudioClient_AddRef(&This->IAudioClient_iface);
1663 }
1664
1665 static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface)
1666 {
1667     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1668     return IAudioClient_Release(&This->IAudioClient_iface);
1669 }
1670
1671 static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
1672         AudioSessionState *state)
1673 {
1674     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1675
1676     FIXME("(%p)->(%p) - stub\n", This, state);
1677
1678     if(!state)
1679         return E_POINTER;
1680
1681     return E_NOTIMPL;
1682 }
1683
1684 static HRESULT WINAPI AudioSessionControl_GetDisplayName(
1685         IAudioSessionControl2 *iface, WCHAR **name)
1686 {
1687     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1688
1689     FIXME("(%p)->(%p) - stub\n", This, name);
1690
1691     return E_NOTIMPL;
1692 }
1693
1694 static HRESULT WINAPI AudioSessionControl_SetDisplayName(
1695         IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
1696 {
1697     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1698
1699     FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
1700
1701     return E_NOTIMPL;
1702 }
1703
1704 static HRESULT WINAPI AudioSessionControl_GetIconPath(
1705         IAudioSessionControl2 *iface, WCHAR **path)
1706 {
1707     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1708
1709     FIXME("(%p)->(%p) - stub\n", This, path);
1710
1711     return E_NOTIMPL;
1712 }
1713
1714 static HRESULT WINAPI AudioSessionControl_SetIconPath(
1715         IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
1716 {
1717     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1718
1719     FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session));
1720
1721     return E_NOTIMPL;
1722 }
1723
1724 static HRESULT WINAPI AudioSessionControl_GetGroupingParam(
1725         IAudioSessionControl2 *iface, GUID *group)
1726 {
1727     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1728
1729     FIXME("(%p)->(%p) - stub\n", This, group);
1730
1731     return E_NOTIMPL;
1732 }
1733
1734 static HRESULT WINAPI AudioSessionControl_SetGroupingParam(
1735         IAudioSessionControl2 *iface, GUID *group, const GUID *session)
1736 {
1737     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1738
1739     FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group),
1740             debugstr_guid(session));
1741
1742     return E_NOTIMPL;
1743 }
1744
1745 static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification(
1746         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1747 {
1748     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1749
1750     FIXME("(%p)->(%p) - stub\n", This, events);
1751
1752     return S_OK;
1753 }
1754
1755 static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification(
1756         IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1757 {
1758     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1759
1760     FIXME("(%p)->(%p) - stub\n", This, events);
1761
1762     return S_OK;
1763 }
1764
1765 static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier(
1766         IAudioSessionControl2 *iface, WCHAR **id)
1767 {
1768     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1769
1770     FIXME("(%p)->(%p) - stub\n", This, id);
1771
1772     return E_NOTIMPL;
1773 }
1774
1775 static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier(
1776         IAudioSessionControl2 *iface, WCHAR **id)
1777 {
1778     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1779
1780     FIXME("(%p)->(%p) - stub\n", This, id);
1781
1782     return E_NOTIMPL;
1783 }
1784
1785 static HRESULT WINAPI AudioSessionControl_GetProcessId(
1786         IAudioSessionControl2 *iface, DWORD *pid)
1787 {
1788     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1789
1790     TRACE("(%p)->(%p)\n", This, pid);
1791
1792     if(!pid)
1793         return E_POINTER;
1794
1795     *pid = GetCurrentProcessId();
1796
1797     return S_OK;
1798 }
1799
1800 static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession(
1801         IAudioSessionControl2 *iface)
1802 {
1803     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1804
1805     TRACE("(%p)\n", This);
1806
1807     return S_FALSE;
1808 }
1809
1810 static HRESULT WINAPI AudioSessionControl_SetDuckingPreference(
1811         IAudioSessionControl2 *iface, BOOL optout)
1812 {
1813     ACImpl *This = impl_from_IAudioSessionControl2(iface);
1814
1815     TRACE("(%p)->(%d)\n", This, optout);
1816
1817     return S_OK;
1818 }
1819
1820 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
1821 {
1822     AudioSessionControl_QueryInterface,
1823     AudioSessionControl_AddRef,
1824     AudioSessionControl_Release,
1825     AudioSessionControl_GetState,
1826     AudioSessionControl_GetDisplayName,
1827     AudioSessionControl_SetDisplayName,
1828     AudioSessionControl_GetIconPath,
1829     AudioSessionControl_SetIconPath,
1830     AudioSessionControl_GetGroupingParam,
1831     AudioSessionControl_SetGroupingParam,
1832     AudioSessionControl_RegisterAudioSessionNotification,
1833     AudioSessionControl_UnregisterAudioSessionNotification,
1834     AudioSessionControl_GetSessionIdentifier,
1835     AudioSessionControl_GetSessionInstanceIdentifier,
1836     AudioSessionControl_GetProcessId,
1837     AudioSessionControl_IsSystemSoundsSession,
1838     AudioSessionControl_SetDuckingPreference
1839 };
1840
1841 static HRESULT WINAPI SimpleAudioVolume_QueryInterface(
1842         ISimpleAudioVolume *iface, REFIID riid, void **ppv)
1843 {
1844     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1845
1846     if(!ppv)
1847         return E_POINTER;
1848     *ppv = NULL;
1849
1850     if(IsEqualIID(riid, &IID_IUnknown) ||
1851             IsEqualIID(riid, &IID_ISimpleAudioVolume))
1852         *ppv = iface;
1853     if(*ppv){
1854         IUnknown_AddRef((IUnknown*)*ppv);
1855         return S_OK;
1856     }
1857
1858     WARN("Unknown interface %s\n", debugstr_guid(riid));
1859     return E_NOINTERFACE;
1860 }
1861
1862 static ULONG WINAPI SimpleAudioVolume_AddRef(ISimpleAudioVolume *iface)
1863 {
1864     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1865     return IAudioClient_AddRef(&This->IAudioClient_iface);
1866 }
1867
1868 static ULONG WINAPI SimpleAudioVolume_Release(ISimpleAudioVolume *iface)
1869 {
1870     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1871     return IAudioClient_Release(&This->IAudioClient_iface);
1872 }
1873
1874 static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
1875         ISimpleAudioVolume *iface, float level, const GUID *context)
1876 {
1877     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1878
1879     FIXME("(%p)->(%f, %p) - stub\n", This, level, context);
1880
1881     return E_NOTIMPL;
1882 }
1883
1884 static HRESULT WINAPI SimpleAudioVolume_GetMasterVolume(
1885         ISimpleAudioVolume *iface, float *level)
1886 {
1887     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1888
1889     FIXME("(%p)->(%p) - stub\n", This, level);
1890
1891     return E_NOTIMPL;
1892 }
1893
1894 static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
1895         BOOL mute, const GUID *context)
1896 {
1897     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1898
1899     FIXME("(%p)->(%u, %p) - stub\n", This, mute, context);
1900
1901     return E_NOTIMPL;
1902 }
1903
1904 static HRESULT WINAPI SimpleAudioVolume_GetMute(ISimpleAudioVolume *iface,
1905         BOOL *mute)
1906 {
1907     ACImpl *This = impl_from_ISimpleAudioVolume(iface);
1908
1909     FIXME("(%p)->(%p) - stub\n", This, mute);
1910
1911     return E_NOTIMPL;
1912 }
1913
1914 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl  =
1915 {
1916     SimpleAudioVolume_QueryInterface,
1917     SimpleAudioVolume_AddRef,
1918     SimpleAudioVolume_Release,
1919     SimpleAudioVolume_SetMasterVolume,
1920     SimpleAudioVolume_GetMasterVolume,
1921     SimpleAudioVolume_SetMute,
1922     SimpleAudioVolume_GetMute
1923 };
1924
1925 static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
1926         REFIID riid, void **ppv)
1927 {
1928     ACImpl *This = impl_from_IAudioClock(iface);
1929
1930     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1931
1932     if(!ppv)
1933         return E_POINTER;
1934     *ppv = NULL;
1935
1936     if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
1937         *ppv = iface;
1938     else if(IsEqualIID(riid, &IID_IAudioClock2))
1939         *ppv = &This->IAudioClock2_iface;
1940     if(*ppv){
1941         IUnknown_AddRef((IUnknown*)*ppv);
1942         return S_OK;
1943     }
1944
1945     WARN("Unknown interface %s\n", debugstr_guid(riid));
1946     return E_NOINTERFACE;
1947 }
1948
1949 static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
1950 {
1951     ACImpl *This = impl_from_IAudioClock(iface);
1952     return IAudioClient_AddRef(&This->IAudioClient_iface);
1953 }
1954
1955 static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
1956 {
1957     ACImpl *This = impl_from_IAudioClock(iface);
1958     return IAudioClient_Release(&This->IAudioClient_iface);
1959 }
1960
1961 static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
1962 {
1963     ACImpl *This = impl_from_IAudioClock(iface);
1964
1965     TRACE("(%p)->(%p)\n", This, freq);
1966
1967     *freq = This->fmt->nSamplesPerSec;
1968
1969     return S_OK;
1970 }
1971
1972 static HRESULT AudioClock_GetPosition_nolock(ACImpl *This,
1973         UINT64 *pos, UINT64 *qpctime, BOOL raw)
1974 {
1975     AudioTimeStamp time;
1976     OSStatus sc;
1977
1978     sc = AudioQueueGetCurrentTime(This->aqueue, NULL, &time, NULL);
1979     if(sc == kAudioQueueErr_InvalidRunState){
1980         *pos = 0;
1981     }else if(sc == noErr){
1982         if(!(time.mFlags & kAudioTimeStampSampleTimeValid)){
1983             FIXME("Sample time not valid, should calculate from something else\n");
1984             return E_FAIL;
1985         }
1986
1987         if(raw)
1988             *pos = time.mSampleTime;
1989         else
1990             *pos = time.mSampleTime - This->last_time;
1991     }else{
1992         WARN("Unable to get current time: %lx\n", sc);
1993         return E_FAIL;
1994     }
1995
1996     if(qpctime){
1997         LARGE_INTEGER stamp, freq;
1998         QueryPerformanceCounter(&stamp);
1999         QueryPerformanceFrequency(&freq);
2000         *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
2001     }
2002
2003     return S_OK;
2004 }
2005
2006 static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
2007         UINT64 *qpctime)
2008 {
2009     ACImpl *This = impl_from_IAudioClock(iface);
2010     HRESULT hr;
2011
2012     TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
2013
2014     if(!pos)
2015         return E_POINTER;
2016
2017     OSSpinLockLock(&This->lock);
2018
2019     hr = AudioClock_GetPosition_nolock(This, pos, qpctime, FALSE);
2020
2021     OSSpinLockUnlock(&This->lock);
2022
2023     return hr;
2024 }
2025
2026 static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
2027         DWORD *chars)
2028 {
2029     ACImpl *This = impl_from_IAudioClock(iface);
2030
2031     TRACE("(%p)->(%p)\n", This, chars);
2032
2033     if(!chars)
2034         return E_POINTER;
2035
2036     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
2037
2038     return S_OK;
2039 }
2040
2041 static const IAudioClockVtbl AudioClock_Vtbl =
2042 {
2043     AudioClock_QueryInterface,
2044     AudioClock_AddRef,
2045     AudioClock_Release,
2046     AudioClock_GetFrequency,
2047     AudioClock_GetPosition,
2048     AudioClock_GetCharacteristics
2049 };
2050
2051 static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
2052         REFIID riid, void **ppv)
2053 {
2054     ACImpl *This = impl_from_IAudioClock2(iface);
2055     return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
2056 }
2057
2058 static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
2059 {
2060     ACImpl *This = impl_from_IAudioClock2(iface);
2061     return IAudioClient_AddRef(&This->IAudioClient_iface);
2062 }
2063
2064 static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
2065 {
2066     ACImpl *This = impl_from_IAudioClock2(iface);
2067     return IAudioClient_Release(&This->IAudioClient_iface);
2068 }
2069
2070 static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
2071         UINT64 *pos, UINT64 *qpctime)
2072 {
2073     ACImpl *This = impl_from_IAudioClock2(iface);
2074
2075     FIXME("(%p)->(%p, %p)\n", This, pos, qpctime);
2076
2077     return E_NOTIMPL;
2078 }
2079
2080 static const IAudioClock2Vtbl AudioClock2_Vtbl =
2081 {
2082     AudioClock2_QueryInterface,
2083     AudioClock2_AddRef,
2084     AudioClock2_Release,
2085     AudioClock2_GetDevicePosition
2086 };