xref: /reactos/dll/win32/mmdevapi/audiovolume.c (revision 02e84521)
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 }
321