Skip to content

[synth] Adding Sequential Fourm - #535

Merged
christofmuc merged 3 commits into
masterfrom
synths/Sequential_Fourm
Sep 4, 2026
Merged

[synth] Adding Sequential Fourm#535
christofmuc merged 3 commits into
masterfrom
synths/Sequential_Fourm

Conversation

@christofmuc

@christofmuc christofmuc commented Apr 26, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added beta support for the Sequential Fourm synthesizer, including program memory access across all banks and edit-buffer auditioning.
    • Added device discovery and program transfer support for the Sequential Fourm.
  • Documentation

    • Added the Sequential Fourm to the supported synthesizer documentation, noting that hardware verification is pending.
  • Tests

    • Added coverage for bank addressing, device identification, program downloads, and edit-buffer export and re-import.

@coderabbitai

coderabbitai Bot commented Apr 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: da444075-28e0-4bdc-8ff5-157432063c9a

📥 Commits

Reviewing files that changed from the base of the PR and between 5a8c5db and 4b9a0f4.

📒 Files selected for processing (5)
  • README.md
  • adaptations/CMakeLists.txt
  • adaptations/Sequential_Fourm.py
  • adaptations/test_Sequential_Fourm.py
  • docs/README.md

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

A new adaptation module registers support for the Sequential Fourm device with a GenericSequential handler, along with test data sourced from a .syx file. A corresponding test validates SysEx message round-trip packing and unpacking behavior with specific payload length and byte sequence assertions.

Changes

Cohort / File(s) Summary
Sequential Fourm Adaptation Module
adaptations/Sequential_Fourm.py
Registers a GenericSequential handler for device 0x3B with memory layout (4 banks, 128 patches/bank); provides make_test_data() that loads test program data from .syx file, creates a program variant ("Fourm Rename Test"), and includes SysEx device detection and dump request sequences.
Sequential Fourm Test
adaptations/test_Sequential_Fourm.py
Tests SysEx round-trip behavior: loads fixture file, validates program name ("A New Legend"), unpacks payload via unescapeSysex, repacks via escapeSysex, and asserts correct lengths (4102 unpacked, 4688 repacked) and reconstructed message equality.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A Fourm device hops into our nest,
With sequential paths and SysEx zest,
Patches packed and named just right,
Round-trip tests burning bright!
Welcome, friend, to our adaptation night! 🎵

Merge Risk: ⚪ Minimal · up to 4b9a0

This adds beta Sequential Fourm support, including packaging and documentation, with automated coverage for its key MIDI, bank, and import workflows. No concrete merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. (3 skipped: 3 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding support for the Sequential Fourm synthesizer.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch synths/Sequential_Fourm

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
adaptations/test_Sequential_Fourm.py (1)

17-22: Round-trip check is solid; the length asserts are largely redundant.

The byte-for-byte reconstruction at line 22 already implies the length asserts at lines 20–21. Keeping them is fine as documentation of expected payload sizes, but a brief comment explaining that 4102 is the unpacked Fourm program payload (and 4688 is its 7-to-8 nibblized form) would help future readers diagnose a failure here without having to re-derive the math. No functional concern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adaptations/test_Sequential_Fourm.py` around lines 17 - 22, Add a short
inline comment above the length asserts explaining what the magic numbers
represent: 4102 is the expected size of the unpacked Fourm program payload and
4688 is the corresponding 7-to-8 nibblized (escaped) size; reference the
variables and functions involved (unpacked, repacked, message and
sequential.GenericSequential.unescapeSysex / escapeSysex) so future readers can
immediately understand the origin of those numbers without re-deriving the math.
adaptations/Sequential_Fourm.py (2)

28-41: Return-type annotations don't match the generator bodies.

Both programs and edit_buffers use yield, so they are generator functions, not functions returning List[...]. The annotations are misleading (and would be wrong if any caller treats them as list).

♻️ Suggested annotation fix
-from typing import List
+from typing import Iterator
@@
-    def programs(data: testing.TestData) -> List[testing.ProgramTestData]:
+    def programs(data: testing.TestData) -> Iterator[testing.ProgramTestData]:
@@
-    def edit_buffers(data: testing.TestData) -> List[testing.ProgramTestData]:
+    def edit_buffers(data: testing.TestData) -> Iterator[testing.ProgramTestData]:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adaptations/Sequential_Fourm.py` around lines 28 - 41, Both programs and
edit_buffers are generator functions (they use yield) but are annotated as
returning List[testing.ProgramTestData]; change their return annotations to a
generator/iterator type such as Iterator[testing.ProgramTestData] or
Generator[testing.ProgramTestData, None, None] and add the corresponding import
from typing (Iterator or Generator) at the top; update the def signatures for
programs(...) and edit_buffers(...) to use the chosen annotation (e.g., def
programs(...) -> Iterator[testing.ProgramTestData]:) so the type matches the
actual generator behavior.

36-41: Ruff F821 flag is valid for this bare name — use this_module.convertToEditBuffer to clarify runtime injection.

convertToEditBuffer is dynamically injected by sequential.GenericSequential.install(this_module) at lines 17–24, which registers it on the module via setattr(). At runtime this works correctly, but Ruff's static analysis cannot see the dynamic injection and flags the bare name as undefined (F821). Since this_module is already available at line 13, qualifying the reference silences Ruff and improves clarity:

Recommended clarity fix
     def edit_buffers(data: testing.TestData) -> List[testing.ProgramTestData]:
         yield testing.ProgramTestData(
-            message=convertToEditBuffer(0, data.all_messages[0]),
+            message=this_module.convertToEditBuffer(0, data.all_messages[0]),
             name="A New Legend",
             rename_name="Fourm Rename Test",
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adaptations/Sequential_Fourm.py` around lines 36 - 41, The bare name
convertToEditBuffer in the generator function edit_buffers triggers Ruff F821;
qualify the call via the module object used for dynamic injection (this_module)
so static analysis sees it. Update the call in edit_buffers to use
this_module.convertToEditBuffer(...) (keeping the same arguments and return
shape), referencing the existing this_module symbol that was set up by
sequential.GenericSequential.install so the runtime behavior is unchanged but
Ruff is satisfied.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@adaptations/Sequential_Fourm.py`:
- Around line 28-41: Both programs and edit_buffers are generator functions
(they use yield) but are annotated as returning List[testing.ProgramTestData];
change their return annotations to a generator/iterator type such as
Iterator[testing.ProgramTestData] or Generator[testing.ProgramTestData, None,
None] and add the corresponding import from typing (Iterator or Generator) at
the top; update the def signatures for programs(...) and edit_buffers(...) to
use the chosen annotation (e.g., def programs(...) ->
Iterator[testing.ProgramTestData]:) so the type matches the actual generator
behavior.
- Around line 36-41: The bare name convertToEditBuffer in the generator function
edit_buffers triggers Ruff F821; qualify the call via the module object used for
dynamic injection (this_module) so static analysis sees it. Update the call in
edit_buffers to use this_module.convertToEditBuffer(...) (keeping the same
arguments and return shape), referencing the existing this_module symbol that
was set up by sequential.GenericSequential.install so the runtime behavior is
unchanged but Ruff is satisfied.

In `@adaptations/test_Sequential_Fourm.py`:
- Around line 17-22: Add a short inline comment above the length asserts
explaining what the magic numbers represent: 4102 is the expected size of the
unpacked Fourm program payload and 4688 is the corresponding 7-to-8 nibblized
(escaped) size; reference the variables and functions involved (unpacked,
repacked, message and sequential.GenericSequential.unescapeSysex / escapeSysex)
so future readers can immediately understand the origin of those numbers without
re-deriving the math.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3639c8a5-4191-4d1a-bd1c-07645751555d

📥 Commits

Reviewing files that changed from the base of the PR and between 783f4a9 and 5a8c5db.

📒 Files selected for processing (3)
  • adaptations/Sequential_Fourm.py
  • adaptations/testData/Sequential_Fourm/a_new_legend.syx
  • adaptations/test_Sequential_Fourm.py

@christofmuc

Copy link
Copy Markdown
Owner Author

Release preparation pushed in 4b9a0f4, after merging current master:

  • Added Fourm to the installer/Linux shipping manifest and the root/docs device lists (beta; hardware verification pending).
  • Cleaned up generator annotations and the explicit GenericSequential instance used by test data.
  • Added independent bank-boundary requests/conversions, broadcast discovery, all four 128-patch mock MIDI downloads, edit-buffer-only audition, and individual/duplicate reimport regressions.

Python 3.12: 35 passed, 14 skipped. Shipping registration and git diff --check verified. No hardware testing performed. Code work is ready for merge consideration once fresh CI and review pass.

@christofmuc christofmuc added the Ready for release Will be part of the next release label Sep 4, 2026
@christofmuc
christofmuc merged commit bf84166 into master Sep 4, 2026
4 of 5 checks passed
@christofmuc
christofmuc deleted the synths/Sequential_Fourm branch September 4, 2026 10:57
@christofmuc christofmuc removed the Ready for release Will be part of the next release label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant