From 7fd7c49538998906535fc0c446f6e04ad0a0cb0d Mon Sep 17 00:00:00 2001 From: Stijn Van der Borght Date: Sun, 10 May 2020 13:26:32 +0100 Subject: [PATCH] wasapi: added listener for getting system volume --- client/player/wasapi_player.cpp | 43 +++++++++++++++++- client/player/wasapi_player.h | 77 +++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/client/player/wasapi_player.cpp b/client/player/wasapi_player.cpp index 2a94e8c2..4f223560 100644 --- a/client/player/wasapi_player.cpp +++ b/client/player/wasapi_player.cpp @@ -45,6 +45,7 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); const IID IID_IAudioClient = __uuidof(IAudioClient); const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); const IID IID_IAudioClock = __uuidof(IAudioClock); +const IID IID_IAudioEndpointVolume = _uuidof(IAudioEndpointVolume); _COM_SMARTPTR_TYPEDEF(IMMDevice, __uuidof(IMMDevice)); _COM_SMARTPTR_TYPEDEF(IMMDeviceCollection, __uuidof(IMMDeviceCollection)); @@ -229,6 +230,8 @@ void WASAPIPlayer::worker() hr = device->Activate(__uuidof(IAudioSessionManager), CLSCTX_INPROC_SERVER, NULL, (void**)&sessionManager); CHECK_HR(hr); + + // Get the control interface for the process-specific audio // session with session GUID = GUID_NULL. This is the session // that an audio stream for a DirectSound, DirectShow, waveOut, @@ -241,6 +244,11 @@ void WASAPIPlayer::worker() hr = control->RegisterAudioSessionNotification(audioEventListener_); CHECK_HR(hr); + AudioEndpointVolumeCallback audioEndpointVolumeCallback; + hr = device->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&audioEndpointListener_); + + audioEndpointListener_->RegisterControlChangeNotify((IAudioEndpointVolumeCallback*)&audioEndpointVolumeCallback); + // Get the device period REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC; hr = audioClient->GetDevicePeriod(NULL, &hnsRequestedDuration); @@ -335,7 +343,16 @@ void WASAPIPlayer::worker() break; // update our volume from IAudioControl - volCorrection_ = audioEventListener_->getVolume(); + if (mode_ == ClientSettings::SharingMode::exclusive) + { + volCorrection_ = audioEventListener_->getVolume(); + // muteOverride = audioEventListener_->getMuted(); // use this for also applying audio mixer mute state + } + + // get audio device volume from IAudioEndpointVolume + // float deviceVolume = audioEndpointVolumeCallback.getVolume(); // system volume (for this audio device) + // bool deviceMuted = audioEndpointVolumeCallback.getMuted(); // system mute (for this audio device) + clock->GetPosition(&position, NULL); @@ -406,6 +423,8 @@ HRESULT STDMETHODCALLTYPE AudioSessionEventListener::QueryInterface(REFIID riid, HRESULT STDMETHODCALLTYPE AudioSessionEventListener::OnSimpleVolumeChanged(float NewVolume, BOOL NewMute, LPCGUID EventContext) { volume_ = NewVolume; + muted_ = NewMute; + if (NewMute) { LOG(DEBUG, LOG_TAG) << ("MUTE\n"); @@ -463,5 +482,27 @@ HRESULT STDMETHODCALLTYPE AudioSessionEventListener::OnSessionDisconnected(Audio } LOG(INFO, LOG_TAG) << "Audio session disconnected (reason: " << pszReason << ")"; + return S_OK; +} + + + +HRESULT STDMETHODCALLTYPE AudioEndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) +{ + if (pNotify == NULL) + { + return E_INVALIDARG; + } + + if (pNotify->bMuted) + { + LOG(DEBUG, LOG_TAG) << ("MASTER MUTE\n"); + } + + LOG(DEBUG, LOG_TAG) << "Volume = " << (UINT32)(100 * pNotify->fMasterVolume + 0.5) << " percent\n"; + + volume_ = pNotify->fMasterVolume; + muted_ = pNotify->bMuted; + return S_OK; } \ No newline at end of file diff --git a/client/player/wasapi_player.h b/client/player/wasapi_player.h index 0d987767..c21db94e 100644 --- a/client/player/wasapi_player.h +++ b/client/player/wasapi_player.h @@ -21,12 +21,14 @@ #include "client_settings.hpp" #include "player.hpp" #include +#include class AudioSessionEventListener : public IAudioSessionEvents { LONG _cRef; float volume_ = 1.f; + bool muted_ = false; public: AudioSessionEventListener() : _cRef(1) @@ -38,6 +40,11 @@ public: return volume_; } + bool getMuted() + { + return muted_; + } + ~AudioSessionEventListener() { } @@ -90,6 +97,75 @@ public: HRESULT STDMETHODCALLTYPE OnSessionDisconnected(AudioSessionDisconnectReason DisconnectReason); }; + +class AudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback +{ + LONG _cRef; + float volume_ = 1.f; + bool muted_ = false; + +public: + AudioEndpointVolumeCallback() : _cRef(1) + { + } + + ~AudioEndpointVolumeCallback() + { + } + + float getVolume() + { + return volume_; + } + + bool getMuted() + { + return muted_; + } + + // IUnknown methods -- AddRef, Release, and QueryInterface + + ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement(&_cRef); + } + + ULONG STDMETHODCALLTYPE Release() + { + ULONG ulRef = InterlockedDecrement(&_cRef); + if (0 == ulRef) + { + delete this; + } + return ulRef; + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface) + { + if (IID_IUnknown == riid) + { + AddRef(); + *ppvInterface = (IUnknown*)this; + } + else if (__uuidof(IAudioEndpointVolumeCallback) == riid) + { + AddRef(); + *ppvInterface = (IAudioEndpointVolumeCallback*)this; + } + else + { + *ppvInterface = NULL; + return E_NOINTERFACE; + } + + return S_OK; + } + + // Callback method for endpoint-volume-change notifications. + + HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify); +}; + class WASAPIPlayer : public Player { public: @@ -103,6 +179,7 @@ protected: private: AudioSessionEventListener* audioEventListener_; + IAudioEndpointVolume* audioEndpointListener_; ClientSettings::SharingMode mode_; };