Skip to content

feat: UI overhaul — input filters, tabs, minimap, dialog standardization#207

Merged
OpenSauce merged 6 commits intomainfrom
feat/ui-overhaul
Mar 1, 2026
Merged

feat: UI overhaul — input filters, tabs, minimap, dialog standardization#207
OpenSauce merged 6 commits intomainfrom
feat/ui-overhaul

Conversation

@OpenSauce
Copy link
Copy Markdown
Owner

@OpenSauce OpenSauce commented Mar 1, 2026

Summary

  • Extract Filter stages from preset chain into dedicated input filter controls (HP/LP)
  • Add tab system and stage category grouping to the GUI
  • Add minimap component for stage chain overview
  • Standardize all dialog styling: shared constants, close button in title row, consistent layout
  • Rename SettingsMessage::Cancel to Close, remove dead overlay from settings
  • Add preset migration for old format, enforce stage ordering by category
  • Preset updates: added Delay/Reverb stages to some presets, adjusted IR gains for tonal balance

Test plan

  • make lint passes
  • make test passes (76 tests)
  • Manual: verify input filter HP/LP toggles and cutoff sliders
  • Manual: verify tab switching and minimap
  • Manual: verify all four dialogs have consistent close button placement
  • Manual: verify old presets auto-migrate on load

Copilot AI review requested due to automatic review settings March 1, 2026 14:30
- Add shared DIALOG_TITLE_SIZE, DIALOG_CONTENT_SPACING, and
  DIALOG_CONTENT_PADDING constants in dialogs/mod.rs
- Move close button to title row (top-right) in all four dialogs
- Fix tuner dialog: match title size, spacing, padding with others;
  use full-screen layout with centered tuner content
- Settings: rename cancel button label to "Close" for consistency
- Replace hardcoded values with shared constants across all dialogs
- Remove dead dark overlay from settings dialog
- Rename SettingsMessage::Cancel to Close to match button label
- Extract DIALOG_TITLE_ROW_SPACING constant, use in all four dialogs
- Remove vestigial row! wrapper around single button in midi dialog
- Restore tuner inner spacing to 10 (intra-component, not inter-section)
- Extract Filter stages from preset chain into dedicated input_filters
  config with independent HP/LP controls
- Add preset migration: auto-converts old format on load
- Enforce stage ordering by category (pre → core → post)
- Add tab system and stage category grouping to the GUI
- Add minimap component for stage chain overview
- Add new presets: Clean_Eb, Djent_Eb
- Remove old Control, StageList, and Filter stage GUI components
- Update engine to support dedicated input filter processing
- Add i18n keys for new UI strings
@OpenSauce OpenSauce requested review from Copilot and removed request for Copilot March 1, 2026 14:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR overhauls the GUI and preset format to support categorized (Amp/Effects) stage management with tabs + minimap, replaces in-chain Filter stages with dedicated input HP/LP controls (including preset migration), and adds a new Freeverb-based Reverb stage.

Changes:

  • Add input_filters to presets, migrate legacy "Filter" stages into the new field, and enforce stage ordering by category on load.
  • Introduce GUI tabs (Amp/Effects/Cabinet/Input), a signal-chain minimap, and category-aware stage insertion/reordering.
  • Add a new Reverb stage (GUI + DSP) and update the audio engine to apply input filters before the amp chain.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/preset/mod.rs Adds input_filters to Preset and updates constructors/defaults.
src/preset/manager.rs Adds preset migration from legacy Filter stages + enforces stage ordering; adds migration tests.
src/i18n/mod.rs Adds translation keys for reverb params, tabs, and input filter UI labels.
src/gui/tabs.rs Introduces Tab enum for GUI navigation.
src/gui/stages/reverb.rs Adds GUI config/message/view for the Reverb stage.
src/gui/stages/mod.rs Adds StageCategory, categorizes stages, removes Filter stage, registers Reverb stage.
src/gui/stages/filter.rs Removes legacy Filter stage UI/config/message.
src/gui/mod.rs Exposes new tabs module.
src/gui/messages/settings.rs Renames SettingsMessage::Cancel to Close.
src/gui/messages/mod.rs Adds tab + input filter messages; removes Filter message exports.
src/gui/handlers/settings.rs Updates handler to use the renamed SettingsMessage::Close.
src/gui/handlers/preset.rs Persists and restores input_filters during preset save/load.
src/gui/components/stage_list.rs Removes old StageList component (replaced by tabbed stage views).
src/gui/components/peak_meter.rs Splits peak meter into main meter + compact status display; adjusts styling.
src/gui/components/mod.rs Registers new minimap + input filter modules; removes old control/stage_list modules.
src/gui/components/minimap.rs Adds minimap component for chain overview and tab switching.
src/gui/components/input_filter_control.rs Adds InputFilterConfig (serde) used by presets and UI.
src/gui/components/dialogs/tuner.rs Standardizes dialog title row (with close button) and shared spacing/padding constants.
src/gui/components/dialogs/settings.rs Standardizes dialog title row (with close button) and shared spacing/padding constants; removes cancel button.
src/gui/components/dialogs/mod.rs Adds shared dialog layout constants.
src/gui/components/dialogs/midi.rs Standardizes dialog title row and shared spacing/padding constants.
src/gui/components/dialogs/hotkey.rs Standardizes dialog title row and shared spacing/padding constants.
src/gui/components/control.rs Removes old control bar component (replaced by tabbed add-stage bar + header actions).
src/gui/app.rs Implements tabs, input filter UI, minimap footer, category-aware stage add/move/collapse behavior.
src/audio/engine.rs Adds engine-level input HP/LP stages and applies them before the amp chain.
src/amp/stages/reverb.rs Adds new Freeverb-based Reverb DSP stage with tests.
src/amp/stages/mod.rs Exposes new reverb module.
presets/Sabbath.json Migrates legacy Filter stages into input_filters.
presets/Petrucci.json Migrates legacy Filter stages into input_filters.
presets/High_Gain.json Migrates legacy Filter stages into input_filters.
presets/Funky_Bass.json Migrates legacy Filter stages into input_filters.
presets/Djent_Eb.json Adds new preset using new format (with input_filters).
presets/Djent.json Migrates legacy Filter stages into input_filters and updates fields.
presets/Crunch.json Migrates legacy Filter stage into input_filters.
presets/Clean_Overdrive.json Migrates legacy Filter stages into input_filters.
presets/Clean_Eb.json Adds new preset using new format (with input_filters).
presets/Clean.json Migrates legacy Filter stages into input_filters and updates stages/fields.
presets/Bitey.json Migrates legacy Filter stages into input_filters.
Comments suppressed due to low confidence (1)

src/gui/components/peak_meter.rs:127

  • view_status hard-codes English labels ("XR" and "CPU") and no longer uses the existing translations (tr!(xruns) / tr!(cpu)) that were previously displayed in this component. If i18n is still expected here, please revert to using translation keys (or add new keys for the abbreviated forms).
        row![
            text(format!("XR {xrun_count}"))
                .size(11)
                .style(move |_: &iced::Theme| iced::widget::text::Style {
                    color: Some(xrun_color),
                }),
            text(format!("CPU {cpu_load:.0}%"))
                .size(11)
                .style(move |_: &iced::Theme| iced::widget::text::Style {
                    color: Some(cpu_color),
                }),
        ]

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/gui/app.rs
Comment thread src/audio/engine.rs Outdated
Comment thread src/preset/manager.rs
- Change stage_header/stage_card API to accept explicit can_move_up and
  can_move_down flags instead of idx/total_stages pair; compute flags
  per-category in app.rs to fix move buttons for categorized stage tabs
- Remove heap allocation in RT audio path: apply input filters in-place
  via the output buffer instead of allocating a Vec every callback
- Move buffer size mismatch check to public process() entry point
- Remove unwrap() calls in preset migration; build stages array directly
  and handle input_filters serialization gracefully
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 43 out of 43 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/audio/engine.rs Outdated
Comment on lines +93 to +95
// Apply input filters in-place via output buffer to avoid allocation
output[..input.len()].copy_from_slice(input);
self.apply_input_filters(&mut output[..input.len()]);
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

copy_from_slice requires that input and output do not overlap. Engine::process doesn't document or enforce this, so callers that ever pass the same buffer for in-place processing could trigger undefined behavior. Consider guarding against aliasing (e.g., skip the copy when the slices have the same base pointer) or documenting the non-overlap requirement on the public API.

Copilot uses AI. Check for mistakes.
Comment thread src/preset/manager.rs
Comment on lines +165 to +170
let input_filters = InputFilterConfig {
hp_enabled: hp_cutoff.is_some(),
hp_cutoff: hp_cutoff.unwrap_or(100.0),
lp_enabled: lp_cutoff.is_some(),
lp_cutoff: lp_cutoff.unwrap_or(8000.0),
};
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

In migrate_preset, hp_enabled/lp_enabled are derived from whether a cutoff value was parsed (*_cutoff.is_some()). If an old preset contains a Filter stage but is missing cutoff_hz (or it’s non-numeric), the stage will be dropped and the corresponding filter will end up disabled instead of enabled with a default cutoff. Consider tracking presence of Highpass/Lowpass stages separately from cutoff parsing, and defaulting the cutoff when missing.

Copilot uses AI. Check for mistakes.
Comment thread presets/Clean.json
Comment on lines +47 to +53
},
{
"Delay": {
"delay_ms": 300.0,
"feedback": 0.3,
"mix": 0.26
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

This preset update adds a new Delay stage to Clean.json, which goes beyond the stated preset-format migration (removing Filter stages + adding input_filters). If this is intentional sound/design change, it should be called out in the PR description; otherwise consider keeping the stage chain unchanged and only applying the mechanical migration.

Copilot uses AI. Check for mistakes.
Comment thread presets/Djent.json
Comment on lines 65 to +67
"ir_name": "Science Amplification/4x12/G12H-150/SM57 Brighter.wav",
"ir_gain": 0.17999999
} No newline at end of file
"ir_gain": 0.14999999,
"pitch_shift_semitones": 0,
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

Djent.json changes ir_gain (0.17999999 -> 0.14999999) as part of the migration. If this gain change is intentional (tone-level adjustment) it should be mentioned in the PR description; otherwise consider preserving the original ir_gain to avoid unexpected loudness changes for existing users.

Copilot uses AI. Check for mistakes.
Comment thread src/gui/components/peak_meter.rs Outdated
Comment on lines +117 to +123
text(format!("XR {xrun_count}"))
.size(11)
.style(move |_: &iced::Theme| iced::widget::text::Style {
color: Some(xrun_color),
}),
text(format!("{}: {cpu_load:.0}%", tr!(cpu)))
.size(14)
.width(Length::Fixed(80.0))
text(format!("CPU {cpu_load:.0}%"))
.size(11)
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

view_status hardcodes the labels "XR" and "CPU", which bypasses the existing translation keys (tr!(xruns), tr!(cpu)) used elsewhere in this component. This makes the status text non-localizable (e.g., ZH_CN). Consider formatting these labels using translated strings (or introduce dedicated short translation keys if you want abbreviations).

Copilot uses AI. Check for mistakes.
…abels

- Guard against input/output buffer aliasing in Engine::process by
  skipping copy_from_slice when pointers match
- Track filter stage presence separately from cutoff parsing in
  migrate_preset so a Highpass/Lowpass stage without cutoff_hz is
  still enabled (with default cutoff)
- Use tr!(xruns) and tr!(cpu) in peak meter status instead of
  hardcoded English strings
@OpenSauce OpenSauce changed the title feat: UI overhaul — reverb, input filters, tabs, dialog standardization feat: UI overhaul — input filters, tabs, minimap, dialog standardization Mar 1, 2026
@OpenSauce OpenSauce merged commit e8fca00 into main Mar 1, 2026
7 checks passed
@OpenSauce OpenSauce deleted the feat/ui-overhaul branch March 1, 2026 15:01
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.

2 participants