Skip to content

feat(shortcuts): add Master Volume Up/Down configurable keyboard shortcuts (#3791)#3820

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:fix/3791-master-vol-shortcut
Jun 26, 2026
Merged

feat(shortcuts): add Master Volume Up/Down configurable keyboard shortcuts (#3791)#3820
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:fix/3791-master-vol-shortcut

Conversation

@jensenpat

Copy link
Copy Markdown
Collaborator

Summary

Adds Master Volume Up and Master Volume Down to the configurable keyboard-shortcut list (Audio category), as requested in #3791.

Root cause

MainWindow::registerShortcutActions() (src/gui/MainWindow_Shortcuts.cpp) registers the Audio category with per-slice AF Gain Up/Down, mute/mute-all, master mute, and squelch — but no master volume up/down. The user is correct that this is simply a gap: the identical nudge logic already ships for external controllers (the Aether Control / StreamDeck "VolumeUp" / "VolumeDown" dispatch in MainWindow_Controllers.cpp).

Fix

Register master_volume_up / master_volume_down in the Audio category, reusing that exact, already-shipped path:

  • clamp MasterVolume ±5 into [0,100],
  • update the title-bar slider via TitleBar::setMasterVolume(),
  • push to the audio path via applyMasterVolume() — keeping GUI, persistence, and TCI in sync.

Registered with no default key (Up/Down are taken by per-slice AF Gain, and master volume is a distinct concept — the user binds keys themselves) and autoRepeat=true so holding the bound key ramps continuously (consistent with rf_gain_up/down and the tune actions). Single TU; one added include (TitleBar.h, needed for the setMasterVolume call since MainWindow.h only forward-declares it).

How the agent automation bridge proved it

Built and driven through the bridge (AETHER_AUTOMATION=1). The two new entries had to be shown to actually appear in the Configure Shortcuts… list.

Reaching that dialog needed the bridge fidelity work in #3819 (closed-menu QAction trigger + per-pid sockets), so the proof was captured against a local merge of this branch with feat/automation-bridge-fidelity. This branch itself is the single-file change above.

1 — machine-readable. The dialog's Action selector is a non-editable QComboBox populated directly from ShortcutManager::actions(). setCurrentText only takes if the item exists, so an exact echo is proof of registration:

invoke AetherSDR::ShortcutDialog/QComboBox setCurrentText "[Audio] Master Volume Up"
  -> newValue="[Audio] Master Volume Up"   PROVEN
invoke AetherSDR::ShortcutDialog/QComboBox setCurrentText "[Audio] Master Volume Down"
  -> newValue="[Audio] Master Volume Down" PROVEN

2 — visual. With the dialog's search filter set to Master Volume, a grab of AetherSDR::ShortcutDialog shows exactly two rows — Master Volume Up and Master Volume Down, both Audio category, both with empty Current/Default Key (no default binding, as designed).

Field Detail
Issue #3791 — add master volume up/down to configurable shortcuts
Root cause feature simply not registered in the Audio shortcut table (MainWindow_Shortcuts.cpp)
Fix +2 registerAction entries reusing the shipped controller VolumeUp/Down nudge; +1 include
Bridge proof non-editable action-combo setCurrentText exact-echo (both entries) + filtered dialog grab showing both Audio rows
Build clean (Ninja, all cores)

💻 Generated with Claude Code (Opus 4.8) with architecture by @jensenpat

…tcuts (aethersdr#3791)

The keyboard-shortcut action table (registerShortcutActions, Audio
category) exposed per-slice AF Gain Up/Down, mute toggles, master mute,
and squelch — but no master volume up/down, even though the identical
nudge logic already shipped for external controllers (Aether Control /
StreamDeck "VolumeUp"/"VolumeDown" in MainWindow_Controllers.cpp).

Register master_volume_up / master_volume_down in the Audio category,
reusing that exact path: clamp MasterVolume ±5 in [0,100], update the
title-bar slider via TitleBar::setMasterVolume(), and push to the audio
path via applyMasterVolume() — keeping GUI, persistence, and TCI in
sync. Registered with no default key (Up/Down are taken by per-slice AF
Gain) and autoRepeat=true so holding the bound key ramps continuously.

Fixes aethersdr#3791

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jensenpat jensenpat marked this pull request as ready for review June 25, 2026 23:13
@jensenpat jensenpat requested a review from a team as a code owner June 25, 2026 23:13

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed and verified against the tree — this is clean. Thanks for the well-scoped change and the clear write-up, @jensenpat. 👍

What I checked:

  • Faithful to the shipped path. The two handlers are an exact mirror of the existing VolumeUp/VolumeDown controller dispatch (MainWindow_Controllers.cpp:1014–1023): same std::clamp(... ±5, 0, 100), same m_titleBar->setMasterVolume(next), same applyMasterVolume(next). Good reuse rather than a parallel implementation.
  • State stays consistent across repeats. applyMasterVolume() (MainWindow.cpp:5556) writes MasterVolume back via AppSettings + save() and clamps internally, so the next read reflects the prior nudge — autoRepeat=true ramps correctly, and GUI/persistence/TCI stay in lockstep.
  • No null-pointer / include risk. m_titleBar is null-guarded (matches the controller path); <algorithm> is already included (MainWindow_Shortcuts.cpp:49, std::clamp used in several existing handlers); and the added TitleBar.h is genuinely needed since MainWindow.h only forward-declares it.
  • registerAction signature supports the trailing bool autoRepeat (ShortcutManager.h:31).

Conventions (AppSettings, RAII, C++20 std::clamp) are all honored, and the change is confined to the stated scope. No blocking concerns from me.

One small optional thought (non-blocking): the read-clamp-write logic now lives in three places (here + both controller dispatch sites). If you ever touch this again, a tiny nudgeMasterVolume(int delta) helper on MainWindow would let all three call sites share it — but that's cleanup for another PR, not something to hold this one for.


🤖 aethersdr-agent · cost: $6.6801 · model: claude-opus-4-8

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Trivial, correct. The two new registrations reuse the exact master-volume nudge logic the controller VolumeUp/Down path already ships (clamp MasterVolume ±5 in [0,100] → m_titleBar->setMasterVolume → applyMasterVolume), so GUI/persistence/audio stay in sync with no new logic. No default key (correct — Up/Down are AF-Gain), autoRepeat=true for hold-to-ramp (consistent with rf_gain), TitleBar.h include added. No TX/safety surface. Nicely bridge-proven via the action-combo setCurrentText echo + filtered dialog grab.

Non-blocking nit: the ±5 nudge now lives in ~4 spots — a small nudgeMasterVolume(delta) helper would DRY it up, but that duplication predates this PR. Thanks @jensenpat.

@ten9876 ten9876 merged commit 8ff3132 into aethersdr:main Jun 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add master volume up and down to the list of configurable shortcut key choices. similar to volume choices on aether control

2 participants