Merge pull request #618 from stijnvdb88/master

wasapi: added listener for getting system volume
This commit is contained in:
Johannes Pohl 2020-05-10 14:56:58 +02:00 committed by GitHub
commit 2a6360a832
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 0 deletions

View file

@ -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);
@ -336,7 +344,14 @@ void WASAPIPlayer::worker()
// update our volume from IAudioControl
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 +421,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 +480,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;
}

View file

@ -20,12 +20,14 @@
#define WASAPI_PLAYER_H
#include "player.hpp"
#include <audiopolicy.h>
#include <endpointvolume.h>
class AudioSessionEventListener : public IAudioSessionEvents
{
LONG _cRef;
float volume_ = 1.f;
bool muted_ = false;
public:
AudioSessionEventListener() : _cRef(1)
@ -37,6 +39,11 @@ public:
return volume_;
}
bool getMuted()
{
return muted_;
}
~AudioSessionEventListener()
{
}
@ -89,6 +96,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:
@ -106,6 +182,8 @@ protected:
private:
AudioSessionEventListener* audioEventListener_;
IAudioEndpointVolume* audioEndpointListener_;
ClientSettings::SharingMode mode_;
};
#endif