Skip to content

[midi] Preserve MIDI bindings when saving device settings#1951

Merged
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/midi-settings-preserve-bindings
Apr 25, 2026
Merged

[midi] Preserve MIDI bindings when saving device settings#1951
ten9876 merged 1 commit intoten9876:mainfrom
jensenpat:aether/midi-settings-preserve-bindings

Conversation

@jensenpat
Copy link
Copy Markdown
Collaborator

Summary

  • preserve existing MIDI bindings before MidiSettings::save() opens midi.settings for writing
  • add a standalone midi_settings_test regression harness for preference-only saves
  • wire the new MIDI settings test target into the CMake test harness section

What we discovered

MidiSettings::save() was intended to update device preferences such as LastDevice and AutoConnect while keeping the existing <Binding> entries. The code opened midi.settings with QIODevice::WriteOnly and then called loadBindings() from the same path. On QFile, opening with WriteOnly truncates the file as soon as open() succeeds, so the subsequent loadBindings() read happened after the old XML contents were already gone. That made preference-only actions, like connecting a MIDI device or toggling auto-connect, capable of rewriting the file with an empty bindings list.

The fix loads the bindings before opening the file for write, then serializes those preserved bindings into the updated settings document.

Testing

  • cmake -S . -B build -G Ninja
  • cmake --build build -j 10
  • build/midi_settings_test
  • build/client_eq_test
  • build/client_comp_test
  • build/client_gate_test
  • build/client_deess_test
  • build/client_tube_test
  • build/client_pudu_test
  • build/client_reverb_test
  • build/passive_spots_policy_test
  • build/device_diagnostics_test
  • build/help_dialog_test
  • QT_QPA_PLATFORM=offscreen build/container_widget_test
  • QT_QPA_PLATFORM=offscreen build/container_manager_test
  • QT_QPA_PLATFORM=offscreen build/container_nesting_test
  • ctest --test-dir build -j 10 --output-on-failure (no registered tests in this build dir)
  • manual: verified MIDI settings persistence behavior in the built app

Build link: /tmp/aether-midi-settings-preserve-bindings/build/AetherSDR.app

👨🏼‍💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat

@jensenpat jensenpat changed the title Preserve MIDI bindings when saving device settings [midi] Preserve MIDI bindings when saving device settings Apr 25, 2026
@jensenpat jensenpat marked this pull request as ready for review April 25, 2026 12:54
@jensenpat jensenpat requested a review from ten9876 as a code owner April 25, 2026 12:54
Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

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

Good catch, @jensenpat — this is a real data-loss bug and the fix is clean.

The fix itself is correct. Moving auto bindings = loadBindings() before the QIODevice::WriteOnly open is exactly right. QFile::open(WriteOnly) truncates immediately on POSIX and Windows, so the old ordering was guaranteed to read back an empty binding list. One-line move, well-scoped — nothing to object to here.

Test coverage looks solid. The regression test creates isolated state via QTemporaryDir + QStandardPaths::setTestModeEnabled(true), exercises the exact save-then-reload sequence that triggered the bug, and cleans up after itself. The CMake target follows the existing standalone-binary pattern (no add_test(), consistent with every other test target in this project).

No scope concerns — all three changed files are directly related to the stated fix.

One observation (not blocking): save() and saveBindings() share the same XML serialization loop for writing <Binding> elements. If you're up for a follow-up, extracting a small helper like writeBindingsToWriter(QXmlStreamWriter&, const QVector<MidiBinding>&) would reduce the duplication — but that's optional cleanup, not something to hold this PR for.

Thanks for the thorough write-up and testing. This is ready for @ten9876 to merge from my perspective.

@ten9876 ten9876 merged commit f52e4ff into ten9876:main Apr 25, 2026
5 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.

2 participants