Skip to content

Add Roland JD-800 - #538

Open
christofmuc wants to merge 4 commits into
masterfrom
adaptation/roland-jd800
Open

Add Roland JD-800#538
christofmuc wants to merge 4 commits into
masterfrom
adaptation/roland-jd800

Conversation

@christofmuc

@christofmuc christofmuc commented Apr 26, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added support for Roland JD-800 synthesizer, now listed in the supported devices table with comprehensive patch management capabilities including edit buffer, single program, and bank dump functionality.

@coderabbitai

coderabbitai Bot commented Apr 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds support for the Roland JD-800 synthesizer by introducing a new adaptation module with complete program and bank management capabilities. The module is registered in the CMake build configuration and documented in the README's device compatibility table.

Changes

Cohort / File(s) Summary
Documentation and Build Configuration
README.md, adaptations/CMakeLists.txt
Adds Roland JD-800 to the synth compatibility table and registers Roland_JD800.py in the adaptation files list for compilation and installation.
JD-800 Adaptation Implementation
adaptations/Roland_JD800.py
New module implementing full JD-800 support with DT1 message handling, edit-buffer and single-program dump detection, MD5 fingerprinting for program identity, bank-dump processing (page detection, sorting, assembly, and individual program reconstruction), and test-data generation with mock MIDI device setup.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #528: Both PRs add new Roland adaptation modules to the same adaptations/CMakeLists.txt file and introduce corresponding README documentation, following a consistent pattern for expanding Roland device support.

Poem

🐰 The JD-800 hops into view,
With DT1 messages dancing through,
Bank dumps assembled, programs born anew,
An adaptation module, crafted true! 🎹✨

🚥 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%. 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 'Add Roland JD-800' directly and clearly describes the main change: adding support for the Roland JD-800 synthesizer. It matches the primary changeset which adds a new adaptation module, CMake configuration, and README documentation for this device.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch adaptation/roland-jd800

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.

@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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
adaptations/Roland_JD800.py (2)

198-213: Missing blank line between top-level functions.

PEP 8 expects two blank lines between top-level definitions; here isSingleProgramDump (lines 211-212) is followed immediately by def blankedOut(message): with no separator. Trivial, but if the project runs flake8/ruff with E305/E302 enabled it will be flagged.

♻️ Suggested fix
 def isSingleProgramDump(messages):
     return jd_800.isSingleProgramDump(messages)
+
+
 def blankedOut(message):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adaptations/Roland_JD800.py` around lines 198 - 213, Add the required PEP8
separation: insert a blank line (so there are two blank lines between top-level
definitions) between the end of isSingleProgramDump and the start of blankedOut;
locate the functions isSingleProgramDump and blankedOut in the file and ensure
there are two newline characters separating these top-level function
definitions.

243-244: createBankDumpRequest ignores its parameters and uses unexplained magic numbers.

channel and bank are accepted but never used. The hardcoded [0x05, 0x00, 0x00] duplicates _jd800_program_dump.base_address, and [0x01, 0x40, 0x00] is the 7-bit-encoded total payload size (96 × 256 = 24576 bytes) but expressed as opaque magic. If the JD-800 only ever has one bank, this is functionally correct, but a future caller passing a non-zero bank will silently get bank 0. Consider either deriving these from the existing constants or asserting/raising on unexpected bank values to make the single-bank assumption explicit.

♻️ Suggested refactor
 def createBankDumpRequest(channel, bank):
-    return jd_800.buildRolandMessage(jd_800.device_id, command_rq1, [0x05, 0x00, 0x00], [0x01, 0x40, 0x00])
+    # JD-800 has a single internal patch bank; ignore `channel`/`bank`.
+    total_size = _BANK_PAGE_COUNT * _BANK_PAGE_SIZE  # 24576 bytes
+    size_bytes = [
+        (total_size >> 14) & 0x7F,
+        (total_size >> 7) & 0x7F,
+        total_size & 0x7F,
+    ]
+    return jd_800.buildRolandMessage(
+        jd_800.device_id,
+        command_rq1,
+        list(_jd800_program_dump.base_address),
+        size_bytes,
+    )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@adaptations/Roland_JD800.py` around lines 243 - 244, The
createBankDumpRequest function currently ignores its channel and bank parameters
and uses hardcoded magic bytes; update it so the base address comes from the
existing _jd800_program_dump.base_address (instead of [0x05,0x00,0x00]) and
compute the 7-bit-encoded payload size from _jd800_program_dump.total_size
(instead of [0x01,0x40,0x00]); if the device is single-bank, add an explicit
assertion or raise if bank != 0 to make that assumption explicit; keep
jd_800.device_id and command_rq1 for the jd_800.buildRolandMessage call and
ensure channel is either used where required or validated likewise.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@adaptations/Roland_JD800.py`:
- Around line 223-224: The MD5 usage in calculateFingerprint triggers Ruff S324;
add an inline suppression comment to the hashlib.md5 call to silence the warning
and document intent (e.g., "# noqa: S324  # MD5 used only for non-security
fingerprinting of blanked-out sysex payloads"). Update the line containing the
hashlib.md5(...) call in the calculateFingerprint function so the noqa
suppression and brief rationale are on the same line.

---

Nitpick comments:
In `@adaptations/Roland_JD800.py`:
- Around line 198-213: Add the required PEP8 separation: insert a blank line (so
there are two blank lines between top-level definitions) between the end of
isSingleProgramDump and the start of blankedOut; locate the functions
isSingleProgramDump and blankedOut in the file and ensure there are two newline
characters separating these top-level function definitions.
- Around line 243-244: The createBankDumpRequest function currently ignores its
channel and bank parameters and uses hardcoded magic bytes; update it so the
base address comes from the existing _jd800_program_dump.base_address (instead
of [0x05,0x00,0x00]) and compute the 7-bit-encoded payload size from
_jd800_program_dump.total_size (instead of [0x01,0x40,0x00]); if the device is
single-bank, add an explicit assertion or raise if bank != 0 to make that
assumption explicit; keep jd_800.device_id and command_rq1 for the
jd_800.buildRolandMessage call and ensure channel is either used where required
or validated likewise.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d5ba9c96-4900-43e1-9fc4-76af125e894c

📥 Commits

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

📒 Files selected for processing (7)
  • README.md
  • adaptations/CMakeLists.txt
  • adaptations/Roland_JD800.py
  • adaptations/testData/Roland_JD800/Bank-002-800.syx
  • adaptations/testData/Roland_JD800/Internal_Demo_Patches.syx
  • adaptations/testData/Roland_JD800/JDBOOK.SYX
  • adaptations/testData/Roland_JD800/jd800_synthetic_bank.syx

Comment on lines +223 to +224
def calculateFingerprint(message):
return hashlib.md5(bytearray(blankedOut(message))).hexdigest()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm other adaptations use md5 for fingerprints (so behavior is consistent).
rg -nP '\bhashlib\.md5\s*\(' adaptations

Repository: christofmuc/KnobKraft-orm

Length of output: 4970


Add inline suppression for Ruff S324 hint on MD5 usage.

MD5 is used consistently across adaptations for non-security fingerprinting of blanked-out sysex payloads. Add the noqa comment to silence the Ruff warning and document intent:

Suggested fix
 def calculateFingerprint(message):
-    return hashlib.md5(bytearray(blankedOut(message))).hexdigest()
+    return hashlib.md5(bytearray(blankedOut(message))).hexdigest()  # noqa: S324 - non-security fingerprint
🧰 Tools
🪛 Ruff (0.15.11)

[error] 224-224: Probable use of insecure hash functions in hashlib: md5

(S324)

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

In `@adaptations/Roland_JD800.py` around lines 223 - 224, The MD5 usage in
calculateFingerprint triggers Ruff S324; add an inline suppression comment to
the hashlib.md5 call to silence the warning and document intent (e.g., "# noqa:
S324  # MD5 used only for non-security fingerprinting of blanked-out sysex
payloads"). Update the line containing the hashlib.md5(...) call in the
calculateFingerprint function so the noqa suppression and brief rationale are on
the same line.

@christofmuc

Copy link
Copy Markdown
Owner Author

Release-readiness follow-up (no fixes applied here):

  • Dump classification accepts reordered DT1 blocks, but conversion through GenericRoland assigns addresses by list position. Reversing a valid patch's two blocks is accepted by isSingleProgramDump, then convertToProgramDump produces a dump that isSingleProgramDump rejects. Match blocks by address or reject noncanonical input before conversion; add regression coverage. The same shared issue affects [synth] Initial Roland Sound Canvas SC-88 adaptation #539/Edirol SD-90 adaptation. #540.
  • Expand independent assertions for the committed real bank fixtures and incomplete/mixed block streams.

23 existing tests pass on Python 3.12 against the current master harness. This is the base of the current #538 -> #539 -> #540 stack; please resolve the shared transport issue before advancing it.

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