Events¶
KSP event handlers use on ... end on syntax. In IVLS, they serve as entry points that dispatch to node callbacks via __RUN_CB__.
on init¶
Executes once at script compilation/load. All declare statements must appear here.
on init
message("")
declare const ON := 1
declare const OFF := 0
SET_CONDITION(NO_SYS_SCRIPT_GROUP_START)
tcm.init(128)
set_snapshot_type(3)
set_key_pressed_support(TRUE)
__RUN_CB__(Init)
__RUN_CB__(ICB)
__RUN_CB__(PostInit)
__RUN_CB__(Post_ICB)
literate_macro(Voice.WriteInitList) on Voice.INIT_LIST
set_listener(NI_SIGNAL_TIMER_MS, 200)
set_listener(NI_SIGNAL_TRANSP_START, 1)
set_listener(NI_SIGNAL_TRANSP_STOP, 1)
end onon note¶
Fires on MIDI note-on.
| Variable | Description |
|---|---|
EVENT_ID |
Unique event identifier |
EVENT_NOTE |
MIDI note number (0-127) |
EVENT_VELOCITY |
Velocity (1-127) |
MIDI_CHANNEL |
Channel (0-15) |
Common functions: play_note(), ignore_event(), disallow_group(), allow_group(), change_note(), change_velo(), change_tune(), change_vol(), change_pan(), set_event_par(), set_event_par_arr().
IVLS intercepts all notes, routes them through voice flows, then dispatches KNCB:
on note
disallow_group(ALL_GROUPS)
ignore_event(EVENT_ID)
if CONDITION.IS_OUTSIDE_EVENT
ivls.play_time := ENGINE_UPTIME
if MIDI_CHANNEL >= 0 and cluster.legal = TRUE and ivls.critical_disable = FALSE ...
and keymap.key_flows[keymap.selected_map, EVENT_NOTE] # -1
ivls.key_parent_vo := Voice.new()
ivls._refurbish_voice(ivls.key_parent_vo)
Voice[ivls.key_parent_vo].note := EVENT_NOTE
Voice[ivls.key_parent_vo].vel := EVENT_VELOCITY
Voice[ivls.key_parent_vo].midi_ch := MIDI_CHANNEL
// ... voice setup and flow routing ...
wait(keymap.key_latency_us[keymap.selected_map, EVENT_NOTE])
Voice._process(ivls.play_vo)
end if
end if
__RUN_CB__(KNCB)
end onon release¶
Fires on MIDI note-off.
Same variables as on note. Additional functions: note_off(), fade_out(), get_event_par().
on release
if CONDITION.IS_OUTSIDE_EVENT and ivls.key_parent_vo # ivls.omni_voice
Voice[ivls.play_vo].midi_duration := ENGINE_UPTIME - ivls.play_time
wait(keymap.key_latency_us[keymap.selected_map, EVENT_NOTE])
wait_ticks(ivls.RELEASE_EXTENSION_TICKS)
wait(DURATION_SIXTEENTH / 8)
Voice[ivls.play_vo].input := ivls.input_type.VOICE_OFF
Voice._process(ivls.play_vo)
Voice.delete(ivls.key_parent_vo)
end if
__RUN_CB__(KRCB)
end onon controller¶
Fires on MIDI CC.
| Variable | Description |
|---|---|
CC_NUM |
Controller number (0-127) |
CC[n] |
Current CC value |
MIDI_CHANNEL |
Channel (0-15) |
VCC_MONO_AT |
Virtual CC: channel aftertouch (128) |
VCC_PITCH_BEND |
Virtual CC: pitch bend (129) |
on controller
__RUN_CB__(CC)
end onon listener¶
Fires on timer signals and transport events. Enable in on init with set_listener().
| Signal | Description |
|---|---|
NI_SIGNAL_TIMER_MS |
Millisecond timer tick |
NI_SIGNAL_TIMER_BEAT |
Beat timer tick |
NI_SIGNAL_TRANSP_START |
DAW transport started |
NI_SIGNAL_TRANSP_STOP |
DAW transport stopped |
on listener
__RUN_CB__(LCB)
if NI_SIGNAL_TYPE = NI_SIGNAL_TIMER_BEAT
__RUN_CB__(TimerBeatTick)
end if
if NI_SIGNAL_TYPE = NI_SIGNAL_TIMER_MS
__RUN_CB__(TimerMsTick)
end if
if NI_SIGNAL_TYPE = NI_SIGNAL_TRANSP_START
__RUN_CB__(TransportStart)
end if
if NI_SIGNAL_TYPE = NI_SIGNAL_TRANSP_STOP
__RUN_CB__(TransportStop)
end if
end onon persistence_changed¶
Fires when persistent state is loaded (instrument load, snapshot recall, preset load).
on persistence_changed
cluster.legal := FALSE
Voice.clear_pool()
NodeEnv.clear_pool()
if ivls.first_load = TRUE
__RUN_CB__(FirstLoad)
ivls.first_load := FALSE
end if
__RUN_CB__(Pre_PCCB)
__RUN_CB__(PreReload)
__RUN_CB__(PCCB)
__RUN_CB__(Reload)
if ivls.critical_disable = FALSE
cluster.legal := TRUE
end if
__RUN_CB__(Post_PCCB)
__RUN_CB__(PostReload)
end onon async_complete¶
Fires when an async operation finishes.
| Variable | Description |
|---|---|
NI_ASYNC_ID |
Completed operation ID |
NI_ASYNC_EXIT_STATUS |
1 = success, 0 = failure/cancelled |
on async_complete
__RUN_CB__(ACCB)
__RUN_CB__(AsyncResponse)
end onon ui_control / on ui_controls / on ui_update¶
on ui_control(control_var)
// Per-control handler
end on
on ui_controls
__RUN_CB__(UICBS)
end on
on ui_update
__RUN_CB__(KUI)
__RUN_CB__(KUICB)
end onon poly_at / on pgs_changed¶
on poly_at // POLY_AT_NUM, POLY_AT
__RUN_CB__(PolyAT)
end on
on pgs_changed // PGS key modified
__RUN_CB__(PGS)
end onSummary Table¶
| Handler | Trigger | Key Variables | IVLS Callbacks |
|---|---|---|---|
on init |
Compilation/load | -- | Init, ICB, PostInit, Post_ICB |
on note |
MIDI note-on | EVENT_ID, EVENT_NOTE, EVENT_VELOCITY, MIDI_CHANNEL |
KNCB |
on release |
MIDI note-off | EVENT_ID, EVENT_NOTE, MIDI_CHANNEL |
KRCB |
on controller |
MIDI CC | CC_NUM, CC[], MIDI_CHANNEL |
CC |
on listener |
Timer/transport | NI_SIGNAL_TYPE |
LCB, TimerMsTick, TimerBeatTick, TransportStart, TransportStop |
on ui_control |
UI change | Control variable | (per-control) |
on ui_update |
Periodic | -- | KUI, KUICB |
on persistence_changed |
State load | -- | FirstLoad, Pre_PCCB, PCCB, Post_PCCB, etc. |
on async_complete |
Async done | NI_ASYNC_ID, NI_ASYNC_EXIT_STATUS |
ACCB, AsyncResponse |
on pgs_changed |
PGS key modified | -- | PGS |
on poly_at |
Poly aftertouch | POLY_AT_NUM, POLY_AT |
PolyAT |