Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251#!/usr/bin/env node
import fs from "fs";import { SaxesParser } from "saxes";
class AbletonSessionParser { constructor() { this.tracks = []; this.currentTrack = null; this.currentClip = null; this.currentElement = ""; this.currentText = ""; this.tempo = 120; }
parseFile(filePath) { const data = fs.readFileSync(filePath, "utf8"); const parser = new SaxesParser({ fragment: false });
parser.on("opentag", (tag) => { this.currentElement = tag.name; if (tag.name === "GroupTrack" || tag.name === "AudioTrack" || tag.name === "MidiTrack") { this.currentTrack = { name: "Track", clips: [], id: tag.attributes?.Id?.value }; } else if (tag.name === "ClipSlot" || tag.name === "GroupTrackSlot") { this.currentClip = { id: tag.attributes?.Id?.value, hasClip: false, name: "", length: 0, activity: 0, color: 0 }; } else if (tag.name === "AudioClip" || tag.name === "MidiClip") { if (this.currentClip) { this.currentClip.hasClip = true; this.currentClip.id = tag.attributes?.Id?.value; this.currentClip.length = parseFloat(tag.attributes?.Length?.value || 1); } } });
parser.on("text", (text) => { this.currentText = text.trim(); });
parser.on("closetag", (tag) => { if (tag.name === "EffectiveName" && this.currentText) { if (this.currentTrack && !this.currentClip) { this.currentTrack.name = this.currentText; } } else if (tag.name === "ClipSlot" || tag.name === "GroupTrackSlot") { if (this.currentTrack && this.currentClip) { this.currentTrack.clips.push({ ...this.currentClip }); } this.currentClip = null; } else if (tag.name === "GroupTrack" || tag.name === "AudioTrack" || tag.name === "MidiTrack") { if (this.currentTrack) { this.tracks.push({ ...this.currentTrack }); } this.currentTrack = null; } this.currentText = ""; this.currentElement = ""; });
parser.write(data); parser.close();
return { tracks: this.tracks, tempo: this.tempo }; }}
class SimpleSessionVisualizer { constructor(sessionData) { this.tracks = sessionData.tracks; this.tempo = sessionData.tempo; this.isPlaying = true; this.beat = 0; this.trackActivity = new Map(); this.aggregateOutput = 0; // Initialize activity this.tracks.forEach((track, i) => { this.trackActivity.set(i, 0); });
this.startUpdateLoop(); }
clearScreen() { process.stdout.write('\x1B[2J\x1B[0f'); }
render() { this.clearScreen(); // Header const playIcon = this.isPlaying ? "▶" : "⏸"; const activeClips = this.getActiveClipCount(); console.log(`🎛 ${playIcon} Beat: ${this.beat.toFixed(1)} | ${this.tempo} BPM | Active: ${activeClips}`); console.log("━".repeat(60)); // Session Grid (simplified) console.log("Session Grid:"); for (let scene = 0; scene < 8; scene++) { let line = `${(scene + 1)} │ `; for (let t = 0; t < Math.min(this.tracks.length, 12); t++) { const track = this.tracks[t]; const clip = track.clips[scene]; const activity = this.trackActivity.get(t) || 0; if (clip && clip.hasClip) { const intensity = Math.min(Math.floor(activity / 25), 3); const symbols = ["▁", "▃", "▅", "█"]; line += `${symbols[intensity]} `; } else { line += "░ "; } } console.log(line); } console.log("━".repeat(60)); // Track Activity (condensed) console.log("Track Activity:"); for (let i = 0; i < Math.min(this.tracks.length, 8); i++) { const track = this.tracks[i]; const activity = this.trackActivity.get(i) || 0; const barLength = 20; const filled = Math.min(Math.floor((activity / 100) * barLength), barLength); const empty = barLength - filled; const trackName = track.name.length > 12 ? track.name.substring(0, 12) : track.name; const bar = "█".repeat(filled) + "░".repeat(empty); const percentage = Math.floor(activity); console.log(`${trackName.padEnd(12)} │${bar}│ ${percentage}%`); } // Aggregate const aggBar = "█".repeat(Math.floor(this.aggregateOutput / 2)) + "░".repeat(50 - Math.floor(this.aggregateOutput / 2)); console.log("━".repeat(60)); console.log(`Aggregate: │${aggBar}│ ${Math.floor(this.aggregateOutput)}%`); console.log("SPACE=pause, 1-8=scenes, T=trigger, Q=quit"); }
triggerScene(sceneIndex) { this.tracks.forEach((track, trackIndex) => { const clip = track.clips[sceneIndex]; if (clip && clip.hasClip) { const activity = 50 + Math.random() * 50; this.trackActivity.set(trackIndex, activity); } }); this.updateAggregateActivity(); }
updateAggregateActivity() { let total = 0; let count = 0; this.trackActivity.forEach((activity) => { if (activity > 0) { total += activity; count++; } }); this.aggregateOutput = count > 0 ? total / count : 0; }
getActiveClipCount() { let count = 0; this.trackActivity.forEach((activity) => { if (activity > 10) count++; }); return count; }
startUpdateLoop() { setInterval(() => { if (this.isPlaying) { this.beat += 0.3; // Fast beat progression }
// Decay activity this.trackActivity.forEach((activity, index) => { const newActivity = Math.max(0, activity - 4); // Fast decay this.trackActivity.set(index, newActivity); });
// Frequent random activity spikes if (Math.random() < 0.2) { const randomTrack = Math.floor(Math.random() * this.tracks.length); const currentActivity = this.trackActivity.get(randomTrack) || 0; const spike = Math.random() * 50; this.trackActivity.set(randomTrack, Math.min(100, currentActivity + spike)); }
// Auto-trigger scenes frequently if (Math.random() < 0.1) { const randomScene = Math.floor(Math.random() * 8); this.triggerScene(randomScene); }
this.updateAggregateActivity(); this.render(); }, 100); // Fast updates }}
// Handle keyboard inputprocess.stdin.setRawMode(true);process.stdin.resume();process.stdin.setEncoding('utf8');
process.stdin.on('data', (key) => { if (key === '\u0003' || key === 'q') { // Ctrl+C or Q process.exit(); }});
// Main executionconst xmlPath = process.argv[2] || "/workspaces/aesthetic-computer/system/public/assets/wipppps/zzzZWAP_extracted.xml";
if (!fs.existsSync(xmlPath)) { console.error(`XML file not found: ${xmlPath}`); console.error("Usage: node ableton-simple-viewer.mjs [path-to-extracted.xml]"); process.exit(1);}
console.log("🎵 Parsing Ableton Live project...");const parser = new AbletonSessionParser();const sessionData = parser.parseFile(xmlPath);
console.log(`📊 Found ${sessionData.tracks.length} tracks`);console.log(`🚀 Starting simple session viewer (auto-play)...`);
new SimpleSessionVisualizer(sessionData);