fix(matrix): persist user saves in load list

This commit is contained in:
L'électron rare
2026-06-30 09:12:04 +02:00
parent f6b350a35c
commit af55f8a145
2 changed files with 48 additions and 20 deletions
+19 -20
View File
@@ -492,28 +492,27 @@ File.exists(~matDir).not.if({ ("mkdir -p " ++ ~matDir.quote).systemCmd });
// Other dirs (e.g. shipped presets): scan via ls+tmpfile (systemCmd is
// synchronous and works headless; pathMatch/Pipe.getLine are unreliable).
~matNames = { |dir|
(dir == ~matDir).if({
~matSavedNames.asArray
}, {
var ext = ".matrix";
var result = [];
File.exists(dir).if({
var tmp = "/tmp/_av_live_matnames_.txt";
("ls -1 '" ++ dir ++ "' > '" ++ tmp ++ "' 2>/dev/null").systemCmd;
File.exists(tmp).if({
var content = File.use(tmp, "r", { |f| f.readAllString });
("rm -f '" ++ tmp ++ "'").systemCmd;
content.split($\n).do({ |fn|
(fn.size > ext.size and: {
fn.copyRange(fn.size - ext.size, fn.size - 1) == ext
}).if({
result = result.add(fn.copyRange(0, fn.size - ext.size - 1).asSymbol)
})
var ext = ".matrix";
var result = [];
File.exists(dir).if({
var tmp = "/tmp/_av_live_matnames_.txt";
("ls -1 '" ++ dir ++ "' > '" ++ tmp ++ "' 2>/dev/null").systemCmd;
File.exists(tmp).if({
var content = File.use(tmp, "r", { |f| f.readAllString });
("rm -f '" ++ tmp ++ "'").systemCmd;
content.split($\n).do({ |fn|
(fn.size > ext.size and: {
fn.copyRange(fn.size - ext.size, fn.size - 1) == ext
}).if({
result = result.add(fn.copyRange(0, fn.size - ext.size - 1).asSymbol)
})
})
});
result
})
})
});
// user dir: union the disk scan with in-memory saves (covers a just-saved
// name even if the fs scan races); other dirs: pure disk scan.
(dir == ~matDir).if({ result = (result ++ ~matSavedNames.asArray).as(Set).asArray });
result
};
// -- ~matGridPush : send full 512-int grid row-major to surfaces --
@@ -0,0 +1,29 @@
// Headless checks for ~matNames disk persistence + ~matWrapStep queued load.
// Run: /Applications/SuperCollider.app/Contents/MacOS/sclang test_matnames.scd
(
var feat = PathName(thisProcess.nowExecutingPath).pathOnly ++ "../matrix.scd";
var pass = true, dir, nm;
~lp = (clock: TempoClock.default); ~toscSend = { |path ...a| }; ~toscTouch = { |a| };
["kick","hats","clap","perc","sub","acid","arp","lead","stab","pad","ride","rim",
"tom","reese","bells","sweep","melody","chord","fx","snare","crash","shaker"].do { |v|
Pdef(("lp_" ++ v).asSymbol, Pbind(\instrument, v.asSymbol, \dur, 1)) };
feat.load;
// -- Part A: a .matrix on disk in ~matDir is listed even with an empty Set --
dir = ~matDir; ("mkdir -p '" ++ dir ++ "'").systemCmd;
File.use(dir +/+ "zz_persist_test.matrix", "w", { |f| f.write("('grid':[])") });
~matSavedNames = Set.new; // simulate a fresh boot (no in-memory saves)
nm = ~matNames.(dir);
nm.includes(\zz_persist_test).not.if({ pass = false; "FAIL: ~matNames missed disk file".postln });
("rm -f '" ++ (dir +/+ "zz_persist_test.matrix") ++ "'").systemCmd;
// -- Part B: ~matWrapStep applies a queued load and clears the queue --
~lp[\matrix] = Array.fill(~matVoices.size, { Array.fill(~matBars, 0) });
~matQueuedLoad = "techno_drive_live";
~matWrapStep.();
(~matQueuedLoad.isNil).not.if({ pass = false; "FAIL: queue not cleared after wrap".postln });
(~lp[\matrix].flatten.sum == 0).if({ pass = false; "FAIL: queued preset not loaded".postln });
pass.if({ "MATNAMES PASS".postln }, { "MATNAMES FAIL".postln });
0.exit;
)