From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winealsa.drv/mmdevdrv.c | 6 ++++++ dlls/winealsa.drv/winealsa.drv.spec | 1 + 2 files changed, 7 insertions(+)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index c46ae41f48b..e760dca9b30 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -2259,3 +2259,9 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
return params.result; } + +HRESULT WINAPI AUDDRV_LockSessions(const BOOL lock) +{ + lock ? EnterCriticalSection(&g_sessions_lock) : LeaveCriticalSection(&g_sessions_lock); + return S_OK; +} diff --git a/dlls/winealsa.drv/winealsa.drv.spec b/dlls/winealsa.drv/winealsa.drv.spec index d6d566e3b13..529a7190465 100644 --- a/dlls/winealsa.drv/winealsa.drv.spec +++ b/dlls/winealsa.drv/winealsa.drv.spec @@ -8,3 +8,4 @@ @ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper @ stdcall -private GetPropValue(ptr ptr ptr) AUDDRV_GetPropValue +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winecoreaudio.drv/mmdevdrv.c | 6 ++++++ dlls/winecoreaudio.drv/winecoreaudio.drv.spec | 1 + 2 files changed, 7 insertions(+)
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 21c2528cab1..f020a71e534 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -2167,3 +2167,9 @@ HRESULT WINAPI AUDDRV_GetAudioSessionWrapper(const GUID *guid, IMMDevice *device
return S_OK; } + +HRESULT WINAPI AUDDRV_LockSessions(const BOOL lock) +{ + lock ? EnterCriticalSection(&g_sessions_lock) : LeaveCriticalSection(&g_sessions_lock); + return S_OK; +} diff --git a/dlls/winecoreaudio.drv/winecoreaudio.drv.spec b/dlls/winecoreaudio.drv/winecoreaudio.drv.spec index 1467fc8b032..db0dc5a4362 100644 --- a/dlls/winecoreaudio.drv/winecoreaudio.drv.spec +++ b/dlls/winecoreaudio.drv/winecoreaudio.drv.spec @@ -7,3 +7,4 @@ @ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs @ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/wineoss.drv/mmdevdrv.c | 6 ++++++ dlls/wineoss.drv/wineoss.drv.spec | 1 + 2 files changed, 7 insertions(+)
diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 56e619dd163..ade8f417c2e 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -2163,3 +2163,9 @@ HRESULT WINAPI AUDDRV_GetAudioSessionWrapper(const GUID *guid, IMMDevice *device
return S_OK; } + +HRESULT WINAPI AUDDRV_LockSessions(const BOOL lock) +{ + lock ? EnterCriticalSection(&g_sessions_lock) : LeaveCriticalSection(&g_sessions_lock); + return S_OK; +} diff --git a/dlls/wineoss.drv/wineoss.drv.spec b/dlls/wineoss.drv/wineoss.drv.spec index 4506cc67ab5..3302bc9f54c 100644 --- a/dlls/wineoss.drv/wineoss.drv.spec +++ b/dlls/wineoss.drv/wineoss.drv.spec @@ -8,3 +8,4 @@ @ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs @ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winepulse.drv/mmdevdrv.c | 6 ++++++ dlls/winepulse.drv/winepulse.drv.spec | 1 + 2 files changed, 7 insertions(+)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 7f1dbb765cf..5f655db2ee8 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -2461,3 +2461,9 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
return params.result; } + +HRESULT WINAPI AUDDRV_LockSessions(const BOOL lock) +{ + lock ? EnterCriticalSection(&session_cs) : LeaveCriticalSection(&session_cs); + return S_OK; +} diff --git a/dlls/winepulse.drv/winepulse.drv.spec b/dlls/winepulse.drv/winepulse.drv.spec index 96cbd97bd68..13b9927d968 100644 --- a/dlls/winepulse.drv/winepulse.drv.spec +++ b/dlls/winepulse.drv/winepulse.drv.spec @@ -8,3 +8,4 @@ @ stdcall -private DriverProc(long long long long long) winealsa.drv.DriverProc @ stdcall -private midMessage(long long long long long) winealsa.drv.midMessage @ stdcall -private modMessage(long long long long long) winealsa.drv.modMessage +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/main.c | 1 + dlls/mmdevapi/mmdevapi_private.h | 1 + 2 files changed, 2 insertions(+)
diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c index d3d4ec6a905..21d0d7fe40d 100644 --- a/dlls/mmdevapi/main.c +++ b/dlls/mmdevapi/main.c @@ -101,6 +101,7 @@ static BOOL load_driver(const WCHAR *name, DriverFuncs *driver) LDFC(GetEndpointIDs); LDFC(GetAudioEndpoint); LDFC(GetAudioSessionWrapper); + LDFC(LockSessions); #undef LDFC
/* optional - do not fail if not found */ diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index 684d303eefb..6f6d5310a8d 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -53,6 +53,7 @@ typedef struct _DriverFuncs { struct audio_session_wrapper **out); HRESULT (WINAPI *pGetPropValue)(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out); + HRESULT (WINAPI *pLockSessions)(BOOL lock); } DriverFuncs;
extern DriverFuncs drvs DECLSPEC_HIDDEN;
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;
Davide Beatrici (@davidebeatrici) commented about dlls/mmdevapi/audiosession.c:
+#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);
+}
This function assumes `ref` never reaches 0, is it guaranteed though?
Davide Beatrici (@davidebeatrici) commented about dlls/winealsa.drv/winealsa.drv.spec:
@ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper @ stdcall -private GetPropValue(ptr ptr ptr) AUDDRV_GetPropValue +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
`BOOL` is 32 bit and so is `long`. Is this line correct?
Davide Beatrici (@davidebeatrici) commented about dlls/winecoreaudio.drv/winecoreaudio.drv.spec:
@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs @ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
`BOOL` is 32 bit and so is `long`. Is this line correct?
Davide Beatrici (@davidebeatrici) commented about dlls/wineoss.drv/wineoss.drv.spec:
@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs @ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint @ stdcall -private GetAudioSessionWrapper(ptr ptr ptr) AUDDRV_GetAudioSessionWrapper +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
`BOOL` is 32 bit and so is `long`. Is this line correct?
Davide Beatrici (@davidebeatrici) commented about dlls/winepulse.drv/winepulse.drv.spec:
@ stdcall -private DriverProc(long long long long long) winealsa.drv.DriverProc @ stdcall -private midMessage(long long long long long) winealsa.drv.midMessage @ stdcall -private modMessage(long long long long long) winealsa.drv.modMessage +@ stdcall -private LockSessions(long) AUDDRV_LockSessions
`BOOL` is 32 bit and so is `long`. Is this line correct?
I'm not too happy with this merge request, honestly... mainly because I'm unable to remove the `IAudioSessionControl` implementation that currently lives in the drivers, as it's accessed in `IAudioClient::GetService()`.
@huw Should I perhaps just build `audiosession.c` in each driver instead of `mmdevapi` for the time being?
Chip Davis (@cdavis5e) commented about dlls/mmdevapi/audiosession.c:
+{
- 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))
Copy-pasto. ```suggestion:-1+0 IsEqualIID(riid, &IID_IAudioSessionControl) || IsEqualIID(riid, &IID_IAudioSessionControl2)) ```
On Tue Apr 18 08:32:30 2023 +0000, Davide Beatrici wrote:
`BOOL` is 32 bit and so is `long`. Is this line correct?
Yes, that is correct.
I'm not too happy with this merge request, honestly... mainly because I'm unable to remove the `IAudioSessionControl` implementation that currently lives in the drivers, as it's accessed in `IAudioClient::GetService()`.
I'm not Huw, and you should probably listen to him over me, but in that case I would suggest moving the `AudioClient` object first.
On Tue Apr 18 09:43:13 2023 +0000, Chip Davis wrote:
Copy-pasto.
IsEqualIID(riid, &IID_IAudioSessionControl) || IsEqualIID(riid, &IID_IAudioSessionControl2))
Well... moving `IAudioSessionControl2` first is clearly not the best approach as tests didn't reveal the issue.
On Tue Apr 18 09:50:51 2023 +0000, Chip Davis wrote:
I'm not too happy with this merge request, honestly... mainly because
I'm unable to remove the `IAudioSessionControl` implementation that currently lives in the drivers, as it's accessed in `IAudioClient::GetService()`. I'm not Huw, and you should probably listen to him over me, but in that case I would suggest moving the `AudioClient` object first.
No worries, thank you very much for your input!
I should indeed do that and export a function that returns a struct object containing the various vtables.
On Tue Apr 18 17:48:24 2023 +0000, Davide Beatrici wrote:
No worries, thank you very much for your input! I should indeed do that and export a function that returns a struct object containing the various vtables.
Actually, turns out all interfaces are interlinked. Moving a single one would require building quite a few bridges between `mmdevapi` and driver.
I think my initial idea (building `audiosession.c` in each driver) is the sanest approach. Let's see how it goes.