[Video Conference Mute] Push to Reverse (#24892)

* Add push to talk

* Fix multiple callback WM_KEYDOWN while holding shortcut

* Code review suggestions

* Rename feature

* Revert "Rename feature"

This reverts commit 82d64bf57c.

* Add switch and settings

* Change type of bool property. Handle settings.

* Description

* Update src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.cpp

Always consume hotkey press

Co-authored-by: Andrey Nekrasov <yuyoyuppe@users.noreply.github.com>

---------

Co-authored-by: Andrey Nekrasov <yuyoyuppe@users.noreply.github.com>
This commit is contained in:
pajawojciech
2023-03-30 10:55:09 +02:00
committed by GitHub
parent 158876059e
commit 9876695cdb
8 changed files with 130 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ VideoConferenceModule* instance = nullptr;
VideoConferenceSettings VideoConferenceModule::settings; VideoConferenceSettings VideoConferenceModule::settings;
Toolbar VideoConferenceModule::toolbar; Toolbar VideoConferenceModule::toolbar;
bool VideoConferenceModule::pushToTalkPressed = false;
HHOOK VideoConferenceModule::hook_handle; HHOOK VideoConferenceModule::hook_handle;
@@ -123,10 +124,10 @@ LRESULT CALLBACK VideoConferenceModule::LowLevelKeyboardProc(int nCode, WPARAM w
{ {
if (nCode == HC_ACTION) if (nCode == HC_ACTION)
{ {
KBDLLHOOKSTRUCT* kbd = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
switch (wParam) switch (wParam)
{ {
case WM_KEYDOWN: case WM_KEYDOWN:
KBDLLHOOKSTRUCT* kbd = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
if (isHotkeyPressed(kbd->vkCode, settings.cameraAndMicrophoneMuteHotkey)) if (isHotkeyPressed(kbd->vkCode, settings.cameraAndMicrophoneMuteHotkey))
{ {
@@ -163,11 +164,31 @@ LRESULT CALLBACK VideoConferenceModule::LowLevelKeyboardProc(int nCode, WPARAM w
reverseMicrophoneMute(); reverseMicrophoneMute();
return 1; return 1;
} }
else if (isHotkeyPressed(kbd->vkCode, settings.microphonePushToTalkHotkey))
{
if (!pushToTalkPressed)
{
if (settings.pushToReverseEnabled || getMicrophoneMuteState())
{
reverseMicrophoneMute();
}
pushToTalkPressed = true;
}
return 1;
}
else if (isHotkeyPressed(kbd->vkCode, settings.cameraMuteHotkey)) else if (isHotkeyPressed(kbd->vkCode, settings.cameraMuteHotkey))
{ {
reverseVirtualCameraMuteState(); reverseVirtualCameraMuteState();
return 1; return 1;
} }
break;
case WM_KEYUP:
if (pushToTalkPressed && (kbd->vkCode == settings.microphonePushToTalkHotkey.get_code()))
{
reverseMicrophoneMute();
pushToTalkPressed = false;
return 1;
}
} }
} }
@@ -228,6 +249,14 @@ void VideoConferenceModule::onModuleSettingsChanged()
{ {
settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
} }
if (const auto val = values.get_json(L"push_to_talk_microphone_hotkey"))
{
settings.microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
}
if (const auto val = values.get_bool_value(L"push_to_reverse_enabled"))
{
settings.pushToReverseEnabled = *val;
}
if (const auto val = values.get_json(L"mute_camera_hotkey")) if (const auto val = values.get_json(L"mute_camera_hotkey"))
{ {
settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
@@ -386,6 +415,14 @@ void VideoConferenceModule::init_settings()
{ {
settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
} }
if (const auto val = powerToysSettings.get_json(L"push_to_talk_microphone_hotkey"))
{
settings.microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
}
if (const auto val = powerToysSettings.get_bool_value(L"push_to_reverse_enabled"))
{
settings.pushToReverseEnabled = *val;
}
if (const auto val = powerToysSettings.get_json(L"mute_camera_hotkey")) if (const auto val = powerToysSettings.get_json(L"mute_camera_hotkey"))
{ {
settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val);

View File

@@ -20,6 +20,7 @@ struct VideoConferenceSettings
{ {
PowerToysSettings::HotkeyObject cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 81); PowerToysSettings::HotkeyObject cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 81);
PowerToysSettings::HotkeyObject microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 65); PowerToysSettings::HotkeyObject microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 65);
PowerToysSettings::HotkeyObject microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 73);
PowerToysSettings::HotkeyObject cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 79); PowerToysSettings::HotkeyObject cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 79);
std::wstring toolbarPositionString; std::wstring toolbarPositionString;
@@ -28,6 +29,8 @@ struct VideoConferenceSettings
std::wstring selectedCamera; std::wstring selectedCamera;
std::wstring imageOverlayPath; std::wstring imageOverlayPath;
std::wstring selectedMicrophone; std::wstring selectedMicrophone;
bool pushToReverseEnabled = false;
}; };
class VideoConferenceModule : public PowertoyModuleIface class VideoConferenceModule : public PowertoyModuleIface
@@ -93,4 +96,5 @@ private:
static VideoConferenceSettings settings; static VideoConferenceSettings settings;
static Toolbar toolbar; static Toolbar toolbar;
static bool pushToTalkPressed;
}; };

View File

@@ -33,6 +33,17 @@ namespace Microsoft.PowerToys.Settings.UI.Library
Code = 65, Code = 65,
}); });
this.PushToTalkMicrophoneHotkey = new KeyboardKeysProperty(
new HotkeySettings()
{
Win = true,
Ctrl = false,
Alt = false,
Shift = true,
Key = "I",
Code = 73,
});
this.MuteCameraHotkey = new KeyboardKeysProperty( this.MuteCameraHotkey = new KeyboardKeysProperty(
new HotkeySettings() new HotkeySettings()
{ {
@@ -43,6 +54,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
Key = "O", Key = "O",
Code = 79, Code = 79,
}); });
this.PushToReverseEnabled = new BoolProperty(false);
} }
[JsonPropertyName("mute_camera_and_microphone_hotkey")] [JsonPropertyName("mute_camera_and_microphone_hotkey")]
@@ -51,6 +64,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("mute_microphone_hotkey")] [JsonPropertyName("mute_microphone_hotkey")]
public KeyboardKeysProperty MuteMicrophoneHotkey { get; set; } public KeyboardKeysProperty MuteMicrophoneHotkey { get; set; }
[JsonPropertyName("push_to_talk_microphone_hotkey")]
public KeyboardKeysProperty PushToTalkMicrophoneHotkey { get; set; }
[JsonPropertyName("push_to_reverse_enabled")]
public BoolProperty PushToReverseEnabled { get; set; }
[JsonPropertyName("mute_camera_hotkey")] [JsonPropertyName("mute_camera_hotkey")]
public KeyboardKeysProperty MuteCameraHotkey { get; set; } public KeyboardKeysProperty MuteCameraHotkey { get; set; }

View File

@@ -25,6 +25,9 @@
<controls:ShortcutWithTextLabelControl <controls:ShortcutWithTextLabelControl
x:Name="HotkeyMicControl" x:Name="HotkeyMicControl"
x:Uid="Oobe_VideoConference_ToggleMic" /> x:Uid="Oobe_VideoConference_ToggleMic" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyPushToTalkControl"
x:Uid="Oobe_VideoConference_PushToTalkMic" />
<controls:ShortcutWithTextLabelControl <controls:ShortcutWithTextLabelControl
x:Name="HotkeyVidControl" x:Name="HotkeyVidControl"
x:Uid="Oobe_VideoConference_ToggleVid" /> x:Uid="Oobe_VideoConference_ToggleVid" />

View File

@@ -40,6 +40,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ViewModel.LogOpeningModuleEvent(); ViewModel.LogOpeningModuleEvent();
HotkeyMicVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraAndMicrophoneHotkey.Value.GetKeysList(); HotkeyMicVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraAndMicrophoneHotkey.Value.GetKeysList();
HotkeyMicControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteMicrophoneHotkey.Value.GetKeysList(); HotkeyMicControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteMicrophoneHotkey.Value.GetKeysList();
HotkeyPushToTalkControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PushToTalkMicrophoneHotkey.Value.GetKeysList();
HotkeyVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraHotkey.Value.GetKeysList(); HotkeyVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraHotkey.Value.GetKeysList();
} }

View File

@@ -207,6 +207,9 @@
<data name="VideoConference_MicrophoneMuteHotkeyControl_Header.Header" xml:space="preserve"> <data name="VideoConference_MicrophoneMuteHotkeyControl_Header.Header" xml:space="preserve">
<value>Mute microphone</value> <value>Mute microphone</value>
</data> </data>
<data name="VideoConference_MicrophonePushToTalkHotkeyControl_Header.Header" xml:space="preserve">
<value>Push to talk</value>
</data>
<data name="VideoConference_CameraMuteHotkeyControl_Header.Header" xml:space="preserve"> <data name="VideoConference_CameraMuteHotkeyControl_Header.Header" xml:space="preserve">
<value>Mute camera</value> <value>Mute camera</value>
</data> </data>
@@ -216,6 +219,12 @@
<data name="VideoConference_SelectedMicrophone.Header" xml:space="preserve"> <data name="VideoConference_SelectedMicrophone.Header" xml:space="preserve">
<value>Selected microphone</value> <value>Selected microphone</value>
</data> </data>
<data name="VideoConference_PushToReverse.Header" xml:space="preserve">
<value>Push to reverse</value>
</data>
<data name="VideoConference_PushToReverse.Description" xml:space="preserve">
<value>If enabled, allows both push to talk and push to mute, depending on microphone state</value>
</data>
<data name="VideoConference_CameraOverlayImagePathHeader.Header" xml:space="preserve"> <data name="VideoConference_CameraOverlayImagePathHeader.Header" xml:space="preserve">
<value>Image displayed when camera is muted</value> <value>Image displayed when camera is muted</value>
</data> </data>
@@ -1720,6 +1729,9 @@ From there, simply click on one of the supported files in the File Explorer and
<data name="Oobe_VideoConference_ToggleMic.Text" xml:space="preserve"> <data name="Oobe_VideoConference_ToggleMic.Text" xml:space="preserve">
<value>to toggle your microphone</value> <value>to toggle your microphone</value>
</data> </data>
<data name="Oobe_VideoConference_PushToTalkMic.Text" xml:space="preserve">
<value>to toggle your microphone until key release</value>
</data>
<data name="Oobe_VideoConference_ToggleVid.Text" xml:space="preserve"> <data name="Oobe_VideoConference_ToggleVid.Text" xml:space="preserve">
<value>to toggle your video</value> <value>to toggle your video</value>
</data> </data>

View File

@@ -96,6 +96,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_cameraAndMicrophoneMuteHotkey = Settings.Properties.MuteCameraAndMicrophoneHotkey.Value; _cameraAndMicrophoneMuteHotkey = Settings.Properties.MuteCameraAndMicrophoneHotkey.Value;
_microphoneMuteHotkey = Settings.Properties.MuteMicrophoneHotkey.Value; _microphoneMuteHotkey = Settings.Properties.MuteMicrophoneHotkey.Value;
_microphonePushToTalkHotkey = Settings.Properties.PushToTalkMicrophoneHotkey.Value;
_pushToReverseEnabled = Settings.Properties.PushToReverseEnabled.Value;
_cameraMuteHotkey = Settings.Properties.MuteCameraHotkey.Value; _cameraMuteHotkey = Settings.Properties.MuteCameraHotkey.Value;
CameraImageOverlayPath = Settings.Properties.CameraOverlayImagePath.Value; CameraImageOverlayPath = Settings.Properties.CameraOverlayImagePath.Value;
SelectOverlayImage = new ButtonClickCommand(SelectOverlayImageAction); SelectOverlayImage = new ButtonClickCommand(SelectOverlayImageAction);
@@ -176,7 +178,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private int _toolbarHideIndex; private int _toolbarHideIndex;
private HotkeySettings _cameraAndMicrophoneMuteHotkey; private HotkeySettings _cameraAndMicrophoneMuteHotkey;
private HotkeySettings _microphoneMuteHotkey; private HotkeySettings _microphoneMuteHotkey;
private HotkeySettings _microphonePushToTalkHotkey;
private HotkeySettings _cameraMuteHotkey; private HotkeySettings _cameraMuteHotkey;
private bool _pushToReverseEnabled;
private int _selectedCameraIndex = -1; private int _selectedCameraIndex = -1;
private int _selectedMicrophoneIndex; private int _selectedMicrophoneIndex;
@@ -340,6 +344,42 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
} }
} }
public HotkeySettings MicrophonePushToTalkHotkey
{
get
{
return _microphonePushToTalkHotkey;
}
set
{
if (value != _microphonePushToTalkHotkey)
{
_microphonePushToTalkHotkey = value;
Settings.Properties.PushToTalkMicrophoneHotkey.Value = value;
RaisePropertyChanged(nameof(MicrophonePushToTalkHotkey));
}
}
}
public bool PushToReverseEnabled
{
get
{
return _pushToReverseEnabled;
}
set
{
if (value != _pushToReverseEnabled)
{
_pushToReverseEnabled = value;
Settings.Properties.PushToReverseEnabled.Value = value;
RaisePropertyChanged(nameof(PushToReverseEnabled));
}
}
}
public HotkeySettings CameraMuteHotkey public HotkeySettings CameraMuteHotkey
{ {
get get

View File

@@ -77,6 +77,12 @@
HotkeySettings="{x:Bind Path=ViewModel.MicrophoneMuteHotkey, Mode=TwoWay}" /> HotkeySettings="{x:Bind Path=ViewModel.MicrophoneMuteHotkey, Mode=TwoWay}" />
</labs:SettingsCard> </labs:SettingsCard>
<labs:SettingsCard x:Uid="VideoConference_MicrophonePushToTalkHotkeyControl_Header">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
HotkeySettings="{x:Bind Path=ViewModel.MicrophonePushToTalkHotkey, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard x:Uid="VideoConference_CameraMuteHotkeyControl_Header"> <labs:SettingsCard x:Uid="VideoConference_CameraMuteHotkeyControl_Header">
<controls:ShortcutControl <controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}" MinWidth="{StaticResource SettingActionControlMinWidth}"
@@ -95,6 +101,13 @@
ItemsSource="{Binding MicrophoneNames, Mode=OneTime}" ItemsSource="{Binding MicrophoneNames, Mode=OneTime}"
SelectedIndex="{Binding Path=SelectedMicrophoneIndex, Mode=TwoWay}" /> SelectedIndex="{Binding Path=SelectedMicrophoneIndex, Mode=TwoWay}" />
</labs:SettingsCard> </labs:SettingsCard>
<labs:SettingsCard
x:Uid="VideoConference_PushToReverse">
<ToggleSwitch
x:Uid="PushToReverseSwitch"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.PushToReverseEnabled}" />
</labs:SettingsCard>
</controls:SettingsGroup> </controls:SettingsGroup>
<controls:SettingsGroup <controls:SettingsGroup