Skip to content

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 node

Lifecycle 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 family

FirstLoad

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] := 64

CC (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 for

LCB / 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 if

Timer 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_CONTROL

Voice 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 if

VoiceConstructor / 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 macro

Flows / 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)

  1. Init -> 2. ICB -> 3. PostInit -> 4. Post_ICB

Persistence Changed (on persistence_changed)

  1. 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