Appearance
Cue Script Reference
A cue script is the text in a cue's script box — the box with the ⚡ Wizard button under a Timeline cue's action, or a Playlist item's Action On Enter / Action On Leave, with the action type Custom. It runs when the cue fires. Each line is one action: a command to Exaplay itself, or a message to another device. You rarely have to type it — ⚡ Wizard builds the lines for you — but this page is the exact syntax the engine reads.
Rules for every line
- One action per line, run top to bottom.
- A line starts at the first character: no leading spaces, and no space between the prefix and
>(OSC>, notOSC >). - Fields are separated by commas. Spaces around the address and the OSC path are ignored; everything else is taken literally.
$Nameor${Name}in an address (and in an OSC path) is replaced by a variable. A name that does not resolve stops the send and shows an ERROR row in the Monitor.REMat the start of a line makes it a comment.
Commands to Exaplay
Any line without a protocol prefix is a dotted command — the same syntax as the TCP Command API:
comp1.play
comp1.cue.go=Act 1
comp2.stop
comp1.media3.set:image.alpha=50
comp1.set:audio.volume=80
system.showmode=on
system.pjlink=192.168.1.50,POWR,1
screen1.calibration.blend=off
comp1.media3.webcapture.reload
comp1.media3.webcapture.click=0.5,0.5A web page clip takes webcapture.reload / .back / .forward / .stop / .click[=x,y] / .js=… — see TCP › Webcapture verbs.
screen1.calibration=on|off|toggle, screen1.calibration.blend=… and screen1.calibration.black=… switch a screen's calibration, its edge blending and its black level (the same switches as the calibration's Edit… dialog — see TCP › Screen verbs). In a multi-client rig a cue runs on every machine, and the switch is the master's: the master's line switches every PC at the same moment, a client's line changes nothing.
In a cue script, system.pjlink= reaches any projector address you write; the same line sent from outside over TCP/UDP only reaches a projector configured under Control → TCP Devices (see TCP › System verbs). set:time= on a Playlist is the time within the current item.
A bare verb acts on the cue's own composition: play, pause, stop, restart (play from start; media3.restart for one Playlist item), cue.go=3, set:time=10. In the ⚡ Wizard, Browse picks the target from the project tree and Set a value… lists the values an operator drives.
Messages to other devices
OSC
OSC>host:port,/address[,i:<integer>][,f:<float>][,s:<text>]OSC>10.0.0.20:8000,/eos/cue/5/fire
OSC>$Console,/cue/5/go,i:1
OSC>$Console,/fader/1,f:0.75,s:main- Argument types are
i,fands; any other type is dropped. - Put a field that contains commas in double quotes. A
:inside ans:value ends the value. - Sent as a plain OSC message (not a bundle).
TCP and UDP
TCP>host:port,payload
UDP>host:port,payloadTCP>192.168.1.30:9500,PLAY 3\r
UDP>$Projector,%1POWR 1\r- The payload is everything after the first comma, sent byte for byte — it may contain commas, and a space after the comma is sent too.
- Escapes in the payload:
\r(CR),\n(LF),\t,\b,\",\\,\xHH(any byte in hex). Any other letter gives a control byte counted froma—\cis0x02(STX),\dis0x03(ETX) — so write a literal backslash as\\. - A field that is exactly
$Nameis replaced by that variable's value when it exists; any other text starting with$(such as$1POWR) is your device's text and is sent as it is. Only an unresolved${Name}makes the line refuse. - TCP opens a connection, sends and closes.
HTTP
Calls a device's REST API or a webhook — a smart plug, a projector or camera with a web API, Node-RED, Home Assistant.
HTTP>METHOD url
HTTP>METHOD url,bodyHTTP>GET http://10.0.0.30/relay/0?turn=on
HTTP>POST http://homeassistant.local:8123/api/webhook/show-start,{"scene":"act2"}
HTTP>PUT http://${Camera}/api/preset,recall 3
HTTP>$LobbyLightsOffMETHODisGET,POST,PUT,PATCHorDELETE(upper or lower case). A line without one is aGET.- The body is everything after the first comma that follows the address, with spaces at both ends removed. A
GETsends no body: write a comma that belongs to the address as%2C(?ids=1%2C2), and a space as%20. - A body that starts with
{or[is sent asapplication/json, anything else astext/plain; charset=utf-8. The body is sent exactly as written: there are no\r/\xHHescapes here (unlike TCP/UDP), so\ninside a JSON string reaches the device as JSON's own\n. http://andhttps://both work. Anhttps://device needs a trusted certificate; a self-signed one is refused, so usehttp://for devices on the local network.${Name}anywhere in the address or the body, or an address that is exactly$Name, is a variable. An unresolved one stops the send.- A user name or password in the address (
http://admin:pw@…) is refused: anyone on the network can read a project's scripts back. A device that needs a key usually takes it in the query or the body — that is just as readable, so give such a device a key that can do only what the show needs. - In a multi-client show only the master sends the request, so a cue that plays on every machine still calls the device once. A client logs not sent here.
- The request runs in the background and never holds up playback. A device that does not connect within about 3 seconds, or does not answer within 10, is given up. At most 16 requests wait for an answer at once.
- The Monitor shows one row per request, after the answer: OUT with the status code and the first characters of the answer for a
2xx, ERROR with the status (or why there was no answer) for anything else. A redirect fromhttpstohttpis not followed.
Art-Net DMX
ARTNET>ip,universe,channel,valueARTNET>10.0.0.50,0,12,255- Port
6454is fixed; a variable must hold the IP only. - The value is clamped to
0–255. Channels you do not name keep the value they had (the same universe can also be driven by a Data Track).
MQTT
Publishes one message to an MQTT broker — Home Assistant (its Mosquitto add-on), Node-RED, Mosquitto or an IoT gateway: switch a light, start an automation, tell the building a scene began.
MQTT>broker,topic,payloadMQTT>Home Assistant,exaplay/scene,act2
MQTT>192.168.1.20,zigbee2mqtt/lobby_light/set,{"state":"ON","brightness":120}
MQTT>$Broker,show/state,${ShowState}
MQTT>mosquitto.local:1884,show/blank,- broker is the name (or the channel name) of an MQTT device in Inputs: its address, port, user name and password are used, so a password never has to be typed into a cue. Anything else is read as
hostorhost:port(port1883if none) and connects without a login. - topic is one topic, without
+or#(those only subscribe). - payload is everything after the second comma, sent byte for byte — a JSON payload keeps its commas, a space after the comma is sent too, and there are no
\r/\xHHescapes (unlike TCP/UDP). It may be empty. - In a multi-client show only the master publishes, so a cue that plays on every machine still sends one message. A client logs not sent here.
- The message goes out with QoS 1, not retained: Exaplay waits for the broker to confirm it, then disconnects. Each line opens its own short connection in the background and never holds up playback; a broker that does not accept the connection within 2 seconds, does not acknowledge it within 5, or does not confirm the message within 3, is given up.
- The broker must be on the local network (10.x, 172.16–31.x, 192.168.x, or this PC). This version speaks plain MQTT over TCP, without TLS (port 8883 is not supported), so a login crosses the network in clear.
$Name/${Name}in the broker and the topic, and${Name}in the payload, are variables. An unresolved one stops the send.- The Monitor shows one row per line (protocol MQTT): OUT with the topic and the start of the payload once the broker confirmed it, ERROR with the reason otherwise (The broker refused the user name or password., no MQTT broker answers at …, the broker did not confirm the message …).
DALI lighting
DALI>gateway,target,action[,value[,fade]]DALI>House,all,off
DALI>House,G2,level,40
DALI>Foyer,G17,scene,2.5,3gatewayis a DALI gateway configured in Control → TCP Devices (a Lunatone DALI-2 IoT or a Helvar router), by name or id — never an address.target:all,G<group>,A<short address>(Lunatone) or@cluster.router.subnet.device(Helvar).action:level(value 0–100),on,off,scene(value: scene number; on a Helvar router alsoblock.scene).fade: seconds, Helvar only. A Lunatone gateway uses the ballasts' own DALI fade time.- The line is queued and returns at once; the engine sends it in the background. A command the gateway cannot do (a fade on a Lunatone,
allon a Helvar router) is refused with the reason in the Monitor and the log. Sent by the master only. See DALI Lighting.
Flow and system
| Line | Effect |
|---|---|
WAIT>milliseconds | Pause before the next line (0–600000, i.e. up to 10 minutes). A script with a WAIT> runs in the background, so the engine never blocks. Loading a project, or deleting the cue's composition, cancels the rest of a running script |
TRACKING>group:<name>=on / =off / =toggle | Switch a group of Inputs mappings |
TRACKING>solo=<name> | Only that group on |
TRACKING>all=on / =off | All groups |
BATCH>command line | Run a command line (cmd.exe /c), e.g. a .bat file |
SHUTDOWN> | Force-shut down this machine |
RESTART> | Force-restart this machine |
REM text | Comment |
Example
REM Act 2: lights, sound, picture
OSC>$Console,/cue/20/go
TCP>$AudioServer,GO 2\r
WAIT>500
comp_act2.cue.go=Opening
system.pjlink=192.168.1.50,AVMT,30Where else these lines work
- Over TCP/UDP from outside: only the dotted commands. Protocol lines (
OSC>,TCP>,HTTP>,TRACKING>, …) are cue-only there; a remote line containing>is refused. - Over HTTP: the
TRACKING>text without its prefix can be sent asPOST /trackingwith{"command": "solo=scene2"}. - Failover "On Promotion Send" (multi-client backup):
OSC>,TCP>andUDP>lines, plus#comments — see Multi-Client.
See Also
- External Show Control — named routes, the ⚡ Wizard, verifying with the Monitor
- TCP Command API — the dotted command set
- OSC Reference — what Exaplay receives and sends over OSC
