Skip to content

  • Projects
  • Groups
  • Snippets
  • Help
  • This project
    • Loading...
  • Sign in / Register
T
Tidal
  • Overview
    • Overview
    • Details
    • Activity
    • Cycle Analytics
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Charts
  • Issues 0
    • Issues 0
    • List
    • Board
    • Labels
    • Milestones
  • Merge Requests 0
    • Merge Requests 0
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
    • Charts
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Charts
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • PLN
  • Tidal
  • Repository

Switch branch/tag
  • Tidal
  • tools
  • lcxl-leds.py
Find file
BlameHistoryPermalink
  • PLN (Algolia)'s avatar
    fix(lcxl): the tap went deaf for six hours and every signal stayed green · e7961f57
    PLN, mid-session: "why atm i see no midi color on lcxl reacting to my touches?"
    
    The LED watcher was enabled, active, 6h uptime, re-parsing the loaded track
    into the journal every few minutes. `systemctl status` was green. And it had
    decoded exactly zero MIDI events the entire time, because its aseqdump child
    was bound to `20:0` while the LCXL had moved to `28:0`.
    
    WHY THE EXISTING DEFENCE DIDN'T FIRE
    
    cmd_watch already re-resolved the port by name on every respawn -- the comment
    on that line even says so, and it is true. It is also useless, because respawn
    is triggered by the child EXITING, and an aseqdump whose sequencer client has
    vanished does not exit. It blocks on a dead subscription indefinitely. The
    read loop never ends, so the re-resolution is never reached.
    
    A re-resolution that is never reached is indistinguishable from a correct one.
    Same shape as the two lenses that shipped with thresholds that could never
    fire: the code was right, the trigger was wrong.
    
    THE FIX
    
    Detect the drift from OUTSIDE the read loop. A 10s poll compares the live
    name resolution against what the current child is actually bound to; on a
    change it invalidates the send-side port cache and terminates the child, and
    the existing main loop respawns and re-resolves through the path it already
    had. No new resolution logic -- find_seq_port() was correct all along and
    returns 28:0 today. Only the re-check was missing.
    
    Deliberately NOT keyed on "no events for N seconds". A board nobody is
    touching is also silent, so that check would fire through every quiet passage
    and respawn the tap mid-set. Port identity changes when the binding is
    genuinely stale and at no other time.
    
    VALIDATION
    
      find_seq_port() -> 28:0                   (resolution was never the bug)
      before restart:  aseqdump -p 20:0         6h stale, 0 events decoded
      after restart:   aseqdump -p 28:0         re-parsed rose_rouge -> 26 controls
    
    The restart also reaped its own orphan. Two unrelated zombie taps remain
    (6.4h on the dead 20:0, 7.7h with no -p at all) -- that is #129/#155, logged
    separately, not addressed here.
    
    NOT PROVEN: the drift watchdog itself has not fired yet, because that needs
    the port to actually move. Unplug and replug the LCXL and the journal should
    show "LCXL moved 28:0 -> NN:0; respawning the tap". Until someone sees that
    line, this fix is reasoned, not demonstrated.
    PLN (Algolia) authored Aug 14, 2026
    e7961f57
lcxl-leds.py 64.4 KB
EditWeb IDE
×

Replace lcxl-leds.py

Attach a file by drag & drop or click to upload


Cancel
A new branch will be created in your fork and a new merge request will be started.