mmdevapi: Add initial audioclient stub.
[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     CRITICAL_SECTION *crst;
66     DWORD init;
67 } ACImpl;
68
69 static const IAudioClientVtbl ACImpl_Vtbl;
70
71 HRESULT AudioClient_Create(MMDevice *parent, IAudioClient **ppv)
72 {
73     ACImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
74     *ppv = (IAudioClient*)This;
75     if (!*ppv)
76         return E_OUTOFMEMORY;
77     This->crst = &parent->crst;
78     This->lpVtbl = &ACImpl_Vtbl;
79     This->ref = 1;
80     This->parent = parent;
81     return S_OK;
82 }
83
84 static void AudioClient_Destroy(ACImpl *This)
85 {
86     HeapFree(GetProcessHeap(), 0, This);
87 }
88
89 static HRESULT WINAPI AC_QueryInterface(IAudioClient *iface, REFIID riid, void **ppv)
90 {
91     TRACE("(%p)->(%s,%p)\n", iface, debugstr_guid(riid), ppv);
92
93     if (!ppv)
94         return E_POINTER;
95     *ppv = NULL;
96     if (IsEqualIID(riid, &IID_IUnknown)
97         || IsEqualIID(riid, &IID_IAudioClient))
98         *ppv = iface;
99     if (*ppv) {
100         IUnknown_AddRef((IUnknown*)*ppv);
101         return S_OK;
102     }
103     WARN("Unknown interface %s\n", debugstr_guid(riid));
104     return E_NOINTERFACE;
105 }
106
107 static ULONG WINAPI AC_AddRef(IAudioClient *iface)
108 {
109     ACImpl *This = (ACImpl*)iface;
110     ULONG ref;
111     ref = InterlockedIncrement(&This->ref);
112     TRACE("Refcount now %i\n", ref);
113     return ref;
114 }
115
116 static ULONG WINAPI AC_Release(IAudioClient *iface)
117 {
118     ACImpl *This = (ACImpl*)iface;
119     ULONG ref;
120     ref = InterlockedDecrement(&This->ref);
121     TRACE("Refcount now %i\n", ref);
122     if (!ref)
123         AudioClient_Destroy(This);
124     return ref;
125 }
126
127 static HRESULT WINAPI AC_Initialize(IAudioClient *iface, AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *pwfx, const GUID *sessionguid)
128 {
129     ACImpl *This = (ACImpl*)iface;
130
131     TRACE("(%p)->(%x,%x,%u,%u,%p,%s)\n", This, mode, flags, (int)duration, (int)period, pwfx, debugstr_guid(sessionguid));
132
133     FIXME("stub\n");
134     return E_NOTIMPL;
135 }
136
137 static HRESULT WINAPI AC_GetBufferSize(IAudioClient *iface, UINT32 *frames)
138 {
139     ACImpl *This = (ACImpl*)iface;
140     TRACE("(%p)->(%p)\n", This, frames);
141     if (!This->init)
142         return AUDCLNT_E_NOT_INITIALIZED;
143     if (!frames)
144         return E_POINTER;
145
146     FIXME("stub\n");
147     return E_NOTIMPL;
148 }
149
150 static HRESULT WINAPI AC_GetStreamLatency(IAudioClient *iface, REFERENCE_TIME *latency)
151 {
152     ACImpl *This = (ACImpl*)iface;
153     TRACE("(%p)->(%p)\n", This, latency);
154
155     if (!This->init)
156         return AUDCLNT_E_NOT_INITIALIZED;
157
158     return IAudioClient_GetDevicePeriod(iface, latency, NULL);
159 }
160
161 static HRESULT WINAPI AC_GetCurrentPadding(IAudioClient *iface, UINT32 *numpad)
162 {
163     ACImpl *This = (ACImpl*)iface;
164
165     TRACE("(%p)->(%p)\n", This, numpad);
166     if (!This->init)
167         return AUDCLNT_E_NOT_INITIALIZED;
168     if (!numpad)
169         return E_POINTER;
170
171     FIXME("stub\n");
172     return E_NOTIMPL;
173 }
174
175 static HRESULT WINAPI AC_IsFormatSupported(IAudioClient *iface, AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *pwfx, WAVEFORMATEX **outpwfx)
176 {
177     ACImpl *This = (ACImpl*)iface;
178     TRACE("(%p)->(%x,%p,%p)\n", This, mode, pwfx, outpwfx);
179     if (!pwfx)
180         return E_POINTER;
181
182     if (mode == AUDCLNT_SHAREMODE_SHARED && !outpwfx)
183         return E_POINTER;
184     if (mode != AUDCLNT_SHAREMODE_SHARED
185         && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) {
186         WARN("Unknown mode %x\n", mode);
187         return E_INVALIDARG;
188     }
189     if (pwfx->wFormatTag != WAVE_FORMAT_EXTENSIBLE
190         && pwfx->wFormatTag != WAVE_FORMAT_PCM)
191         return AUDCLNT_E_UNSUPPORTED_FORMAT;
192     if (pwfx->nSamplesPerSec < 8000
193         || pwfx->nSamplesPerSec > 192000)
194         return AUDCLNT_E_UNSUPPORTED_FORMAT;
195     if (pwfx->wFormatTag != WAVE_FORMAT_EXTENSIBLE
196         || !IsEqualIID(&((WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
197         if (pwfx->wBitsPerSample > 16)
198             return AUDCLNT_E_UNSUPPORTED_FORMAT;
199     }
200     if (outpwfx)
201         *outpwfx = NULL;
202     return S_OK;
203 }
204
205 static HRESULT WINAPI AC_GetMixFormat(IAudioClient *iface, WAVEFORMATEX **pwfx)
206 {
207     ACImpl *This = (ACImpl*)iface;
208
209     TRACE("(%p)->(%p)\n", This, pwfx);
210     if (!pwfx)
211         return E_POINTER;
212
213     FIXME("stub\n");
214     return E_NOTIMPL;
215 }
216
217 static HRESULT WINAPI AC_GetDevicePeriod(IAudioClient *iface, REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod)
218 {
219     ACImpl *This = (ACImpl*)iface;
220
221     TRACE("(%p)->(%p)\n", This, minperiod);
222     if (!defperiod && !minperiod)
223         return E_POINTER;
224
225     FIXME("stub\n");
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI AC_Start(IAudioClient *iface)
230 {
231     ACImpl *This = (ACImpl*)iface;
232
233     TRACE("(%p)\n", This);
234     if (!This->init)
235         return AUDCLNT_E_NOT_INITIALIZED;
236
237     FIXME("stub\n");
238     return E_NOTIMPL;
239 }
240
241 static HRESULT WINAPI AC_Stop(IAudioClient *iface)
242 {
243     ACImpl *This = (ACImpl*)iface;
244     TRACE("(%p)\n", This);
245     if (!This->init)
246         return AUDCLNT_E_NOT_INITIALIZED;
247
248     FIXME("stub\n");
249     return E_NOTIMPL;
250 }
251
252 static HRESULT WINAPI AC_Reset(IAudioClient *iface)
253 {
254     ACImpl *This = (ACImpl*)iface;
255     TRACE("(%p)\n", This);
256     if (!This->init)
257         return AUDCLNT_E_NOT_INITIALIZED;
258
259     FIXME("stub\n");
260     return E_NOTIMPL;
261 }
262
263 static HRESULT WINAPI AC_SetEventHandle(IAudioClient *iface, HANDLE handle)
264 {
265     ACImpl *This = (ACImpl*)iface;
266     TRACE("(%p)\n", This);
267     if (!This->init)
268         return AUDCLNT_E_NOT_INITIALIZED;
269     if (!handle)
270         return E_INVALIDARG;
271
272     FIXME("stub\n");
273     return E_NOTIMPL;
274 }
275
276 static HRESULT WINAPI AC_GetService(IAudioClient *iface, REFIID riid, void **ppv)
277 {
278     ACImpl *This = (ACImpl*)iface;
279     HRESULT hr = S_OK;
280     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
281     if (!This->init)
282         return AUDCLNT_E_NOT_INITIALIZED;
283     if (!ppv)
284         return E_POINTER;
285     *ppv = NULL;
286
287     if (FAILED(hr))
288         return hr;
289
290     if (*ppv) {
291         IUnknown_AddRef((IUnknown*)*ppv);
292         return S_OK;
293     }
294
295     FIXME("stub %s\n", debugstr_guid(riid));
296     return E_NOINTERFACE;
297 }
298
299 static const IAudioClientVtbl ACImpl_Vtbl =
300 {
301     AC_QueryInterface,
302     AC_AddRef,
303     AC_Release,
304     AC_Initialize,
305     AC_GetBufferSize,
306     AC_GetStreamLatency,
307     AC_GetCurrentPadding,
308     AC_IsFormatSupported,
309     AC_GetMixFormat,
310     AC_GetDevicePeriod,
311     AC_Start,
312     AC_Stop,
313     AC_Reset,
314     AC_SetEventHandle,
315     AC_GetService
316 };
317
318 #endif