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
19 #include <audiopolicy.h>
20 #include <mmdeviceapi.h>
23 #include <wine/debug.h>
24 #include <wine/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
, ¶ms
);
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
);
70 if (IsEqualIID(riid
, &IID_IUnknown
) ||
71 IsEqualIID(riid
, &IID_IAudioSessionControl
) ||
72 IsEqualIID(riid
, &IID_IAudioSessionControl2
))
79 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
101 This
->client
->session_wrapper
= NULL
;
103 IAudioClient3_Release(&This
->client
->IAudioClient3_iface
);
106 HeapFree(GetProcessHeap(), 0, This
);
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
);
125 if (list_empty(&This
->session
->clients
)) {
126 *state
= AudioSessionStateExpired
;
131 LIST_FOR_EACH_ENTRY(client
, &This
->session
->clients
, struct audio_client
, entry
) {
132 params
.stream
= client
->stream
;
133 WINE_UNIX_CALL(is_started
, ¶ms
);
134 if (params
.result
== S_OK
) {
135 *state
= AudioSessionStateActive
;
143 *state
= AudioSessionStateInactive
;
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
);
155 static HRESULT WINAPI
control_SetDisplayName(IAudioSessionControl2
*iface
, const WCHAR
*name
,
158 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
159 FIXME("(%p)->(%p, %s) - stub\n", This
, name
, debugstr_guid(session
));
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
);
170 static HRESULT WINAPI
control_SetIconPath(IAudioSessionControl2
*iface
, const WCHAR
*path
,
173 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
174 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_w(path
), debugstr_guid(session
));
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
);
185 static HRESULT WINAPI
control_SetGroupingParam(IAudioSessionControl2
*iface
, const GUID
*group
,
188 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
189 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_guid(group
), debugstr_guid(session
));
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
);
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
);
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
);
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
);
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
);
232 *pid
= GetCurrentProcessId();
237 static HRESULT WINAPI
control_IsSystemSoundsSession(IAudioSessionControl2
*iface
)
239 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
240 TRACE("(%p)\n", This
);
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
);
251 const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
=
253 control_QueryInterface
,
257 control_GetDisplayName
,
258 control_SetDisplayName
,
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
,
275 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
280 if (IsEqualIID(riid
, &IID_IUnknown
) ||
281 IsEqualIID(riid
, &IID_IChannelAudioVolume
))
285 return E_NOINTERFACE
;
288 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
315 *out
= session
->channel_count
;
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
)
332 if (index
>= session
->channel_count
)
336 FIXME("Notifications not supported yet\n");
340 session
->channel_vols
[index
] = level
;
342 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
343 set_stream_volumes(client
);
350 static HRESULT WINAPI
channelvolume_GetChannelVolume(IChannelAudioVolume
*iface
, UINT32 index
,
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
);
361 if (index
>= session
->channel_count
)
364 *level
= session
->channel_vols
[index
];
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
;
377 TRACE("(%p)->(%d, %p, %s)\n", session
, count
, levels
, wine_dbgstr_guid(context
));
382 if (count
!= session
->channel_count
)
386 FIXME("Notifications not supported yet\n");
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
);
401 static HRESULT WINAPI
channelvolume_GetAllVolumes(IChannelAudioVolume
*iface
, UINT32 count
,
404 struct audio_session_wrapper
*This
= impl_from_IChannelAudioVolume(iface
);
405 struct audio_session
*session
= This
->session
;
408 TRACE("(%p)->(%d, %p)\n", session
, count
, levels
);
413 if (count
!= session
->channel_count
)
416 for (i
= 0; i
< count
; ++i
)
417 levels
[i
] = session
->channel_vols
[i
];
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
,
437 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
442 if (IsEqualIID(riid
, &IID_IUnknown
) ||
443 IsEqualIID(riid
, &IID_ISimpleAudioVolume
))
447 return E_NOINTERFACE
;
450 IUnknown_AddRef((IUnknown
*)*ppv
);
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
,
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
)
480 FIXME("Notifications not supported yet\n");
484 session
->master_vol
= level
;
486 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
487 set_stream_volumes(client
);
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
);
504 *level
= session
->master_vol
;
509 static HRESULT WINAPI
simplevolume_SetMute(ISimpleAudioVolume
*iface
, BOOL mute
,
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
));
519 FIXME("Notifications not supported yet\n");
523 session
->mute
= mute
;
525 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
526 set_stream_volumes(client
);
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
);
543 *mute
= session
->mute
;
548 const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
=
550 simplevolume_QueryInterface
,
552 simplevolume_Release
,
553 simplevolume_SetMasterVolume
,
554 simplevolume_GetMasterVolume
,
555 simplevolume_SetMute
,