From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/Makefile.in | 1 + dlls/mmdevapi/audiosession.c | 248 ++++++++++++++++++++++++++++ dlls/mmdevapi/audiosessionmanager.c | 4 + 3 files changed, 253 insertions(+) create mode 100644 dlls/mmdevapi/audiosession.c
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in index 85a52d87184..60573cd8b0e 100644 --- a/dlls/mmdevapi/Makefile.in +++ b/dlls/mmdevapi/Makefile.in @@ -2,6 +2,7 @@ MODULE = mmdevapi.dll IMPORTS = uuid ole32 oleaut32 user32 advapi32
C_SRCS = \ + audiosession.c \ audiosessionmanager.c \ audiovolume.c \ devenum.c \ diff --git a/dlls/mmdevapi/audiosession.c b/dlls/mmdevapi/audiosession.c new file mode 100644 index 00000000000..9c3927be06d --- /dev/null +++ b/dlls/mmdevapi/audiosession.c @@ -0,0 +1,248 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS + +#include <audiopolicy.h> +#include <mmdeviceapi.h> + +#include <wine/debug.h> + +#include "mmdevapi_private.h" + +#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER) + +WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi); + +static inline struct audio_session_wrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface) +{ + return CONTAINING_RECORD(iface, struct audio_session_wrapper, IAudioSessionControl2_iface); +} + +static void AudioClient_DecRef(IAudioClient3 *iface) +{ + struct audio_client *This = CONTAINING_RECORD(iface, struct audio_client, IAudioClient3_iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) Refcount now %lu\n", This, ref); +} + +static HRESULT WINAPI ASC_QueryInterface(IAudioSessionControl2 *iface, REFIID riid, void **ppv) +{ + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + + if (!ppv) + return E_POINTER; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IAudioSessionManager) || + IsEqualIID(riid, &IID_IAudioSessionManager2)) + *ppv = iface; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ppv); + + return S_OK; +} + +static ULONG WINAPI ASC_AddRef(IAudioSessionControl2 *iface) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) Refcount now %lu\n", This, ref); + return ref; +} + +static ULONG WINAPI ASC_Release(IAudioSessionControl2 *iface) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) Refcount now %lu\n", This, ref); + + if (!ref){ + if (This->client) { + drvs.pLockSessions(TRUE); + This->client->session_wrapper = NULL; + drvs.pLockSessions(TRUE); + AudioClient_DecRef(&This->client->IAudioClient3_iface); + } + + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI ASC_GetState(IAudioSessionControl2 *iface, AudioSessionState *state) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + struct is_started_params params; + struct audio_client *client; + + TRACE("(%p)->(%p)\n", This, state); + + if (!state) + return NULL_PTR_ERR; + + drvs.pLockSessions(TRUE); + + if (list_empty(&This->session->clients)) { + *state = AudioSessionStateExpired; + drvs.pLockSessions(FALSE); + return S_OK; + } + + LIST_FOR_EACH_ENTRY(client, &This->session->clients, struct audio_client, entry) { + params.stream = client->stream; + __wine_unix_call(drvs.module_unixlib, is_started, ¶ms); + if (params.result == S_OK) { + *state = AudioSessionStateActive; + drvs.pLockSessions(FALSE); + return S_OK; + } + } + + drvs.pLockSessions(FALSE); + + *state = AudioSessionStateInactive; + + return S_OK; +} + +static HRESULT WINAPI ASC_GetDisplayName(IAudioSessionControl2 *iface, WCHAR **name) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, name); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_SetDisplayName(IAudioSessionControl2 *iface, const WCHAR *name, + const GUID *session) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session)); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_GetIconPath(IAudioSessionControl2 *iface, WCHAR **path) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, path); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_SetIconPath(IAudioSessionControl2 *iface, const WCHAR *path, + const GUID *session) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_w(path), debugstr_guid(session)); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_GetGroupingParam(IAudioSessionControl2 *iface, GUID *group) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, group); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_SetGroupingParam(IAudioSessionControl2 *iface, const GUID *group, + const GUID *session) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group), debugstr_guid(session)); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_RegisterAudioSessionNotification(IAudioSessionControl2 *iface, + IAudioSessionEvents *events) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, events); + return S_OK; +} + +static HRESULT WINAPI ASC_UnregisterAudioSessionNotification(IAudioSessionControl2 *iface, + IAudioSessionEvents *events) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, events); + return S_OK; +} + +static HRESULT WINAPI ASC_GetSessionIdentifier(IAudioSessionControl2 *iface, WCHAR **id) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_GetSessionInstanceIdentifier(IAudioSessionControl2 *iface, WCHAR **id) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + FIXME("(%p)->(%p) - stub\n", This, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI ASC_GetProcessId(IAudioSessionControl2 *iface, DWORD *pid) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + + TRACE("(%p)->(%p)\n", This, pid); + + if (!pid) + return E_POINTER; + + *pid = GetCurrentProcessId(); + + return S_OK; +} + +static HRESULT WINAPI ASC_IsSystemSoundsSession(IAudioSessionControl2 *iface) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + TRACE("(%p)\n", This); + return S_FALSE; +} + +static HRESULT WINAPI ASC_SetDuckingPreference(IAudioSessionControl2 *iface, BOOL optout) +{ + struct audio_session_wrapper *This = impl_from_IAudioSessionControl2(iface); + TRACE("(%p)->(%d)\n", This, optout); + return S_OK; +} + +const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl = +{ + ASC_QueryInterface, + ASC_AddRef, + ASC_Release, + ASC_GetState, + ASC_GetDisplayName, + ASC_SetDisplayName, + ASC_GetIconPath, + ASC_SetIconPath, + ASC_GetGroupingParam, + ASC_SetGroupingParam, + ASC_RegisterAudioSessionNotification, + ASC_UnregisterAudioSessionNotification, + ASC_GetSessionIdentifier, + ASC_GetSessionInstanceIdentifier, + ASC_GetProcessId, + ASC_IsSystemSoundsSession, + ASC_SetDuckingPreference +}; diff --git a/dlls/mmdevapi/audiosessionmanager.c b/dlls/mmdevapi/audiosessionmanager.c index 039b1c264df..fbfc068d74d 100644 --- a/dlls/mmdevapi/audiosessionmanager.c +++ b/dlls/mmdevapi/audiosessionmanager.c @@ -26,6 +26,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
+extern const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl; + static struct list g_sessions = LIST_INIT(g_sessions);
static inline struct session_mgr *impl_from_IAudioSessionManager2(IAudioSessionManager2 *iface) @@ -89,6 +91,8 @@ static HRESULT WINAPI ASM_GetAudioSessionControl(IAudioSessionManager2 *iface, if (FAILED(hr)) return hr;
+ wrapper->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl; + *out = (IAudioSessionControl*)&wrapper->IAudioSessionControl2_iface;
return S_OK;