From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/Makefile.in | 1 + dlls/mmdevapi/client.c | 218 +++++++++++++++++++++++++++++++++ dlls/mmdevapi/session.c | 15 +-- dlls/winepulse.drv/Makefile.in | 1 + dlls/winepulse.drv/mmdevdrv.c | 168 +------------------------ 5 files changed, 223 insertions(+), 180 deletions(-) create mode 100644 dlls/mmdevapi/client.c
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in index 120f9d81fa4..ee2848ff2de 100644 --- a/dlls/mmdevapi/Makefile.in +++ b/dlls/mmdevapi/Makefile.in @@ -4,6 +4,7 @@ IMPORTS = uuid ole32 oleaut32 user32 advapi32 C_SRCS = \ audiosessionmanager.c \ audiovolume.c \ + client.c \ devenum.c \ main.c \ session.c \ diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c new file mode 100644 index 00000000000..312bc462c3b --- /dev/null +++ b/dlls/mmdevapi/client.c @@ -0,0 +1,218 @@ +/* + * Copyright 2011-2012 Maarten Lankhorst + * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers + * Copyright 2011 Andrew Eikum for CodeWeavers + * Copyright 2022 Huw Davies + * + * 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 <winternl.h> + +#include <wine/debug.h> +#include <wine/unixlib.h> + +#include "mmdevdrv.h" +#include "unixlib.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi); + +extern void sessions_lock(void) DECLSPEC_HIDDEN; +extern void sessions_unlock(void) DECLSPEC_HIDDEN; + +void set_stream_volumes(struct audio_client *This) +{ + struct set_volumes_params params; + + params.stream = This->stream; + params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol); + params.volumes = This->vols; + params.session_volumes = This->session->channel_vols; + + WINE_UNIX_CALL(set_volumes, ¶ms); +} + +static inline struct audio_client *impl_from_IAudioStreamVolume(IAudioStreamVolume *iface) +{ + return CONTAINING_RECORD(iface, struct audio_client, IAudioStreamVolume_iface); +} + +static HRESULT WINAPI streamvolume_QueryInterface(IAudioStreamVolume *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_IAudioStreamVolume)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IMarshal)) { + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + return IUnknown_QueryInterface(This->marshal, riid, ppv); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ppv); + + return S_OK; +} + +static ULONG WINAPI streamvolume_AddRef(IAudioStreamVolume *iface) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + return IAudioClient3_AddRef(&This->IAudioClient3_iface); +} + +static ULONG WINAPI streamvolume_Release(IAudioStreamVolume *iface) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + return IAudioClient3_Release(&This->IAudioClient3_iface); +} + +static HRESULT WINAPI streamvolume_GetChannelCount(IAudioStreamVolume *iface, UINT32 *out) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + + TRACE("(%p)->(%p)\n", This, out); + + if (!out) + return E_POINTER; + + *out = This->channel_count; + + return S_OK; +} + +static HRESULT WINAPI streamvolume_SetChannelVolume(IAudioStreamVolume *iface, UINT32 index, + float level) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + + TRACE("(%p)->(%d, %f)\n", This, index, level); + + if (level < 0.f || level > 1.f) + return E_INVALIDARG; + + if (!This->stream) + return AUDCLNT_E_NOT_INITIALIZED; + + if (index >= This->channel_count) + return E_INVALIDARG; + + sessions_lock(); + + This->vols[index] = level; + set_stream_volumes(This); + + sessions_unlock(); + + return S_OK; +} + +static HRESULT WINAPI streamvolume_GetChannelVolume(IAudioStreamVolume *iface, UINT32 index, + float *level) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + + TRACE("(%p)->(%d, %p)\n", This, index, level); + + if (!level) + return E_POINTER; + + if (!This->stream) + return AUDCLNT_E_NOT_INITIALIZED; + + if (index >= This->channel_count) + return E_INVALIDARG; + + *level = This->vols[index]; + + return S_OK; +} + +static HRESULT WINAPI streamvolume_SetAllVolumes(IAudioStreamVolume *iface, UINT32 count, + const float *levels) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + unsigned int i; + + TRACE("(%p)->(%d, %p)\n", This, count, levels); + + if (!levels) + return E_POINTER; + + if (!This->stream) + return AUDCLNT_E_NOT_INITIALIZED; + + if (count != This->channel_count) + return E_INVALIDARG; + + sessions_lock(); + + for (i = 0; i < count; ++i) + This->vols[i] = levels[i]; + set_stream_volumes(This); + + sessions_unlock(); + + return S_OK; +} + +static HRESULT WINAPI streamvolume_GetAllVolumes(IAudioStreamVolume *iface, UINT32 count, + float *levels) +{ + struct audio_client *This = impl_from_IAudioStreamVolume(iface); + unsigned int i; + + TRACE("(%p)->(%d, %p)\n", This, count, levels); + + if (!levels) + return E_POINTER; + + if (!This->stream) + return AUDCLNT_E_NOT_INITIALIZED; + + if (count != This->channel_count) + return E_INVALIDARG; + + sessions_lock(); + + for (i = 0; i < count; ++i) + levels[i] = This->vols[i]; + + sessions_unlock(); + + return S_OK; +} + +const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl = +{ + streamvolume_QueryInterface, + streamvolume_AddRef, + streamvolume_Release, + streamvolume_GetChannelCount, + streamvolume_SetChannelVolume, + streamvolume_GetChannelVolume, + streamvolume_SetAllVolumes, + streamvolume_GetAllVolumes +}; diff --git a/dlls/mmdevapi/session.c b/dlls/mmdevapi/session.c index 6a675a7656c..81cea5b3482 100644 --- a/dlls/mmdevapi/session.c +++ b/dlls/mmdevapi/session.c @@ -13,6 +13,7 @@ * 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> @@ -32,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi); extern void sessions_lock(void) DECLSPEC_HIDDEN; extern void sessions_unlock(void) DECLSPEC_HIDDEN;
-extern const IAudioClient3Vtbl AudioClient3_Vtbl; +extern void set_stream_volumes(struct audio_client *This) DECLSPEC_HIDDEN;
static inline struct audio_session_wrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface) { @@ -49,18 +50,6 @@ static inline struct audio_session_wrapper *impl_from_ISimpleAudioVolume(ISimple return CONTAINING_RECORD(iface, struct audio_session_wrapper, ISimpleAudioVolume_iface); }
-static void set_stream_volumes(struct audio_client *This) -{ - struct set_volumes_params params; - - params.stream = This->stream; - params.master_volume = (This->session->mute ? 0.0f : This->session->master_vol); - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - - WINE_UNIX_CALL(set_volumes, ¶ms); -} - static HRESULT WINAPI control_QueryInterface(IAudioSessionControl2 *iface, REFIID riid, void **ppv) { TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); diff --git a/dlls/winepulse.drv/Makefile.in b/dlls/winepulse.drv/Makefile.in index 8a6d6f1ae91..f5593dbcc70 100644 --- a/dlls/winepulse.drv/Makefile.in +++ b/dlls/winepulse.drv/Makefile.in @@ -6,6 +6,7 @@ UNIX_LIBS = $(PULSE_LIBS) $(PTHREAD_LIBS) -lm UNIX_CFLAGS = $(PULSE_CFLAGS)
C_SRCS = \ + client.c \ mmdevdrv.c \ pulse.c \ session.c diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 84ac537701b..333848e4242 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -132,7 +132,7 @@ extern const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl; extern const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl; static const IAudioClockVtbl AudioClock_Vtbl; static const IAudioClock2Vtbl AudioClock2_Vtbl; -static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl; +extern const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl;
static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client);
@@ -161,11 +161,6 @@ static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface) return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface); }
-static inline ACImpl *impl_from_IAudioStreamVolume(IAudioStreamVolume *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioStreamVolume_iface); -} - static void pulse_call(enum unix_funcs code, void *params) { NTSTATUS status; @@ -1696,167 +1691,6 @@ static const IAudioClock2Vtbl AudioClock2_Vtbl = AudioClock2_GetDevicePosition };
-static HRESULT WINAPI AudioStreamVolume_QueryInterface( - IAudioStreamVolume *iface, REFIID riid, void **ppv) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if (!ppv) - return E_POINTER; - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioStreamVolume)) - *ppv = iface; - if (*ppv) { - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - - if (IsEqualIID(riid, &IID_IMarshal)) - return IUnknown_QueryInterface(This->marshal, riid, ppv); - - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioStreamVolume_AddRef(IAudioStreamVolume *iface) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - return IAudioClient3_AddRef(&This->IAudioClient3_iface); -} - -static ULONG WINAPI AudioStreamVolume_Release(IAudioStreamVolume *iface) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - return IAudioClient3_Release(&This->IAudioClient3_iface); -} - -static HRESULT WINAPI AudioStreamVolume_GetChannelCount( - IAudioStreamVolume *iface, UINT32 *out) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - - TRACE("(%p)->(%p)\n", This, out); - - if (!out) - return E_POINTER; - - *out = This->channel_count; - - return S_OK; -} - -struct pulse_info_cb_data { - UINT32 n; - float *levels; -}; - -static HRESULT WINAPI AudioStreamVolume_SetAllVolumes( - IAudioStreamVolume *iface, UINT32 count, const float *levels) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - int i; - - TRACE("(%p)->(%d, %p)\n", This, count, levels); - - if (!levels) - return E_POINTER; - - if (!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - if (count != This->channel_count) - return E_INVALIDARG; - - sessions_lock(); - for (i = 0; i < count; ++i) - This->vols[i] = levels[i]; - - set_stream_volumes(This); - sessions_unlock(); - return S_OK; -} - -static HRESULT WINAPI AudioStreamVolume_GetAllVolumes( - IAudioStreamVolume *iface, UINT32 count, float *levels) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - int i; - - TRACE("(%p)->(%d, %p)\n", This, count, levels); - - if (!levels) - return E_POINTER; - - if (!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - if (count != This->channel_count) - return E_INVALIDARG; - - sessions_lock(); - for (i = 0; i < count; ++i) - levels[i] = This->vols[i]; - sessions_unlock(); - return S_OK; -} - -static HRESULT WINAPI AudioStreamVolume_SetChannelVolume( - IAudioStreamVolume *iface, UINT32 index, float level) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - - TRACE("(%p)->(%d, %f)\n", This, index, level); - - if (level < 0.f || level > 1.f) - return E_INVALIDARG; - - if (!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - if (index >= This->channel_count) - return E_INVALIDARG; - - sessions_lock(); - This->vols[index] = level; - set_stream_volumes(This); - sessions_unlock(); - return S_OK; -} - -static HRESULT WINAPI AudioStreamVolume_GetChannelVolume( - IAudioStreamVolume *iface, UINT32 index, float *level) -{ - ACImpl *This = impl_from_IAudioStreamVolume(iface); - - TRACE("(%p)->(%d, %p)\n", This, index, level); - - if (!level) - return E_POINTER; - - if (!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - if (index >= This->channel_count) - return E_INVALIDARG; - - sessions_lock(); - *level = This->vols[index]; - sessions_unlock(); - return S_OK; -} - -static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl = -{ - AudioStreamVolume_QueryInterface, - AudioStreamVolume_AddRef, - AudioStreamVolume_Release, - AudioStreamVolume_GetChannelCount, - AudioStreamVolume_SetChannelVolume, - AudioStreamVolume_GetChannelVolume, - AudioStreamVolume_SetAllVolumes, - AudioStreamVolume_GetAllVolumes -}; - static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client) { AudioSessionWrapper *ret;