Skip to content

FEAT(client): Add shortcut to toggle whispers for voice activation/continuous transmission modes#7219

Open
darustam-1 wants to merge 4 commits into
mumble-voip:masterfrom
darustam-1:whisper-shout-toggle
Open

FEAT(client): Add shortcut to toggle whispers for voice activation/continuous transmission modes#7219
darustam-1 wants to merge 4 commits into
mumble-voip:masterfrom
darustam-1:whisper-shout-toggle

Conversation

@darustam-1
Copy link
Copy Markdown

Currently, whispering requires setting a whisper/shout shortcut in settings for a designated target, then using that key as a push-to-talk key that overrides the current transmission target. This is fine in push-to-talk mode as it operates in a similar fashion with different key bindings set for other targets, but in automatic transmit modes (continuous/voice activation), this means you are forced to push-to-whisper, rather than just being able to latch to a target for some time while keeping your fingers free.

This branch implements a feature that allows the user to bind "Whisper Hold" keys for automatic transmission modes. In automatic modes it allows the user to latch the transmission target until the key is either pressed again, returning to default state (shout mode) or another whisper hold key is pressed, changing the target once again.

In addition, this feature rests beneath existing whisper/shout functionality, meaning that while latched to a whisper target, holding down a whisper/shout shortcut to any target will activate a temporary override, like a push-to-talk key.

The implementation reuses Mumble's existing whisper target routing functionality without any new audio packet path or server protocol. Whisper Hold stores its own latch state using:

  • bWhisperHoldActive(user has latched a target)
  • bWhisperHoldTargetApplied (latched target is currently in qmCurrentTargets
  • IWhisperShoutTargetsActive (regular W/S PTT targets are active, including pttHold
  • ShortcutTarget (selected latch target)

In push-to-talk it has no functionality and is therefore disabled. Switching to PTT through the toolbar, settings, or audio wizard clears the latch. Switching between continuous and voice activation does not clear the latch. The state is also automatically reset on app close, disconnect, or modifying shortcut settings.

The feature also adds a message type for whisper hold. It has no default sound but console is enabled, thus pressing the "Whisper Hold" shortcut for a given target will inform the user in the console that they are being held to a target or if the hold is cleared.

This is my first open-source contribution. It builds on Windows and passes my runtime testing in multiple servers.

Implements #6754 with additional functionality.

Checks

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

Walkthrough

This PR introduces a Whisper Hold feature to Mumble. It extends the type system by adding WhisperHold as a new enum value in GlobalShortcutType::Type and Log::MsgType, with corresponding string conversions and log initialization. The implementation adds state tracking and helper methods to MainWindow for applying, refreshing, and resetting the whisper-hold target layer. The shortcut handler toggles hold state on/off and persists the selected Whisper/Shout target. Integration with existing whisper/shout mechanics ensures the hold target reapplies when whisper-shout releases and all active targets clear. Lifecycle hooks reset hold state when closing, disconnecting, or switching to Push-to-Talk mode. Configuration dialogs detect shortcut changes and clear hold state as needed.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a shortcut to toggle whispers in automatic transmission modes.
Description check ✅ Passed The description is comprehensive, covering the feature purpose, implementation details, state management, and interaction with existing features. The checkbox is marked as completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mumble/MainWindow.cpp`:
- Around line 3272-3284: Current code calls removeWhisperHoldTarget() which
performs an immediate updateTarget(), causing a brief fallback to the default
when switching held targets; instead, when switching from one held target to
another, clear the old target without triggering an update and only call the
update once after the new target is set. Change the block around
stWhisperHoldTarget/bWhisperHoldActive so that when stWhisperHoldTarget != st
you call a non-updating removal (either an existing no-update variant or add a
boolean parameter to removeWhisperHoldTarget, e.g.,
removeWhisperHoldTarget(false)) to clear the old target, then assign
stWhisperHoldTarget = st, set bWhisperHoldActive = true and call
refreshWhisperHoldTarget() once to apply the new target; keep the existing
immediate-remove path when stWhisperHoldTarget == st to clear and update
immediately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b944f76-9c93-4a9d-9440-fea964d32146

📥 Commits

Reviewing files that changed from the base of the PR and between 7fba6df and 55f2bfb.

📒 Files selected for processing (7)
  • src/mumble/EnumStringConversions.cpp
  • src/mumble/GlobalShortcutTypes.h
  • src/mumble/Log.cpp
  • src/mumble/Log.h
  • src/mumble/MainWindow.cpp
  • src/mumble/MainWindow.h
  • src/mumble/Settings.cpp

Comment thread src/mumble/MainWindow.cpp Outdated
@Hartmnt Hartmnt added client feature-request This issue or PR deals with a new feature labels Jun 1, 2026
@Hartmnt Hartmnt added this to the 1.7.0 milestone Jun 1, 2026
Copy link
Copy Markdown
Member

@Hartmnt Hartmnt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash the first 3 commits into one. You will need to force-push your branch after that which is fine. Leave the translation commit as is for now.

Comment thread src/mumble/MainWindow.cpp
Comment thread src/mumble/EnumStringConversions.cpp Outdated
Comment thread src/mumble/MainWindow.cpp Outdated
Comment thread src/mumble/MainWindow.cpp Outdated
This commit changes the earlier test where whisper/shout was set up as a
global toggle, which while it worked for my purposes in current channel
scope, it seemed an improperly implemented feature that could add a lot
of useful functionality if properly fleshed out.

This is replacing the toggle with a shortcut action "Whisper Hold."
Whisper Hold acts much like the Whisper/Shout shortcut, but for voice
activity and continuous transmission instead of requiring push to talk.
It is disabled when push-to-talk is in use, as that functionality is
handled by the existing whisper/shout shortcut.

It operates as a latched target selector for those transmission modes,
where pressing the shortcut sends a console message to the user by
default and then sends all voice activity to the assigned whisper target
until either unlatched by a repeated press, or latching to another
whisper target if an alternative binding is simultaneously bound,
much like having multiple whisper/shout PTS keybinds set up at once.

It operates under the existing whisper/shout framework and thus the old
PTS binding overrides the whisper hold, up until the pttHold delay ends.

Implements mumble-voip#6754 with additional functionality
@darustam-1 darustam-1 force-pushed the whisper-shout-toggle branch from dee8310 to 5200b54 Compare June 2, 2026 04:05
@darustam-1
Copy link
Copy Markdown
Author

Squashed the existing commits. The two whitespace issues are vscode default clang-format artifacts (when I use "format document") that I didn't catch; I will review the other notes soon and respond to them respectively.

Refactored some settings validation code into the respective
ConfigDialog and added ShortcutTarget conversion guards.
Identified this bug later on--changing channel while whisper holding to
the "Current" channel setting works on the channel when the hold is
enabled, but changing channels keeps you whispering to that channel.
This is because UserModel:moveUser() emits userMoved before moveItem()
updates the user's channel. Thus, just adding an updateTarget() doesn't
work because ClientUser::get()->cChannel still points to the old
channel. Thus, an emitter localUserChannelChanged() was added to emit
after moveItem(), so cChannel is updated, and it doesn't intrude on
existing code and functions. More lines than I would like to add but it
does the trick.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client feature-request This issue or PR deals with a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants