Monorepo for Aesthetic.Computer aesthetic.computer
1
fork

Configure Feed

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

at main 189 lines 4.9 kB view raw
1#!/usr/bin/env node 2/** 3 * Automated Notepat Playlist Player 4 * 5 * Plays a playlist of folk and traditional melodies 6 */ 7 8import Artery from '../../artery/artery.mjs'; 9import { melodies, noteToKey } from './melodies.mjs'; 10 11const PURPLE_BG = '\x1b[45m'; 12const WHITE = '\x1b[97m'; 13const RESET = '\x1b[0m'; 14const GREEN = '\x1b[92m'; 15const CYAN = '\x1b[96m'; 16const YELLOW = '\x1b[93m'; 17 18const testLog = (msg) => console.log(`${PURPLE_BG}${WHITE}🧪${RESET} ${msg}`); 19const successLog = (msg) => console.log(`${GREEN}${msg}${RESET}`); 20const playingLog = (msg) => console.log(`${YELLOW}🎵 ${msg}${RESET}`); 21 22// Default playlist: all folk/traditional songs 23const defaultPlaylist = [ 24 'twinkle', 25 'mary', 26 'old-macdonald', 27 'yankee-doodle', 28 'frere-jacques', 29 'london-bridge', 30 'row-row-row', 31 'skip-to-my-lou', 32 'camptown-races', 33 'oh-susanna', 34 'amazing-grace', 35 'auld-lang-syne', 36 'shenandoah', 37 'home-on-the-range', 38 'red-river-valley', 39 'scarborough-fair', 40 'greensleeves', 41 'when-the-saints', 42 'danny-boy', 43 'ode-to-joy', 44 'jingle-bells', 45 'happy-birthday', 46]; 47 48async function playMelody(client, melodyName) { 49 const melody = melodies[melodyName]; 50 if (!melody) { 51 console.error(`Unknown melody: ${melodyName}`); 52 return 0; 53 } 54 55 playingLog(`Now playing: ${melodyName} (${melody.length} notes)`); 56 57 let notesPlayed = 0; 58 for (const {note, octave, duration} of melody) { 59 const key = noteToKey(note, octave); 60 const noteDisplay = `${note.toUpperCase()}${octave}`; 61 62 // Show the note being played 63 process.stdout.write(`${CYAN}${noteDisplay.padEnd(4)} ${RESET}`); 64 65 // Dispatch keydown 66 await client.send('Input.dispatchKeyEvent', { 67 type: 'keyDown', 68 text: key, 69 key: key, 70 code: `Key${key.toUpperCase()}`, 71 windowsVirtualKeyCode: key.charCodeAt(0) 72 }); 73 74 await new Promise(r => setTimeout(r, duration)); 75 76 // Dispatch keyup 77 await client.send('Input.dispatchKeyEvent', { 78 type: 'keyUp', 79 key: key, 80 code: `Key${key.toUpperCase()}`, 81 windowsVirtualKeyCode: key.charCodeAt(0) 82 }); 83 84 notesPlayed++; 85 86 // Line break every 8 notes 87 if (notesPlayed % 8 === 0) { 88 console.log(''); 89 } 90 91 // Small gap between notes 92 await new Promise(r => setTimeout(r, 50)); 93 } 94 95 if (notesPlayed % 8 !== 0) { 96 console.log(''); // Final line break 97 } 98 99 console.log(''); 100 return notesPlayed; 101} 102 103async function playPlaylist(playlist = defaultPlaylist) { 104 105 try { 106 console.log(''); 107 testLog(`Starting Notepat Playlist Player`); 108 playingLog(`Playlist: ${playlist.length} melodies`); 109 console.log(''); 110 111 // Ensure panel is open 112 await Artery.openPanelStandalone(); 113 await new Promise(resolve => setTimeout(resolve, 500)); 114 115 // Connect 116 const client = new Artery(); 117 await client.connect(); 118 testLog('Connected to AC'); 119 120 await client.jump('notepat'); 121 testLog('Navigated to notepat'); 122 123 // Wait for page to fully load and reconnect context 124 await new Promise(r => setTimeout(r, 2000)); 125 126 // Reconnect after navigation 127 client.close(); 128 await client.connect(); 129 testLog('Reconnected after navigation'); 130 await new Promise(r => setTimeout(r, 500)); 131 132 // Activate audio context 133 await client.activateAudio(); 134 testLog('Audio context activated'); 135 136 console.log(''); 137 console.log(`${CYAN}${'='.repeat(60)}${RESET}`); 138 console.log(''); 139 140 let totalNotes = 0; 141 let songsPlayed = 0; 142 143 // Play each melody in the playlist 144 for (const melodyName of playlist) { 145 const notesPlayed = await playMelody(client, melodyName); 146 totalNotes += notesPlayed; 147 songsPlayed++; 148 149 // Pause between songs 150 await new Promise(r => setTimeout(r, 1000)); 151 } 152 153 console.log(`${CYAN}${'='.repeat(60)}${RESET}`); 154 console.log(''); 155 successLog(`Playlist complete! Played ${songsPlayed} songs, ${totalNotes} total notes`); 156 console.log(''); 157 158 // Return to prompt 159 await client.jump('prompt'); 160 testLog('Returned to prompt'); 161 await new Promise(r => setTimeout(r, 500)); 162 163 // Close the AC panel 164 await Artery.closePanelStandalone(); 165 166 client.close(); 167 process.exit(0); 168 169 } catch (error) { 170 console.error(`💔 Playlist failed: ${error.message}`); 171 process.exit(1); 172 } 173} 174 175// Parse custom playlist from command line or use default 176const args = process.argv.slice(2); 177let playlist; 178 179if (args.length > 0) { 180 // Custom playlist from command line 181 playlist = args; 182 console.log(`${CYAN}🎵 Custom playlist: ${playlist.join(', ')}${RESET}`); 183} else { 184 // Use default playlist 185 playlist = defaultPlaylist; 186 console.log(`${CYAN}🎵 Playing all ${playlist.length} melodies${RESET}`); 187} 188 189playPlaylist(playlist);