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