winepulse: Move AudioStreamVolume into mmdevapi.
[wine.git] / dlls / mmdevapi / session.c
blob9c1b87a229b4cc8341e94fa42aaf2c3fe25871c5
1 /*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 #define COBJMACROS
19 #include <audiopolicy.h>
20 #include <mmdeviceapi.h>
21 #include <winternl.h>
23 #include <wine/debug.h>
24 #include <wine/unixlib.h>
26 #include "mmdevdrv.h"
27 #include "unixlib.h"
29 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
31 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
33 extern void sessions_lock(void) DECLSPEC_HIDDEN;
34 extern void sessions_unlock(void) DECLSPEC_HIDDEN;
36 void set_stream_volumes(struct audio_client *This)
38 struct set_volumes_params params;
40 params.stream = This->stream;
41 params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol);
42 params.volumes = This->vols;
43 params.session_volumes = This->session->channel_vols;
45 WINE_UNIX_CALL(set_volumes, &params);
48 static inline struct audio_session_wrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
50 return CONTAINING_RECORD(iface, struct audio_session_wrapper, IAudioSessionControl2_iface);
53 static inline struct audio_session_wrapper *impl_from_IChannelAudioVolume(IChannelAudioVolume *iface)
55 return CONTAINING_RECORD(iface, struct audio_session_wrapper, IChannelAudioVolume_iface);
58 static inline struct audio_session_wrapper *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
60 return CONTAINING_RECORD(iface, struct audio_session_wrapper, ISimpleAudioVolume_iface);
63 static HRESULT WINAPI control_QueryInterface(IAudioSessionControl2 *iface, REFIID riid, void **ppv)
65 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
67 if (!ppv)
68 return E_POINTER;
70 if (IsEqualIID(riid, &IID_IUnknown) ||
71 IsEqualIID(riid, &IID_IAudioSessionControl) ||
72 IsEqualIID(riid, &IID_IAudioSessionControl2))
73 *ppv = iface;
74 else {
75 *ppv = NULL;
76 return E_NOINTERFACE;
79 IUnknown_AddRef((IUnknown *)*ppv);
81 return S_OK;
84 static ULONG WINAPI control_AddRef(IAudioSessionControl2 *iface)
86 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
87 ULONG ref = InterlockedIncrement(&This->ref);
88 TRACE("(%p) Refcount now %lu\n", This, ref);
89 return ref;
92 static ULONG WINAPI control_Release(IAudioSessionControl2 *iface)
94 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
95 ULONG ref = InterlockedDecrement(&This->ref);
96 TRACE("(%p) Refcount now %lu\n", This, ref);
98 if (!ref) {
99 if (This->client) {
100 sessions_lock();
101 This->client->session_wrapper = NULL;
102 sessions_unlock();
103 IAudioClient3_Release(&This->client->IAudioClient3_iface);
106 HeapFree(GetProcessHeap(), 0, This);
109 return ref;
112 static HRESULT WINAPI control_GetState(IAudioSessionControl2 *iface, AudioSessionState *state)
114 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
115 struct is_started_params params;
116 struct audio_client *client;
118 TRACE("(%p)->(%p)\n", This, state);
120 if (!state)
121 return NULL_PTR_ERR;
123 sessions_lock();
125 if (list_empty(&This->session->clients)) {
126 *state = AudioSessionStateExpired;
127 sessions_unlock();
128 return S_OK;
131 LIST_FOR_EACH_ENTRY(client, &This->session->clients, struct audio_client, entry) {
132 params.stream = client->stream;
133 WINE_UNIX_CALL(is_started, &params);
134 if (params.result == S_OK) {
135 *state = AudioSessionStateActive;
136 sessions_unlock();
137 return S_OK;
141 sessions_unlock();
143 *state = AudioSessionStateInactive;
145 return S_OK;
148 static HRESULT WINAPI control_GetDisplayName(IAudioSessionControl2 *iface, WCHAR **name)
150 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
151 FIXME("(%p)->(%p) - stub\n", This, name);
152 return E_NOTIMPL;
155 static HRESULT WINAPI control_SetDisplayName(IAudioSessionControl2 *iface, const WCHAR *name,
156 const GUID *session)
158 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
159 FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
160 return E_NOTIMPL;
163 static HRESULT WINAPI control_GetIconPath(IAudioSessionControl2 *iface, WCHAR **path)
165 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
166 FIXME("(%p)->(%p) - stub\n", This, path);
167 return E_NOTIMPL;
170 static HRESULT WINAPI control_SetIconPath(IAudioSessionControl2 *iface, const WCHAR *path,
171 const GUID *session)
173 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
174 FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_w(path), debugstr_guid(session));
175 return E_NOTIMPL;
178 static HRESULT WINAPI control_GetGroupingParam(IAudioSessionControl2 *iface, GUID *group)
180 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
181 FIXME("(%p)->(%p) - stub\n", This, group);
182 return E_NOTIMPL;
185 static HRESULT WINAPI control_SetGroupingParam(IAudioSessionControl2 *iface, const GUID *group,
186 const GUID *session)
188 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
189 FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group), debugstr_guid(session));
190 return E_NOTIMPL;
193 static HRESULT WINAPI control_RegisterAudioSessionNotification(IAudioSessionControl2 *iface,
194 IAudioSessionEvents *events)
196 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
197 FIXME("(%p)->(%p) - stub\n", This, events);
198 return S_OK;
201 static HRESULT WINAPI control_UnregisterAudioSessionNotification(IAudioSessionControl2 *iface,
202 IAudioSessionEvents *events)
204 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
205 FIXME("(%p)->(%p) - stub\n", This, events);
206 return S_OK;
209 static HRESULT WINAPI control_GetSessionIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
211 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
212 FIXME("(%p)->(%p) - stub\n", This, id);
213 return E_NOTIMPL;
216 static HRESULT WINAPI control_GetSessionInstanceIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
218 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
219 FIXME("(%p)->(%p) - stub\n", This, id);
220 return E_NOTIMPL;
223 static HRESULT WINAPI control_GetProcessId(IAudioSessionControl2 *iface, DWORD *pid)
225 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
227 TRACE("(%p)->(%p)\n", This, pid);
229 if (!pid)
230 return E_POINTER;
232 *pid = GetCurrentProcessId();
234 return S_OK;
237 static HRESULT WINAPI control_IsSystemSoundsSession(IAudioSessionControl2 *iface)
239 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
240 TRACE("(%p)\n", This);
241 return S_FALSE;
244 static HRESULT WINAPI control_SetDuckingPreference(IAudioSessionControl2 *iface, BOOL optout)
246 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
247 TRACE("(%p)->(%d)\n", This, optout);
248 return S_OK;
251 const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
253 control_QueryInterface,
254 control_AddRef,
255 control_Release,
256 control_GetState,
257 control_GetDisplayName,
258 control_SetDisplayName,
259 control_GetIconPath,
260 control_SetIconPath,
261 control_GetGroupingParam,
262 control_SetGroupingParam,
263 control_RegisterAudioSessionNotification,
264 control_UnregisterAudioSessionNotification,
265 control_GetSessionIdentifier,
266 control_GetSessionInstanceIdentifier,
267 control_GetProcessId,
268 control_IsSystemSoundsSession,
269 control_SetDuckingPreference
272 static HRESULT WINAPI channelvolume_QueryInterface(IChannelAudioVolume *iface, REFIID riid,
273 void **ppv)
275 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
277 if (!ppv)
278 return E_POINTER;
280 if (IsEqualIID(riid, &IID_IUnknown) ||
281 IsEqualIID(riid, &IID_IChannelAudioVolume))
282 *ppv = iface;
283 else {
284 *ppv = NULL;
285 return E_NOINTERFACE;
288 IUnknown_AddRef((IUnknown *)*ppv);
290 return S_OK;
293 static ULONG WINAPI channelvolume_AddRef(IChannelAudioVolume *iface)
295 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
296 return IAudioSessionControl2_AddRef(&This->IAudioSessionControl2_iface);
299 static ULONG WINAPI channelvolume_Release(IChannelAudioVolume *iface)
301 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
302 return IAudioSessionControl2_Release(&This->IAudioSessionControl2_iface);
305 static HRESULT WINAPI channelvolume_GetChannelCount(IChannelAudioVolume *iface, UINT32 *out)
307 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
308 struct audio_session *session = This->session;
310 TRACE("(%p)->(%p)\n", session, out);
312 if (!out)
313 return NULL_PTR_ERR;
315 *out = session->channel_count;
317 return S_OK;
320 static HRESULT WINAPI channelvolume_SetChannelVolume(IChannelAudioVolume *iface, UINT32 index,
321 float level, const GUID *context)
323 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
324 struct audio_session *session = This->session;
325 struct audio_client *client;
327 TRACE("(%p)->(%d, %f, %s)\n", session, index, level, wine_dbgstr_guid(context));
329 if (level < 0.f || level > 1.f)
330 return E_INVALIDARG;
332 if (index >= session->channel_count)
333 return E_INVALIDARG;
335 if (context)
336 FIXME("Notifications not supported yet\n");
338 sessions_lock();
340 session->channel_vols[index] = level;
342 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
343 set_stream_volumes(client);
345 sessions_unlock();
347 return S_OK;
350 static HRESULT WINAPI channelvolume_GetChannelVolume(IChannelAudioVolume *iface, UINT32 index,
351 float *level)
353 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
354 struct audio_session *session = This->session;
356 TRACE("(%p)->(%d, %p)\n", session, index, level);
358 if (!level)
359 return NULL_PTR_ERR;
361 if (index >= session->channel_count)
362 return E_INVALIDARG;
364 *level = session->channel_vols[index];
366 return S_OK;
369 static HRESULT WINAPI channelvolume_SetAllVolumes(IChannelAudioVolume *iface, UINT32 count,
370 const float *levels, const GUID *context)
372 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
373 struct audio_session *session = This->session;
374 struct audio_client *client;
375 unsigned int i;
377 TRACE("(%p)->(%d, %p, %s)\n", session, count, levels, wine_dbgstr_guid(context));
379 if (!levels)
380 return NULL_PTR_ERR;
382 if (count != session->channel_count)
383 return E_INVALIDARG;
385 if (context)
386 FIXME("Notifications not supported yet\n");
388 sessions_lock();
390 for (i = 0; i < count; ++i)
391 session->channel_vols[i] = levels[i];
393 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
394 set_stream_volumes(client);
396 sessions_unlock();
398 return S_OK;
401 static HRESULT WINAPI channelvolume_GetAllVolumes(IChannelAudioVolume *iface, UINT32 count,
402 float *levels)
404 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
405 struct audio_session *session = This->session;
406 unsigned int i;
408 TRACE("(%p)->(%d, %p)\n", session, count, levels);
410 if (!levels)
411 return NULL_PTR_ERR;
413 if (count != session->channel_count)
414 return E_INVALIDARG;
416 for (i = 0; i < count; ++i)
417 levels[i] = session->channel_vols[i];
419 return S_OK;
422 const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
424 channelvolume_QueryInterface,
425 channelvolume_AddRef,
426 channelvolume_Release,
427 channelvolume_GetChannelCount,
428 channelvolume_SetChannelVolume,
429 channelvolume_GetChannelVolume,
430 channelvolume_SetAllVolumes,
431 channelvolume_GetAllVolumes
434 static HRESULT WINAPI simplevolume_QueryInterface(ISimpleAudioVolume *iface, REFIID riid,
435 void **ppv)
437 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
439 if (!ppv)
440 return E_POINTER;
442 if (IsEqualIID(riid, &IID_IUnknown) ||
443 IsEqualIID(riid, &IID_ISimpleAudioVolume))
444 *ppv = iface;
445 else {
446 *ppv = NULL;
447 return E_NOINTERFACE;
450 IUnknown_AddRef((IUnknown *)*ppv);
452 return S_OK;
455 static ULONG WINAPI simplevolume_AddRef(ISimpleAudioVolume *iface)
457 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
458 return IAudioSessionControl2_AddRef(&This->IAudioSessionControl2_iface);
461 static ULONG WINAPI simplevolume_Release(ISimpleAudioVolume *iface)
463 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
464 return IAudioSessionControl2_Release(&This->IAudioSessionControl2_iface);
467 static HRESULT WINAPI simplevolume_SetMasterVolume(ISimpleAudioVolume *iface, float level,
468 const GUID *context)
470 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
471 struct audio_session *session = This->session;
472 struct audio_client *client;
474 TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
476 if (level < 0.f || level > 1.f)
477 return E_INVALIDARG;
479 if (context)
480 FIXME("Notifications not supported yet\n");
482 sessions_lock();
484 session->master_vol = level;
486 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
487 set_stream_volumes(client);
489 sessions_unlock();
491 return S_OK;
494 static HRESULT WINAPI simplevolume_GetMasterVolume(ISimpleAudioVolume *iface, float *level)
496 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
497 struct audio_session *session = This->session;
499 TRACE("(%p)->(%p)\n", session, level);
501 if (!level)
502 return NULL_PTR_ERR;
504 *level = session->master_vol;
506 return S_OK;
509 static HRESULT WINAPI simplevolume_SetMute(ISimpleAudioVolume *iface, BOOL mute,
510 const GUID *context)
512 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
513 struct audio_session *session = This->session;
514 struct audio_client *client;
516 TRACE("(%p)->(%u, %s)\n", session, mute, debugstr_guid(context));
518 if (context)
519 FIXME("Notifications not supported yet\n");
521 sessions_lock();
523 session->mute = mute;
525 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
526 set_stream_volumes(client);
528 sessions_unlock();
530 return S_OK;
533 static HRESULT WINAPI simplevolume_GetMute(ISimpleAudioVolume *iface, BOOL *mute)
535 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
536 struct audio_session *session = This->session;
538 TRACE("(%p)->(%p)\n", session, mute);
540 if (!mute)
541 return NULL_PTR_ERR;
543 *mute = session->mute;
545 return S_OK;
548 const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =
550 simplevolume_QueryInterface,
551 simplevolume_AddRef,
552 simplevolume_Release,
553 simplevolume_SetMasterVolume,
554 simplevolume_GetMasterVolume,
555 simplevolume_SetMute,
556 simplevolume_GetMute