wineoss: Use mmdevapi's AudioStreamVolume.
[wine.git] / dlls / mmdevapi / session.c
blob81cea5b3482a5854ecc5c4f32d5c5373eb49b5de
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 extern void set_stream_volumes(struct audio_client *This) DECLSPEC_HIDDEN;
38 static inline struct audio_session_wrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface)
40 return CONTAINING_RECORD(iface, struct audio_session_wrapper, IAudioSessionControl2_iface);
43 static inline struct audio_session_wrapper *impl_from_IChannelAudioVolume(IChannelAudioVolume *iface)
45 return CONTAINING_RECORD(iface, struct audio_session_wrapper, IChannelAudioVolume_iface);
48 static inline struct audio_session_wrapper *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface)
50 return CONTAINING_RECORD(iface, struct audio_session_wrapper, ISimpleAudioVolume_iface);
53 static HRESULT WINAPI control_QueryInterface(IAudioSessionControl2 *iface, REFIID riid, void **ppv)
55 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
57 if (!ppv)
58 return E_POINTER;
60 if (IsEqualIID(riid, &IID_IUnknown) ||
61 IsEqualIID(riid, &IID_IAudioSessionControl) ||
62 IsEqualIID(riid, &IID_IAudioSessionControl2))
63 *ppv = iface;
64 else {
65 *ppv = NULL;
66 return E_NOINTERFACE;
69 IUnknown_AddRef((IUnknown *)*ppv);
71 return S_OK;
74 static ULONG WINAPI control_AddRef(IAudioSessionControl2 *iface)
76 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
77 ULONG ref = InterlockedIncrement(&This->ref);
78 TRACE("(%p) Refcount now %lu\n", This, ref);
79 return ref;
82 static ULONG WINAPI control_Release(IAudioSessionControl2 *iface)
84 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
85 ULONG ref = InterlockedDecrement(&This->ref);
86 TRACE("(%p) Refcount now %lu\n", This, ref);
88 if (!ref) {
89 if (This->client) {
90 sessions_lock();
91 This->client->session_wrapper = NULL;
92 sessions_unlock();
93 IAudioClient3_Release(&This->client->IAudioClient3_iface);
96 HeapFree(GetProcessHeap(), 0, This);
99 return ref;
102 static HRESULT WINAPI control_GetState(IAudioSessionControl2 *iface, AudioSessionState *state)
104 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
105 struct is_started_params params;
106 struct audio_client *client;
108 TRACE("(%p)->(%p)\n", This, state);
110 if (!state)
111 return NULL_PTR_ERR;
113 sessions_lock();
115 if (list_empty(&This->session->clients)) {
116 *state = AudioSessionStateExpired;
117 sessions_unlock();
118 return S_OK;
121 LIST_FOR_EACH_ENTRY(client, &This->session->clients, struct audio_client, entry) {
122 params.stream = client->stream;
123 WINE_UNIX_CALL(is_started, &params);
124 if (params.result == S_OK) {
125 *state = AudioSessionStateActive;
126 sessions_unlock();
127 return S_OK;
131 sessions_unlock();
133 *state = AudioSessionStateInactive;
135 return S_OK;
138 static HRESULT WINAPI control_GetDisplayName(IAudioSessionControl2 *iface, WCHAR **name)
140 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
141 FIXME("(%p)->(%p) - stub\n", This, name);
142 return E_NOTIMPL;
145 static HRESULT WINAPI control_SetDisplayName(IAudioSessionControl2 *iface, const WCHAR *name,
146 const GUID *session)
148 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
149 FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session));
150 return E_NOTIMPL;
153 static HRESULT WINAPI control_GetIconPath(IAudioSessionControl2 *iface, WCHAR **path)
155 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
156 FIXME("(%p)->(%p) - stub\n", This, path);
157 return E_NOTIMPL;
160 static HRESULT WINAPI control_SetIconPath(IAudioSessionControl2 *iface, const WCHAR *path,
161 const GUID *session)
163 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
164 FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_w(path), debugstr_guid(session));
165 return E_NOTIMPL;
168 static HRESULT WINAPI control_GetGroupingParam(IAudioSessionControl2 *iface, GUID *group)
170 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
171 FIXME("(%p)->(%p) - stub\n", This, group);
172 return E_NOTIMPL;
175 static HRESULT WINAPI control_SetGroupingParam(IAudioSessionControl2 *iface, const GUID *group,
176 const GUID *session)
178 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
179 FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group), debugstr_guid(session));
180 return E_NOTIMPL;
183 static HRESULT WINAPI control_RegisterAudioSessionNotification(IAudioSessionControl2 *iface,
184 IAudioSessionEvents *events)
186 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
187 FIXME("(%p)->(%p) - stub\n", This, events);
188 return S_OK;
191 static HRESULT WINAPI control_UnregisterAudioSessionNotification(IAudioSessionControl2 *iface,
192 IAudioSessionEvents *events)
194 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
195 FIXME("(%p)->(%p) - stub\n", This, events);
196 return S_OK;
199 static HRESULT WINAPI control_GetSessionIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
201 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
202 FIXME("(%p)->(%p) - stub\n", This, id);
203 return E_NOTIMPL;
206 static HRESULT WINAPI control_GetSessionInstanceIdentifier(IAudioSessionControl2 *iface, WCHAR **id)
208 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
209 FIXME("(%p)->(%p) - stub\n", This, id);
210 return E_NOTIMPL;
213 static HRESULT WINAPI control_GetProcessId(IAudioSessionControl2 *iface, DWORD *pid)
215 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
217 TRACE("(%p)->(%p)\n", This, pid);
219 if (!pid)
220 return E_POINTER;
222 *pid = GetCurrentProcessId();
224 return S_OK;
227 static HRESULT WINAPI control_IsSystemSoundsSession(IAudioSessionControl2 *iface)
229 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
230 TRACE("(%p)\n", This);
231 return S_FALSE;
234 static HRESULT WINAPI control_SetDuckingPreference(IAudioSessionControl2 *iface, BOOL optout)
236 struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface);
237 TRACE("(%p)->(%d)\n", This, optout);
238 return S_OK;
241 const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl =
243 control_QueryInterface,
244 control_AddRef,
245 control_Release,
246 control_GetState,
247 control_GetDisplayName,
248 control_SetDisplayName,
249 control_GetIconPath,
250 control_SetIconPath,
251 control_GetGroupingParam,
252 control_SetGroupingParam,
253 control_RegisterAudioSessionNotification,
254 control_UnregisterAudioSessionNotification,
255 control_GetSessionIdentifier,
256 control_GetSessionInstanceIdentifier,
257 control_GetProcessId,
258 control_IsSystemSoundsSession,
259 control_SetDuckingPreference
262 static HRESULT WINAPI channelvolume_QueryInterface(IChannelAudioVolume *iface, REFIID riid,
263 void **ppv)
265 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
267 if (!ppv)
268 return E_POINTER;
270 if (IsEqualIID(riid, &IID_IUnknown) ||
271 IsEqualIID(riid, &IID_IChannelAudioVolume))
272 *ppv = iface;
273 else {
274 *ppv = NULL;
275 return E_NOINTERFACE;
278 IUnknown_AddRef((IUnknown *)*ppv);
280 return S_OK;
283 static ULONG WINAPI channelvolume_AddRef(IChannelAudioVolume *iface)
285 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
286 return IAudioSessionControl2_AddRef(&This->IAudioSessionControl2_iface);
289 static ULONG WINAPI channelvolume_Release(IChannelAudioVolume *iface)
291 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
292 return IAudioSessionControl2_Release(&This->IAudioSessionControl2_iface);
295 static HRESULT WINAPI channelvolume_GetChannelCount(IChannelAudioVolume *iface, UINT32 *out)
297 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
298 struct audio_session *session = This->session;
300 TRACE("(%p)->(%p)\n", session, out);
302 if (!out)
303 return NULL_PTR_ERR;
305 *out = session->channel_count;
307 return S_OK;
310 static HRESULT WINAPI channelvolume_SetChannelVolume(IChannelAudioVolume *iface, UINT32 index,
311 float level, const GUID *context)
313 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
314 struct audio_session *session = This->session;
315 struct audio_client *client;
317 TRACE("(%p)->(%d, %f, %s)\n", session, index, level, wine_dbgstr_guid(context));
319 if (level < 0.f || level > 1.f)
320 return E_INVALIDARG;
322 if (index >= session->channel_count)
323 return E_INVALIDARG;
325 if (context)
326 FIXME("Notifications not supported yet\n");
328 sessions_lock();
330 session->channel_vols[index] = level;
332 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
333 set_stream_volumes(client);
335 sessions_unlock();
337 return S_OK;
340 static HRESULT WINAPI channelvolume_GetChannelVolume(IChannelAudioVolume *iface, UINT32 index,
341 float *level)
343 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
344 struct audio_session *session = This->session;
346 TRACE("(%p)->(%d, %p)\n", session, index, level);
348 if (!level)
349 return NULL_PTR_ERR;
351 if (index >= session->channel_count)
352 return E_INVALIDARG;
354 *level = session->channel_vols[index];
356 return S_OK;
359 static HRESULT WINAPI channelvolume_SetAllVolumes(IChannelAudioVolume *iface, UINT32 count,
360 const float *levels, const GUID *context)
362 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
363 struct audio_session *session = This->session;
364 struct audio_client *client;
365 unsigned int i;
367 TRACE("(%p)->(%d, %p, %s)\n", session, count, levels, wine_dbgstr_guid(context));
369 if (!levels)
370 return NULL_PTR_ERR;
372 if (count != session->channel_count)
373 return E_INVALIDARG;
375 if (context)
376 FIXME("Notifications not supported yet\n");
378 sessions_lock();
380 for (i = 0; i < count; ++i)
381 session->channel_vols[i] = levels[i];
383 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
384 set_stream_volumes(client);
386 sessions_unlock();
388 return S_OK;
391 static HRESULT WINAPI channelvolume_GetAllVolumes(IChannelAudioVolume *iface, UINT32 count,
392 float *levels)
394 struct audio_session_wrapper *This = impl_from_IChannelAudioVolume(iface);
395 struct audio_session *session = This->session;
396 unsigned int i;
398 TRACE("(%p)->(%d, %p)\n", session, count, levels);
400 if (!levels)
401 return NULL_PTR_ERR;
403 if (count != session->channel_count)
404 return E_INVALIDARG;
406 for (i = 0; i < count; ++i)
407 levels[i] = session->channel_vols[i];
409 return S_OK;
412 const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl =
414 channelvolume_QueryInterface,
415 channelvolume_AddRef,
416 channelvolume_Release,
417 channelvolume_GetChannelCount,
418 channelvolume_SetChannelVolume,
419 channelvolume_GetChannelVolume,
420 channelvolume_SetAllVolumes,
421 channelvolume_GetAllVolumes
424 static HRESULT WINAPI simplevolume_QueryInterface(ISimpleAudioVolume *iface, REFIID riid,
425 void **ppv)
427 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
429 if (!ppv)
430 return E_POINTER;
432 if (IsEqualIID(riid, &IID_IUnknown) ||
433 IsEqualIID(riid, &IID_ISimpleAudioVolume))
434 *ppv = iface;
435 else {
436 *ppv = NULL;
437 return E_NOINTERFACE;
440 IUnknown_AddRef((IUnknown *)*ppv);
442 return S_OK;
445 static ULONG WINAPI simplevolume_AddRef(ISimpleAudioVolume *iface)
447 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
448 return IAudioSessionControl2_AddRef(&This->IAudioSessionControl2_iface);
451 static ULONG WINAPI simplevolume_Release(ISimpleAudioVolume *iface)
453 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
454 return IAudioSessionControl2_Release(&This->IAudioSessionControl2_iface);
457 static HRESULT WINAPI simplevolume_SetMasterVolume(ISimpleAudioVolume *iface, float level,
458 const GUID *context)
460 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
461 struct audio_session *session = This->session;
462 struct audio_client *client;
464 TRACE("(%p)->(%f, %s)\n", session, level, wine_dbgstr_guid(context));
466 if (level < 0.f || level > 1.f)
467 return E_INVALIDARG;
469 if (context)
470 FIXME("Notifications not supported yet\n");
472 sessions_lock();
474 session->master_vol = level;
476 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
477 set_stream_volumes(client);
479 sessions_unlock();
481 return S_OK;
484 static HRESULT WINAPI simplevolume_GetMasterVolume(ISimpleAudioVolume *iface, float *level)
486 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
487 struct audio_session *session = This->session;
489 TRACE("(%p)->(%p)\n", session, level);
491 if (!level)
492 return NULL_PTR_ERR;
494 *level = session->master_vol;
496 return S_OK;
499 static HRESULT WINAPI simplevolume_SetMute(ISimpleAudioVolume *iface, BOOL mute,
500 const GUID *context)
502 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
503 struct audio_session *session = This->session;
504 struct audio_client *client;
506 TRACE("(%p)->(%u, %s)\n", session, mute, debugstr_guid(context));
508 if (context)
509 FIXME("Notifications not supported yet\n");
511 sessions_lock();
513 session->mute = mute;
515 LIST_FOR_EACH_ENTRY(client, &session->clients, struct audio_client, entry)
516 set_stream_volumes(client);
518 sessions_unlock();
520 return S_OK;
523 static HRESULT WINAPI simplevolume_GetMute(ISimpleAudioVolume *iface, BOOL *mute)
525 struct audio_session_wrapper *This = impl_from_ISimpleAudioVolume(iface);
526 struct audio_session *session = This->session;
528 TRACE("(%p)->(%p)\n", session, mute);
530 if (!mute)
531 return NULL_PTR_ERR;
533 *mute = session->mute;
535 return S_OK;
538 const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl =
540 simplevolume_QueryInterface,
541 simplevolume_AddRef,
542 simplevolume_Release,
543 simplevolume_SetMasterVolume,
544 simplevolume_GetMasterVolume,
545 simplevolume_SetMute,
546 simplevolume_GetMute