Events & Callbacks
Persistent scripts stay alive and react to DAW changes in real time. Start a persistent script with lua:start instead of lua:execute.
Registering Callbacks
Section titled “Registering Callbacks”pl.on("event_name", function() -- called when the event firesend)Available Events
Section titled “Available Events”| Event | Fires when |
|---|---|
transport_changed | Play/stop state changes |
tempo_changed | Tempo changes |
track_added | A track is added |
track_removed | A track is removed |
selection_changed | Selection changes |
region_added | A region is added |
region_removed | A region is removed |
beat | Each beat (musical time) |
bar | Each bar (musical time) |
midi | Incoming MIDI event |
Convenience Shortcuts
Section titled “Convenience Shortcuts”pl.on_beat(function() ... end) -- same as pl.on("beat", fn)pl.on_bar(function() ... end) -- same as pl.on("bar", fn)pl.on_midi(function() ... end) -- same as pl.on("midi", fn)Unregistering
Section titled “Unregistering”pl.off("beat") -- remove all beat callbacksExample: Metronome Logger
Section titled “Example: Metronome Logger”local beat_count = 0
pl.on_beat(function() beat_count = beat_count + 1 local transport = pl.get_transport() pl.log("Beat " .. beat_count .. " at " .. transport.tempo .. " BPM")end)Example: Auto-Mute on Stop
Section titled “Example: Auto-Mute on Stop”pl.on("transport_changed", function() local t = pl.get_transport() if not t.isPlaying then -- Mute all armed tracks when playback stops local tracks = pl.get_tracks() for _, track in ipairs(tracks) do if track.arm and not track.mute then pl.cmd("track:toggle-mute", { trackId = track.id }) end end endend)Starting & Stopping
Section titled “Starting & Stopping”From the command system:
-- Start a persistent script (from another script or the command palette)pl.cmd("lua:start", { scriptId = "my-script" })
-- Stop itpl.cmd("lua:stop", { scriptId = "my-script" })
-- Stop all persistent scriptspl.cmd("lua:stop-all")Performance
Section titled “Performance”- Events are detected by reading atomics — zero allocations on the audio thread
- Callbacks run on the main thread during the render frame
- The audio thread never knows Lua exists
- Scripts with no callbacks or timers are automatically cleaned up