diff --git a/sound_algo/data_only/matrix.scd b/sound_algo/data_only/matrix.scd index 0862e49..01dcb58 100644 --- a/sound_algo/data_only/matrix.scd +++ b/sound_algo/data_only/matrix.scd @@ -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 -- diff --git a/sound_algo/data_only/matrix_presets/test_matnames.scd b/sound_algo/data_only/matrix_presets/test_matnames.scd new file mode 100644 index 0000000..27016b9 --- /dev/null +++ b/sound_algo/data_only/matrix_presets/test_matnames.scd @@ -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; +)