Overview
When you need to write more complex conditions or expressions than is possible with just the COGS UI tools, you need to drop down to using “custom code”.
Anywhere where it’s possible to use custom code, when you switch away from the UI based template, the custom code input will be populated with the expression that was being used under the hood when using the UI tools. This is a good way to get started in understanding how to write expressions:
becomes
Examples
Version | Expression | |
---|---|---|
4.0 → | pre_show.in_progress |
Show is in "pre-show" |
4.11 → | scene.variables.score.value * 10 |
The player’s score x 10 |
4.11 → | !this.value |
Invert on/off value |
Conditions vs Expression Values
In COGS land we refer to all these “custom code” snippets as expressions, but there are two main places they can be used which have slightly different uses.
Conditions
When writing expressions in the WHEN of a behaviour, or the condition section of an IF/THEN/OTHERWISE or a LOOP then these are conditions. The aim is to write an expression which will return true or false. In the case of a WHEN condition, the behaviour will run when the condition returns true but was previously false.
Expression Values
When writing expressions to display as values (such as in a scene dashboard widget), then the aim is to write an expression that returns a value of the correct type. e.g. for a “Text widget” on a dashboard, the expression should return a string type.
JEXL Expression Language
COGS expressions are written in the JEXL expression language, which is based on Javascript syntax.
This supports many of the standard operators common to many programming languages and more, e.g.
JEXL Operators
Symbol | Description | Examples | Result |
---|---|---|---|
! |
Negate | !true |
false |
+ |
Add numbers Concat strings |
1 + 2 + 3 "hello" + " " + "world" |
6 "hello world" |
- |
Subtract | 5 - 3 |
2 |
* |
Multiply | 5 * 9 |
45 |
/ |
Divide | 27 / 4 |
6.75 |
// |
Divide and floor | 27 // 4 |
6 |
% |
Modulus | 27 % 4 |
3 |
^ |
Power of | 2 ^ 10 |
1024 |
&& |
Logical AND | true && true && false |
false |
|| |
Logical OR | true || false || false |
true |
== |
Equal | "hello" == "HELLO" |
false |
!= |
Not equal | "hello" != "HELLO" |
true |
> |
Greater than | 3 > 2 "abc" > "abd" |
true false |
>= |
Greater than or equal | 3 >= 2 "abc" >= "abd" |
true false |
< |
Less than | 3 < 2 "abc" < "abd" |
false true |
<= |
Less than or equal | 3 >= 2 "abc" <= "abd" |
false true |
in |
Item is in array or string | "Yellow" in ["Red", "Green", "Blue"] "car" in "scarper" |
false true |
Functions
Version | Function | Description |
---|---|---|
4.7 → | random() |
A random number between 0 and 1 |
4.12 → | now() |
The current time in UTC milliseconds |
Expression Context
When writing an expression, COGS makes a context available which allows you to refer to things like channels and scene variables inside your expressions. What exactly is available is tied to the context, e.g. if it’s in a "Scene" behaviour you have access to scene
with the current scene's context.
Version | Value | Type | Description | Availability |
---|---|---|---|---|
4.7 → | this |
User Value | The value being set | When updating a value |
pre_show.in_progress |
Boolean | True if currently in pre-show | ||
4.11 → |
channels.KEY channel.KEY |
User Value | The current value of channel KEY | |
4.11 → |
devices.NAME.config.KEY box.NAME.config.KEY |
Boolean, String, or Number | Config Value of KEY for device NAME (Only custom Media Master) | |
4.11 → |
devices.NAME.event.KEY box.NAME.event.KEY |
User Value or {} |
Event value of KEY received from device NAME (Only custom Media Master) | |
4.12 → | devices.NAME.state.KEY |
User Value | Value of state with KEY sent to device NAME (Only custom Media Master) | |
5.4 → | devices.NAME.connected |
Boolean | Whether the device NAME is currently connected to COGS |
|
4.7 → | audio.FILE.playing |
Array of Media Locations | An array of outputs the audio FILE is playing on e.g. ["local:audio_player", "remote:My Speaker"] |
|
4.7 → | audio.FILE.paused |
Array of Media Locations | An array of outputs the audio FILE is paused on |
|
4.7 → | audio.FILE.stopped |
Array of Media Locations | An array of outputs the audio FILE is not playing on |
|
4.7 → | video.FILE.playing |
Array of Media Locations | An array of outputs the video FILE is playing on e.g. ["local:audio_player", "remote:My Screen"] |
|
4.7 → | video.FILE.paused |
Array of Media Locations | An array of outputs the video FILE is paused on |
|
4.7 → | video.FILE.stopped |
Array of Media Locations | An array of outputs the video FILE is not playing on |
|
4.9 → | osc.message.address |
String | Address of the OSC message received e.g. "/foo/bar" |
|
4.9 → | osc.message.arguments |
Array of number, string, or boolean | Arguments of the OSC message received at the address e.g. ["one", 2] |
|
4.11 → | plugins.ID.config.KEY |
User Value | Config value of KEY for plugin with ID | Custom plugin enabled |
4.11 → | plugins.ID.event.KEY |
User Value or {} |
Event value of KEY received from plugin with ID | Custom plugin enabled Plugin event received |
4.12 → | plugins.ID.state.KEY |
User Value | Value of state with KEY sent to plugin with ID | Custom plugin enabled |
5.0 → | midi.commands.note_off |
8 |
Number constant of the "note off" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.note_on |
9 |
Number constant of the "note on" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.key_pressure |
10 |
Number constant of the "key pressure" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.control_change |
11 |
Number constant of the "control change" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.program_change |
12 |
Number constant of the "program change" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.channel_pressure |
13 |
Number constant of the "channel pressure" MIDI command. | MIDI plugin enabled |
5.0 → | midi.commands.pitch_bend |
14 |
Number constant of the "pitch bend" MIDI command. | MIDI plugin enabled |
5.0 → | midi.message.device_id |
String | The ID of the MIDI input device which we have received a message from | MIDI plugin enabled MIDI message received |
5.0 → | midi.message.type |
"channel" , "sysex" , or "system" |
Type of MIDI message that has been received | MIDI plugin enabled MIDI message received |
5.0 → | midi.message.command |
Number | The command number for the message that has ben received. Can be compared with the number constants in midi.commands . 8 to 14 for "channel", 240 for "sysex", and 244 to 255 for "system" |
MIDI plugin enabled MIDI message received |
5.0 → | midi.message.data |
Array of Numbers | Data for the MIDI message that has been received. What these mean will change based on the command and type | MIDI plugin enabled MIDI message received |
5.0 → | midi.message.channel_number |
Number | Only given when midi.message.type is "channel" . Number from 1 to 16 |
MIDI plugin enabled MIDI message received |
5.0 → | midi.message.channel_index |
Number | Only given when midi.message.type is "channel" . Number from 0 to 15 |
MIDI plugin enabled MIDI message received |
5.0 → | midi.message.manufacturer_id |
Array of Numbers | Only given when midi.message.type is "sysex" . Is an array of either 1 or 3 numbers which identifies the manufacturer of the system extension |
MIDI plugin enabled MIDI message received |
5.0 → | midi.message.is_msc |
Boolean | Only given when midi.message.type is "sysex" . Will be true when the message is detected as being an MSC message |
MIDI plugin enabled MIDI message received |
5.0 → | midi.message.raw |
Array of Numbers | The raw bytes of the entire MIDI message received | MIDI plugin enabled MIDI message received |
4.13.6 → | timer.duration |
Number | Total duration in ms of the timer configured in the Timer plugin | Timer plugin enabled |
4.13.6 → | timer.remaining |
Number | Time in ms remaining on the timer Cannot be used to trigger a behaviour |
Timer plugin enabled |
5.0 → | zigbee.devices.NAME.address |
String | The network address of the Zigbee device for device NAME | Zigbee plugin enabled |
5.0 → | zigbee.devices.NAME.state.KEY |
Boolean, String, or Number | The value of state with KEY for Zigbee device NAME | Zigbee plugin enabled |
5.0 → | zigbee.devices.NAME.action |
String | The action just received for Zigbee device NAME | Zigbee plugin enabled Zigbee action received |
4.12 → | show.time_elapsed |
Number | Time in ms since the show started Cannot be used to trigger a behaviour |
Show |
show.in_progress |
Boolean | True if currently in a show | Show | |
show.finished |
Boolean | True if currently finished show | Show | |
show.cancelled |
Boolean | True if currently cancelled show | Show | |
show.variables.KEY |
User Value | The show variable KEY | Show | |
show.values.KEY |
Return value of expression | Current value of show value KEY | Show | |
4.13 → | scenes.NAME.* |
See scene.* below |
Refers to another scene in the project with NAME | Show |
scene.in_progress |
Boolean | True if scene is in progress | Scene | |
scene.finished |
Boolean | True if scene is finished | Scene | |
scene.skipped |
Boolean | True if scene is skipped | Scene | |
scene.cancelled |
Boolean | True if scene is cancelled | Scene | |
scene.variables.KEY |
User Value | The value of scene variable KEY | Scene | |
scene.values.KEY |
Return value of expression | Current value of scene value KEY | Scene |
Transforms
Transforms allow you to modify the values you are using in an expression in some useful way. These operate on arrays of values, for example to determine the length of the array or maximum value in the array.
Version | Transform | Description | Example | Result |
---|---|---|---|---|
length |
The length of the array | [1,2,3] | length |
3 |
|
min |
The lowest number in the array | [1,2,3] | min |
1 |
|
max |
The highest number in the array | [1,2,3] | max |
3 |
|
count(value) |
How many items of given value are in the array |
[1,1,2,3,1] | count(1) |
3 |
|
all(value) |
Do all the values in the array match the given value |
[1,2,3,4] | all(1) |
false |
|
any(value) |
Do any of the values in the array match the given value |
[1,2,3,4] | any(1) |
true |
|
4.7 → | pickRandom |
Pick a random item from an array | ["A","B","C"] | pickRandom |
"A" , "B" or "C" |
4.11 → | randomValue |
Pick a random value for the given User Value | this | randomValue |
Any valid value |
4.11 → | randomValue({ differentValue: true }) |
The same as randomValue but chooses a value that is not the current value |
this | randomValue({ differentValue: true }} |
Any valid value |
4.7 → | round |
Round a number to the nearest whole number | 1.6 | round |
2 |
4.7 → | floor |
Round a number down to a whole number | 1.6 | floor |
1 |
4.7 → | ceil |
Round a number up to a whole number | 1.4 | ceil |
2 |
5.2 → | abs |
Convert a number to its absolute value | -2 | abs |
2 |
4.9 → | matchesOscAddress(pattern) |
Match the OSC address pattern |
"/foo/1" | matchesOscAddress("/foo/[0-9]") |
true |
5.4 → | toJSON |
Encode the data to a JSON string | { foo: "bar" } | toJSON |
'{"foo":"bar"}' |
5.4 → | fromJSON |
Decode the data from a JSON string | '{ "foo": "bar" }' | fromJSON |
{foo:"bar"} |
User Values
COGS 4.11 introduces a more detailed value type for variables and channel values, allowing you to access metadata about the expected value.
COGS 4.10 and lower represents these values as either a string, number, or boolean value.
On/Off
Key | Required | Value |
---|---|---|
type |
✓ | "boolean" |
value |
✓ | Boolean value |
Text
Key | Required | Value |
---|---|---|
type |
✓ | "string" |
value |
✓ | String value |
Number
Key | Required | Value |
---|---|---|
type |
✓ | "number" |
value |
✓ | Number value |
min |
𐄂 | Minimum allowed value (inclusive) |
max |
𐄂 | Maximum allowed value (inclusive) |
integer |
𐄂 | true if only whole numbers are allowed, otherwise false |
Option List
Key | Required | Value |
---|---|---|
type |
✓ | "option" |
options |
✓ | Array of all possible string values |
value |
✓ | String value, always one of options |
Media Locations
Media locations are strings that represent the local machine or a Media Master.
Local audio output is represented as local:audio_player
.
Remote media outputs are represented as remote:NAME
where NAME
is the name you have given the Media Master.