authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-07-05 13:00:12-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-07-05 13:01:04-07:00
logdf4a98ec1ad2493896b0c50e5abf5f95402fa8e1
treefd028a49f6d9625c2b9290db794b8d51fecb5e10
parentefa2473ccc8ba2de27d5d8a7a0f9e62c3968deb5
signaturebadge-check Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU

fix recording button


2 files changed, 25 insertions(+), 28 deletions(-)

control/config/reaper.ts+5-4
......@@ -30,12 +30,13 @@ export default config.forApp(
3030 const recording = keypad.overlay((overlay) => {
3131 overlay.key("down-left", lucide("Save").fg("green"), () => {
3232 reaper.runAction("transport-stop-save-all-recorded-media");
33 reaper.runAction("transport-record");
3334 });
34 overlay.key("down", lucide("Redo").fg("green"), () => {
35 reaper.runAction("transport-stop-save-all-recorded-media");
35 overlay.key("down", lucide("Undo").fg("red"), () => {
36 reaper.runAction("transport-stop-delete-all-recorded-media");
3637 reaper.runAction("transport-record");
3738 });
38 overlay.key("down-right", lucide("Trash").fg("#ff6b6b"), () => {
39 overlay.key("down-right", lucide("Trash").fg("red"), () => {
3940 reaper.runAction("transport-stop-delete-all-recorded-media");
4041 });
4142 });
......@@ -67,7 +68,7 @@ export default config.forApp(
6768 });
6869
6970 dialpad.on("rotate", (delta) => {
70 console.log({delta})
71 console.log({ delta });
7172 reaper.runAction(
7273 delta > 0
7374 ? "tempo-increase-current-project-tempo-0-1-bpm"
control/src/icons.ts+20-24
......@@ -9,8 +9,8 @@
99//
1010// The result's `.svg` is what KeypadUI rasterizes to JPEG. Everything here is
1111// pure string building — no build step, no runtime SVG parsing beyond a trim.
12import type { MdiIcon } from "mdi-ts";
1312import * as lucideIcons from "lucide-static";
13import type { MdiIcon } from "mdi-ts";
1414import { readFileSync } from "node:fs";
1515import { createRequire } from "node:module";
1616import { dirname, join } from "node:path";
......@@ -33,7 +33,7 @@ const colorMap = {
3333 white: "#ffffff",
3434 grey: "#8a8a8a",
3535 gray: "#8a8a8a",
36 red: "#ff5a36",
36 red: "#ff6b6b",
3737 orange: "#ff9f43",
3838 amber: "#ffbf47",
3939 yellow: "#ffd23f",
......@@ -137,8 +137,7 @@ export class Icon implements Svg {
137137 return glyph(lucideInner(this.#source.name), this.#glyphSize(), {
138138 fill: "none",
139139 stroke: fg,
140 extra:
141 `stroke-width="2" stroke-linecap="round" stroke-linejoin="round"`,
140 extra: `stroke-width="2" stroke-linecap="round" stroke-linejoin="round"`,
142141 });
143142 case "mdi":
144143 return glyph(mdiInner(this.#source.name), this.#glyphSize(), {
......@@ -156,8 +155,8 @@ export class Icon implements Svg {
156155 fg,
157156 );
158157 case "blank":
159 return `<circle cx="${KEY_SIZE / 2}" cy="${KEY_SIZE / 2}" r="7" ` +
160 `fill="${BLANK_DOT}"/>`;
158 return `<circle cx="${KEY_SIZE / 2}" cy="${KEY_SIZE / 2}" r="7" `
159 + `fill="${BLANK_DOT}"/>`;
161160 }
162161 }
163162
......@@ -232,8 +231,8 @@ export const blank: Icon = new Icon({ kind: "blank" }, BLANK_BG);
232231
233232/** Wrap inner markup in a full key-sized document with a solid background. */
234233function wrapSvg(inner: string, bg: string): string {
235 return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${KEY_SIZE} ${KEY_SIZE}">` +
236 `<rect width="${KEY_SIZE}" height="${KEY_SIZE}" fill="${bg}"/>${inner}</svg>`;
234 return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${KEY_SIZE} ${KEY_SIZE}">`
235 + `<rect width="${KEY_SIZE}" height="${KEY_SIZE}" fill="${bg}"/>${inner}</svg>`;
237236}
238237
239238interface GlyphStyle {
......@@ -247,8 +246,8 @@ function glyph(inner: string, size: number, style: GlyphStyle): string {
247246 const offset = (KEY_SIZE - size) / 2;
248247 const scale = size / 24;
249248 const extra = style.extra ? ` ${style.extra}` : "";
250 return `<g transform="translate(${offset} ${offset}) scale(${scale})" ` +
251 `fill="${style.fill}" stroke="${style.stroke}"${extra}>${inner}</g>`;
249 return `<g transform="translate(${offset} ${offset}) scale(${scale})" `
250 + `fill="${style.fill}" stroke="${style.stroke}"${extra}>${inner}</g>`;
252251}
253252
254253const SANS_FONT = "Helvetica, Arial, sans-serif";
......@@ -276,9 +275,9 @@ function textAt(
276275): string {
277276 const family = style.family ?? SANS_FONT;
278277 const weight = style.weight ?? 600;
279 return `<text x="${x}" y="${y}" fill="${fg}" font-family="${family}" ` +
280 `font-size="${size}" font-weight="${weight}" text-anchor="middle" ` +
281 `dominant-baseline="central">${escapeXml(label)}</text>`;
278 return `<text x="${x}" y="${y}" fill="${fg}" font-family="${family}" `
279 + `font-size="${size}" font-weight="${weight}" text-anchor="middle" `
280 + `dominant-baseline="central">${escapeXml(label)}</text>`;
282281}
283282
284283function text(label: string, fg: string, size: number): string {
......@@ -291,11 +290,9 @@ const STACK_GAP = 6;
291290
292291/** Lay text lines out vertically, centered as a group. */
293292function stackInner(lines: readonly StackSpec[], fg: string): string {
294 const sizes = lines.map((line, index) =>
295 line.size ?? (index === 0 ? STACK_PRIMARY : STACK_SECONDARY)
296 );
297 const height = sizes.reduce((sum, size) => sum + size, 0) +
298 STACK_GAP * Math.max(0, lines.length - 1);
293 const sizes = lines.map((line, index) => line.size ?? (index === 0 ? STACK_PRIMARY : STACK_SECONDARY));
294 const height = sizes.reduce((sum, size) => sum + size, 0)
295 + STACK_GAP * Math.max(0, lines.length - 1);
299296 let top = (KEY_SIZE - height) / 2;
300297
301298 return lines
......@@ -330,15 +327,14 @@ function timeSignatureInner(
330327 let staff = "";
331328 for (let i = 0; i < STAFF_LINES; i += 1) {
332329 const y = top + i * STAFF_GAP;
333 staff += `<line x1="${STAFF_INSET}" y1="${y}" x2="${KEY_SIZE - STAFF_INSET}" ` +
334 `y2="${y}" stroke="${fg}" stroke-width="1.5" opacity="0.4"/>`;
330 staff += `<line x1="${STAFF_INSET}" y1="${y}" x2="${KEY_SIZE - STAFF_INSET}" `
331 + `y2="${y}" stroke="${fg}" stroke-width="1.5" opacity="0.4"/>`;
335332 }
336333 const style: TextStyle = { family: SERIF_FONT, weight: 700 };
337334 const numeral = TIMESIG_GLYPH;
338335 const middle = KEY_SIZE / 2;
339 const glyphs =
340 textAt(KEY_SIZE / 2, middle - TIMESIG_STACK_OFFSET, numerator, fg, numeral, style) +
341 textAt(KEY_SIZE / 2, middle + TIMESIG_STACK_OFFSET, denominator, fg, numeral, style);
336 const glyphs = textAt(KEY_SIZE / 2, middle - TIMESIG_STACK_OFFSET, numerator, fg, numeral, style)
337 + textAt(KEY_SIZE / 2, middle + TIMESIG_STACK_OFFSET, denominator, fg, numeral, style);
342338 return staff + glyphs;
343339}
344340
......@@ -350,7 +346,7 @@ function escapeXml(value: string): string {
350346 ? "&gt;"
351347 : char === "&"
352348 ? "&amp;"
353 : char === '"'
349 : char === "\""
354350 ? "&quot;"
355351 : "&apos;");
356352}