From cb3ab2431acbde1a584d5b6d13a5d20ac1712964 Mon Sep 17 00:00:00 2001 From: zheng_xing Date: Tue, 30 Jun 2020 17:03:30 +0800 Subject: [PATCH] Try to add Get/Set Mute and RegisterControlChangeNotify calback --- UWPGlobalVolume/Volume.cpp | 40 +++++++++++++++++++++++++++- UWPGlobalVolume/Volume.h | 3 +++ UWPGlobalVolume/VolumeImpl.cpp | 48 ++++++++++++++++++++++++++++++---- UWPGlobalVolume/VolumeImpl.h | 17 +++++++++--- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/UWPGlobalVolume/Volume.cpp b/UWPGlobalVolume/Volume.cpp index aaa7d94..d498873 100644 --- a/UWPGlobalVolume/Volume.cpp +++ b/UWPGlobalVolume/Volume.cpp @@ -25,7 +25,7 @@ Windows::Foundation::IAsyncOperation^ Volume::SetVolume(float volume) }); } -Windows::Foundation::IAsyncOperation^ Volume::GetVolume() +Windows::Foundation::IAsyncOperation^ Volume::GetVolume() { return create_async([this] { @@ -39,5 +39,43 @@ Windows::Foundation::IAsyncOperation^ Volume::GetVolume() }); } +Windows::Foundation::IAsyncOperation^ Volume::SetMute(bool isMuted) +{ + return create_async([this, isMuted] + { + if (m_volumeImpl == nullptr) + { + // Create a new WASAPI capture instance + m_volumeImpl = Make(); + } + + return m_volumeImpl->SetMute(isMuted); + }); +} + +Windows::Foundation::IAsyncOperation^ Volume::GetMute() +{ + return create_async([this] + { + if (m_volumeImpl == nullptr) + { + // Create a new WASAPI capture instance + m_volumeImpl = Make(); + } + + return m_volumeImpl->GetMute(); + }); +} + +void Volume::RegisterVolumeChangedNotify(VolumeChangedHandler^ volumeChangedAction) +{ + if (m_volumeImpl == nullptr) + { + m_volumeImpl = Make(); + } + + m_volumeImpl->VolumeChangedAction = volumeChangedAction; +} + diff --git a/UWPGlobalVolume/Volume.h b/UWPGlobalVolume/Volume.h index 848954f..073dc71 100644 --- a/UWPGlobalVolume/Volume.h +++ b/UWPGlobalVolume/Volume.h @@ -12,6 +12,9 @@ namespace UWPGlobalVolume Volume(); Windows::Foundation::IAsyncOperation^ SetVolume(float volume); Windows::Foundation::IAsyncOperation^ GetVolume(); + Windows::Foundation::IAsyncOperation^ SetMute(bool isMuted); + Windows::Foundation::IAsyncOperation^ GetMute(); + void RegisterVolumeChangedNotify(VolumeChangedHandler^ volumeChangedAction); private: Microsoft::WRL::ComPtr m_volumeImpl; diff --git a/UWPGlobalVolume/VolumeImpl.cpp b/UWPGlobalVolume/VolumeImpl.cpp index 56664ce..b1321d0 100644 --- a/UWPGlobalVolume/VolumeImpl.cpp +++ b/UWPGlobalVolume/VolumeImpl.cpp @@ -11,11 +11,12 @@ VolumeImpl::VolumeImpl() { m_event = CreateEvent(nullptr, false, false, nullptr); // register for changes in Default audio device - m_token = MediaDevice::DefaultAudioRenderDeviceChanged += ref new Windows::Foundation::TypedEventHandler(std::bind(&VolumeImpl::OnDefaultAudioCaptureDeviceChanged, this, _1, _2)); + m_token = MediaDevice::DefaultAudioRenderDeviceChanged += ref new Windows::Foundation::TypedEventHandler(std::bind(&VolumeImpl::OnDefaultAudioCaptureDeviceChanged, this, _1, _2)); } VolumeImpl::~VolumeImpl() { + UnregisterControlChangeNotify(); CloseHandle(m_event); MediaDevice::DefaultAudioCaptureDeviceChanged -= m_token; } @@ -23,12 +24,12 @@ VolumeImpl::~VolumeImpl() HRESULT VolumeImpl::InitializeVolumeInterface() { std::lock_guard lock(m_mutex); - + if (m_volumeInterface != nullptr) { return S_OK; } - + ComPtr asyncOp; m_result = S_OK; auto id = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default); @@ -41,7 +42,7 @@ HRESULT VolumeImpl::InitializeVolumeInterface() return m_result; } -void VolumeImpl::OnDefaultAudioCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) +void VolumeImpl::OnDefaultAudioCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args) { // force next Set/GetVolume call to reinitialize the IAudioEndpointInterface std::lock_guard lock(m_mutex); @@ -69,16 +70,46 @@ float VolumeImpl::GetVolume() hr = m_volumeInterface->GetMasterVolumeLevelScalar(&volume); } return volume; +} + +bool VolumeImpl::SetMute(bool isMuted) +{ + HRESULT hr = InitializeVolumeInterface(); + if (SUCCEEDED(hr) && m_volumeInterface != nullptr) + { + hr = m_volumeInterface->SetMute(isMuted, NULL); + } + return SUCCEEDED(hr); +} + +bool VolumeImpl::GetMute() +{ + BOOL isMuted = false; + HRESULT hr = InitializeVolumeInterface(); + if (SUCCEEDED(hr) && m_volumeInterface != nullptr) + { + hr = m_volumeInterface->GetMute(&isMuted); + } + return isMuted; } +void VolumeImpl::UnregisterControlChangeNotify() +{ + HRESULT hr = InitializeVolumeInterface(); + if (SUCCEEDED(hr) && m_volumeInterface != nullptr) + { + hr = m_volumeInterface->UnregisterControlChangeNotify(this); + } +} + // // ActivateCompleted() // // Callback implementation of ActivateAudioInterfaceAsync function. This will be called on MTA thread // when results of the activation are available. // -HRESULT VolumeImpl::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *operation) +HRESULT VolumeImpl::ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) { HRESULT hr = S_OK; HRESULT hrActivateResult = S_OK; @@ -102,10 +133,17 @@ HRESULT VolumeImpl::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *ope hr = E_NOINTERFACE; goto exit; } + m_volumeInterface->RegisterControlChangeNotify(this); exit: SetEvent(m_event); m_result = hr; // Need to return S_OK return S_OK; +} + +HRESULT VolumeImpl::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) +{ + this->VolumeChangedAction(pNotify->bMuted, pNotify->fMasterVolume); + return S_OK; } \ No newline at end of file diff --git a/UWPGlobalVolume/VolumeImpl.h b/UWPGlobalVolume/VolumeImpl.h index d52fc9c..13910ca 100644 --- a/UWPGlobalVolume/VolumeImpl.h +++ b/UWPGlobalVolume/VolumeImpl.h @@ -7,9 +7,11 @@ namespace UWPGlobalVolume { + public delegate void VolumeChangedHandler(bool isMuted, float volume); + // Primary WASAPI Capture Class class VolumeImpl : - public Microsoft::WRL::RuntimeClass, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler > + public Microsoft::WRL::RuntimeClass, Microsoft::WRL::FtmBase, IActivateAudioInterfaceCompletionHandler, IAudioEndpointVolumeCallback > { public: VolumeImpl(); @@ -17,6 +19,10 @@ namespace UWPGlobalVolume bool SetVolume(float volume); float GetVolume(); + bool SetMute(bool isMuted); + bool GetMute(); + + VolumeChangedHandler^ VolumeChangedAction; private: std::mutex m_mutex; @@ -26,10 +32,15 @@ namespace UWPGlobalVolume HRESULT InitializeVolumeInterface(); - void OnDefaultAudioCaptureDeviceChanged(Platform::Object^ sender, Windows::Media::Devices::DefaultAudioRenderDeviceChangedEventArgs ^ args); + void OnDefaultAudioCaptureDeviceChanged(Platform::Object^ sender, Windows::Media::Devices::DefaultAudioRenderDeviceChangedEventArgs^ args); // IActivateAudioInterfaceCompletionHandler - STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation); + STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation* operation); Microsoft::WRL::ComPtr m_volumeInterface; + + // Inherited via IAudioEndpointVolumeCallback + STDMETHOD(OnNotify)(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify); + + void UnregisterControlChangeNotify(); }; }