Skip to content

T-bar as a real lever (ping-pong), flicker fixed, T-bar widget - #113

Merged
LeeO86 merged 3 commits into
devfrom
feat/fb-tbar
Oct 23, 2026
Merged

LeeO86 merged 3 commits into
devfrom
feat/fb-tbar

Conversation

@LeeO86

@LeeO86 LeeO86 commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Adrian's T-bar item (2026-10-23).

1. The T-bar is a real lever (ping-pong)

Before: at the bottom (transition complete) the GUI handle jumped back to the top; a mouse at the end of travel kept sending positions near 1, which started the next transition (and positions sent in parallel could arrive out of order) → flicker between full up and full down.

Server state (so every console, the widget and a hardware panel agree):

  • MixerPanel.tbar_end (top | bottom, default top, saved and exported): where the lever rests. Each transition the T-bar or an Auto completes (and a Cut of a held one) flips it. A Cut at rest leaves it.
  • POST /mixer/position takes lever (0 top … 1 bottom, where the lever physically is) as an alternative to position. The mixer turns it into the progress from the resting end (lever from the top, 1 − lever from the bottom). Within 2 % of the resting end it starts nothing (end-of-travel hysteresis, also for hardware panels).
  • Backwards compatible: position keeps its meaning (the transition's progress); the engine API is unchanged. Exactly one of the two is required (422 otherwise).
  • GET /console → tbar per ME: end, position (of a held transition), lever.
  • Fixed on the way: position: 1 straight from rest answered 500 (KeyError); now it completes the transition.

GUI (components/TBar.tsx, logic in src/tbar.ts, shared with the widget):

  • The drag takes its resting end when it starts; the mixer's answers don't move the handle while dragging (no echo fighting the drag).
  • The handle moves with the pointer from where it was grabbed (a click on the track does nothing: no accidental take).
  • One request at a time, in order; a newer position replaces a waiting one, so a completion is never overtaken by an older position.
  • At the far end (the last 1 % snaps there) the transition completes and the drag is latched until release; back to the resting end ends it without the swap.
  • preventDefault on pointerdown, no native drag, user-select: none: Chrome cancelled the pointer mid-drag when text was selected (pointercancel, found while testing; likely the "sometimes" in the flicker).
  • Not dragging: the handle follows the mixer; when an Auto (or another console) moved the lever to the other end, it runs there at the ME's rate.

2. T-bar widget

/widget/tbar[?me=<n>][&buttons=false][&theme=…], registered like the others: widget.tsx route, nginx location = /widget/tbar (checks me, buttons, theme; CSP frame-ancestors), GET /api/v1/widgets (params me default 1, buttons default true; min 120×240), README. It shows the same lever with Cut and Auto (as in the bus widget).

Tests

  • pytest tests/test_tbar.py: a drag down that completes and stays at the bottom, wiggling at the end starts nothing, the reverse drag up completes the next one, back to the start without the swap, Auto (from rest and from a held position) and Cut (at rest and held) leave the lever at the right end, the API with lever/position/neither/both, console tbar, tbar_end in the export. Widgets list updated.
  • gui/scripts/check-tbar.ts (in CI): a drag down that completes (latched, handle stays), the reverse drag up, the deadband at both ends, back to the start, picking up a transition held elsewhere, no repeats, the Auto travel time.
  • Browser (headless Chrome, WebDriver pointer actions, simulate mode): console drag down → cam-2 on Program, end bottom, handle 100 %; drag up halfway → held 50 % from the bottom; up to the top → swapped back, end top; Auto → end bottom, handle 100 %; widget: a click on the track away from the handle does nothing; drag up from the bottom → held, then completed at the top.
  • Screenshots: ~/mxl-lab/shots/fxfb-tbar-1-bottom.jpg, fxfb-tbar-2-held-up.jpg, fxfb-tbar-3-after-auto.jpg, fxfb-tbar-5-widget-held.jpg.
  • Docs: README (GUI transition section, API table, widgets table and routes), CHANGELOG.

🤖 Generated with Claude Code

https://claude.ai/code/session_01St7QwmonpoG9EEEqaLFXLi

LeeO86 and others added 3 commits October 23, 2026 07:17
…T-bar widget

- The mixer keeps where the lever rests (panel.tbar_end, saved) and flips
  it when the T-bar, an Auto or a Cut of a held transition completes.
  POST /mixer/position takes `lever` (0 top .. 1 bottom, counted from the
  resting end; 2 % deadband) besides `position` (unchanged); GET /console
  -> tbar. position 1 straight from rest no longer answers 500.
- GUI: shared TBar (src/tbar.ts): relative grab, one request at a time in
  order, latched at the end until release, no native drag/selection
  cancelling the pointer, Auto runs the handle to the other end.
- /widget/tbar[?me=<n>][&buttons=false] with Cut and Auto.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01St7QwmonpoG9EEEqaLFXLi
- A lever request carries `from` (the end its drag began at): a drag from
  an end another console's Auto or Cut changed is ignored (no take back);
  the GUI latches such a drag. A lever without `from` (hardware) is picked
  up at the new resting end after each change of the end.
- Stinger / BKGD off: one Auto per drag (GUI latches after the first send;
  the server flip plus from/pickup ignore the rest).
- Auto flips the lever's end only once it has started.
- A held lever snaps within 2 % of either end.
- GUI: the handle resyncs to the mixer after a drag that did not complete
  (also when the pointer capture is lost); newest-wins send queue as
  createSender, tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01St7QwmonpoG9EEEqaLFXLi
- A lever without `from` counts only after pickup at the resting end, also
  while a transition is held; pickup is armed at start, on engine restart,
  on a loaded state and on each change of the end; several hardware levers
  are told apart by `source`.
- A `from` that is not the resting end is ignored also while something is
  held.
- Ignored values answer {status: "ignored", reason: stale_from|pickup}
  (logged at debug).
- GUI: each queued lever value keeps the `from` of its own drag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01St7QwmonpoG9EEEqaLFXLi
@LeeO86
LeeO86 merged commit 0615e84 into dev Oct 23, 2026
4 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.

1 participant