feat(midi): MIDI CC control surface for live performance#73
Merged
Conversation
Adds a process-wide midi_control.py service (scene jumps, style-cycle, transport, live effect/generator param sweeps) driven by MIDI, so a performer can control a running playlist in real time from a controller. Every action routes through the cheapest correct mechanism for its latency class — Playlist Events for discrete actions, a new request_jump() primitive generalizing skip_event for scene jumps, and direct unlocked setattr() via a new LIVE_PARAMS registry on FrameEffect/GenerativeSource for continuous CC sweeps — with no coalescing, since this module never writes to the DMA socket directly. Ships a sensible default [midi_control].cc_map out of the box (16-pad scene-jump bank + transport + an example knob bank) and targets ensemble systems by MIDI channel. Verified end-to-end on real Ultimate 64 hardware with a KeyLab mkII 49: skip/cycle_style/toggle_pause/jump and a live knob-driven param sweep all confirmed working. Also fixes a doctor.py bug found along the way: print_report's category_order omitted any category not already known, so a Diagnostic in an uncovered category (like the new midi_control one) would silently vanish from the printed report while still counting toward the ok/warn/error totals.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #73 +/- ##
==========================================
- Coverage 79.65% 79.61% -0.05%
==========================================
Files 76 77 +1
Lines 15403 15676 +273
Branches 2315 2373 +58
==========================================
+ Hits 12269 12480 +211
- Misses 2607 2657 +50
- Partials 527 539 +12 ☔ View full report in Codecov by Harness. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
c64cast/midi_control.py, a process-wide MIDI control surface for live performance: scene jumps, style-cycle, transport (pause/resume/skip), and live effect/generator parameter sweeps, driven by MIDI CC/note/program-change messages.PlaylistEvent-flag pattern (newPlaylist.request_jump()generalizesskip_event); continuous CC sweeps use a newLIVE_PARAMSregistry onFrameEffect/GenerativeSourcefor a direct, unlockedsetattr()with no Event/frame-boundary indirection — the cheapest path in the system. No coalescing anywhere (unlikemidi_scene.py), since this module never writes to the DMA socket.[midi_control]config section (MidiControlCfg) following the existing[control]process-wide pattern; ships a sensible defaultcc_mapout of the box (16-pad scene-jump bank, transport, example knob bank); ensemble targeting by MIDI channel.doctor.pybug found along the way:print_report'scategory_ordersilently dropped anyDiagnosticcategory it didn't already know about (including the newmidi_controlone) from the printed report, while still counting it in the summary totals.Test plan
make check(ruff, mypy --strict, pyright, full test suite — 1953 tests) greenmake schemaregenerated, drift tests passtests/test_midi_control.py(dispatch, channel targeting, crash guards, port selection, lifecycle),Playlist.request_jump()tests intests/test_playlist.py,LIVE_PARAMStests intests/test_generative.py,print_reportcategory-drift regression tests intests/test_doctor.py