← Commit history

0.9.291: kicad_demo adopts the ab 2.1.17 demo-panel contract: the first show passes eventCallbackUrl (loopback POST /demo/event on the bridge's own port) so a press lands the instant it is clicked; mute/unmute silence or replay the beat's narration at once; pause/stop silence at once and apply at the beat boundary; stage-advance shows send only the stage so a user's pause or mute is never undone; the poll stays as backstop and skips presses already delivered. The tour now foregrounds each beat's window exactly once (John: the user must see which window is being demoed, but keeps full control between beats); no persistent focus guardian during the tour. One short ab caption per beat stays.

John Lauer ·8c8c4ba60b ·1mo ago ·parent 154ff54
1 file changed +20
server.py+20
@@ -91,6 +91,7 @@ import plugin_install import caller_identity  DEFAULT_PORT = 8772+BOUND = {"host": "127.0.0.1", "port": None}   # set once the HTTP server binds (demo panel callbacks)   def _read_bridge_version() -> str:@@ -1502,6 +1503,24 @@ class KiCadBridgeHandler(BaseHTTPRequestHandler):         }      def do_POST(self):+        if self.path == "/demo/event":+            # ab 2.1.17 demo panel: every button press is POSTed here the+            # instant it is clicked ({id, button, at, state, stage, muted}),+            # loopback only (ab refuses non-loopback callback URLs). The poll+            # queue stays the backstop; this is the fast path so a pause lands+            # within the beat. No caller identity: the panel is the user's hand.+            n = int(self.headers.get("Content-Length", 0))+            raw = self.rfile.read(n) if n else b""+            try:+                ev = json.loads(raw or b"{}")+            except json.JSONDecodeError:+                ev = {}+            try:+                from handlers.demo import on_panel_event+                self._respond(200, {"ok": True, **(on_panel_event(ev) or {})})+            except Exception as e:  # pylint: disable=broad-except+                self._respond(200, {"ok": False, "error": f"{type(e).__name__}: {e}"})+            return         if self.path != "/command":             self._respond(404, {"error": "Not found"})             return@@ -1705,6 +1724,7 @@ def main():     bind_host = os.environ.get("ADOM_BIND_HOST", "127.0.0.1")     try:         server = _SingleInstanceHTTPServer((bind_host, port), KiCadBridgeHandler)+        BOUND["host"], BOUND["port"] = bind_host, port   # demo panel callback URL is built from this     except OSError as e:         print(f"[KiCad Bridge] Port {port} already in use ({e}). "               f"Another bridge instance owns it — exiting cleanly (single-instance guard).")