Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145#!/usr/bin/env node// ableton-tiny.mjs — shrink Ableton Live to a tiny concern: small UI zoom + small window.//// node ableton-tiny.mjs # every mapped host: 50% zoom, 560x380 window// node ableton-tiny.mjs blueberry # just blueberry// node ableton-tiny.mjs neo --zoom 75 --size 720x480// node ableton-tiny.mjs blueberry --reset # back to 100% zoom, roomy 1200x800 window//// Live 12's UI scale is Settings > Display & Input > Zoom (50-200%, native). Like the theme// sliders, it rejects `set value` but honours AXIncrement/AXDecrement in steps of 1, so this// drives it over Accessibility. The window is then resized directly. Companion to// ableton-theme.mjs (colour) — same requirements: Live must be RUNNING and the Mac UNLOCKED,// and the zoom lives in Preferences.cfg, so an ableton-sync.sh run carries the source's zoom to// the target; re-run this afterwards.import { execFile } from "node:child_process";import { promisify } from "node:util";const run = promisify(execFile);
const HOSTS = ["neo", "blueberry"];// 720x579 is Live's actual minimum window at 50% zoom — measured by asking for {1,1} and reading// back what it clamped to. Anything smaller is silently ignored, so this IS "as small as possible".// Zoom's own floor is 50%. Ask for less than either and you just get these numbers back.const TINY = { zoom: 50, w: 720, h: 579 };const ROOMY = { zoom: 100, w: 1200, h: 800 };
// Sets Zoom (Display page) then resizes the main window. args: zoom width heightconst SCPT = `on run argv set targetZoom to (item 1 of argv) as number set winW to (item 2 of argv) as number set winH to (item 3 of argv) as number tell application "Ableton Live 12 Suite" to activate delay 1 tell application "System Events" tell process "Live" my dismissModal() if not (exists window "Settings") then click menu item "Settings..." of menu 1 of menu bar item "Live" of menu bar 1 delay 2 end if tell window "Settings" click radio button 1 of radio group 1 of group 1 delay 1 my drive(group "Display, Language, and Input Settings" of group 1, "Zoom", targetZoom) end tell key code 53 delay 0.5 set out to "zoom=" & targetZoom & " " repeat with w in windows if name of w is not "Settings" then try set position of w to {60, 60} set size of w to {winW, winH} set out to out & "window=" & winW & "x" & winH on error e set out to out & "resize failed: " & e end try end if end repeat return out end tell end tellend run
on drive(g, sliderName, target) tell application "System Events" set sl to missing value repeat with s in sliders of g if description of s is sliderName then set sl to s end repeat if sl is missing value then return set v to value of sl set guard to 0 repeat while (v < target) and (guard < 400) perform action "AXIncrement" of sl set v to value of sl set guard to guard + 1 end repeat repeat while (v > target) and (guard < 400) perform action "AXDecrement" of sl set v to value of sl set guard to guard + 1 end repeat end tellend drive
-- Live's global alerts ("Audio is disabled...") are app-modal and BLOCK every other AX call, so-- anything that runs before them just hangs. They are not addressable as a normal dialog either-- (\`button "OK" of window 1\` errors -1728) — the OK sits at button 1 of group 1 of window 1.on dismissModal() tell application "System Events" tell process "Live" try if exists (button 1 of group 1 of window 1) then click button 1 of group 1 of window 1 delay 0.5 end if end try end tell end tellend dismissModal`;
const ssh = (host, cmd) => run("ssh", ["-o", "ConnectTimeout=8", host, cmd], { maxBuffer: 1 << 22 });
async function liveRunning(host) { const { stdout } = await ssh( host, `osascript -e 'tell application "System Events" to return (exists process "Live")'`, ); return stdout.trim() === "true";}
const argv = process.argv.slice(2);const flag = (n) => argv.includes(n);const valueOf = (n) => (argv.includes(n) ? argv[argv.indexOf(n) + 1] : null);const positional = argv.filter( (a, i) => !a.startsWith("--") && !["--zoom", "--size"].includes(argv[i - 1]),);
const base = flag("--reset") ? ROOMY : TINY;const zoom = valueOf("--zoom") ? Number(valueOf("--zoom")) : base.zoom;const [w, h] = valueOf("--size") ? valueOf("--size").split("x").map(Number) : [base.w, base.h];const hosts = positional.length ? [positional[0]] : HOSTS;
const b64 = Buffer.from(SCPT).toString("base64");for (const host of hosts) { console.log(`=== ${host} ===`); try { if (!(await liveRunning(host))) { console.log(" ✗ Live is not running (or the Mac is locked) — start it and re-run"); continue; } const { stdout } = await ssh( host, `printf %s '${b64}' | base64 -d > /tmp/ac-ableton-tiny.scpt && ` + `osascript /tmp/ac-ableton-tiny.scpt ${zoom} ${w} ${h}`, ); console.log(` ✓ ${stdout.trim()}`); } catch (err) { console.log(` ✗ ${err.message.split("\n")[0]}`); }}