Free forever·no account, no tracking, no third-party requests ·open data, free API
showstack / learn / code
Stage 5 of 7 · What you build with3 of 4 in this stage13 min read

Code on a show

Most people in this industry write code only when a show needs it — a console macro, a bit of glue between two systems, a bridge to an automation platform. Those are three different jobs, and the reason "just use Python" is sometimes right and sometimes dangerous.

Start here

Three places code shows up, and they are not the same job

The confusion that wastes the most time is treating these as one skill. They have different tools, different constraints, and completely different definitions of the word working.

Scripting inside a tool

You are writing inside somebody else's application, using the language they chose to embed. The application decides when your code runs and what it can touch.

Lua in grandMA3 plugins · Python in TouchDesigner and Ableton control-surface scripts · AppleScript and JavaScript in QLab · JavaScript modules in Companion

Glue between systems

A small program of your own that listens to one thing and talks to another — OSC in, HTTP out; a webhook that fires a cue; a translator between two vendors who will never support each other.

Python or Node most often · runs on a laptop or a small PC · nothing moves if it crashes, which is exactly why it is allowed to be simple

Machine control

Something physical moves. Winches, lifts, revolves, kinetic scenery. The code must run on a guaranteed schedule, and the safety chain is separate hardware regardless of what the code does.

PLC platforms — TwinCAT, Siemens TIA, CODESYS · IEC 61131-3 languages · EtherCAT or PROFINET underneath

rule
Ask which of the three you are in before choosing a language. The third one is not a harder version of the second — it is a different discipline, with a different regulatory reality behind it.

The vocabulary

What actually separates one language from another

Three distinctions do most of the work, and once you have them the landscape stops being a list of names.

Compiled or interpreted. A compiled language (C, C++, Rust, Go) is translated to machine code once, before it runs; from then on the processor is executing it directly. An interpreted language (Python, JavaScript, Lua) ships as source and a runtime reads and executes it as it goes. Compiled is faster and less forgiving; interpreted is quicker to change and easier to get running, which is why so much show glue is written in it.

Managed or manual memory. Most modern languages have a garbage collector: it finds memory you are no longer using and reclaims it, at a moment of its own choosing. That is a huge convenience and it is also a timing hazard, because "a moment of its own choosing" can land in the middle of something you needed to happen on time. C and C++ have no collector — you manage memory yourself, which is more work and more dangerous, and it is why they are still what real-time media engines and firmware are written in.

General-purpose or embedded. Some languages are designed to be the application; some are designed to live inside one. Lua is the clearest example — small, fast to embed, easy to sandbox — which is precisely why it turns up inside so many consoles and media servers rather than as anybody's main language.

The landscape

What each one is actually for

This is not a ranking. Every row is the right answer to some question and the wrong answer to most of the others.

LanguageKindWhat it is good atWhere you meet it on a show
HTML + CSSmarkupNot programming languages at all. HTML describes structure; CSS describes appearance. Neither can make a decision.Touch-panel layouts, web remotes, lower-third and overlay templates, any browser-based control surface.
JavaScriptinterpretedThe one language every browser runs. Event-driven by nature, so it is comfortable waiting for things. Also runs outside the browser as Node.Companion modules, browser-based controllers, web remotes, small OSC-to-HTTP bridges.
PythoninterpretedThe fastest way from an idea to a working script, with a library for almost everything. Slow in raw terms, and almost never slow enough to matter for glue.TouchDesigner, Blender, Ableton remote scripts, disguise scripting, and most one-off integration tools in this industry.
LuaembeddedTiny, fast, trivially embeddable and easy to sandbox. Designed to be hosted inside another application rather than to stand alone.grandMA3 plugins, and scripting hooks inside a range of consoles, media servers and control systems.
C / C++compiledDirect control of memory and timing, no garbage collector, no runtime surprises. Correspondingly unforgiving.Fixture and console firmware, media server engines, audio DSP, plug-ins, and custom TwinCAT modules.
C#compiled + managedComfortable, strongly typed, excellent tooling. Garbage collected, so not for hard real time.Unity-based interactive and XR work, Windows show tools, plenty of vendor SDKs.
Structured TextPLC (IEC 61131-3)Looks like ordinary code and compiles to a guaranteed scan cycle. Written to be reviewable by someone who did not write it.Automation: winches, lifts, revolves, turntables, kinetic scenery.
Ladder / FBDPLC (IEC 61131-3)Graphical. Ladder reads like a relay schematic; function block diagram reads like a signal flow. Both are chosen for auditability, not for expressiveness.The same automation systems — often alongside Structured Text in the same project.
Shell / batchscriptingStarting things, moving files, wiring existing tools together. Not for logic of any depth.Show-machine startup, log collection, backup jobs, media prep.

The word that matters

Determinism, and why it disqualifies almost everything

Ask a laptop to do something every 10 milliseconds and it will, on average. Most cycles will be close to 10 ms. Some will not: the operating system schedules something else, the garbage collector runs, a network driver takes a moment, an antivirus scanner wakes up. Averages are excellent and individual guarantees are absent.

For a cue-triggering bridge that is completely fine — a few milliseconds late is invisible. For a motion control loop it is not fine at all, because the loop is what keeps a moving load under control, and "usually on time" is not a property you can write a safety case around.

A real-time system inverts the priority. It is not necessarily fast; it is predictable. The cycle happens every cycle, on time, and if it cannot, the system faults rather than quietly running late. That guarantee is the entire reason PLC platforms exist, and it is why show automation runs on them instead of on the laptop that is already sitting there.

The platform

What TwinCAT actually is

TwinCAT is Beckhoff's automation platform, and the thing that makes it interesting is what it does to an ordinary industrial PC: it runs a hard real-time kernel alongside Windows, with CPU cores reserved for the real-time side. Windows can be as busy or as badly behaved as Windows normally is, and the control task still runs on its cycle.

TwinCAT 3 is developed inside Microsoft Visual Studio, which means the control engineering and any surrounding software tooling live in one environment. It supports the IEC 61131-3 languages — Structured Text, Ladder, Function Block Diagram, Sequential Function Chart, Instruction List — and it will also take compiled C++ modules and models exported from MATLAB/Simulink, so a control algorithm designed in simulation can be deployed as a real-time task rather than rewritten.

Underneath it, EtherCAT is the fieldbus: drives, I/O and sensors on one line, updated every cycle with the determinism the whole design exists to protect. Upward, an OPC UA server is the usual way the automation platform exposes state to the rest of the building — which is also, in practice, how a show-control system asks it a question without being anywhere near the control loop.

Everything on the show-network side of that boundary is advisory. The automation platform decides what it does.

the same idea in three languages

-- Lua, inside a console: run when the operator presses the plugin local level = Cmd("Attribute 'Dimmer' Group 3") if level < 50 then Cmd("At 50") end # Python, as glue: listen for a cue, tell something else about it def on_cue(addr, number): requests.post("http://mediaserver/api/play", json={"clip": number}) (* Structured Text, on a PLC: this runs every cycle, forever *) IF bEnable AND NOT bFault AND fPosition < fTarget THEN fVelocity := fMaxVelocity; ELSE fVelocity := 0; END_IF

Read those three again and notice what changes. The first runs when a human asks. The second runs when a message arrives. The third runs whether anything happened or not — and that is the difference the whole page is about.

ST — Structured Text
Textual, closest to conventional programming. Where most non-trivial logic lives.
LD — Ladder
Drawn like a relay schematic so an electrician can read it. Still the default for interlocks.
FBD — Function Block
Blocks wired together. Reads like a signal flow diagram.
SFC — Sequential Function Chart
Steps and transitions. Good for a machine that moves through defined states.
rule
A PLC language is chosen for how easily a second person can audit it, not for how quickly the first person can write it. That is the opposite of the trade-off you make when writing show glue, and it is not a criticism of either.

The boundary

Where custom code is allowed to be, and where it is not

This is the same principle as the arming chain on the drone and pyro page, and it is worth stating in the same words.

Functional safety — emergency stops, limits, guarding, the interlocks that stop a load before it hurts somebody — is a separate, rated channel. On a Beckhoff system that is TwinSAFE; other vendors have their own. It is certified, it is reviewed, and it is not where your code goes. It remains valid regardless of what the control program does, which is exactly the point: it has to be true even when the control program is wrong.

Custom code belongs on the control side of that boundary and on the show network above it. It can request, sequence, report and integrate. It cannot be the reason a machine stops safely.

If you are starting

What is actually worth learning first

For almost everyone in this industry the honest answer is Python, and it is not close. It reads clearly, the library ecosystem covers every protocol you are likely to meet, and it is what the tools you already use have embedded.

Learn JavaScript when what you need lives in a browser or in Companion — which is often enough that it is a fair second.

Learn Lua when the console you are on has it, because it is a small language and you can be useful in it in an afternoon.

Learn Structured Text and a PLC platform when you are moving into automation — and treat that as a career decision rather than a language decision, because the discipline around it is the substantial part, not the syntax.

What survives across all four is not syntax. It is the protocol and timing thinking the rest of this section is about: knowing what you are speaking, and what promises it does and does not make.

Building glue on top of the index?

Every collection here is plain JSON at a fixed URL with permissive CORS — no key, no rate limit — so it is a reasonable thing to hang a script off. Start at /api/v1/index.json, and see how software talks to software for the protocol-versus-API-versus-SDK distinction that decides most integration questions.

You can now answer
  • Which language should I learn?
  • What is determinism?
  • What is TwinCAT for?
Kept in this browser on this device. Nothing is sent anywhere.

Where to go next

These pages are a chain rather than a library — the next one along usually answers the question this one raised.

Everything on this page, in the index

Each of these has its own entry with sources, ports, gotchas and an open gap where a field is missing.