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