Actions
Actions are immediate Lua scripts that run against the Plinken engine. They can execute DAW commands, query session state, call external programs, and automate any task you’d otherwise do by hand.
Open the Action Editor from the Action menu, or run a script programmatically with the lua:execute command.
Script Lifecycle
Section titled “Script Lifecycle”| Command | Description |
|---|---|
lua:create | Create a new empty action |
lua:load | Load an action into the editor |
lua:save | Save the current action |
lua:execute | Run the current action |
lua:delete | Delete an action |
lua:list | List all available actions |
API Reference
Section titled “API Reference”pl.cmd(id, payload)
Section titled “pl.cmd(id, payload)”Execute any DAW command. The call is deferred to the next frame — it queues the command and returns immediately. Use the same command IDs as Plinken’s internal command system.
-- Mute track 1pl.cmd("track:mute", { trackId = 1 })
-- Set tempopl.cmd("transport:set-tempo", { tempo = 128 })
-- Solo a trackpl.cmd("track:solo", { trackId = 3 })| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | yes | Command ID (e.g. "track:mute", "transport:play") |
payload | table | no | Command-specific parameters |
Use
plinken.list_commands()to discover all available command IDs.
pl.log(msg)
Section titled “pl.log(msg)”Output a message to the console panel. Useful for debugging and status updates.
pl.log("Processing complete")pl.log("Track count: " .. tostring(trackCount))| Parameter | Type | Required | Description |
|---|---|---|---|
msg | string | yes | Message to display |
print(…)
Section titled “print(…)”The standard Lua print function is redirected to the script output buffer. Output appears in the Action Editor’s result pane.
print("hello") -- appears in output bufferprint("a", "b", "c") -- tab-separated, as normal Lua printpl.sleep(ms)
Section titled “pl.sleep(ms)”Yield execution for the specified number of milliseconds. Maximum sleep time is 30 000 ms (30 seconds). Use this to wait for commands to take effect before querying state.
pl.cmd("transport:play", {})pl.sleep(1000) -- wait 1 secondpl.cmd("transport:stop", {})| Parameter | Type | Required | Description |
|---|---|---|---|
ms | number | yes | Milliseconds to sleep (1–30 000) |
pl.get_context()
Section titled “pl.get_context()”Returns session context as a table. Useful for scripts that need to know which project or space they’re operating in.
local ctx = pl.get_context()pl.log("Account: " .. ctx.account)pl.log("Project: " .. ctx.project)Return Table
Section titled “Return Table”| Field | Type | Description |
|---|---|---|
account | string | Current account ID |
project | string | Current project name |
space | string | Active space/session |
team | string | Team identifier |
video | string | Active video asset (if any) |
pl.get_transport()
Section titled “pl.get_transport()”Returns the current transport state. Tempo, playback status, time position, and more.
local t = pl.get_transport()pl.log("Tempo: " .. t.tempo .. " BPM")pl.log("Playing: " .. tostring(t.playing))pl.log("Position: " .. t.position .. " beats")Return Table
Section titled “Return Table”| Field | Type | Description |
|---|---|---|
tempo | number | Current tempo in BPM |
playing | bool | Whether transport is playing |
recording | bool | Whether transport is recording |
position | number | Playhead position in beats |
time | number | Playhead position in seconds |
time_sig_num | number | Time signature numerator |
time_sig_den | number | Time signature denominator |
loop_start | number | Loop region start (beats) |
loop_end | number | Loop region end (beats) |
loop_enabled | bool | Whether loop is active |
plinken.list_commands()
Section titled “plinken.list_commands()”Returns a table of all registered command IDs. Use this to discover what commands are available for pl.cmd().
local cmds = plinken.list_commands()for _, id in ipairs(cmds) do print(id)endReturns: array of strings — command IDs like "track:mute", "transport:play", "mixer:set-volume".
pl.exec(program, args)
Section titled “pl.exec(program, args)”Run an allowlisted external program. The call blocks until the program finishes and returns its stdout as a string.
-- Get duration of a media filelocal info = pl.exec("ffprobe", { "-v", "quiet", "-print_format", "json", "-show_format", "assets/vocals.wav"})pl.log(info)| Parameter | Type | Required | Description |
|---|---|---|---|
program | string | yes | Program name (must be allowlisted) |
args | table | no | Array of string arguments |
Returns: string — the program’s stdout output.
The Lua sandbox restricts which programs can be executed. See the allowlist below.
plinken.allowed_programs()
Section titled “plinken.allowed_programs()”Returns the list of programs that pl.exec() can call.
local progs = plinken.allowed_programs()for _, name in ipairs(progs) do print(name)endReturns: array of strings.
Allowlisted Programs
Section titled “Allowlisted Programs”These programs are available to pl.exec():
| Program | Category | Description |
|---|---|---|
ffmpeg | Media | Video/audio encoding and conversion |
ffprobe | Media | Media file inspection |
imagemagick | Media | Image processing (legacy name) |
convert | Media | ImageMagick convert command |
sox | Audio | Audio processing and effects |
blender | 3D | Blender headless rendering and scripting |
houdini | 3D | Houdini interactive |
hython | 3D | Houdini Python scripting |
hbatch | 3D | Houdini batch processing |
unity | 3D | Unity batch mode |
resolve | Video | DaVinci Resolve scripting |
lilypond | Music | Music engraving / sheet music |
csound | Music | Audio synthesis |
sonic-pi | Music | Live coding music |
python3 | General | Python 3 interpreter |
python | General | Python interpreter |
node | General | Node.js runtime |
Examples
Section titled “Examples”Toggle Playback
Section titled “Toggle Playback”local t = pl.get_transport()if t.playing then pl.cmd("transport:stop", {}) pl.log("Stopped")else pl.cmd("transport:play", {}) pl.log("Playing")endMute Multiple Tracks
Section titled “Mute Multiple Tracks”local tracks_to_mute = { 1, 3, 5 }for _, id in ipairs(tracks_to_mute) do pl.cmd("track:mute", { trackId = id })endpl.log("Muted tracks 1, 3, 5")Batch Export with FFmpeg
Section titled “Batch Export with FFmpeg”local files = { "vocals.wav", "drums.wav", "bass.wav" }for _, f in ipairs(files) do local out = f:gsub("%.wav$", ".mp3") pl.exec("ffmpeg", { "-i", "assets/" .. f, "-codec:a", "libmp3lame", "-b:a", "320k", "exports/" .. out }) pl.log("Exported " .. out)endProbe Media Files
Section titled “Probe Media Files”local info = pl.exec("ffprobe", { "-v", "quiet", "-print_format", "json", "-show_streams", "assets/final_mix.wav"})print(info)Generate Sheet Music
Section titled “Generate Sheet Music”-- Write a LilyPond source file, then render to PDFpl.exec("lilypond", { "--output=exports/score", "assets/arrangement.ly"})pl.log("Score rendered to exports/score.pdf")Full Example: Session Report
Section titled “Full Example: Session Report”-- Print a full session summarylocal ctx = pl.get_context()local transport = pl.get_transport()
pl.log("=== Session Report ===")pl.log("Project: " .. ctx.project)pl.log("Space: " .. ctx.space)pl.log("Tempo: " .. transport.tempo .. " BPM")pl.log("Time Sig: " .. transport.time_sig_num .. "/" .. transport.time_sig_den)pl.log("Position: " .. string.format("%.2f", transport.time) .. "s")pl.log("Playing: " .. tostring(transport.playing))pl.log("Loop: " .. tostring(transport.loop_enabled))
local cmds = plinken.list_commands()pl.log("Commands: " .. #cmds .. " registered")
local progs = plinken.allowed_programs()pl.log("Programs: " .. #progs .. " available")pl.log("======================")