Hello,
Is there a specific reason why thisProcess. nowExecutingPath
, thisProcess. nowExecutingPath.dirname
, etc do not work with ServerBoot.add
?
A code example can be found here:
Hello,
Is there a specific reason why thisProcess. nowExecutingPath
, thisProcess. nowExecutingPath.dirname
, etc do not work with ServerBoot.add
?
A code example can be found here:
You need to evaluate thisProcess.nowExecutingPath
first, outside ServerBoot.add
(
var soundFolder = thisProcess.nowExecutingPath;// +/+ "BW2 Exports";
ServerBoot.add({
Buffer.freeAll; // I am not sure if it is necessary.
soundFolder.postln;
...
thisProcess.nowExecutingPath
returns the path to a file executing interactively by the interpreter.
when you call add
on ServerBoot
the function you pass as an argument is added to ServerBoot.objects
- when the server boots, that function is evaluated, but it is not evaluated interactively
Thank you very much!
I understand it word for word… However, I do not seem to really understand it because I have the following question:
Can interactivity be implemented in the future or not? Is it logical that the interpreter does not interactively evaluate the part of the code that belongs to ServerBoot.objects? Honestly, I thought it was a bug at first glance.
It’s inside a synchronous process (inside a Routine), so the language blocks the following message until the previous one is completed. With s.sync, it also ensures the server is ready.
Also remember, the server does seomthing, but you can’t forget the language, the one who is sending timed/scheduled messages to the server.
So this scheduling confusion you said is figured out by the language.
Kind of
yes looking into it further I’m not sure I have understood it correctly!
I tried doing:
ServerTree.add({thisProcess.dump})
and doing Cmd-.
and then comparing it to thisProcess.dump
you will see that the in one case the current thread is Main with the correct nowExecutingPath and in the other it is a Routine with nowExecutingPath = nil
I’m going to read around in AbstractServerAction Kernel Thread and Main to see if I can understand this better - I think that Thread sets its executingPath via a primitive _Thread_Init and it may be that that an nil value is what we are ending up with in this case
One question here is, what are the semantics of nowExecutingPath
?
I wanted to foreground this question because it’s being assumed that the first meaning is (“obviously”?) better. Maybe…? Probably…? But it might also not be quite so obvious.
If I create a file, say, “23-1217-nowexec-proto.scd”:
(
testFunction: {
thisProcess.nowExecutingPath
}
)
And a second file in the same location, “23-1217-nowexec-caller.scd”:
a = (thisProcess.nowExecutingPath.dirname +/+ "23-1217-nowexec-proto.scd").load;
a.testFunction;
… which path should be returned? “xxx-proto” or “xxx-caller”?
The current behavior is to return the caller’s path. From one point of view, that’s a stretch: the line of code accessing the current path is written into the “proto” file. But, you hit cmd-return in the caller file, and… maybe it’s useful to know that?
In any case, if it’s desired to refer always to the location where the function was defined, then I think the only solution is to move filenameSymbol
out of Method and into FunctionDef, and change the C++ compiler code to fill in this variable at compile time. Then the nowExecutingPath
method would have to trace back to the currently active FunctionDef.
(If a method calls nowExecutingPath, should it be the location where the method was defined, or the user code that called the method?)
Edit: Or perhaps keep both. If all functions are tagged with their path, then thisFunction.filenameSymbol
would (should…?) give you the location-where-defined, and it may not be necessary to change/break the current semantic of nowExecutingPath.
A Routine’s path is set at the moment of creation.
Has your ServerTree.add
code file created the routine that runs during server initialization?
Nope… so, how would the (internally-produced) Routine know about your file?
(I think the difference for Routines is that they last for a relatively long time, while Function execution is assumed to be instantaneous.)
In any case, it needs to be understood (and perhaps better documented) that nowExecutingPath
operates with a synchronous time scope. It gives you access to the current user-code path (not method definitions) within the block that is running synchronously in response to a cmd-return. If that block defines actions that will happen later, nowExecutingPath
does not cover this, except for Routines that are created synchronously within the block. If you need the path to be available for later operations, then (currently) it is the user’s responsibility to grab the path and stash it in a variable on their own.
hjh
thanks James that makes perfect sense
…indeed if I interpret
CmdPeriod.run
it does set nowExecutingPath
I made a PR based on this thread:
If there is anything I should revise, please let me know.
Thanks for your response and advice!
The evaluation of the following code blocks in a saved scd file shows inconsistent behaviour.
Using thisProcess.nowExecutingPath
with CmdPeriod
alone, it seems to be consistent:
Evaluate the following code to register a functionality:
(
f = {
("CmdPeriod’s thisProcess.nowExecutingPath:" + thisProcess.nowExecutingPath).postln
};
CmdPeriod.add(f)
)
Pressing command/control
+ .
returns (whether or not there is the startup.scd
file in Platform.userAppSupportDir
):
CmdPeriod’s thisProcess.nowExecutingPath: nil
Evaluate the following code to remove the registered functionality:
CmdPeriod.remove(f)
Repeating steps 1 to 3 shows always the same behaviour.
The following example shows the expected behaviour only when evaluated after starting SC-IDE (or when evaluated after restarting sclang after exiting sclang using 0.exit
). Repeating steps 1 to 2 again after step 3 returns nil
for the thisProcess.nowExecutingPath
, even though the startp.scd
exists:
Evaluate the following code to register the functionalities after launching SC-IDE:
(
CmdPeriod.add {
var path = thisProcess.nowExecutingPath;
("CmdPeriod’s thisProcess.nowExecutingPath:" + path).postln
};
ServerBoot.add {
var path = thisProcess.nowExecutingPath;
("ServerBoot’s thisProcess.nowExecutingPath:" + path).postln
};
ServerTree.add {
var path = thisProcess.nowExecutingPath;
("ServerTree’s thisProcess.nowExecutingPath:" + path).postln
};
s.reboot
)
After rebooting, post window’s last two lines are as follows if there is the startup.scd
file in Platform.userAppSupportDir
:
ServerBoot’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
ServerTree’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
Pressing command/control
+ .
returns the following if there is the startup.scd
file in Platform.userAppSupportDir
:
CmdPeriod’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
ServerTree’s thisProcess.nowExecutingPath: /Users/prko/Library/Application Support/SuperCollider/startup.scd
Evaluate the following code to remove the registered functionalities:
CmdPeriod.removeAll;ServerBoot.removeAll;ServerTree.removeAll
Evaluate the code in Step 1 of the Example 2 again. After rebooting, post window’s last two lines are as follows although there is the startup.scd
file in Platform.userAppSupportDir
:
ServerBoot’s thisProcess.nowExecutingPath: nil
ServerTree’s thisProcess.nowExecutingPath: nil
Pressing command/control
+ .
returns the following although there is the startup.scd
file in Platform.userAppSupportDir
:
CmdPeriod’s thisProcess.nowExecutingPath: nil
ServerTree’s thisProcess.nowExecutingPath: nil
I have the following questions:
cmd/control
+ .
behave differently in Example 1 and 2?I thought I understood, but today I am confused.
Thank you in advance.
nowExecutingPath
isn’t fully implemented for functions.
For it to be reliable, it needs to be written like this.
(
var thisPath = thisProcess.nowExecutingPath;
f = {
("CmdPeriod’s thisProcess.nowExecutingPath:" + thisPath).postln
};
CmdPeriod.add(f)
)
Otherwise the behavior is not guaranteed.
That is, it’s the cases where you got the executing path that I can’t explain. The ones where you didn’t get it show the behavior I’d expect.
hjh
Thank you!
I updated the PR: