wineoss: Use mmdevapi's AudioStreamVolume.
[wine.git] / dlls / mmdevapi / client.c
blob312bc462c3b3fb663df1c2424e47e3c5b085ed47
1 /*
2 * Copyright 2011-2012 Maarten Lankhorst
3 * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers
4 * Copyright 2011 Andrew Eikum for CodeWeavers
5 * Copyright 2022 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
24 #include <audiopolicy.h>
25 #include <mmdeviceapi.h>
26 #include <winternl.h>
28 #include <wine/debug.h>
29 #include <wine/unixlib.h>
31 #include "mmdevdrv.h"
32 #include "unixlib.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
36 extern void sessions_lock(void) DECLSPEC_HIDDEN;
37 extern void sessions_unlock(void) DECLSPEC_HIDDEN;
39 void set_stream_volumes(struct audio_client *This)
41 struct set_volumes_params params;
43 params.stream = This->stream;
44 params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol);
45 params.volumes = This->vols;
46 params.session_volumes = This->session->channel_vols;
48 WINE_UNIX_CALL(set_volumes, &params);
51 static inline struct audio_client *impl_from_IAudioStreamVolume(IAudioStreamVolume *iface)
53 return CONTAINING_RECORD(iface, struct audio_client, IAudioStreamVolume_iface);
56 static HRESULT WINAPI streamvolume_QueryInterface(IAudioStreamVolume *iface, REFIID riid,
57 void **ppv)
59 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
61 if (!ppv)
62 return E_POINTER;
64 if (IsEqualIID(riid, &IID_IUnknown) ||
65 IsEqualIID(riid, &IID_IAudioStreamVolume))
66 *ppv = iface;
67 else if (IsEqualIID(riid, &IID_IMarshal)) {
68 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
69 return IUnknown_QueryInterface(This->marshal, riid, ppv);
70 } else {
71 *ppv = NULL;
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown *)*ppv);
77 return S_OK;
80 static ULONG WINAPI streamvolume_AddRef(IAudioStreamVolume *iface)
82 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
83 return IAudioClient3_AddRef(&This->IAudioClient3_iface);
86 static ULONG WINAPI streamvolume_Release(IAudioStreamVolume *iface)
88 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
89 return IAudioClient3_Release(&This->IAudioClient3_iface);
92 static HRESULT WINAPI streamvolume_GetChannelCount(IAudioStreamVolume *iface, UINT32 *out)
94 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
96 TRACE("(%p)->(%p)\n", This, out);
98 if (!out)
99 return E_POINTER;
101 *out = This->channel_count;
103 return S_OK;
106 static HRESULT WINAPI streamvolume_SetChannelVolume(IAudioStreamVolume *iface, UINT32 index,
107 float level)
109 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
111 TRACE("(%p)->(%d, %f)\n", This, index, level);
113 if (level < 0.f || level > 1.f)
114 return E_INVALIDARG;
116 if (!This->stream)
117 return AUDCLNT_E_NOT_INITIALIZED;
119 if (index >= This->channel_count)
120 return E_INVALIDARG;
122 sessions_lock();
124 This->vols[index] = level;
125 set_stream_volumes(This);
127 sessions_unlock();
129 return S_OK;
132 static HRESULT WINAPI streamvolume_GetChannelVolume(IAudioStreamVolume *iface, UINT32 index,
133 float *level)
135 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
137 TRACE("(%p)->(%d, %p)\n", This, index, level);
139 if (!level)
140 return E_POINTER;
142 if (!This->stream)
143 return AUDCLNT_E_NOT_INITIALIZED;
145 if (index >= This->channel_count)
146 return E_INVALIDARG;
148 *level = This->vols[index];
150 return S_OK;
153 static HRESULT WINAPI streamvolume_SetAllVolumes(IAudioStreamVolume *iface, UINT32 count,
154 const float *levels)
156 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
157 unsigned int i;
159 TRACE("(%p)->(%d, %p)\n", This, count, levels);
161 if (!levels)
162 return E_POINTER;
164 if (!This->stream)
165 return AUDCLNT_E_NOT_INITIALIZED;
167 if (count != This->channel_count)
168 return E_INVALIDARG;
170 sessions_lock();
172 for (i = 0; i < count; ++i)
173 This->vols[i] = levels[i];
174 set_stream_volumes(This);
176 sessions_unlock();
178 return S_OK;
181 static HRESULT WINAPI streamvolume_GetAllVolumes(IAudioStreamVolume *iface, UINT32 count,
182 float *levels)
184 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
185 unsigned int i;
187 TRACE("(%p)->(%d, %p)\n", This, count, levels);
189 if (!levels)
190 return E_POINTER;
192 if (!This->stream)
193 return AUDCLNT_E_NOT_INITIALIZED;
195 if (count != This->channel_count)
196 return E_INVALIDARG;
198 sessions_lock();
200 for (i = 0; i < count; ++i)
201 levels[i] = This->vols[i];
203 sessions_unlock();
205 return S_OK;
208 const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
210 streamvolume_QueryInterface,
211 streamvolume_AddRef,
212 streamvolume_Release,
213 streamvolume_GetChannelCount,
214 streamvolume_SetChannelVolume,
215 streamvolume_GetChannelVolume,
216 streamvolume_SetAllVolumes,
217 streamvolume_GetAllVolumes