Callbacks¶
Callbacks are the primary mechanism for nodes to execute code in response to events. IVLS dispatches callbacks to all registered nodes via __RUN_CB__(CallbackName).
node MyNode:
cb Init:
// Initialization code
cb NoteOn:
// Note-on handling
cb Functions:
// Function definitions
end nodeLifecycle Callbacks¶
These execute during on init and on persistence_changed in a defined order.
Init / ICB / PostInit / Post_ICB¶
Run sequentially during on init for staged initialization.
node Ivls.Flows:
cb Init:
family ivls
const flow_entry
NODE
FLOW
end const
declare flow_count := 0
declare flows[IVLS.MAX_FLOWS, IVLS.NODES_PER_FLOW] := (-1)
declare flow_lengths[IVLS.MAX_FLOWS] := (0)
end familyFirstLoad¶
Runs during on persistence_changed only on the very first instrument load (not snapshots/presets).
node Ivls.Flows:
cb FirstLoad:
ivls.flow_count := 0
literate_macro(#l# := ivls.new_flow()) on FLOWS
__RUN_CB__(Flows)
ivls._count_flows()Pre_PCCB / PreReload¶
Prepare for state restoration before the main reload phase.
PCCB / Reload¶
Main state restoration during on persistence_changed:
node Ivls.Keymaps:
cb Reload:
keymap.state.connected_to_kontakt := FALSE
call keymap._init()
call keymap.reboot()
keymap.state.connected_to_kontakt := TRUE
call keymap.push_all()Post_PCCB / PostReload¶
Finalization after state restoration -- validation, UI updates, etc.
Event Callbacks¶
KNCB / KRCB (Keyboard Note/Release)¶
Fire during on note / on release after IVLS voice processing. Access EVENT_NOTE, EVENT_VELOCITY, MIDI_CHANNEL, EVENT_ID.
node Stl.MPE:
cb KNCB:
mpe.note_press[MIDI_CHANNEL] := EVENT_VELOCITY
mpe.note_slide[MIDI_CHANNEL] := 64CC (Controller Change)¶
Fires during on controller. Access CC_NUM, CC[cc_num], MIDI_CHANNEL.
node Stl.Pedals:
cb CC:
keys.cc[MIDI_CHANNEL, CC_NUM] := CC[CC_NUM]
for pedal.i := 0 to pedal.type.size - 1
if CC_NUM = pedal.cc[pedal.i]
if pedal.multi_states[MIDI_CHANNEL, pedal.i] # sh_right(keys.cc[MIDI_CHANNEL, pedal.cc[pedal.i]], 6)
pedal.multi_states[MIDI_CHANNEL, pedal.i] := sh_right(keys.cc[MIDI_CHANNEL, pedal.cc[pedal.i]], 6)
keys.pedal_changed(MIDI_CHANNEL, pedal.i)
end if
end if
end forLCB / PolyAT / PGS / ACCB / AsyncResponse¶
| Callback | Trigger | Key Variables |
|---|---|---|
LCB |
on listener |
NI_SIGNAL_TYPE |
PolyAT |
on poly_at |
POLY_AT_NUM, POLY_AT |
PGS |
on pgs_changed |
PGS keys |
ACCB / AsyncResponse |
on async_complete |
NI_ASYNC_ID, NI_ASYNC_EXIT_STATUS |
node Stl.NKAManager:
cb AsyncResponse:
if NI_ASYNC_ID = param_nka.async_save_ID
if NI_ASYNC_EXIT_STATUS = 1
param_nka.async_save_ID := -1
message("Parameter array saved!")
else
param_nka.async_save_ID := -2
message("Problem with saving parameter array, or saving cancelled!")
end if
end ifTimer Callbacks¶
| Callback | Signal | Purpose |
|---|---|---|
TimerBeatTick |
NI_SIGNAL_TIMER_BEAT |
Beat-synchronized events |
TimerMsTick |
NI_SIGNAL_TIMER_MS |
Millisecond timer events |
TransportStart |
NI_SIGNAL_TRANSP_START |
DAW playback started |
TransportStop |
NI_SIGNAL_TRANSP_STOP |
DAW playback stopped |
node Stl.RoundRobins:
cb TransportStart:
util.array.fill(rr.counter, 0)UI Callbacks¶
| Callback | Trigger | Purpose |
|---|---|---|
KUI / KUICB |
on ui_update |
Periodic UI refresh |
UICBS |
on ui_controls |
UI control value changes |
UIOpen |
Dev mode open | Show development UI |
UIClose |
Production mode | Hide development UI |
ProductionUI |
Production mode | Set up final UI |
node Stl.Lib:
cb UIOpen:
ram_panel -> hide := HIDE_PART_NOTHING
cb UIClose:
ram_panel -> hide := HIDE_WHOLE_CONTROLVoice Callbacks¶
These handle the IVLS voice processing pipeline. Available variables: self (current Voice ref), nenv (NodeEnv context), path_on (path still active).
NoteOn / NoteOff¶
node Stl.Pedals:
cb NoteOn:
declare mp.note := Voice[self].note
declare mp.midi_ch := Voice[self].midi_ch
keys.pressed[mp.midi_ch, mp.note] := ON
keys.active[mp.midi_ch, mp.note] := ON
ivls.pass()
if pedal.multi_states[mp.midi_ch, pedal.type.SUS] = TRUE
ivls.reparent_voice(NodeEnv[nenv].sentVoice, pedal.runtime[mp.midi_ch, pedal.type.SUS])
end if
keys.KeyBuffer.append(mp.midi_ch, NodeEnv[nenv].sentVoice)NotePass¶
Process voices without consuming them (pass-through):
node Stl.RoundRobins:
cb NotePass:
rr.result := ivls.RoundRobins.query_rr(self)
if rr.result = -1
message("Couldn't calculate RR!")
else
Voice[self].rr := rr.result
ivls.RoundRobins.advance_rr(self)
end ifVoiceConstructor / VoiceDestructor / VoiceCopyConstructor¶
Lifecycle hooks triggered by Voice.new(), Voice.delete(), Voice.copy(). Access ref (the Voice reference).
node Ivls.VMC:
cb VoiceDestructor:
VMC.remove_ref(Voice[ref].vmc)
EMCache.delete(Voice[ref].emc)
cb VoiceCopyConstructor:
VMC.add_ref(Voice[ref].vmc)PathCancellation¶
Triggered when a voice path is interrupted (e.g., parent released during a wait).
Code Generation Callbacks¶
Functions / Macros¶
Define functions and macros globally, outside any KSP callback:
node Ivls.VoiceOps:
cb Functions:
function ivls._fire_new_child(vo, vo_pa)
ivls._fire_voice(vo)
ivls.add_child_to_parent(vo, vo_pa)
end function
cb Macros:
macro for_each_child(#v#)
if check_ref(Voice, #v#)
declare parent := #v#
declare iter_child := Voice[parent].vo_child
declare sibling
while (check_ref(Voice, iter_child))
sibling := Voice[iter_child].vo_right
end macro
macro end_for_each_child()
iter_child := sibling
end while
end if
end macroFlows / Keymaps¶
Flows configures voice processing flows during FirstLoad. Keymaps configures keyboard mappings during reload.
node Fades:
cb Flows:
fades.in_flow := ivls.new_flow()
fades.out_flow := ivls.new_flow()
ivls.register_node(fades.in_flow, FadeIn)
ivls.register_node(fades.out_flow, FadeOut)Callback Execution Order¶
Initialization (on init)¶
Init-> 2.ICB-> 3.PostInit-> 4.Post_ICB
Persistence Changed (on persistence_changed)¶
FirstLoad(first load only) -> 2.Pre_PCCB/PreReload-> 3.PCCB/Reload-> 4.Post_PCCB/PostReload
Runtime Events¶
- Note:
KNCB,KRCB - Voice:
NoteOn,NoteOff,NotePass - Controllers:
CC,PolyAT - Timers:
LCB,TimerBeatTick,TimerMsTick - Transport:
TransportStart,TransportStop - UI:
KUI/KUICB,UICBS - Async:
ACCB/AsyncResponse - PGS:
PGS
Callback Reference Table¶
| Callback | Trigger Context | Primary Use |
|---|---|---|
Init |
on init |
Variable declarations |
ICB |
on init |
Initial configuration |
PostInit / Post_ICB |
on init |
Cross-node / final init |
FirstLoad |
on persistence_changed |
One-time setup |
Pre_PCCB / PreReload |
on persistence_changed |
Pre-reload prep |
PCCB / Reload |
on persistence_changed |
State restoration |
Post_PCCB / PostReload |
on persistence_changed |
Post-reload finalization |
KNCB / KRCB |
on note / on release |
MIDI note events |
CC |
on controller |
MIDI CC |
PolyAT |
on poly_at |
Polyphonic aftertouch |
PGS |
on pgs_changed |
Inter-script comms |
ACCB / AsyncResponse |
on async_complete |
Async operations |
TimerBeatTick / TimerMsTick |
on listener |
Timer events |
TransportStart / TransportStop |
on listener |
DAW transport |
KUI / KUICB |
on ui_update |
UI refresh |
UICBS |
on ui_controls |
UI interaction |
UIOpen / UIClose |
Dev/production mode | UI visibility |
ProductionUI |
Production mode | Final UI setup |
NoteOn / NoteOff / NotePass |
Voice processing | Voice events |
VoiceConstructor / VoiceDestructor |
Voice.new() / .delete() |
Voice lifecycle |
VoiceCopyConstructor |
Voice.copy() |
Voice copying |
PathCancellation |
Wait interruption | Path cleanup |
Functions / Macros |
Compile-time | Code definitions |
Flows / Keymaps |
FirstLoad / Reload |
Configuration |