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