INScore Scripting Language
Introduction
INScore scripting language is based on a textual version of OSC messages, extended with variables, Javascript sections and Mathematical expressions. INScore scripts files are expected to carry a .inscore extension. You can drop them to the INScoreViewer application or to any opened INScore scene.
The application or scene state can be saved (using the save message) as files containing textual OSC messages. These files can be edited or created from scratch using any text editor.
Statements
An INScore file is a list of textual expressions. An expression is:
- a message: basically a textual OSC message extended to support URL like addresses and variables as parameters.
- a variable declaration.
- a javascript section that may generate messages as output.
- comments.
- an end marker '\inscoreend' to declare a script end. After the marker, the remaining part of the script will be ignored.
Messages and variables declarations must be followed by a semicolon that is used as statements separator.
Messages
Messages are basic OSC messages that support an OSC address extension scheme and relative addresses that are described below. Messages parameters can be replaced by variables that are evaluated at parsing level. Variables are described in section scriptvar.
Extended OSC addresses
OSC addresses can be extended to target other applications, including on other hosts.
Using the address extension scheme, a script may be designed to initialize an INScore scene and external applications as well, including on remote hosts.
Example Initializing a score and an external application listening on port 12000 and running on a remote host named host.adomain.net.
/ITL/scene/score set gmnf 'myscore.gmn';
host.adomain.net:12000/run 1;
Relative addresses
Relative addresses have been introduced to provide more flexibility in the score design process. A relative address starts with './'. It is evaluated in the context of the message receiver: a legal OSC address is dynamically constructed using the receiver address to prefix the relative address.
Example
the relative address ./score
addressed to /ITL/scene/layer
will be evaluted as /ITL/scene/layer/score
The receiver context may be:
- the INScore application address (i.e. /ITL) for messages enclosed in a file loaded at application level (using the load message addressed to the application) or for files dropped to the application or given as arguments of the INScoreViewer application.
- a scene address for messages enclosed in a file loaded at scene level (using the load message addressed to a scene) or for files or messages dropped to a scene window.
- any object address when the messages are passed as arguments of an eval message (see OSCMsg reference).
Example Using a set of messages in different contexts:
score = (
./score set gmn '[a f g]',
./score scale 2.
);
/ITL/scene/l1 eval $score;
/ITL/scene/l2 eval $score;
Note: Legal OSC addresses (i.e. addresses that start with '/') that are given as argument of an eval message are not affected by the address evaluation.
Types
The message parameters types are constrained by the OSC protocol: any parameter is converted to an OSC type (i.e. int32, float or string) at parsing level. A special attention must be given to strings in order to discriminate addresses and parameters. Strings intended as parameters must:
- be quoted, using single or double quotes. Note that an ambiguous quote included in a string can be escaped using a '\'.
- or avoid any special characters i.e. any other character than [_-a-zA-Z0-9].
Note: text objects are permissive with the above rules: spaces don't have to be quoted, they accept also numbers as input arguments (they are converted to strings).
Example Different string parameters
/ITL/scene/text set txt "Hello world"; # string including a space can be quoted
/ITL/scene/text set txt Hello world; # text objects support stream like parameters
/ITL/scene/img set file 'anImage.png'; # dots must be quoted too
/ITL/scene/foo set txt no_quotes_needed;
Variables
A variable declaration associates a name with a list of parameters or a list of messages. Parameters must follow the rules given in section scripttypes. They may include previously declared variables. A message list must be enclosed in parenthesis and a comma must be used as messages separator.
Example Variables declarations
color = 200 200 200;
colorwithalpha = $color 100; # using another variable
msgsvar= ( # a variable referring to a message list
localhost:7001/world "Hello world",
localhost:7001/world "how are you ?" );
A variable may be used in place of any message parameter. A reference to a variable must have the form $ident where ident is a previously declared variable. A variable is evaluated at parsing level and replaced by its content.
Example Using a variable to share a common position:
x = 0.5;
/ITL/scene/a x $x;
/ITL/scene/b x $x;
Variables can be used in interaction messages as well, which may also use the variables available from events context. To differentiate between a script and an interaction variable, the latter must be quoted to be passed as strings and to prevent their evaluation by the parser.
Example Using variables in interaction messages: $sx is evaluated at event occurrence and $y is evaluated at parsing level.
y = 0.5;
/ITL/scene/foo watch mouseDown (/ITL/scene/foo "$sx" $y);
Environnement variables
Environnement variables are predefined variables available in a script context. They provide information related to the current context. Current environment variables are:
- OSName: gives the current operating system name. The value is among "MacOS", "Windows", "Linux", "Android", "iOS" and "Web".
-
OSId : gives the current operating system as a numeric identifier. Returned value is (in alphabetic order):
-
1 for Android
- 2 for iOS
- 3 for Linux
- 4 for MacOS
- 5 for Windows
- 6 for the Web environment
Note: There is nothing to prevent overriding of an environment variable. It's the script responsibility to handle variable names collisions.
Message based parameters
A message parameter may also use the result of a get message as parameter specified like a message based variable. The message must be enclosed in parenthesis with a leading $ sign.
Example Displaying INScore version using a message parameter:
/ITL/scene/version set txt "INScore version is" $(/ITL get version);
Note: Message based parameters are evaluated by the parser. Thus when the system state is modified by a script before a message parameter, these modifications won't be visible at the time of the parameter evaluation because all the messages will be processed by the next time task. For example:
/ITL/scene/obj x 0.1;
/ITL/scene/foo x $(/ITL/scene/foo get x);
x position of /ITL/scene/foo will be set to x position of /ITL/scene/obj at the time of the script evaluation (that may be different to 0.1).
Javascript
INScore supports Javascript as scripting languages. Javascript is embedded using the Qt Javascript engine. A script section is indicated similarly to a Javascript section in html i.e. enclosed in an opening <? and a closing ?>.
The principle of using Javascript sections in INScore files is the following: the Javascript sections are passed to the Javascript engine and are expected to produce textual INScore messages on output. These messages are then parsed as if replacing the corresponding script section. INScore variables are exported to the Javascript environment.
Note: A Javascript section may produce not output, for example when it declares functions to be used later.
Example
<? javascript
"/ITL/scene/version set txt 'Javascript v. " + version() + "';"
?>
A single persistent Javascript context is created at application level and shared with each scene.
The Javascript object
The Javascript engine is available at runtime at the address /ITL/scene/javascript. It has a run method that takes a javascript string as parameter.
The run method evaluates the code. Similarly to javascript sections in scripts, the output of the evaluation is expected to be a string containing valid INScore messages that are next executed. Actually, including a javascript section in a script is equivalent to send the run message with the same code as parameter to the javascript object.
The Javascript engine is based on the Qt5 Javascrip engine, extended with INScore specific functions:
- version(): gives the javascript engine version number as a string.
- print(val1 [, val2 [, ...]]): print the arguments to the OSC standard output. The arguments list is prefixed by 'javascript:'. The function is provided for debug purpose.
- readfile(file): read a file and returns its content as a string. The file name could be specified as an absolute or relative path. When relative, the file is searched in the application current rootPath.
- post(address [,...]): build an OSC message and post it for delayed processing i.e. to be processed by the next time task. address is an OSC or an extended OSC address. Optional arguments are the message parameters.
- osname(): gives the current operating system name.
-
osid(): gives the current operating system as a numeric identifiant. Returned value is (in alphabetic order):
-
1 for Android
- 2 for iOS.
- 3 for Linux,
- 4 for MacOS,
- 5 for Windows
Example Posting a message from a Javascript section:
<?javascript
post ("/ITL/scene/obj", "dalpha", -1);";
// The message /ITL/scene/obj dalpha -1
// will be evaluated by the next time task.
?>
Declaration of a Javascript function to be used later:
<?javascript
// declare a function foo()
function foo(arg) {
return "/ITL/scene/obj set txt foo called with " + arg + ";";
}
?>
# call the foo function
<?javascript foo(1)?>
# or call the foo function using the run message
/ITL/scene/javascript run "foo(1)";
Comments
There are two ways to comment code inside a script:
- line comments: the '#' character is used for line comments, anything after a '#' is ignored.
- section comments: section comments start with '(' and end with ')', anything between them is ignored.
Example
# this is a line comment
/ITL/scene/* del;
(*
here is a section comment
section comments are multi-lines comments
{*})
/ITL/scene/hello set txt "Hello world!"; # the preceding message is not commented
\inscoreend
and everything below the \inscoreend marker is also ignored