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