winmm: Update Dutch translation.
[wine] / dlls / mmdevapi / audio.c
1 /*
2  * Copyright 2010 Maarten Lankhorst 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 CINTERFACE
21 #define COBJMACROS
22 #include "config.h"
23
24 #include <stdarg.h>
25 #ifdef HAVE_AL_AL_H
26 #include <AL/al.h>
27 #include <AL/alc.h>
28 #elif defined(HAVE_OPENAL_AL_H)
29 #include <OpenAL/al.h>
30 #include <OpenAL/alc.h>
31 #endif
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
36 #include "winreg.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
39
40 #include "ole2.h"
41 #include "mmdeviceapi.h"
42 #include "dshow.h"
43 #include "dsound.h"
44 #include "audioclient.h"
45 #include "endpointvolume.h"
46 #include "audiopolicy.h"
47
48 #include "mmdevapi.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
51
52 #ifdef HAVE_OPENAL
53
54 typedef struct ACRender ACRender;
55 typedef struct ACCapture ACCapture;
56 typedef struct ACSession ACSession;
57 typedef struct ASVolume ASVolume;
58 typedef struct AClock AClock;
59
60 typedef struct ACImpl {
61     const IAudioClientVtbl *lpVtbl;
62     LONG ref;
63
64     MMDevice *parent;
65     BOOL init, running;
66     CRITICAL_SECTION *crst;
67     HANDLE handle;
68     DWORD locked, flags, bufsize, pad, padpartial, ofs, psize;
69     BYTE *buffer;
70     WAVEFORMATEX *pwfx;
71     ALuint source;
72     INT64 frameswritten;
73     REFERENCE_TIME laststamp;
74     HANDLE timer_id;
75     ALCdevice *capdev;
76     ALint format;
77
78     ACRender *render;
79     ACCapture *capture;
80     ACSession *session;
81     ASVolume *svolume;
82     AClock *clock;
83 } ACImpl;
84
85 struct ACRender {
86     const IAudioRenderClientVtbl *lpVtbl;
87     LONG ref;
88     ACImpl *parent;
89 };
90
91 struct ACCapture {
92     const IAudioCaptureClientVtbl *lpVtbl;
93     LONG ref;
94     ACImpl *parent;
95 };
96
97 struct ACSession {
98     const IAudioSessionControl2Vtbl *lpVtbl;
99     LONG ref;
100     ACImpl *parent;
101 };
102
103 struct ASVolume {
104     const ISimpleAudioVolumeVtbl *lpVtbl;
105     LONG ref;
106     ACImpl *parent;
107 };
108
109 struct AClock {
110     const IAudioClockVtbl *lpVtbl;
111     const IAudioClock2Vtbl *lp2Vtbl;
112     LONG ref;
113     ACImpl *parent;
114 };
115
116 static const IAudioClientVtbl ACImpl_Vtbl;
117 static const IAudioRenderClientVtbl ACRender_Vtbl;
118 static const IAudioCaptureClientVtbl ACCapture_Vtbl;
119 static const IAudioSessionControl2Vtbl ACSession_Vtbl;
120 static const ISimpleAudioVolumeVtbl ASVolume_Vtbl;
121 static const IAudioClockVtbl AClock_Vtbl;
122 static const IAudioClock2Vtbl AClock2_Vtbl;
123
124 static HRESULT AudioRenderClient_Create(ACImpl *parent, ACRender **ppv);
125 static void AudioRenderClient_Destroy(ACRender *This);
126 static HRESULT AudioCaptureClient_Create(ACImpl *parent, ACCapture **ppv);
127 static void AudioCaptureClient_Destroy(ACCapture *This);
128 static HRESULT AudioSessionControl_Create(ACImpl *parent, ACSession **ppv);
129 static void AudioSessionControl_Destroy(ACSession *This);
130 static HRESULT AudioSimpleVolume_Create(ACImpl *parent, ASVolume **ppv);
131 static void AudioSimpleVolume_Destroy(ASVolume *This);
132 static HRESULT AudioClock_Create(ACImpl *parent, AClock **ppv);
133 static void AudioClock_Destroy(AClock *This);
134
135 static int get_format_PCM(WAVEFORMATEX *format)
136 {
137     if (format->nChannels > 2) {
138         FIXME("nChannels > 2 not documented for WAVE_FORMAT_PCM!\n");
139         return 0;
140     }
141
142     format->cbSize = 0;
143
144     if (format->nBlockAlign != format->wBitsPerSample/8*format->nChannels) {
145         WARN("Invalid nBlockAlign %u, from %u %u\n",
146              format->nBlockAlign, format->wBitsPerSample, format->nChannels);
147         return 0;
148     }
149
150     switch (format->wBitsPerSample) {
151         case 8: {
152             switch (format->nChannels) {
153             case 1: return AL_FORMAT_MONO8;
154             case 2: return AL_FORMAT_STEREO8;
155             }
156         }
157         case 16: {
158             switch (format->nChannels) {
159             case 1: return AL_FORMAT_MONO16;
160             case 2: return AL_FORMAT_STEREO16;
161             }
162         }
163     }
164
165     if (!(format->wBitsPerSample % 8))
166         WARN("Could not get OpenAL format (%d-bit, %d channels)\n",
167              format->wBitsPerSample, format->nChannels);
168     return 0;
169 }
170
171 /* Speaker configs */
172 #define MONO SPEAKER_FRONT_CENTER
173 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
174 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
175 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
176 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
177 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
178 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
179
180 static int get_format_EXT(WAVEFORMATEX *format)
181 {
182     WAVEFORMATEXTENSIBLE *wfe;
183
184     if(format->cbSize < sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)) {
185         WARN("Invalid cbSize specified for WAVE_FORMAT_EXTENSIBLE (%d)\n", format->cbSize);
186         return 0;
187     }
188
189     wfe = (WAVEFORMATEXTENSIBLE*)format;
190     wfe->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
191     if (wfe->Samples.wValidBitsPerSample &&
192         wfe->Samples.wValidBitsPerSample != format->wBitsPerSample) {
193         FIXME("wValidBitsPerSample(%u) != wBitsPerSample(%u) unsupported\n",
194               wfe->Samples.wValidBitsPerSample, format->wBitsPerSample);
195         return 0;
196     }
197
198     TRACE("Extensible values:\n"
199           "    Samples     = %d\n"
200           "    ChannelMask = 0x%08x\n"
201           "    SubFormat   = %s\n",
202           wfe->Samples.wReserved, wfe->dwChannelMask,
203           debugstr_guid(&wfe->SubFormat));
204
205     if (wfe->dwChannelMask != MONO
206         && wfe->dwChannelMask != STEREO
207         && !palIsExtensionPresent("AL_EXT_MCFORMATS")) {
208         /* QUAD PCM might still work, special case */
209         if (palIsExtensionPresent("AL_LOKI_quadriphonic")
210             && IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)
211             && wfe->dwChannelMask == QUAD) {
212             if (format->wBitsPerSample == 16)
213                 return AL_FORMAT_QUAD16_LOKI;
214             else if (format->wBitsPerSample == 8)
215                 return AL_FORMAT_QUAD8_LOKI;
216         }
217         WARN("Not all formats available\n");
218         return 0;
219     }
220
221     if(IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
222         if (format->wBitsPerSample == 8) {
223             switch (wfe->dwChannelMask) {
224             case   MONO: return AL_FORMAT_MONO8;
225             case STEREO: return AL_FORMAT_STEREO8;
226             case   REAR: return AL_FORMAT_REAR8;
227             case   QUAD: return AL_FORMAT_QUAD8;
228             case X5DOT1: return AL_FORMAT_51CHN8;
229             case X6DOT1: return AL_FORMAT_61CHN8;
230             case X7DOT1: return AL_FORMAT_71CHN8;
231             default: break;
232             }
233         } else if (format->wBitsPerSample  == 16) {
234             switch (wfe->dwChannelMask) {
235             case   MONO: return AL_FORMAT_MONO16;
236             case STEREO: return AL_FORMAT_STEREO16;
237             case   REAR: return AL_FORMAT_REAR16;
238             case   QUAD: return AL_FORMAT_QUAD16;
239             case X5DOT1: return AL_FORMAT_51CHN16;
240             case X6DOT1: return AL_FORMAT_61CHN16;
241             case X7DOT1: return AL_FORMAT_71CHN16;
242             default: break;
243             }
244         }
245         else if (!(format->wBitsPerSample  % 8))
246             ERR("Could not get OpenAL PCM format (%d-bit, mask 0x%08x)\n",
247                 format->wBitsPerSample, wfe->dwChannelMask);
248         return 0;
249     }
250     else if(IsEqualGUID(&wfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
251         if (format->wBitsPerSample != 32) {
252             WARN("Invalid valid bits %u/32\n", format->wBitsPerSample);
253             return 0;
254         }
255         switch (wfe->dwChannelMask) {
256         case   MONO: return AL_FORMAT_MONO_FLOAT32;
257         case STEREO: return AL_FORMAT_STEREO_FLOAT32;
258         case   REAR: return AL_FORMAT_REAR32;
259         case   QUAD: return AL_FORMAT_QUAD32;
260         case X5DOT1: return AL_FORMAT_51CHN32;
261         case X6DOT1: return AL_FORMAT_61CHN32;
262         case X7DOT1: return AL_FORMAT_71CHN32;
263         default:
264             ERR("Could not get OpenAL float format (%d-bit, mask 0x%08x)\n",
265                 format->wBitsPerSample, wfe->dwChannelMask);
266             return 0;
267         }
268     }
269     else if (!IsEqualGUID(&wfe->SubFormat, &GUID_NULL))
270         ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe->SubFormat));
271     return 0;
272 }
273
274 static ALint get_format(WAVEFORMATEX *in)
275 {
276     int ret = 0;
277     if (in->wFormatTag == WAVE_FORMAT_PCM)
278         ret = get_format_PCM(in);
279     else if (in->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
280         ret = get_format_EXT(in);
281     return ret;
282 }
283
284 static REFERENCE_TIME gettime(void) {
285     LARGE_INTEGER stamp, freq;
286     QueryPerformanceCounter(&stamp);
287     QueryPerformanceFrequency(&freq);
288     return (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
289 }
290
291 HRESULT AudioClient_Create(MMDevice *parent, IAudioClient **ppv)
292 {
293     ACImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
294     *ppv = (IAudioClient*)This;
295     if (!*ppv)
296         return E_OUTOFMEMORY;
297     This->crst = &parent->crst;
298     This->lpVtbl = &ACImpl_Vtbl;
299     This->ref = 1;
300     This->parent = parent;
301     return S_OK;
302 }
303
304 static void AudioClient_Destroy(ACImpl *This)
305 {
306     if (This->timer_id)
307         DeleteTimerQueueTimer(NULL, This->timer_id, INVALID_HANDLE_VALUE);
308     if (This->render)
309         AudioRenderClient_Destroy(This->render);
310     if (This->capture)
311         AudioCaptureClient_Destroy(This->capture);
312     if (This->session)
313         AudioSessionControl_Destroy(This->session);
314     if (This->svolume)
315         AudioSimpleVolume_Destroy(This->svolume);
316     if (This->clock)
317         AudioClock_Destroy(This->clock);
318     if (This->parent->flow == eRender && This->init) {
319         setALContext(This->parent->ctx);
320         IAudioClient_Stop((IAudioClient*)This);
321         IAudioClient_Reset((IAudioClient*)This);
322         palDeleteSources(1, &This->source);
323         getALError();
324         popALContext();
325     }
326     if (This->capdev)
327         palcCaptureCloseDevice(This->capdev);
328     HeapFree(GetProcessHeap(), 0, This->pwfx);
329     HeapFree(GetProcessHeap(), 0, This->buffer);
330     HeapFree(GetProcessHeap(), 0, This);
331 }
332
333 static void CALLBACK AC_tick(void *data, BOOLEAN fired)
334 {
335     ACImpl *This = data;
336     DWORD pad;
337
338     EnterCriticalSection(This->crst);
339     if (This->running)
340         IAudioClient_GetCurrentPadding((IAudioClient*)This, &pad);
341     LeaveCriticalSection(This->crst);
342 }
343
344 /* Open device and set/update internal mixing format based on information
345  * openal provides us. if the device cannot be opened, assume 48khz
346  * Guessing the frequency is harmless, since if GetMixFormat fails to open
347  * the device, then Initialize will likely fail as well
348  */
349 static HRESULT AC_OpenRenderAL(ACImpl *This)
350 {
351     char alname[MAX_PATH];
352     MMDevice *cur = This->parent;
353
354     alname[sizeof(alname)-1] = 0;
355     if (cur->device)
356         return cur->ctx ? S_OK : AUDCLNT_E_SERVICE_NOT_RUNNING;
357
358     WideCharToMultiByte(CP_UNIXCP, 0, cur->alname, -1,
359                         alname, sizeof(alname)/sizeof(*alname)-1, NULL, NULL);
360     cur->device = palcOpenDevice(alname);
361     if (!cur->device) {
362         ALCenum err = palcGetError(NULL);
363         FIXME("Could not open device %s: 0x%04x\n", alname, err);
364         return AUDCLNT_E_DEVICE_IN_USE;
365     }
366     cur->ctx = palcCreateContext(cur->device, NULL);
367     if (!cur->ctx) {
368         ALCenum err = palcGetError(cur->device);
369         FIXME("Could not create context: 0x%04x\n", err);
370         return AUDCLNT_E_SERVICE_NOT_RUNNING;
371     }
372     if (!cur->device)
373         return AUDCLNT_E_DEVICE_IN_USE;
374     return S_OK;
375 }
376
377 static HRESULT AC_OpenCaptureAL(ACImpl *This)
378 {
379     char alname[MAX_PATH];
380     ALint freq, size;
381
382     freq = This->pwfx->nSamplesPerSec;
383     size = This->bufsize;
384
385     alname[sizeof(alname)-1] = 0;
386     if (This->capdev) {
387         FIXME("Attempting to open device while already open\n");
388         return S_OK;
389     }
390     WideCharToMultiByte(CP_UNIXCP, 0, This->parent->alname, -1,
391                         alname, sizeof(alname)/sizeof(*alname)-1, NULL, NULL);
392     This->capdev = palcCaptureOpenDevice(alname, freq, This->format, size);
393     if (!This->capdev) {
394         ALCenum err = palcGetError(NULL);
395         FIXME("Could not open device %s with buf size %u: 0x%04x\n",
396               alname, This->bufsize, err);
397         return AUDCLNT_E_DEVICE_IN_USE;
398     }
399     return S_OK;
400 }
401
402 static HRESULT WINAPI AC_QueryInterface(IAudioClient *iface, REFIID riid, void **ppv)
403 {
404     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
405
406     if (!ppv)
407         return E_POINTER;
408     *ppv = NULL;
409     if (IsEqualIID(riid, &IID_IUnknown)
410         || IsEqualIID(riid, &IID_IAudioClient))
411         *ppv = iface;
412     if (*ppv) {
413         IUnknown_AddRef((IUnknown*)*ppv);
414         return S_OK;
415     }
416     WARN("Unknown interface %s\n", debugstr_guid(riid));
417     return E_NOINTERFACE;
418 }
419
420 static ULONG WINAPI AC_AddRef(IAudioClient *iface)
421 {
422     ACImpl *This = (ACImpl*)iface;
423     ULONG ref;
424     ref = InterlockedIncrement(&This->ref);
425     TRACE("Refcount now %i\n", ref);
426     return ref;
427 }
428
429 static ULONG WINAPI AC_Release(IAudioClient *iface)
430 {
431     ACImpl *This = (ACImpl*)iface;
432     ULONG ref;
433     ref = InterlockedDecrement(&This->ref);
434     TRACE("Refcount now %i\n", ref);
435     if (!ref)
436         AudioClient_Destroy(This);
437     return ref;
438 }
439
440 static HRESULT WINAPI AC_Initialize(IAudioClient *iface, AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *pwfx, const GUID *sessionguid)
441 {
442     ACImpl *This = (ACImpl*)iface;
443     HRESULT hr = S_OK;
444     WAVEFORMATEX *pwfx2;
445     REFERENCE_TIME time, bufsize;
446
447     TRACE("(%p)->(%x,%x,%u,%u,%p,%s)\n", This, mode, flags, (int)duration, (int)period, pwfx, debugstr_guid(sessionguid));
448     if (This->init)
449         return AUDCLNT_E_ALREADY_INITIALIZED;
450     if (mode != AUDCLNT_SHAREMODE_SHARED
451         && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) {
452         WARN("Unknown mode %x\n", mode);
453         return AUDCLNT_E_NOT_INITIALIZED;
454     }
455
456     if (flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS
457                   |AUDCLNT_STREAMFLAGS_LOOPBACK
458                   |AUDCLNT_STREAMFLAGS_EVENTCALLBACK
459                   |AUDCLNT_STREAMFLAGS_NOPERSIST
460                   |AUDCLNT_STREAMFLAGS_RATEADJUST
461                   |AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED
462                   |AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE
463                   |AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED)) {
464         WARN("Unknown flags 0x%08x\n", flags);
465         return E_INVALIDARG;
466     }
467     if (flags)
468         WARN("Flags 0x%08x ignored\n", flags);
469     if (!pwfx)
470         return E_POINTER;
471     if (sessionguid)
472         WARN("Session guid %s ignored\n", debugstr_guid(sessionguid));
473
474     hr = IAudioClient_IsFormatSupported(iface, mode, pwfx, &pwfx2);
475     CoTaskMemFree(pwfx2);
476     if (FAILED(hr) || pwfx2) {
477         WARN("Format not supported, or had to be modified!\n");
478         return AUDCLNT_E_UNSUPPORTED_FORMAT;
479     }
480     EnterCriticalSection(This->crst);
481     HeapFree(GetProcessHeap(), 0, This->pwfx);
482     This->pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(*pwfx) + pwfx->cbSize);
483     if (!This->pwfx) {
484         hr = E_OUTOFMEMORY;
485         goto out;
486     }
487     memcpy(This->pwfx, pwfx, sizeof(*pwfx) + pwfx->cbSize);
488     if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
489         WAVEFORMATEXTENSIBLE *wfe = (WAVEFORMATEXTENSIBLE *)This->pwfx;
490         switch (pwfx->nChannels) {
491             case 1: wfe->dwChannelMask = MONO; break;
492             case 2: wfe->dwChannelMask = STEREO; break;
493             case 4: wfe->dwChannelMask = QUAD; break;
494             case 6: wfe->dwChannelMask = X5DOT1; break;
495             case 7: wfe->dwChannelMask = X6DOT1; break;
496             case 8: wfe->dwChannelMask = X7DOT1; break;
497         default:
498             ERR("How did we end up with %i channels?\n", pwfx->nChannels);
499             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
500             goto out;
501         }
502     }
503
504     hr = IAudioClient_GetDevicePeriod(iface, &time, NULL);
505     if (FAILED(hr))
506         goto out;
507
508     This->psize = (DWORD64)This->pwfx->nSamplesPerSec * time / (DWORD64)10000000;
509     if (duration > 20000000)
510         duration = 20000000;
511
512     bufsize = duration / time * This->psize;
513     if (duration % time)
514         bufsize += This->psize;
515     This->bufsize = bufsize;
516     This->psize *= This->pwfx->nBlockAlign;
517     bufsize *= pwfx->nBlockAlign;
518
519     This->format = get_format(This->pwfx);
520     if (This->parent->flow == eRender) {
521         char silence[32];
522         ALuint buf = 0, towrite;
523
524         hr = AC_OpenRenderAL(This);
525         if (FAILED(hr))
526             goto out;
527
528         /* Test the returned format */
529         towrite = sizeof(silence);
530         towrite -= towrite % This->pwfx->nBlockAlign;
531         if (This->pwfx->wBitsPerSample != 8)
532             memset(silence, 0, sizeof(silence));
533         else
534             memset(silence, 128, sizeof(silence));
535         setALContext(This->parent->ctx);
536         getALError();
537         palGenBuffers(1, &buf);
538         palBufferData(buf, This->format, silence, towrite, This->pwfx->nSamplesPerSec);
539         palDeleteBuffers(1, &buf);
540         if (palGetError())
541             hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
542         else if (!This->source) {
543             palGenSources(1, &This->source);
544             palSourcei(This->source, AL_LOOPING, AL_FALSE);
545             getALError();
546         }
547         popALContext();
548     }
549     else
550         hr = AC_OpenCaptureAL(This);
551
552     if (FAILED(hr))
553         goto out;
554
555     This->buffer = HeapAlloc(GetProcessHeap(), 0, bufsize);
556     if (!This->buffer) {
557         hr = E_OUTOFMEMORY;
558         goto out;
559     }
560     This->flags = flags;
561     This->handle = NULL;
562     This->running = FALSE;
563     This->init = TRUE;
564 out:
565     LeaveCriticalSection(This->crst);
566     return hr;
567 }
568
569 static HRESULT WINAPI AC_GetBufferSize(IAudioClient *iface, UINT32 *frames)
570 {
571     ACImpl *This = (ACImpl*)iface;
572     TRACE("(%p)->(%p)\n", This, frames);
573     if (!This->init)
574         return AUDCLNT_E_NOT_INITIALIZED;
575     if (!frames)
576         return E_POINTER;
577     *frames = This->bufsize;
578     return S_OK;
579 }
580
581 static HRESULT WINAPI AC_GetStreamLatency(IAudioClient *iface, REFERENCE_TIME *latency)
582 {
583     ACImpl *This = (ACImpl*)iface;
584     TRACE("(%p)->(%p)\n", This, latency);
585
586     if (!This->init)
587         return AUDCLNT_E_NOT_INITIALIZED;
588
589     if (!latency)
590         return E_POINTER;
591
592     *latency = 50000;
593
594     return S_OK;
595 }
596
597 static HRESULT WINAPI AC_GetCurrentPadding(IAudioClient *iface, UINT32 *numpad)
598 {
599     ACImpl *This = (ACImpl*)iface;
600     ALint avail = 0;
601
602     TRACE("(%p)->(%p)\n", This, numpad);
603     if (!This->init)
604         return AUDCLNT_E_NOT_INITIALIZED;
605     if (!numpad)
606         return E_POINTER;
607     EnterCriticalSection(This->crst);
608     if (This->parent->flow == eRender) {
609         UINT64 played = 0;
610         ALint state, padpart;
611         setALContext(This->parent->ctx);
612
613         palGetSourcei(This->source, AL_BYTE_OFFSET, &padpart);
614         palGetSourcei(This->source, AL_SOURCE_STATE, &state);
615         padpart /= This->pwfx->nBlockAlign;
616         if (state == AL_STOPPED && This->running)
617             padpart = This->pad;
618         if (This->running && This->padpartial != padpart) {
619             This->padpartial = padpart;
620             This->laststamp = gettime();
621 #if 0 /* Manipulative lie */
622         } else if (This->running) {
623             ALint size = This->pad - padpart;
624             if (size > This->psize)
625                 size = This->psize;
626             played = (gettime() - This->laststamp)*8;
627             played = played * This->pwfx->nSamplesPerSec / 10000000;
628             if (played > size)
629                 played = size;
630 #endif
631         }
632         *numpad = This->pad - This->padpartial - played;
633         if (This->handle && *numpad + This->psize <= This->bufsize)
634             SetEvent(This->handle);
635         getALError();
636         popALContext();
637     } else {
638         DWORD block = This->pwfx->nBlockAlign;
639         DWORD psize = This->psize / block;
640         palcGetIntegerv(This->capdev, ALC_CAPTURE_SAMPLES, 1, &avail);
641         if (avail) {
642             DWORD ofs = This->ofs + This->pad;
643             BYTE *buf1;
644             ofs %= This->bufsize;
645             buf1 = This->buffer + (ofs * block);
646             This->laststamp = gettime();
647             if (This->handle)
648                 SetEvent(This->handle);
649
650             if (ofs + avail <= This->bufsize)
651                 palcCaptureSamples(This->capdev, buf1, avail);
652             else {
653                 DWORD part1 = This->bufsize - ofs;
654                 palcCaptureSamples(This->capdev, buf1, part1);
655                 palcCaptureSamples(This->capdev, This->buffer, avail - part1);
656             }
657             This->pad += avail;
658             This->frameswritten += avail;
659             /* Increase ofs if the app forgets to read */
660             if (This->pad > This->bufsize) {
661                 DWORD rest;
662                 WARN("Overflowed! %u bytes\n", This->pad - This->bufsize);
663                 This->ofs += This->pad - This->bufsize;
664                 rest = This->ofs % psize;
665                 if (rest)
666                     This->ofs += psize - rest;
667                 This->ofs %= This->bufsize;
668                 This->pad = This->bufsize;
669             }
670         }
671         if (This->pad >= psize)
672             *numpad = psize;
673         else
674             *numpad = 0;
675     }
676     LeaveCriticalSection(This->crst);
677
678     TRACE("%u queued\n", *numpad);
679     return S_OK;
680 }
681
682 static HRESULT WINAPI AC_IsFormatSupported(IAudioClient *iface, AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *pwfx, WAVEFORMATEX **outpwfx)
683 {
684     ACImpl *This = (ACImpl*)iface;
685     WAVEFORMATEX *tmp;
686     DWORD mask;
687     DWORD size;
688     TRACE("(%p)->(%x,%p,%p)\n", This, mode, pwfx, outpwfx);
689     if (!pwfx)
690         return E_POINTER;
691
692     if (mode == AUDCLNT_SHAREMODE_SHARED && !outpwfx)
693         return E_POINTER;
694     if (mode != AUDCLNT_SHAREMODE_SHARED
695         && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) {
696         WARN("Unknown mode %x\n", mode);
697         return E_INVALIDARG;
698     }
699
700     if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
701         size = sizeof(WAVEFORMATEXTENSIBLE);
702     else if (pwfx->wFormatTag == WAVE_FORMAT_PCM)
703         size = sizeof(WAVEFORMATEX);
704     else
705         return AUDCLNT_E_UNSUPPORTED_FORMAT;
706
707     if (pwfx->nSamplesPerSec < 8000
708         || pwfx->nSamplesPerSec > 192000)
709         return AUDCLNT_E_UNSUPPORTED_FORMAT;
710     if (pwfx->wFormatTag != WAVE_FORMAT_EXTENSIBLE
711         || !IsEqualIID(&((WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
712         if (pwfx->wBitsPerSample > 16)
713             return AUDCLNT_E_UNSUPPORTED_FORMAT;
714     }
715
716     switch (pwfx->nChannels) {
717         case 1: mask = MONO; break;
718         case 2: mask = STEREO; break;
719         case 4: mask = QUAD; break;
720         case 6: mask = X5DOT1; break;
721         case 7: mask = X6DOT1; break;
722         case 8: mask = X7DOT1; break;
723         default:
724             TRACE("Unsupported channel count %i\n", pwfx->nChannels);
725             return AUDCLNT_E_UNSUPPORTED_FORMAT;;
726     }
727     tmp = CoTaskMemAlloc(size);
728     if (outpwfx)
729         *outpwfx = tmp;
730     if (!tmp)
731         return E_OUTOFMEMORY;
732
733     memcpy(tmp, pwfx, size);
734     tmp->nBlockAlign = tmp->nChannels * tmp->wBitsPerSample / 8;
735     tmp->nAvgBytesPerSec = tmp->nBlockAlign * tmp->nSamplesPerSec;
736     tmp->cbSize = size - sizeof(WAVEFORMATEX);
737     if (tmp->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
738         WAVEFORMATEXTENSIBLE *ex = (WAVEFORMATEXTENSIBLE*)tmp;
739
740         if (ex->Samples.wValidBitsPerSample)
741             ex->Samples.wValidBitsPerSample = ex->Format.wBitsPerSample;
742
743         /* Rear is a special allowed case */
744         if (ex->dwChannelMask
745             && !(ex->Format.nChannels == 2 && ex->dwChannelMask == REAR))
746             ex->dwChannelMask = mask;
747     }
748
749     if (memcmp(pwfx, tmp, size)) {
750         if (outpwfx)
751             return S_FALSE;
752         CoTaskMemFree(tmp);
753         return AUDCLNT_E_UNSUPPORTED_FORMAT;
754     }
755     if (outpwfx)
756         *outpwfx = NULL;
757     CoTaskMemFree(tmp);
758     return S_OK;
759 }
760
761 static HRESULT WINAPI AC_GetMixFormat(IAudioClient *iface, WAVEFORMATEX **pwfx)
762 {
763     ACImpl *This = (ACImpl*)iface;
764     PROPVARIANT pv = { VT_EMPTY };
765     HRESULT hr = S_OK;
766
767     TRACE("(%p)->(%p)\n", This, pwfx);
768     if (!pwfx)
769         return E_POINTER;
770
771     hr = MMDevice_GetPropValue(&This->parent->devguid, This->parent->flow,
772                                &PKEY_AudioEngine_DeviceFormat, &pv);
773     *pwfx = (WAVEFORMATEX*)pv.u.blob.pBlobData;
774     if (SUCCEEDED(hr) && pv.vt == VT_EMPTY)
775         return E_FAIL;
776
777     TRACE("Returning 0x%08x\n", hr);
778     return hr;
779 }
780
781 static HRESULT WINAPI AC_GetDevicePeriod(IAudioClient *iface, REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
782 {
783     ACImpl *This = (ACImpl*)iface;
784
785     TRACE("(%p)->(%p)\n", This, minperiod);
786     if (!defperiod && !minperiod)
787         return E_POINTER;
788
789     if (minperiod)
790         *minperiod = 30000;
791     if (defperiod)
792         *defperiod = 200000;
793     return S_OK;
794 }
795
796 static HRESULT WINAPI AC_Start(IAudioClient *iface)
797 {
798     ACImpl *This = (ACImpl*)iface;
799     HRESULT hr;
800     REFERENCE_TIME refresh;
801
802     TRACE("(%p)\n", This);
803     if (!This->init)
804         return AUDCLNT_E_NOT_INITIALIZED;
805     if (This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) {
806         if (!This->handle)
807             return AUDCLNT_E_EVENTHANDLE_NOT_SET;
808         FIXME("Event handles not fully tested\n");
809     }
810     EnterCriticalSection(This->crst);
811     if (This->running) {
812         hr = AUDCLNT_E_NOT_STOPPED;
813         goto out;
814     }
815     if (This->parent->flow == eRender) {
816         setALContext(This->parent->ctx);
817         palSourcePlay(This->source);
818         getALError();
819         popALContext();
820     }
821     else
822         palcCaptureStart(This->capdev);
823
824     AC_GetDevicePeriod(iface, &refresh, NULL);
825     if (!This->timer_id && This->handle)
826         CreateTimerQueueTimer(&This->timer_id, NULL, AC_tick, This,
827                               refresh / 20000, refresh / 20000,
828                               WT_EXECUTEINTIMERTHREAD);
829     /* Set to 0, otherwise risk running the clock backwards
830      * This will cause AudioClock::GetPosition to return the maximum
831      * possible value for the current buffer
832      */
833     This->laststamp = 0;
834     This->running = TRUE;
835     hr = S_OK;
836 out:
837     LeaveCriticalSection(This->crst);
838     return hr;
839 }
840
841 static HRESULT WINAPI AC_Stop(IAudioClient *iface)
842 {
843     ACImpl *This = (ACImpl*)iface;
844     HANDLE timer_id;
845     TRACE("(%p)\n", This);
846     if (!This->init)
847         return AUDCLNT_E_NOT_INITIALIZED;
848     if (!This->running)
849         return S_FALSE;
850     EnterCriticalSection(This->crst);
851     if (This->parent->flow == eRender) {
852         ALint state;
853         setALContext(This->parent->ctx);
854         This->running = FALSE;
855         palSourcePause(This->source);
856         while (1) {
857             state = AL_STOPPED;
858             palGetSourcei(This->source, AL_SOURCE_STATE, &state);
859             if (state != AL_PLAYING)
860                 break;
861             Sleep(1);
862         }
863         getALError();
864         popALContext();
865     }
866     else
867         palcCaptureStop(This->capdev);
868     timer_id = This->timer_id;
869     This->timer_id = 0;
870     LeaveCriticalSection(This->crst);
871     if (timer_id)
872         DeleteTimerQueueTimer(NULL, timer_id, INVALID_HANDLE_VALUE);
873     return S_OK;
874 }
875
876 static HRESULT WINAPI AC_Reset(IAudioClient *iface)
877 {
878     ACImpl *This = (ACImpl*)iface;
879     HRESULT hr = S_OK;
880     TRACE("(%p)\n", This);
881     if (!This->init)
882         return AUDCLNT_E_NOT_INITIALIZED;
883     if (This->running)
884         return AUDCLNT_E_NOT_STOPPED;
885     EnterCriticalSection(This->crst);
886     if (This->locked) {
887         hr = AUDCLNT_E_BUFFER_OPERATION_PENDING;
888         goto out;
889     }
890     if (This->parent->flow == eRender) {
891         ALuint buf;
892         ALint n = 0;
893         setALContext(This->parent->ctx);
894         palSourceStop(This->source);
895         palGetSourcei(This->source, AL_BUFFERS_PROCESSED, &n);
896         while (n--) {
897             palSourceUnqueueBuffers(This->source, 1, &buf);
898             palDeleteBuffers(1, &buf);
899         }
900         getALError();
901         popALContext();
902     } else {
903         ALint avail = 0;
904         palcGetIntegerv(This->capdev, ALC_CAPTURE_SAMPLES, 1, &avail);
905         if (avail)
906             palcCaptureSamples(This->capdev, This->buffer, avail);
907     }
908     This->pad = This->padpartial = 0;
909     This->ofs = 0;
910     This->frameswritten = 0;
911 out:
912     LeaveCriticalSection(This->crst);
913     return hr;
914 }
915
916 static HRESULT WINAPI AC_SetEventHandle(IAudioClient *iface, HANDLE handle)
917 {
918     ACImpl *This = (ACImpl*)iface;
919     TRACE("(%p)\n", This);
920     if (!This->init)
921         return AUDCLNT_E_NOT_INITIALIZED;
922     if (!handle)
923         return E_INVALIDARG;
924     if (!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))
925         return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
926     This->handle = handle;
927     return S_OK;
928 }
929
930 static HRESULT WINAPI AC_GetService(IAudioClient *iface, REFIID riid, void **ppv)
931 {
932     ACImpl *This = (ACImpl*)iface;
933     HRESULT hr = S_OK;
934     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
935     if (!This->init)
936         return AUDCLNT_E_NOT_INITIALIZED;
937     if (!ppv)
938         return E_POINTER;
939     *ppv = NULL;
940
941     if (IsEqualIID(riid, &IID_IAudioRenderClient)) {
942         if (This->parent->flow != eRender)
943             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
944         if (!This->render)
945             hr = AudioRenderClient_Create(This, &This->render);
946         *ppv = This->render;
947     } else if (IsEqualIID(riid, &IID_IAudioCaptureClient)) {
948         if (This->parent->flow != eCapture)
949             return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
950         if (!This->capture)
951             hr = AudioCaptureClient_Create(This, &This->capture);
952         *ppv = This->capture;
953     } else if (IsEqualIID(riid, &IID_IAudioSessionControl)) {
954         if (!This->session)
955             hr = AudioSessionControl_Create(This, &This->session);
956         *ppv = This->session;
957     } else if (IsEqualIID(riid, &IID_ISimpleAudioVolume)) {
958         if (!This->svolume)
959             hr = AudioSimpleVolume_Create(This, &This->svolume);
960         *ppv = This->svolume;
961     } else if (IsEqualIID(riid, &IID_IAudioClock)) {
962         if (!This->clock)
963             hr = AudioClock_Create(This, &This->clock);
964         *ppv = This->clock;
965     }
966
967     if (FAILED(hr))
968         return hr;
969
970     if (*ppv) {
971         IUnknown_AddRef((IUnknown*)*ppv);
972         return S_OK;
973     }
974
975     FIXME("stub %s\n", debugstr_guid(riid));
976     return E_NOINTERFACE;
977 }
978
979 static const IAudioClientVtbl ACImpl_Vtbl =
980 {
981     AC_QueryInterface,
982     AC_AddRef,
983     AC_Release,
984     AC_Initialize,
985     AC_GetBufferSize,
986     AC_GetStreamLatency,
987     AC_GetCurrentPadding,
988     AC_IsFormatSupported,
989     AC_GetMixFormat,
990     AC_GetDevicePeriod,
991     AC_Start,
992     AC_Stop,
993     AC_Reset,
994     AC_SetEventHandle,
995     AC_GetService
996 };
997
998 static HRESULT AudioRenderClient_Create(ACImpl *parent, ACRender **ppv)
999 {
1000     ACRender *This;
1001
1002     This = *ppv = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1003     if (!This)
1004         return E_OUTOFMEMORY;
1005     This->lpVtbl = &ACRender_Vtbl;
1006     This->ref = 0;
1007     This->parent = parent;
1008     return S_OK;
1009 }
1010
1011 static void AudioRenderClient_Destroy(ACRender *This)
1012 {
1013     This->parent->render = NULL;
1014     HeapFree(GetProcessHeap(), 0, This);
1015 }
1016
1017 static HRESULT WINAPI ACR_QueryInterface(IAudioRenderClient *iface, REFIID riid, void **ppv)
1018 {
1019     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
1020
1021     if (!ppv)
1022         return E_POINTER;
1023     *ppv = NULL;
1024     if (IsEqualIID(riid, &IID_IUnknown)
1025         || IsEqualIID(riid, &IID_IAudioRenderClient))
1026         *ppv = iface;
1027     if (*ppv) {
1028         IUnknown_AddRef((IUnknown*)*ppv);
1029         return S_OK;
1030     }
1031     WARN("Unknown interface %s\n", debugstr_guid(riid));
1032     return E_NOINTERFACE;
1033 }
1034
1035 static ULONG WINAPI ACR_AddRef(IAudioRenderClient *iface)
1036 {
1037     ACRender *This = (ACRender*)iface;
1038     ULONG ref;
1039     ref = InterlockedIncrement(&This->ref);
1040     TRACE("Refcount now %i\n", ref);
1041     return ref;
1042 }
1043
1044 static ULONG WINAPI ACR_Release(IAudioRenderClient *iface)
1045 {
1046     ACRender *This = (ACRender*)iface;
1047     ULONG ref;
1048     ref = InterlockedDecrement(&This->ref);
1049     TRACE("Refcount now %i\n", ref);
1050     if (!ref)
1051         AudioRenderClient_Destroy(This);
1052     return ref;
1053 }
1054
1055 static HRESULT WINAPI ACR_GetBuffer(IAudioRenderClient *iface, UINT32 frames, BYTE **data)
1056 {
1057     ACRender *This = (ACRender*)iface;
1058     DWORD free, framesize;
1059     TRACE("(%p)->(%u,%p)\n", This, frames, data);
1060
1061     if (!data)
1062         return E_POINTER;
1063     if (!frames)
1064         return S_OK;
1065     *data = NULL;
1066     if (This->parent->locked) {
1067         ERR("Locked\n");
1068         return AUDCLNT_E_OUT_OF_ORDER;
1069     }
1070     AC_GetCurrentPadding((IAudioClient*)This->parent, &free);
1071     if (This->parent->bufsize-free < frames) {
1072         ERR("Too large: %u %u %u\n", This->parent->bufsize, free, frames);
1073         return AUDCLNT_E_BUFFER_TOO_LARGE;
1074     }
1075     EnterCriticalSection(This->parent->crst);
1076     This->parent->locked = frames;
1077     framesize = This->parent->pwfx->nBlockAlign;
1078
1079     /* Exact offset doesn't matter, offset could be 0 forever
1080      * but increasing it is easier to debug */
1081     if (This->parent->ofs + frames > This->parent->bufsize)
1082         This->parent->ofs = 0;
1083     *data = This->parent->buffer + This->parent->ofs * framesize;
1084
1085     LeaveCriticalSection(This->parent->crst);
1086     return S_OK;
1087 }
1088
1089 static HRESULT WINAPI ACR_ReleaseBuffer(IAudioRenderClient *iface, UINT32 written, DWORD flags)
1090 {
1091     ACRender *This = (ACRender*)iface;
1092     BYTE *buf = This->parent->buffer;
1093     DWORD framesize = This->parent->pwfx->nBlockAlign;
1094     DWORD ofs = This->parent->ofs;
1095     DWORD bufsize = This->parent->bufsize;
1096     DWORD locked = This->parent->locked;
1097     DWORD freq = This->parent->pwfx->nSamplesPerSec;
1098     DWORD bpp = This->parent->pwfx->wBitsPerSample;
1099     ALuint albuf;
1100
1101     TRACE("(%p)->(%u,%x)\n", This, written, flags);
1102
1103     if (locked < written)
1104         return AUDCLNT_E_INVALID_SIZE;
1105
1106     if (flags & ~AUDCLNT_BUFFERFLAGS_SILENT)
1107         return E_INVALIDARG;
1108
1109     if (!written) {
1110         if (This->parent->locked)
1111             FIXME("Handled right?\n");
1112         This->parent->locked = 0;
1113         return S_OK;
1114     }
1115
1116     if (!This->parent->locked)
1117         return AUDCLNT_E_OUT_OF_ORDER;
1118
1119     EnterCriticalSection(This->parent->crst);
1120     setALContext(This->parent->parent->ctx);
1121
1122     This->parent->ofs += written;
1123     This->parent->ofs %= bufsize;
1124     This->parent->pad += written;
1125     This->parent->frameswritten += written;
1126
1127     ofs *= framesize;
1128     written *= framesize;
1129     bufsize *= framesize;
1130     locked *= framesize;
1131
1132     if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
1133         memset(buf+ofs, bpp != 8 ? 0 : 128, written);
1134     TRACE("buf: %p, ofs: %x, written %u, freq %u\n", buf, ofs, written, freq);
1135
1136     palGenBuffers(1, &albuf);
1137     palBufferData(albuf, This->parent->format, buf+ofs, written, freq);
1138     palSourceQueueBuffers(This->parent->source, 1, &albuf);
1139     TRACE("Queued %u\n", albuf);
1140
1141     if (This->parent->running) {
1142         ALint state = AL_PLAYING, done = 0, padpart = 0;
1143
1144         palGetSourcei(This->parent->source, AL_BUFFERS_PROCESSED, &done);
1145         palGetSourcei(This->parent->source, AL_BYTE_OFFSET, &padpart);
1146         palGetSourcei(This->parent->source, AL_SOURCE_STATE, &state);
1147         padpart /= framesize;
1148
1149         if (state == AL_STOPPED) {
1150             padpart = This->parent->pad;
1151             /* Buffer might have been processed in the small window
1152              * between first and third call */
1153             palGetSourcei(This->parent->source, AL_BUFFERS_PROCESSED, &done);
1154         }
1155         if (done || This->parent->padpartial != padpart)
1156             This->parent->laststamp = gettime();
1157         This->parent->padpartial = padpart;
1158
1159         while (done--) {
1160             ALint size, bits, chan;
1161             ALuint which;
1162
1163             palSourceUnqueueBuffers(This->parent->source, 1, &which);
1164             palGetBufferi(which, AL_SIZE, &size);
1165             palGetBufferi(which, AL_BITS, &bits);
1166             palGetBufferi(which, AL_CHANNELS, &chan);
1167             size /= bits * chan / 8;
1168             if (size > This->parent->pad) {
1169                 ERR("Overflow!\n");
1170                 size = This->parent->pad;
1171             }
1172             This->parent->pad -= size;
1173             This->parent->padpartial -= size;
1174             TRACE("Unqueued %u\n", which);
1175             palDeleteBuffers(1, &which);
1176         }
1177
1178         if (state != AL_PLAYING) {
1179             ERR("Starting from %x\n", state);
1180             palSourcePlay(This->parent->source);
1181         }
1182         getALError();
1183     }
1184     This->parent->locked = 0;
1185
1186     getALError();
1187     popALContext();
1188     LeaveCriticalSection(This->parent->crst);
1189
1190     return S_OK;
1191 }
1192
1193 static const IAudioRenderClientVtbl ACRender_Vtbl = {
1194     ACR_QueryInterface,
1195     ACR_AddRef,
1196     ACR_Release,
1197     ACR_GetBuffer,
1198     ACR_ReleaseBuffer
1199 };
1200
1201 static HRESULT AudioCaptureClient_Create(ACImpl *parent, ACCapture **ppv)
1202 {
1203     ACCapture *This;
1204     This = *ppv = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1205     if (!This)
1206         return E_OUTOFMEMORY;
1207     This->lpVtbl = &ACCapture_Vtbl;
1208     This->ref = 0;
1209     This->parent = parent;
1210     return S_OK;
1211 }
1212
1213 static void AudioCaptureClient_Destroy(ACCapture *This)
1214 {
1215     This->parent->capture = NULL;
1216     HeapFree(GetProcessHeap(), 0, This);
1217 }
1218
1219 static HRESULT WINAPI ACC_QueryInterface(IAudioCaptureClient *iface, REFIID riid, void **ppv)
1220 {
1221     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
1222
1223     if (!ppv)
1224         return E_POINTER;
1225     *ppv = NULL;
1226     if (IsEqualIID(riid, &IID_IUnknown)
1227         || IsEqualIID(riid, &IID_IAudioCaptureClient))
1228         *ppv = iface;
1229     if (*ppv) {
1230         IUnknown_AddRef((IUnknown*)*ppv);
1231         return S_OK;
1232     }
1233     WARN("Unknown interface %s\n", debugstr_guid(riid));
1234     return E_NOINTERFACE;
1235 }
1236
1237 static ULONG WINAPI ACC_AddRef(IAudioCaptureClient *iface)
1238 {
1239     ACCapture *This = (ACCapture*)iface;
1240     ULONG ref;
1241     ref = InterlockedIncrement(&This->ref);
1242     TRACE("Refcount now %i\n", ref);
1243     return ref;
1244 }
1245
1246 static ULONG WINAPI ACC_Release(IAudioCaptureClient *iface)
1247 {
1248     ACCapture *This = (ACCapture*)iface;
1249     ULONG ref;
1250     ref = InterlockedDecrement(&This->ref);
1251     TRACE("Refcount now %i\n", ref);
1252     if (!ref)
1253         AudioCaptureClient_Destroy(This);
1254     return ref;
1255 }
1256
1257 static HRESULT WINAPI ACC_GetBuffer(IAudioCaptureClient *iface, BYTE **data, UINT32 *frames, DWORD *flags, UINT64 *devpos, UINT64 *qpcpos)
1258 {
1259     ACCapture *This = (ACCapture*)iface;
1260     HRESULT hr;
1261     DWORD block = This->parent->pwfx->nBlockAlign;
1262     DWORD ofs, bufsize;
1263     TRACE("(%p)->(%p,%p,%p,%p,%p)\n", This, data, frames, flags, devpos, qpcpos);
1264
1265     if (!data)
1266         return E_POINTER;
1267     if (!frames)
1268         return E_POINTER;
1269     if (!flags) {
1270         FIXME("Flags can be null?\n");
1271         return E_POINTER;
1272     }
1273     EnterCriticalSection(This->parent->crst);
1274     hr = AUDCLNT_E_OUT_OF_ORDER;
1275     if (This->parent->locked)
1276         goto out;
1277     IAudioCaptureClient_GetNextPacketSize(iface, frames);
1278     ofs = This->parent->ofs;
1279     bufsize = This->parent->bufsize;
1280     if ( (ofs*block) % This->parent->psize)
1281         ERR("Unaligned offset %u with %u\n", ofs*block, This->parent->psize);
1282     *data = This->parent->buffer + ofs * block;
1283     This->parent->locked = *frames;
1284     if (devpos)
1285         *devpos = This->parent->frameswritten - This->parent->pad;
1286     if (qpcpos)
1287         *qpcpos = This->parent->laststamp;
1288     if (*frames)
1289         hr = S_OK;
1290     else
1291         hr = AUDCLNT_S_BUFFER_EMPTY;
1292 out:
1293     LeaveCriticalSection(This->parent->crst);
1294     TRACE("Returning %08x %i\n", hr, *frames);
1295     return hr;
1296 }
1297
1298 static HRESULT WINAPI ACC_ReleaseBuffer(IAudioCaptureClient *iface, UINT32 written)
1299 {
1300     ACCapture *This = (ACCapture*)iface;
1301     HRESULT hr = S_OK;
1302     EnterCriticalSection(This->parent->crst);
1303     if (!written || written == This->parent->locked) {
1304         This->parent->locked = 0;
1305         This->parent->ofs += written;
1306         This->parent->ofs %= This->parent->bufsize;
1307         This->parent->pad -= written;
1308     } else if (!This->parent->locked)
1309         hr = AUDCLNT_E_OUT_OF_ORDER;
1310     else
1311         hr = AUDCLNT_E_INVALID_SIZE;
1312     LeaveCriticalSection(This->parent->crst);
1313     return hr;
1314 }
1315
1316 static HRESULT WINAPI ACC_GetNextPacketSize(IAudioCaptureClient *iface, UINT32 *frames)
1317 {
1318     ACCapture *This = (ACCapture*)iface;
1319
1320     return AC_GetCurrentPadding((IAudioClient*)This->parent, frames);
1321 }
1322
1323 static const IAudioCaptureClientVtbl ACCapture_Vtbl =
1324 {
1325     ACC_QueryInterface,
1326     ACC_AddRef,
1327     ACC_Release,
1328     ACC_GetBuffer,
1329     ACC_ReleaseBuffer,
1330     ACC_GetNextPacketSize
1331 };
1332
1333 static HRESULT AudioSessionControl_Create(ACImpl *parent, ACSession **ppv)
1334 {
1335     ACSession *This;
1336     This = *ppv = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1337     if (!This)
1338         return E_OUTOFMEMORY;
1339     This->lpVtbl = &ACSession_Vtbl;
1340     This->ref = 0;
1341     This->parent = parent;
1342     return S_OK;
1343 }
1344
1345 static void AudioSessionControl_Destroy(ACSession *This)
1346 {
1347     This->parent->session = NULL;
1348     HeapFree(GetProcessHeap(), 0, This);
1349 }
1350
1351 static HRESULT WINAPI ACS_QueryInterface(IAudioSessionControl2 *iface, REFIID riid, void **ppv)
1352 {
1353     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
1354
1355     if (!ppv)
1356         return E_POINTER;
1357     *ppv = NULL;
1358     if (IsEqualIID(riid, &IID_IUnknown)
1359         || IsEqualIID(riid, &IID_IAudioSessionControl)
1360         || IsEqualIID(riid, &IID_IAudioSessionControl2))
1361         *ppv = iface;
1362     if (*ppv) {
1363         IUnknown_AddRef((IUnknown*)*ppv);
1364         return S_OK;
1365     }
1366     WARN("Unknown interface %s\n", debugstr_guid(riid));
1367     return E_NOINTERFACE;
1368 }
1369
1370 static ULONG WINAPI ACS_AddRef(IAudioSessionControl2 *iface)
1371 {
1372     ACSession *This = (ACSession*)iface;
1373     ULONG ref;
1374     ref = InterlockedIncrement(&This->ref);
1375     TRACE("Refcount now %i\n", ref);
1376     return ref;
1377 }
1378
1379 static ULONG WINAPI ACS_Release(IAudioSessionControl2 *iface)
1380 {
1381     ACSession *This = (ACSession*)iface;
1382     ULONG ref;
1383     ref = InterlockedDecrement(&This->ref);
1384     TRACE("Refcount now %i\n", ref);
1385     if (!ref)
1386         AudioSessionControl_Destroy(This);
1387     return ref;
1388 }
1389
1390 static HRESULT WINAPI ACS_GetState(IAudioSessionControl2 *iface, AudioSessionState *state)
1391 {
1392     ACSession *This = (ACSession*)iface;
1393     TRACE("(%p)->(%p)\n", This, state);
1394
1395     if (!state)
1396         return E_POINTER;
1397     *state = This->parent->parent->state;
1398     return E_NOTIMPL;
1399 }
1400
1401 static HRESULT WINAPI ACS_GetDisplayName(IAudioSessionControl2 *iface, WCHAR **name)
1402 {
1403     ACSession *This = (ACSession*)iface;
1404     TRACE("(%p)->(%p)\n", This, name);
1405     FIXME("stub\n");
1406     if (name)
1407         *name = NULL;
1408     return E_NOTIMPL;
1409 }
1410
1411 static HRESULT WINAPI ACS_SetDisplayName(IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session)
1412 {
1413     ACSession *This = (ACSession*)iface;
1414     TRACE("(%p)->(%p,%s)\n", This, name, debugstr_guid(session));
1415     FIXME("stub\n");
1416     return E_NOTIMPL;
1417 }
1418
1419 static HRESULT WINAPI ACS_GetIconPath(IAudioSessionControl2 *iface, WCHAR **path)
1420 {
1421     ACSession *This = (ACSession*)iface;
1422     TRACE("(%p)->(%p)\n", This, path);
1423     FIXME("stub\n");
1424     if (path)
1425         *path = NULL;
1426     return E_NOTIMPL;
1427 }
1428
1429 static HRESULT WINAPI ACS_SetIconPath(IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session)
1430 {
1431     ACSession *This = (ACSession*)iface;
1432     TRACE("(%p)->(%p,%s)\n", This, path, debugstr_guid(session));
1433     FIXME("stub\n");
1434     return E_NOTIMPL;
1435 }
1436
1437 static HRESULT WINAPI ACS_GetGroupingParam(IAudioSessionControl2 *iface, GUID *group)
1438 {
1439     ACSession *This = (ACSession*)iface;
1440     TRACE("(%p)->(%p)\n", This, group);
1441     FIXME("stub\n");
1442     if (group)
1443         *group = GUID_NULL;
1444     return E_NOTIMPL;
1445 }
1446
1447 static HRESULT WINAPI ACS_SetGroupingParam(IAudioSessionControl2 *iface, GUID *group, const GUID *session)
1448 {
1449     ACSession *This = (ACSession*)iface;
1450     TRACE("(%p)->(%s,%s)\n", This, debugstr_guid(group), debugstr_guid(session));
1451     FIXME("stub\n");
1452     return E_NOTIMPL;
1453 }
1454
1455 static HRESULT WINAPI ACS_RegisterAudioSessionNotification(IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1456 {
1457     ACSession *This = (ACSession*)iface;
1458     TRACE("(%p)->(%p)\n", This, events);
1459     FIXME("stub\n");
1460     return S_OK;
1461 }
1462
1463 static HRESULT WINAPI ACS_UnregisterAudioSessionNotification(IAudioSessionControl2 *iface, IAudioSessionEvents *events)
1464 {
1465     ACSession *This = (ACSession*)iface;
1466     TRACE("(%p)->(%p)\n", This, events);
1467     FIXME("stub\n");
1468     return S_OK;
1469 }
1470
1471 static HRESULT WINAPI ACS_GetSessionIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
1472 {
1473     ACSession *This = (ACSession*)iface;
1474     TRACE("(%p)->(%p)\n", This, id);
1475     FIXME("stub\n");
1476     if (id)
1477         *id = NULL;
1478     return E_NOTIMPL;
1479 }
1480
1481 static HRESULT WINAPI ACS_GetSessionInstanceIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
1482 {
1483     ACSession *This = (ACSession*)iface;
1484     TRACE("(%p)->(%p)\n", This, id);
1485     FIXME("stub\n");
1486     if (id)
1487         *id = NULL;
1488     return E_NOTIMPL;
1489 }
1490
1491 static HRESULT WINAPI ACS_GetProcessId(IAudioSessionControl2 *iface, DWORD *pid)
1492 {
1493     ACSession *This = (ACSession*)iface;
1494     TRACE("(%p)->(%p)\n", This, pid);
1495
1496     if (!pid)
1497         return E_POINTER;
1498     *pid = GetCurrentProcessId();
1499     return S_OK;
1500 }
1501
1502 static HRESULT WINAPI ACS_IsSystemSoundsSession(IAudioSessionControl2 *iface)
1503 {
1504     ACSession *This = (ACSession*)iface;
1505     TRACE("(%p)\n", This);
1506
1507     return S_FALSE;
1508 }
1509
1510 static HRESULT WINAPI ACS_SetDuckingPreference(IAudioSessionControl2 *iface, BOOL optout)
1511 {
1512     ACSession *This = (ACSession*)iface;
1513     TRACE("(%p)\n", This);
1514
1515     return S_OK;
1516 }
1517
1518 static const IAudioSessionControl2Vtbl ACSession_Vtbl =
1519 {
1520     ACS_QueryInterface,
1521     ACS_AddRef,
1522     ACS_Release,
1523     ACS_GetState,
1524     ACS_GetDisplayName,
1525     ACS_SetDisplayName,
1526     ACS_GetIconPath,
1527     ACS_SetIconPath,
1528     ACS_GetGroupingParam,
1529     ACS_SetGroupingParam,
1530     ACS_RegisterAudioSessionNotification,
1531     ACS_UnregisterAudioSessionNotification,
1532     ACS_GetSessionIdentifier,
1533     ACS_GetSessionInstanceIdentifier,
1534     ACS_GetProcessId,
1535     ACS_IsSystemSoundsSession,
1536     ACS_SetDuckingPreference
1537 };
1538
1539 static HRESULT AudioSimpleVolume_Create(ACImpl *parent, ASVolume **ppv)
1540 {
1541     ASVolume *This;
1542     This = *ppv = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1543     if (!This)
1544         return E_OUTOFMEMORY;
1545     This->lpVtbl = &ASVolume_Vtbl;
1546     This->ref = 0;
1547     This->parent = parent;
1548     return S_OK;
1549 }
1550
1551 static void AudioSimpleVolume_Destroy(ASVolume *This)
1552 {
1553     This->parent->svolume = NULL;
1554     HeapFree(GetProcessHeap(), 0, This);
1555 }
1556
1557 static HRESULT WINAPI ASV_QueryInterface(ISimpleAudioVolume *iface, REFIID riid, void **ppv)
1558 {
1559     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
1560
1561     if (!ppv)
1562         return E_POINTER;
1563     *ppv = NULL;
1564     if (IsEqualIID(riid, &IID_IUnknown)
1565         || IsEqualIID(riid, &IID_ISimpleAudioVolume))
1566         *ppv = iface;
1567     if (*ppv) {
1568         IUnknown_AddRef((IUnknown*)*ppv);
1569         return S_OK;
1570     }
1571     WARN("Unknown interface %s\n", debugstr_guid(riid));
1572     return E_NOINTERFACE;
1573 }
1574
1575 static ULONG WINAPI ASV_AddRef(ISimpleAudioVolume *iface)
1576 {
1577     ASVolume *This = (ASVolume*)iface;
1578     ULONG ref;
1579     ref = InterlockedIncrement(&This->ref);
1580     TRACE("Refcount now %i\n", ref);
1581     return ref;
1582 }
1583
1584 static ULONG WINAPI ASV_Release(ISimpleAudioVolume *iface)
1585 {
1586     ASVolume *This = (ASVolume*)iface;
1587     ULONG ref;
1588     ref = InterlockedDecrement(&This->ref);
1589     TRACE("Refcount now %i\n", ref);
1590     if (!ref)
1591         AudioSimpleVolume_Destroy(This);
1592     return ref;
1593 }
1594
1595 static HRESULT WINAPI ASV_SetMasterVolume(ISimpleAudioVolume *iface, float level, const GUID *context)
1596 {
1597     ASVolume *This = (ASVolume*)iface;
1598     TRACE("(%p)->(%f,%p)\n", This, level, context);
1599
1600     FIXME("stub\n");
1601     return S_OK;
1602 }
1603
1604 static HRESULT WINAPI ASV_GetMasterVolume(ISimpleAudioVolume *iface, float *level)
1605 {
1606     ASVolume *This = (ASVolume*)iface;
1607     TRACE("(%p)->(%p)\n", This, level);
1608
1609     *level = 1.f;
1610     FIXME("stub\n");
1611     return S_OK;
1612 }
1613
1614 static HRESULT WINAPI ASV_SetMute(ISimpleAudioVolume *iface, BOOL mute, const GUID *context)
1615 {
1616     ASVolume *This = (ASVolume*)iface;
1617     TRACE("(%p)->(%u,%p)\n", This, mute, context);
1618
1619     FIXME("stub\n");
1620     return S_OK;
1621 }
1622
1623 static HRESULT WINAPI ASV_GetMute(ISimpleAudioVolume *iface, BOOL *mute)
1624 {
1625     ASVolume *This = (ASVolume*)iface;
1626     TRACE("(%p)->(%p)\n", This, mute);
1627
1628     *mute = 0;
1629     FIXME("stub\n");
1630     return S_OK;
1631 }
1632
1633 static const ISimpleAudioVolumeVtbl ASVolume_Vtbl  =
1634 {
1635     ASV_QueryInterface,
1636     ASV_AddRef,
1637     ASV_Release,
1638     ASV_SetMasterVolume,
1639     ASV_GetMasterVolume,
1640     ASV_SetMute,
1641     ASV_GetMute
1642 };
1643
1644 static HRESULT AudioClock_Create(ACImpl *parent, AClock **ppv)
1645 {
1646     AClock *This;
1647     This = *ppv = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1648     if (!This)
1649         return E_OUTOFMEMORY;
1650     This->lpVtbl = &AClock_Vtbl;
1651     This->lp2Vtbl = &AClock2_Vtbl;
1652     This->ref = 0;
1653     This->parent = parent;
1654     return S_OK;
1655 }
1656
1657 static void AudioClock_Destroy(AClock *This)
1658 {
1659     This->parent->clock = NULL;
1660     HeapFree(GetProcessHeap(), 0, This);
1661 }
1662
1663 static HRESULT WINAPI AClock_QueryInterface(IAudioClock *iface, REFIID riid, void **ppv)
1664 {
1665     AClock *This = (AClock*)iface;
1666     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
1667
1668     if (!ppv)
1669         return E_POINTER;
1670     *ppv = NULL;
1671     if (IsEqualIID(riid, &IID_IUnknown)
1672         || IsEqualIID(riid, &IID_IAudioClock))
1673         *ppv = iface;
1674     else if (IsEqualIID(riid, &IID_IAudioClock2))
1675         *ppv = &This->lp2Vtbl;
1676     if (*ppv) {
1677         IUnknown_AddRef((IUnknown*)*ppv);
1678         return S_OK;
1679     }
1680     WARN("Unknown interface %s\n", debugstr_guid(riid));
1681     return E_NOINTERFACE;
1682 }
1683
1684 static ULONG WINAPI AClock_AddRef(IAudioClock *iface)
1685 {
1686     AClock *This = (AClock*)iface;
1687     ULONG ref;
1688     ref = InterlockedIncrement(&This->ref);
1689     TRACE("Refcount now %i\n", ref);
1690     return ref;
1691 }
1692
1693 static ULONG WINAPI AClock_Release(IAudioClock *iface)
1694 {
1695     AClock *This = (AClock*)iface;
1696     ULONG ref;
1697     ref = InterlockedDecrement(&This->ref);
1698     TRACE("Refcount now %i\n", ref);
1699     if (!ref)
1700         AudioClock_Destroy(This);
1701     return ref;
1702 }
1703
1704 static HRESULT WINAPI AClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
1705 {
1706     AClock *This = (AClock*)iface;
1707     TRACE("(%p)->(%p)\n", This, freq);
1708
1709     *freq = (UINT64)This->parent->pwfx->nSamplesPerSec;
1710     return S_OK;
1711 }
1712
1713 static HRESULT WINAPI AClock_GetPosition(IAudioClock *iface, UINT64 *pos, UINT64 *qpctime)
1714 {
1715     AClock *This = (AClock*)iface;
1716     DWORD pad;
1717
1718     TRACE("(%p)->(%p,%p)\n", This, pos, qpctime);
1719
1720     if (!pos)
1721         return E_POINTER;
1722
1723     EnterCriticalSection(This->parent->crst);
1724     AC_GetCurrentPadding((IAudioClient*)This->parent, &pad);
1725     *pos = This->parent->frameswritten - pad;
1726     if (qpctime)
1727         *qpctime = gettime();
1728     LeaveCriticalSection(This->parent->crst);
1729
1730     return S_OK;
1731 }
1732
1733 static HRESULT WINAPI AClock_GetCharacteristics(IAudioClock *iface, DWORD *chars)
1734 {
1735     AClock *This = (AClock*)iface;
1736     TRACE("(%p)->(%p)\n", This, chars);
1737
1738     if (!chars)
1739         return E_POINTER;
1740     *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
1741     return S_OK;
1742 }
1743
1744 static const IAudioClockVtbl AClock_Vtbl =
1745 {
1746     AClock_QueryInterface,
1747     AClock_AddRef,
1748     AClock_Release,
1749     AClock_GetFrequency,
1750     AClock_GetPosition,
1751     AClock_GetCharacteristics
1752 };
1753
1754 static AClock *get_clock_from_clock2(IAudioClock2 *iface)
1755 {
1756     return (AClock*)((char*)iface - offsetof(AClock,lp2Vtbl));
1757 }
1758
1759 static HRESULT WINAPI AClock2_QueryInterface(IAudioClock2 *iface, REFIID riid, void **ppv)
1760 {
1761     AClock *This = get_clock_from_clock2(iface);
1762     return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
1763 }
1764
1765 static ULONG WINAPI AClock2_AddRef(IAudioClock2 *iface)
1766 {
1767     AClock *This = get_clock_from_clock2(iface);
1768     return IUnknown_AddRef((IUnknown*)This);
1769 }
1770
1771 static ULONG WINAPI AClock2_Release(IAudioClock2 *iface)
1772 {
1773     AClock *This = get_clock_from_clock2(iface);
1774     return IUnknown_Release((IUnknown*)This);
1775 }
1776
1777 static HRESULT WINAPI AClock2_GetPosition(IAudioClock2 *iface, UINT64 *pos, UINT64 *qpctime)
1778 {
1779     AClock *This = get_clock_from_clock2(iface);
1780     return AClock_GetPosition((IAudioClock*)This, pos, qpctime);
1781 }
1782
1783 static const IAudioClock2Vtbl AClock2_Vtbl =
1784 {
1785     AClock2_QueryInterface,
1786     AClock2_AddRef,
1787     AClock2_Release,
1788     AClock2_GetPosition
1789 };
1790
1791 #endif