xref: /reactos/dll/win32/mmdevapi/audiovolume.c (revision 3e1f4074)
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 
48 static inline AEVImpl *impl_from_IAudioEndpointVolumeEx(IAudioEndpointVolumeEx *iface)
49 {
50     return CONTAINING_RECORD(iface, AEVImpl, IAudioEndpointVolumeEx_iface);
51 }
52 
53 static void AudioEndpointVolume_Destroy(AEVImpl *This)
54 {
55     HeapFree(GetProcessHeap(), 0, This);
56 }
57 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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