Skip to content

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 on

on 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 on

on 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 on

on 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 on

on 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 on

on 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 on

on 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 on

on 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 on

on 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 on

Summary 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