[MMDEVAPI] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / win32 / mmdevapi / audiovolume.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 COBJMACROS
20 #include "config.h"
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
30
31 #include "ole2.h"
32 #include "mmdeviceapi.h"
33 #include "mmsystem.h"
34 #include "dsound.h"
35 #include "audioclient.h"
36 #include "endpointvolume.h"
37 #include "audiopolicy.h"
38
39 #include "mmdevapi.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
42
43 typedef struct AEVImpl {
44 IAudioEndpointVolumeEx IAudioEndpointVolumeEx_iface;
45 LONG ref;
46 float master_vol;
47 BOOL mute;
48 } AEVImpl;
49
50 static inline AEVImpl *impl_from_IAudioEndpointVolumeEx(IAudioEndpointVolumeEx *iface)
51 {
52 return CONTAINING_RECORD(iface, AEVImpl, IAudioEndpointVolumeEx_iface);
53 }
54
55 static void AudioEndpointVolume_Destroy(AEVImpl *This)
56 {
57 HeapFree(GetProcessHeap(), 0, This);
58 }
59
60 static HRESULT WINAPI AEV_QueryInterface(IAudioEndpointVolumeEx *iface, REFIID riid, void **ppv)
61 {
62 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
63 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
64 if (!ppv)
65 return E_POINTER;
66 *ppv = NULL;
67 if (IsEqualIID(riid, &IID_IUnknown) ||
68 IsEqualIID(riid, &IID_IAudioEndpointVolume) ||
69 IsEqualIID(riid, &IID_IAudioEndpointVolumeEx)) {
70 *ppv = &This->IAudioEndpointVolumeEx_iface;
71 }
72 else
73 return E_NOINTERFACE;
74 IUnknown_AddRef((IUnknown *)*ppv);
75 return S_OK;
76 }
77
78 static ULONG WINAPI AEV_AddRef(IAudioEndpointVolumeEx *iface)
79 {
80 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
81 ULONG ref = InterlockedIncrement(&This->ref);
82 TRACE("(%p) new ref %u\n", This, ref);
83 return ref;
84 }
85
86 static ULONG WINAPI AEV_Release(IAudioEndpointVolumeEx *iface)
87 {
88 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
89 ULONG ref = InterlockedDecrement(&This->ref);
90 TRACE("(%p) new ref %u\n", This, ref);
91 if (!ref)
92 AudioEndpointVolume_Destroy(This);
93 return ref;
94 }
95
96 static HRESULT WINAPI AEV_RegisterControlChangeNotify(IAudioEndpointVolumeEx *iface, IAudioEndpointVolumeCallback *notify)
97 {
98 TRACE("(%p)->(%p)\n", iface, notify);
99 if (!notify)
100 return E_POINTER;
101 FIXME("stub\n");
102 return S_OK;
103 }
104
105 static HRESULT WINAPI AEV_UnregisterControlChangeNotify(IAudioEndpointVolumeEx *iface, IAudioEndpointVolumeCallback *notify)
106 {
107 TRACE("(%p)->(%p)\n", iface, notify);
108 if (!notify)
109 return E_POINTER;
110 FIXME("stub\n");
111 return S_OK;
112 }
113
114 static HRESULT WINAPI AEV_GetChannelCount(IAudioEndpointVolumeEx *iface, UINT *count)
115 {
116 TRACE("(%p)->(%p)\n", iface, count);
117 if (!count)
118 return E_POINTER;
119 FIXME("stub\n");
120 return E_NOTIMPL;
121 }
122
123 static HRESULT WINAPI AEV_SetMasterVolumeLevel(IAudioEndpointVolumeEx *iface, float leveldb, const GUID *ctx)
124 {
125 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
126
127 TRACE("(%p)->(%f,%s)\n", iface, leveldb, debugstr_guid(ctx));
128
129 if(leveldb < -100.f || leveldb > 0.f)
130 return E_INVALIDARG;
131
132 This->master_vol = leveldb;
133
134 return S_OK;
135 }
136
137 static HRESULT WINAPI AEV_SetMasterVolumeLevelScalar(IAudioEndpointVolumeEx *iface, float level, const GUID *ctx)
138 {
139 TRACE("(%p)->(%f,%s)\n", iface, level, debugstr_guid(ctx));
140 FIXME("stub\n");
141 return E_NOTIMPL;
142 }
143
144 static HRESULT WINAPI AEV_GetMasterVolumeLevel(IAudioEndpointVolumeEx *iface, float *leveldb)
145 {
146 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
147
148 TRACE("(%p)->(%p)\n", iface, leveldb);
149
150 if (!leveldb)
151 return E_POINTER;
152
153 *leveldb = This->master_vol;
154
155 return S_OK;
156 }
157
158 static HRESULT WINAPI AEV_GetMasterVolumeLevelScalar(IAudioEndpointVolumeEx *iface, float *level)
159 {
160 TRACE("(%p)->(%p)\n", iface, level);
161 if (!level)
162 return E_POINTER;
163 FIXME("stub\n");
164 return E_NOTIMPL;
165 }
166
167 static HRESULT WINAPI AEV_SetChannelVolumeLevel(IAudioEndpointVolumeEx *iface, UINT chan, float leveldb, const GUID *ctx)
168 {
169 TRACE("(%p)->(%f,%s)\n", iface, leveldb, debugstr_guid(ctx));
170 FIXME("stub\n");
171 return E_NOTIMPL;
172 }
173
174 static HRESULT WINAPI AEV_SetChannelVolumeLevelScalar(IAudioEndpointVolumeEx *iface, UINT chan, float level, const GUID *ctx)
175 {
176 TRACE("(%p)->(%u,%f,%s)\n", iface, chan, level, debugstr_guid(ctx));
177 FIXME("stub\n");
178 return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI AEV_GetChannelVolumeLevel(IAudioEndpointVolumeEx *iface, UINT chan, float *leveldb)
182 {
183 TRACE("(%p)->(%u,%p)\n", iface, chan, leveldb);
184 if (!leveldb)
185 return E_POINTER;
186 FIXME("stub\n");
187 return E_NOTIMPL;
188 }
189
190 static HRESULT WINAPI AEV_GetChannelVolumeLevelScalar(IAudioEndpointVolumeEx *iface, UINT chan, float *level)
191 {
192 TRACE("(%p)->(%u,%p)\n", iface, chan, level);
193 if (!level)
194 return E_POINTER;
195 FIXME("stub\n");
196 return E_NOTIMPL;
197 }
198
199 static HRESULT WINAPI AEV_SetMute(IAudioEndpointVolumeEx *iface, BOOL mute, const GUID *ctx)
200 {
201 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
202 HRESULT ret;
203
204 TRACE("(%p)->(%u,%s)\n", iface, mute, debugstr_guid(ctx));
205
206 ret = This->mute == mute ? S_FALSE : S_OK;
207
208 This->mute = mute;
209
210 return ret;
211 }
212
213 static HRESULT WINAPI AEV_GetMute(IAudioEndpointVolumeEx *iface, BOOL *mute)
214 {
215 AEVImpl *This = impl_from_IAudioEndpointVolumeEx(iface);
216
217 TRACE("(%p)->(%p)\n", iface, mute);
218
219 if (!mute)
220 return E_POINTER;
221
222 *mute = This->mute;
223
224 return S_OK;
225 }
226
227 static HRESULT WINAPI AEV_GetVolumeStepInfo(IAudioEndpointVolumeEx *iface, UINT *stepsize, UINT *stepcount)
228 {
229 TRACE("(%p)->(%p,%p)\n", iface, stepsize, stepcount);
230 if (!stepsize && !stepcount)
231 return E_POINTER;
232 FIXME("stub\n");
233 return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI AEV_VolumeStepUp(IAudioEndpointVolumeEx *iface, const GUID *ctx)
237 {
238 TRACE("(%p)->(%s)\n", iface, debugstr_guid(ctx));
239 FIXME("stub\n");
240 return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI AEV_VolumeStepDown(IAudioEndpointVolumeEx *iface, const GUID *ctx)
244 {
245 TRACE("(%p)->(%s)\n", iface, debugstr_guid(ctx));
246 FIXME("stub\n");
247 return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI AEV_QueryHardwareSupport(IAudioEndpointVolumeEx *iface, DWORD *mask)
251 {
252 TRACE("(%p)->(%p)\n", iface, mask);
253 if (!mask)
254 return E_POINTER;
255 FIXME("stub\n");
256 return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI AEV_GetVolumeRange(IAudioEndpointVolumeEx *iface, float *mindb, float *maxdb, float *inc)
260 {
261 TRACE("(%p)->(%p,%p,%p)\n", iface, mindb, maxdb, inc);
262
263 if (!mindb || !maxdb || !inc)
264 return E_POINTER;
265
266 *mindb = -100.f;
267 *maxdb = 0.f;
268 *inc = 1.f;
269
270 return S_OK;
271 }
272
273 static HRESULT WINAPI AEV_GetVolumeRangeChannel(IAudioEndpointVolumeEx *iface, UINT chan, float *mindb, float *maxdb, float *inc)
274 {
275 TRACE("(%p)->(%p,%p,%p)\n", iface, mindb, maxdb, inc);
276 if (!mindb || !maxdb || !inc)
277 return E_POINTER;
278 FIXME("stub\n");
279 return E_NOTIMPL;
280 }
281
282 static const IAudioEndpointVolumeExVtbl AEVImpl_Vtbl = {
283 AEV_QueryInterface,
284 AEV_AddRef,
285 AEV_Release,
286 AEV_RegisterControlChangeNotify,
287 AEV_UnregisterControlChangeNotify,
288 AEV_GetChannelCount,
289 AEV_SetMasterVolumeLevel,
290 AEV_SetMasterVolumeLevelScalar,
291 AEV_GetMasterVolumeLevel,
292 AEV_GetMasterVolumeLevelScalar,
293 AEV_SetChannelVolumeLevel,
294 AEV_SetChannelVolumeLevelScalar,
295 AEV_GetChannelVolumeLevel,
296 AEV_GetChannelVolumeLevelScalar,
297 AEV_SetMute,
298 AEV_GetMute,
299 AEV_GetVolumeStepInfo,
300 AEV_VolumeStepUp,
301 AEV_VolumeStepDown,
302 AEV_QueryHardwareSupport,
303 AEV_GetVolumeRange,
304 AEV_GetVolumeRangeChannel
305 };
306
307 HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv)
308 {
309 AEVImpl *This;
310
311 *ppv = NULL;
312 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
313 if (!This)
314 return E_OUTOFMEMORY;
315 This->IAudioEndpointVolumeEx_iface.lpVtbl = &AEVImpl_Vtbl;
316 This->ref = 1;
317
318 *ppv = &This->IAudioEndpointVolumeEx_iface;
319 return S_OK;
320 }