Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: eliminate ALL let* locals in native notepat — pure defvars

Convert dw, dh, scale, sw, sh, display to *np-* defvars too.
SBCL standalone binary loses every lexical binding through
unwind-protect. No more let* — everything is defvar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+54 -47
+54 -47
fedac/native/cl/main.lisp
··· 122 122 ;; Identity 123 123 (defvar *boot-handle* nil "Handle from config, set during boot splash.") 124 124 125 - ;; Native notepat runtime state (defvar to survive unwind-protect after save-lisp-and-die) 125 + ;; Native notepat runtime state (defvar — SBCL standalone loses let* locals) 126 + (defvar *np-dw* 0) 127 + (defvar *np-dh* 0) 128 + (defvar *np-scale* 1) 129 + (defvar *np-sw* 0) 130 + (defvar *np-sh* 0) 126 131 (defvar *np-screen* nil) 127 132 (defvar *np-graph* nil) 128 133 (defvar *np-input* nil) 129 134 (defvar *np-audio* nil) 130 135 (defvar *np-frame* 0) 136 + (defvar *np-display* nil) 131 137 132 138 ;; Network 133 139 (defvar *ip-address* "") ··· 336 342 337 343 (init-key-note-map) 338 344 339 - (let ((display (handler-case (ac-native.drm:drm-init) 340 - (error (e) 341 - (format *error-output* "[notepat] DRM error: ~A~%" e) 342 - (force-output *error-output*) nil)))) 343 - (unless display 344 - (format *error-output* "[notepat] FATAL: no display~%") 345 - (force-output *error-output*) (sleep 30) (return-from main 1)) 345 + (setf *np-display* (handler-case (ac-native.drm:drm-init) 346 + (error (e) 347 + (format *error-output* "[notepat] DRM error: ~A~%" e) 348 + (force-output *error-output*) nil))) 349 + (unless *np-display* 350 + (format *error-output* "[notepat] FATAL: no display~%") 351 + (force-output *error-output*) (sleep 30) (return-from main 1)) 346 352 347 - (let* ((dw (ac-native.drm:display-width display)) 348 - (dh (ac-native.drm:display-height display)) 349 - (scale (compute-pixel-scale dw)) 350 - (sw (floor dw scale)) 351 - (sh (floor dh scale))) 352 - (setf *np-screen* (fb-create sw sh) 353 - *np-graph* (make-graph :fb *np-screen* :screen *np-screen*) 354 - *np-input* (ac-native.input:input-init dw dh scale) 355 - *np-audio* (ac-native.audio:audio-init) 356 - *np-frame* 0) 353 + (setf *np-dw* (ac-native.drm:display-width *np-display*) 354 + *np-dh* (ac-native.drm:display-height *np-display*) 355 + *np-scale* (compute-pixel-scale *np-dw*) 356 + *np-sw* (floor *np-dw* *np-scale*) 357 + *np-sh* (floor *np-dh* *np-scale*) 358 + *np-screen* (fb-create *np-sw* *np-sh*) 359 + *np-graph* (make-graph :fb *np-screen* :screen *np-screen*) 360 + *np-input* (ac-native.input:input-init *np-dw* *np-dh* *np-scale*) 361 + *np-audio* (ac-native.audio:audio-init) 362 + *np-frame* 0) 363 + (progn 357 364 358 365 (format *error-output* "[notepat] ~Dx~D scale:~D → ~Dx~D~%" 359 - dw dh scale sw sh) 366 + *np-dw* *np-dh* *np-scale* *np-sw* *np-sh*) 360 367 (format *error-output* "[notepat] audio: ~A~%" 361 368 (if *np-audio* "OK" "FAILED")) 362 369 (force-output *error-output*) ··· 384 391 (return))) 385 392 ;; Paint splash 386 393 (graph-wipe *np-graph* (make-color :r 10 :g 12 :b 18)) 387 - (let ((cy (floor sh 3))) 394 + (let ((cy (floor *np-sh* 3))) 388 395 (if has-handle 389 396 (progn 390 397 ;; Greeting 391 398 (graph-ink *np-graph* (make-color :r 140 :g 160 :b 200 :a 220)) 392 399 (font-draw *np-graph* greeting 393 - (- (floor sw 2) (floor (font-measure greeting) 2)) cy) 400 + (- (floor *np-sw* 2) (floor (font-measure greeting) 2)) cy) 394 401 ;; @handle 395 402 (let ((htxt (format nil "@~A" handle))) 396 403 (graph-ink *np-graph* (make-color :r 80 :g 255 :b 140 :a 255)) 397 404 (font-draw *np-graph* htxt 398 - (- (floor sw 2) (floor (font-measure htxt) 2)) (+ cy 14))) 405 + (- (floor *np-sw* 2) (floor (font-measure htxt) 2)) (+ cy 14))) 399 406 ;; Subtitle 400 407 (graph-ink *np-graph* (make-color :r 80 :g 80 :b 100 :a 160)) 401 408 (font-draw *np-graph* "aesthetic.computer" 402 - (- (floor sw 2) (floor (font-measure "aesthetic.computer") 2)) (+ cy 32))) 409 + (- (floor *np-sw* 2) (floor (font-measure "aesthetic.computer") 2)) (+ cy 32))) 403 410 (progn 404 411 ;; No handle: just show name 405 412 (graph-ink *np-graph* (make-color :r 80 :g 255 :b 140 :a 255)) 406 413 (font-draw *np-graph* "aesthetic.computer" 407 - (- (floor sw 2) (floor (font-measure "aesthetic.computer") 2)) cy) 414 + (- (floor *np-sw* 2) (floor (font-measure "aesthetic.computer") 2)) cy) 408 415 (graph-ink *np-graph* (make-color :r 140 :g 160 :b 200 :a 180)) 409 416 (font-draw *np-graph* "notepat" 410 - (- (floor sw 2) (floor (font-measure "notepat") 2)) (+ cy 18))))) 417 + (- (floor *np-sw* 2) (floor (font-measure "notepat") 2)) (+ cy 18))))) 411 418 ;; Build name (bottom center) 412 419 (graph-ink *np-graph* (make-color :r 60 :g 60 :b 80 :a 120)) 413 420 (font-draw *np-graph* *build-name* 414 - (- (floor sw 2) (floor (font-measure *build-name*) 2)) (- sh 20)) 421 + (- (floor *np-sw* 2) (floor (font-measure *build-name*) 2)) (- *np-sh* 20)) 415 422 ;; LISP tag (top right) when CL variant 416 423 (when (string= *build-variant* "cl") 417 424 (graph-ink *np-graph* (make-color :r 255 :g 200 :b 80 :a 200)) 418 - (font-draw *np-graph* "LISP" (- sw (font-measure "LISP") 6) 6))) 419 - (ac-native.drm:drm-present display *np-screen* scale) 425 + (font-draw *np-graph* "LISP" (- *np-sw* (font-measure "LISP") 6) 6))) 426 + (ac-native.drm:drm-present *np-display* *np-screen* *np-scale*) 420 427 (frame-sync-60fps))) 421 428 422 429 ;; Start Swank server for remote REPL ··· 629 636 (note-idx (or (position note-name *chromatic* :test #'string=) 0)) 630 637 (semi (+ (* (- oct 1) 12) note-idx)) 631 638 (total-semitones (* 9 12)) 632 - (bar-h (max 2 (floor (- sh 30) total-semitones))) 633 - (bar-y (+ 14 (floor (* semi (- sh 30)) total-semitones))) 634 - (bar-w (max 1 (floor (* val sw)))) 635 - (bar-x (floor (- sw bar-w) 2)) 639 + (bar-h (max 2 (floor (- *np-sh* 30) total-semitones))) 640 + (bar-y (+ 14 (floor (* semi (- *np-sh* 30)) total-semitones))) 641 + (bar-w (max 1 (floor (* val *np-sw*)))) 642 + (bar-x (floor (- *np-sw* bar-w) 2)) 636 643 (alpha (max 1 (min 255 (floor (* val 200)))))) 637 644 (graph-ink *np-graph* (make-color :r (first rgb) 638 645 :g (second rgb) ··· 650 657 (note-idx (or (position note-name *chromatic* :test #'string=) 0)) 651 658 (semi (+ (* (- oct 1) 12) note-idx)) 652 659 (total-semitones (* 9 12)) 653 - (bar-h (max 2 (floor (- sh 30) total-semitones))) 654 - (bar-y (+ 14 (floor (* semi (- sh 30)) total-semitones)))) 660 + (bar-h (max 2 (floor (- *np-sh* 30) total-semitones))) 661 + (bar-y (+ 14 (floor (* semi (- *np-sh* 30)) total-semitones)))) 655 662 (graph-ink *np-graph* (make-color :r (min 255 (+ (first rgb) 40)) 656 663 :g (min 255 (+ (second rgb) 40)) 657 664 :b (min 255 (+ (third rgb) 40)) 658 665 :a 220)) 659 - (graph-box *np-graph* 0 bar-y sw bar-h))) 666 + (graph-box *np-graph* 0 bar-y *np-sw* bar-h))) 660 667 *active-notes*) 661 668 662 669 ;; ── Metronome pendulum ── 663 670 (when *metronome-on* 664 - (let* ((cx (floor sw 2)) 665 - (cy (- sh 24)) 666 - (arm-len (min 20 (floor sh 8))) 671 + (let* ((cx (floor *np-sw* 2)) 672 + (cy (- *np-sh* 24)) 673 + (arm-len (min 20 (floor *np-sh* 8))) 667 674 (bx (+ cx (floor (* *metronome-phase* arm-len)))) 668 675 (bright (floor (* *metronome-flash* 255)))) 669 676 ;; Arm line ··· 676 683 (graph-circle *np-graph* bx (- cy arm-len) 3))) 677 684 678 685 ;; ── Wave type indicators (bottom bar) ── 679 - (let* ((bar-y (- sh 14)) 680 - (btn-w (max 12 (floor sw 6))) 686 + (let* ((bar-y (- *np-sh* 14)) 687 + (btn-w (max 12 (floor *np-sw* 6))) 681 688 (gap 2) 682 689 (total-w (+ (* 5 btn-w) (* 4 gap))) 683 - (start-x (floor (- sw total-w) 2))) 690 + (start-x (floor (- *np-sw* total-w) 2))) 684 691 (dotimes (i 5) 685 692 (let* ((bx (+ start-x (* i (+ btn-w gap)))) 686 693 (selected (= i *wave-index*)) ··· 731 738 ;; FPS (top-right) 732 739 (let ((fps-txt (format nil "~D" *fps-display*))) 733 740 (graph-ink *np-graph* (make-color :r 80 :g 80 :b 90 :a 120)) 734 - (font-draw *np-graph* fps-txt (- sw (* (length fps-txt) 6) 3) 3)) 741 + (font-draw *np-graph* fps-txt (- *np-sw* (* (length fps-txt) 6) 3) 3)) 735 742 736 743 ;; Voice count (top-right, below FPS) 737 744 (let ((vc (hash-table-count *active-voices*))) 738 745 (when (> vc 0) 739 746 (let ((txt (format nil "~Dv" vc))) 740 747 (graph-ink *np-graph* (make-color :r 200 :g 200 :b 200 :a 180)) 741 - (font-draw *np-graph* txt (- sw (* (length txt) 6) 3) 14)))) 748 + (font-draw *np-graph* txt (- *np-sw* (* (length txt) 6) 3) 14)))) 742 749 743 750 ;; IP + Swank (top center) 744 751 (when (> (length *ip-address*) 0) 745 752 (let ((txt (format nil "~A:4005" *ip-address*))) 746 753 (graph-ink *np-graph* (make-color :r 60 :g 180 :b 60 :a 160)) 747 - (font-draw *np-graph* txt (- (floor sw 2) (floor (font-measure txt) 2)) 3))) 754 + (font-draw *np-graph* txt (- (floor *np-sw* 2) (floor (font-measure txt) 2)) 3))) 748 755 749 756 ;; Refresh IP every ~5 seconds 750 757 (when (zerop (mod *np-frame* 300)) (refresh-ip)) 751 758 752 759 ;; ── Present ── 753 - (ac-native.drm:drm-present display *np-screen* scale) 760 + (ac-native.drm:drm-present *np-display* *np-screen* *np-scale*) 754 761 (frame-sync-60fps)) 755 762 756 763 ;; ── Cleanup ── ··· 758 765 (when *np-audio* (ignore-errors (audio-destroy *np-audio*))) 759 766 (when *np-input* (ignore-errors (ac-native.input:input-destroy *np-input*))) 760 767 (when *np-screen* (ignore-errors (fb-destroy *np-screen*))) 761 - (ignore-errors (ac-native.drm:drm-destroy display)) 768 + (ignore-errors (ac-native.drm:drm-destroy *np-display*)) 762 769 (format *error-output* "[notepat] shutdown~%") 763 - (force-output *error-output*)))) 770 + (force-output *error-output*)))