how to load startup.scd path automatically on boot? i have the file, it gets interpreted without errors. i can execute it with load command, but i want to add that instruction to the supercollider boot sequence. how can i do that? cheers
i figured out. i have to edit the server class. i just donβt know exactly how. this is what i guessed
boot { | startAliveThread = true, recover = false, onFailure |
(...)
statusWatcher.doWhenBooted({
statusWatcher.serverBooting = false;
this.bootInit(recover);
Platform.userConfigDir +/+ "startup.scd";
}, onFailure: onFailure ? false);
(...)
}
however i have supercollider to discard changes automatically
As far as I know, the complete code blocks in the βstartup.scdβ file are automatically evaluated as soon as sclang is booted.
Code requiring server boot should be written inside s.waitForBoot { ... }.
This behaviour is independent of the IDE, as I observed it is the same when using VSCode and Vscodium.
So I think checking the server boot status is usually not required.
Could you refer to the following GitHub PR?
Additionally, if you want to register post-boot actions for the server so that they will run for any boot request (including ctrl- / cmd-B), there are:
(
ServerBoot.add { |server|
"this will happen after the server boots but before groups are created".postln;
server.dumpOSC(1);
};
ServerTree.add { |server|
"this happens after default groups are created and synthdefs are sent".postln;
};
)
s.boot;
Thatβs potentially risky β for one thing, your modifications would be lost when you upgrade the SC version.
Itβs also unnecessary, because SC already has user-facing bootup hooks.
BTW startup.scd should be for language startup actions. You shouldnβt need to repeat language startup actions when booting a server. I think you should keep your server boot stuff in a separate file. Then, in your language startup.scd:
ServerTree.add { |server|
thisProcess.interpreter.executeFile(
"/path/to/server-boot.scd",
server
)
};
Now any server boot process will load that file. Write arg server; at the top of the file so that the script knows which server object booted.
hjh
This snippet, based on @jamshark70βs idea from another discussion, is good for demonstration.
(
~remapConfig = IdentityDictionary[
0 -> 1,
1 -> 2,
2 -> 3,
3 -> 4,
4 -> 5,
5 -> 6,
6 -> 7,
7 -> 8,
8 -> 9,
9 -> 12,
10 -> 13,
11 -> 14,
12 -> 15,
13 -> 16,
14 -> 17
];
~generateRemapSynthDef = { |numInputChannels, numOutputChannels|
SynthDef(\remapOutputs, {
var sig = In.ar(0, numInputChannels);
var remapped = Array.fill(numOutputChannels, { Silent.ar(1) });
~remapConfig.keysValuesDo { |src, dest|
if (src < numInputChannels and: { dest < numOutputChannels }) {
remapped[dest] = sig[src];
}
};
ReplaceOut.ar(0, remapped);
}).add;
};
~generateRemapSynthDef.(16, 18);
)
(
~createRemapSynth = {
~remapSynth = Synth(\remapOutputs, target: s.defaultGroup, addAction: \addAfter);
};
ServerTree.add( ~createRemapSynth);
)
Hi everyone,
Iβm currently trying to run some older code that relies on Server.waitForBoot. To make this work smoothly in certain contexts, Iβve been experimenting with modifications to Server.sc.
I know thereβs already an open PR addressing this exact issue, and I really appreciate the effort that went into it! Thank you especially for pushing it forward and testing it so quickly.
Iβm not personally building nightly versions of SuperCollider on Windows, but Iβm very eager to see this change land in an official release. This behavior was actually shown to me years ago (around 2013) by Bas Gebbing at Sonology), and itβs always stuck with me as something that should βjust workβ out of the box.
Iβm really looking forward to the day this becomes part of the standard distribution.
Any idea when the next official SuperCollider release might be coming?
Thanks again for all the hard work, Cheers, T.
s.waitForBoot({
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 1. Start the four Ndefs (stereo output, nice crossfading)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[\a, \b, \c, \d].do { |name|
Ndef(name).play.fadeTime_(2); // 2-second crossfade feels great
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 2. Define the three banks in a compact way
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~bankTest = [
{ WhiteNoise.ar ! 2 },
{ BrownNoise.ar ! 2 },
{ PinkNoise.ar ! 2 },
{ GrayNoise.ar ! 2 },
{ ClipNoise.ar ! 2 }
];
// Helper that returns a random LFD noise ugen (mono)
~rndLFD = {
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose
.ar( rrand(1, 30) * [1, 10].choose ) // normal or MAX version
};
// Normal LFD bank (5 identical entries β just pick random each time)
~bankLFD = 5.collect {
{ [~rndLFD.(), ~rndLFD.()] } // always stereo, random each evaluation
};
// MAX version (10Γ faster rates)
~bankMAX = 5.collect {
{
var freq = rrand(1, 30) * 10;
[
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq),
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq)
]
}
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 3. Master random picker (chooses bank β chooses synth)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~pick = {
[~bankTest, ~bankLFD, ~bankMAX].choose.choose.value;
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 4. Handy functions you can call anytime
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~one = { Ndef( [\a,\b,\c,\d].choose, ~pick ).play; };
~all = { [\a,\b,\c,\d].do { |n| Ndef(n, ~pick).play; } };
~stop = { Ndef.clear(4) }; // gentle 4-second fade-out of all
~panic = { Ndef.all.do(_.end(0)) }; // hard kill if needed
"βΊ Noise drone system ready!
β ~one.() β change one random layer
β ~all.() β change everything
β ~stop.() β gentle stop
β ~panic.() β emergency kill".postln;
});
by the way, this is how my current supercollider startup.scd looks like, in a quick and short reply to prko. all the code was done by me from scratch but i revamped it with grok
I think you could use this code when removing () enclosing { ... } as follows:
s.waitForBoot {
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 1. Start the four Ndefs (stereo output, nice crossfading)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[\a, \b, \c, \d].do { |name|
Ndef(name).play.fadeTime_(2); // 2-second crossfade feels great
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 2. Define the three banks in a compact way
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~bankTest = [
{ WhiteNoise.ar ! 2 },
{ BrownNoise.ar ! 2 },
{ PinkNoise.ar ! 2 },
{ GrayNoise.ar ! 2 },
{ ClipNoise.ar ! 2 }
];
// Helper that returns a random LFD noise ugen (mono)
~rndLFD = {
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose
.ar( rrand(1, 30) * [1, 10].choose ) // normal or MAX version
};
// Normal LFD bank (5 identical entries β just pick random each time)
~bankLFD = 5.collect {
{ [~rndLFD.(), ~rndLFD.()] } // always stereo, random each evaluation
};
// MAX version (10Γ faster rates)
~bankMAX = 5.collect {
{
var freq = rrand(1, 30) * 10;
[
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq),
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq)
]
}
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 3. Master random picker (chooses bank β chooses synth)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~pick = {
[~bankTest, ~bankLFD, ~bankMAX].choose.choose.value;
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 4. Handy functions you can call anytime
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~one = { Ndef( [\a,\b,\c,\d].choose, ~pick ).play; };
~all = { [\a,\b,\c,\d].do { |n| Ndef(n, ~pick).play; } };
~stop = { Ndef.clear(4) }; // gentle 4-second fade-out of all
~panic = { Ndef.all.do(_.end(0)) }; // hard kill if needed
"βΊ Noise drone system ready!
β ~one.() β change one random layer
β ~all.() β change everything
β ~stop.() β gentle stop
β ~panic.() β emergency kill".postln;
}
As for me, I would enclose the whole code block with () as follows:
(
s.waitForBoot {
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 1. Start the four Ndefs (stereo output, nice crossfading)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
[\a, \b, \c, \d].do { |name|
Ndef(name).play.fadeTime_(2); // 2-second crossfade feels great
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 2. Define the three banks in a compact way
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~bankTest = [
{ WhiteNoise.ar ! 2 },
{ BrownNoise.ar ! 2 },
{ PinkNoise.ar ! 2 },
{ GrayNoise.ar ! 2 },
{ ClipNoise.ar ! 2 }
];
// Helper that returns a random LFD noise ugen (mono)
~rndLFD = {
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose
.ar( rrand(1, 30) * [1, 10].choose ) // normal or MAX version
};
// Normal LFD bank (5 identical entries β just pick random each time)
~bankLFD = 5.collect {
{ [~rndLFD.(), ~rndLFD.()] } // always stereo, random each evaluation
};
// MAX version (10Γ faster rates)
~bankMAX = 5.collect {
{
var freq = rrand(1, 30) * 10;
[
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq),
[LFDNoise0, LFDNoise1, LFDNoise3, LFDClipNoise].choose.ar(freq)
]
}
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 3. Master random picker (chooses bank β chooses synth)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~pick = {
[~bankTest, ~bankLFD, ~bankMAX].choose.choose.value;
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 4. Handy functions you can call anytime
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
~one = { Ndef( [\a,\b,\c,\d].choose, ~pick ).play; };
~all = { [\a,\b,\c,\d].do { |n| Ndef(n, ~pick).play; } };
~stop = { Ndef.clear(4) }; // gentle 4-second fade-out of all
~panic = { Ndef.all.do(_.end(0)) }; // hard kill if needed
"βΊ Noise drone system ready!
β ~one.() β change one random layer
β ~all.() β change everything
β ~stop.() β gentle stop
β ~panic.() β emergency kill".postln;
}
)
I believe you donβt need to change any SC files.
There are, however, some details missing from this request, such that, in its current form, nobody can act on it.
ββ¦ thereβs already an open PRβ¦β Which PR?
ββ¦ modifications to Server.scβ¦β Which modifications? (There is one modification listed in an earlier post, but that was βthis doesnβt work, how to fix it?β which wouldnβt be suitable for a PR. So I have to assume you mean a different modification, but, no other detail is given so I canβt begin to guess.)
ββ¦ something that should βjust workβ out of the box.β Feature requests are, of course, welcome, but there isnβt anything concrete to evaluate here. What should βjust workβ?
There are already two persistent server boot hooks:
- ServerBoot β run a function immediately after the server is ready for commands, but before default groups are up
- ServerTree β run a function after default groups have been created
The purpose of these is to make it easy for users to customize the server boot sequence without needing to modify the class library.
So thereβs a claim in this thread that the existing mechanisms donβt meet your requirement. Thatβs a fair claim to evaluate, but no specifics have been provided about what it is you need to do that isnβt supported by ServerBoot or ServerTree. Without anything concrete to evaluate, thereβs no action to be taken.
hjh
Hi @jamshark70 , @prko
Iβve noticed that the documentation could be more comprehensive. Perhaps a resource/blog post or a PR could highlight some βreal-worldβ problems that ServerBoot and ServerTree effectively solve.
Thank you for sharing your opinion.
I attempted to add some examples relating to ServerBoot and ServerTree, but the developers did not accept them:
However, that pull request is not directly relevant to the issue under discussion in this thread.
I would be grateful if you could suggest more concrete improvements to the following PR:
Add Guide to .scd File Evaluation and Execution: AutoRun, Load, CLI Methods, etc by prko Β· Pull Request #7272 Β· supercollider/supercollider Β· GitHub.
A direct change would be even more welcome!
Sure, thereβs plenty of room for that. These help files are indeed a bit thin.
hjh