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 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
);
60 if (IsEqualIID(riid
, &IID_IUnknown
) ||
61 IsEqualIID(riid
, &IID_IAudioSessionControl
) ||
62 IsEqualIID(riid
, &IID_IAudioSessionControl2
))
69 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
91 This
->client
->session_wrapper
= NULL
;
93 IAudioClient3_Release(&This
->client
->IAudioClient3_iface
);
96 HeapFree(GetProcessHeap(), 0, This
);
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
);
115 if (list_empty(&This
->session
->clients
)) {
116 *state
= AudioSessionStateExpired
;
121 LIST_FOR_EACH_ENTRY(client
, &This
->session
->clients
, struct audio_client
, entry
) {
122 params
.stream
= client
->stream
;
123 WINE_UNIX_CALL(is_started
, ¶ms
);
124 if (params
.result
== S_OK
) {
125 *state
= AudioSessionStateActive
;
133 *state
= AudioSessionStateInactive
;
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
);
145 static HRESULT WINAPI
control_SetDisplayName(IAudioSessionControl2
*iface
, const WCHAR
*name
,
148 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
149 FIXME("(%p)->(%p, %s) - stub\n", This
, name
, debugstr_guid(session
));
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
);
160 static HRESULT WINAPI
control_SetIconPath(IAudioSessionControl2
*iface
, const WCHAR
*path
,
163 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
164 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_w(path
), debugstr_guid(session
));
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
);
175 static HRESULT WINAPI
control_SetGroupingParam(IAudioSessionControl2
*iface
, const GUID
*group
,
178 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
179 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_guid(group
), debugstr_guid(session
));
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
);
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
);
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
);
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
);
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
);
222 *pid
= GetCurrentProcessId();
227 static HRESULT WINAPI
control_IsSystemSoundsSession(IAudioSessionControl2
*iface
)
229 struct audio_session_wrapper
*This
= impl_from_IAudioSessionControl2(iface
);
230 TRACE("(%p)\n", This
);
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
);
241 const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
=
243 control_QueryInterface
,
247 control_GetDisplayName
,
248 control_SetDisplayName
,
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
,
265 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
270 if (IsEqualIID(riid
, &IID_IUnknown
) ||
271 IsEqualIID(riid
, &IID_IChannelAudioVolume
))
275 return E_NOINTERFACE
;
278 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
305 *out
= session
->channel_count
;
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
)
322 if (index
>= session
->channel_count
)
326 FIXME("Notifications not supported yet\n");
330 session
->channel_vols
[index
] = level
;
332 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
333 set_stream_volumes(client
);
340 static HRESULT WINAPI
channelvolume_GetChannelVolume(IChannelAudioVolume
*iface
, UINT32 index
,
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
);
351 if (index
>= session
->channel_count
)
354 *level
= session
->channel_vols
[index
];
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
;
367 TRACE("(%p)->(%d, %p, %s)\n", session
, count
, levels
, wine_dbgstr_guid(context
));
372 if (count
!= session
->channel_count
)
376 FIXME("Notifications not supported yet\n");
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
);
391 static HRESULT WINAPI
channelvolume_GetAllVolumes(IChannelAudioVolume
*iface
, UINT32 count
,
394 struct audio_session_wrapper
*This
= impl_from_IChannelAudioVolume(iface
);
395 struct audio_session
*session
= This
->session
;
398 TRACE("(%p)->(%d, %p)\n", session
, count
, levels
);
403 if (count
!= session
->channel_count
)
406 for (i
= 0; i
< count
; ++i
)
407 levels
[i
] = session
->channel_vols
[i
];
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
,
427 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
432 if (IsEqualIID(riid
, &IID_IUnknown
) ||
433 IsEqualIID(riid
, &IID_ISimpleAudioVolume
))
437 return E_NOINTERFACE
;
440 IUnknown_AddRef((IUnknown
*)*ppv
);
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
,
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
)
470 FIXME("Notifications not supported yet\n");
474 session
->master_vol
= level
;
476 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
477 set_stream_volumes(client
);
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
);
494 *level
= session
->master_vol
;
499 static HRESULT WINAPI
simplevolume_SetMute(ISimpleAudioVolume
*iface
, BOOL mute
,
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
));
509 FIXME("Notifications not supported yet\n");
513 session
->mute
= mute
;
515 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, struct audio_client
, entry
)
516 set_stream_volumes(client
);
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
);
533 *mute
= session
->mute
;
538 const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
=
540 simplevolume_QueryInterface
,
542 simplevolume_Release
,
543 simplevolume_SetMasterVolume
,
544 simplevolume_GetMasterVolume
,
545 simplevolume_SetMute
,