mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-06 19:26:39 +02:00
Add new VideoConference module for muting mic/cam (#11798)
* add new VideoConference module for muting mic/cam Co-authored-by: PrzemyslawTusinski <61138537+PrzemyslawTusinski@users.noreply.github.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
#include "MicrophoneDevice.h"
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
#include <Functiondiscoverykeys_devpkey.h>
|
||||
|
||||
MicrophoneDevice::MicrophoneDevice(wil::com_ptr_nothrow<IMMDevice> device, wil::com_ptr_nothrow<IAudioEndpointVolume> endpoint) :
|
||||
_device{ std::move(device) },
|
||||
_endpoint{ std::move(endpoint) }
|
||||
{
|
||||
if (!_device || !_endpoint)
|
||||
{
|
||||
throw std::logic_error("MicrophoneDevice was initialized with null objects");
|
||||
}
|
||||
_device->GetId(&_id);
|
||||
wil::com_ptr_nothrow<IPropertyStore> props;
|
||||
_device->OpenPropertyStore(
|
||||
STGM_READ, &props);
|
||||
if (props)
|
||||
{
|
||||
props->GetValue(PKEY_Device_FriendlyName, &_friendly_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MicrophoneDevice::MicrophoneDevice couldn't open property store");
|
||||
}
|
||||
}
|
||||
|
||||
MicrophoneDevice::~MicrophoneDevice()
|
||||
{
|
||||
if (_notifier)
|
||||
{
|
||||
_endpoint->UnregisterControlChangeNotify(_notifier.get());
|
||||
}
|
||||
}
|
||||
|
||||
bool MicrophoneDevice::active() const noexcept
|
||||
{
|
||||
DWORD state = 0;
|
||||
_device->GetState(&state);
|
||||
return state == DEVICE_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
void MicrophoneDevice::set_muted(const bool muted) noexcept
|
||||
{
|
||||
_endpoint->SetMute(muted, nullptr);
|
||||
}
|
||||
|
||||
bool MicrophoneDevice::muted() const noexcept
|
||||
{
|
||||
BOOL muted = FALSE;
|
||||
_endpoint->GetMute(&muted);
|
||||
return muted;
|
||||
}
|
||||
|
||||
void MicrophoneDevice::toggle_muted() noexcept
|
||||
{
|
||||
set_muted(!muted());
|
||||
}
|
||||
|
||||
std::wstring_view MicrophoneDevice::id() const noexcept
|
||||
{
|
||||
return _id ? _id.get() : FALLBACK_ID;
|
||||
}
|
||||
|
||||
std::wstring_view MicrophoneDevice::name() const noexcept
|
||||
{
|
||||
return _friendly_name.pwszVal ? _friendly_name.pwszVal : FALLBACK_NAME;
|
||||
}
|
||||
|
||||
void MicrophoneDevice::set_mute_changed_callback(mute_changed_cb_t callback) noexcept
|
||||
{
|
||||
_mute_changed_callback = std::move(callback);
|
||||
_notifier = winrt::make<VolumeNotifier>(this);
|
||||
|
||||
_endpoint->RegisterControlChangeNotify(_notifier.get());
|
||||
}
|
||||
|
||||
std::optional<MicrophoneDevice> MicrophoneDevice::getDefault()
|
||||
{
|
||||
auto deviceEnumerator = wil::CoCreateInstanceNoThrow<MMDeviceEnumerator, IMMDeviceEnumerator>();
|
||||
if (!deviceEnumerator)
|
||||
{
|
||||
LOG("MicrophoneDevice::getDefault MMDeviceEnumerator returned null");
|
||||
return std::nullopt;
|
||||
}
|
||||
wil::com_ptr_nothrow<IMMDevice> captureDevice;
|
||||
deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &captureDevice);
|
||||
if (!captureDevice)
|
||||
{
|
||||
LOG("MicrophoneDevice::getDefault captureDevice is null");
|
||||
return std::nullopt;
|
||||
}
|
||||
wil::com_ptr_nothrow<IAudioEndpointVolume> microphoneEndpoint;
|
||||
captureDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast<LPVOID*>(µphoneEndpoint));
|
||||
if (!microphoneEndpoint)
|
||||
{
|
||||
LOG("MicrophoneDevice::getDefault captureDevice is null");
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::make_optional<MicrophoneDevice>(std::move(captureDevice), std::move(microphoneEndpoint));
|
||||
}
|
||||
|
||||
std::vector<MicrophoneDevice> MicrophoneDevice::getAllActive()
|
||||
{
|
||||
std::vector<MicrophoneDevice> microphoneDevices;
|
||||
auto deviceEnumerator = wil::CoCreateInstanceNoThrow<MMDeviceEnumerator, IMMDeviceEnumerator>();
|
||||
if (!deviceEnumerator)
|
||||
{
|
||||
LOG("MicrophoneDevice::getAllActive MMDeviceEnumerator returned null");
|
||||
return microphoneDevices;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<IMMDeviceCollection> captureDevices;
|
||||
deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &captureDevices);
|
||||
if (!captureDevices)
|
||||
{
|
||||
LOG("MicrophoneDevice::getAllActive EnumAudioEndpoints returned null");
|
||||
return microphoneDevices;
|
||||
}
|
||||
UINT nDevices = 0;
|
||||
captureDevices->GetCount(&nDevices);
|
||||
microphoneDevices.reserve(nDevices);
|
||||
for (UINT i = 0; i < nDevices; ++i)
|
||||
{
|
||||
wil::com_ptr_nothrow<IMMDevice> device;
|
||||
captureDevices->Item(i, &device);
|
||||
if (!device)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
wil::com_ptr_nothrow<IAudioEndpointVolume> microphoneEndpoint;
|
||||
device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast<LPVOID*>(µphoneEndpoint));
|
||||
if (!microphoneEndpoint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
microphoneDevices.emplace_back(std::move(device), std::move(microphoneEndpoint));
|
||||
}
|
||||
return microphoneDevices;
|
||||
}
|
||||
|
||||
MicrophoneDevice::VolumeNotifier::VolumeNotifier(MicrophoneDevice* subscribedDevice) :
|
||||
_subscribedDevice{ subscribedDevice }
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT __stdcall MicrophoneDevice::VolumeNotifier::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA data)
|
||||
{
|
||||
_subscribedDevice->_mute_changed_callback(data->bMuted);
|
||||
return S_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user