Nodes¶
Nodes are the fundamental organizational unit in IVLS. They encapsulate state, callbacks, functions, and macros into modules that are registered and dispatched by the IVLS system.
Declaration¶
node NodeName:
cb CallbackName:
// code
end nodeCallbacks end implicitly when the next cb begins or end node is reached.
Minimal Example¶
{{ MyNode }}
node MyNode:
cb Init:
family mn
declare value := 0
end family
cb NoteOn:
ivls.SendSelf()
cb Functions:
function mn.process(x) -> result
result := x * mn.value
end function
end nodeInheritance¶
Nodes inherit from parent nodes using from. The child can override or extend virtual callbacks.
node ChildNode from ParentNode:
// child body
end nodeVirtual Callbacks (__VIRTUAL__, __PARENT__)¶
The parent defines extension points with __VIRTUAL__(). The child provides implementations:
node Stl.PlayEvent.Template:
cb NoteOn:
declare event.note := Voice[self].note
declare event.vel := Voice[self].vel
__VIRTUAL__(EventArgs)
Voice[self].event := play_note(event.note, event.vel, 0, 0)
__VIRTUAL__(EventGroups)
cb NoteOff:
__VIRTUAL__(EventDismiss)
end node
node Stl.PlayEvent from Stl.PlayEvent.Template:
cb Init:
family event
declare groups[10000] := (FALSE)
end family
cb EventArgs:
__RUN_CB__(EventArgs)
cb EventGroups:
__RUN_CB__(EventGroups)
cb EventDismiss:
__RUN_CB__(EventDismiss)
end nodeThe compiler replaces __VIRTUAL__(EventArgs) in the template with the child's cb EventArgs: body.
Callback Blocks¶
| Category | Callbacks |
|---|---|
| Lifecycle | Init, ICB, PostInit, Post_ICB |
| Persistence | FirstLoad, Pre_PCCB/PreReload, PCCB/Reload, Post_PCCB/PostReload |
| Voice | NoteOn, NoteOff, NotePass |
| Events | KNCB, KRCB, CC, PolyAT |
| Timers | LCB, TimerMsTick, TimerBeatTick, TransportStart, TransportStop |
| UI | KUI/KUICB, UICBS, UIOpen, UIClose |
| Async | ACCB/AsyncResponse, PGS |
| Codegen | Functions, Macros, Flows, Keymaps |
| Lifecycle hooks | VoiceConstructor, VoiceDestructor, VoiceCopyConstructor, PathCancellation |
node Stl.Midi:
cb Init:
family midi
declare const NOTES := 128
declare last_note
declare last_vel
end family
cb CC:
midi.cc[MIDI_CHANNEL, CC_NUM] := CC[CC_NUM]
cb KNCB:
midi.last_note := EVENT_NOTE
midi.last_vel := EVENT_VELOCITY
cb Functions:
function midi.get_note_octave(note) -> oct
oct := (note / 12)
end function
end nodeNamespacing¶
IVLS uses dot-notation for node names. At compilation, dots become double underscores.
| Namespace | Purpose |
|---|---|
Ivls.* |
Core IVLS framework |
Stl.* |
Standard Library |
Ext.* |
Extended Library |
| Custom | Application-specific |
Template Pattern¶
node Stl.PlayEvent.Template:
cb NoteOn:
// base implementation with __VIRTUAL__() hooks
end node
node Stl.PlayEvent from Stl.PlayEvent.Template:
cb EventArgs:
// override virtual callback
end nodeThe {{ NodeName }} Comment Convention¶
A visual delimiter placed before node declarations for navigation:
{{ Stl.Lib }}
node Stl.Lib:
cb Init:
set_ui_color(0666666h)
declare bool_validator
cb Functions:
function lib.is_dev_mode() -> result
result := dev_mode[0]
end function
end node
{{ Stl.Lib_Post }}
node Stl.Lib_Post:
cb Init:
if use_ram_report = TRUE
message("Object RAM Load: " & TO_MB(lib_mem) & " MB")
end if
end nodeNode Registration¶
Nodes must be registered via the IVLS_ALL_NODES define to participate in callback dispatch:
define IVLS_BASE_NODES := Ivls.NodeUI, Ivls.STL, Ivls.VoiceOps, ...
define IVLS_NODES := MyApp.Core, MyApp.Synth, MyApp.UI
define IVLS_ALL_NODES := IVLS_BASE_NODES, IVLS_NODES, Stl.Lib_PostRegistration generates:
// Node ID constants
family ivls
const node
literate_macro(#l#) on IVLS_ALL_NODES
end const
end family
// Node name strings
declare !node_names[ivls.node.SIZE]
literate_macro(ivls.node_names[ivls.node.#l#] := "#l#") on IVLS_ALL_NODESRegistration order determines callback execution order and node IDs.
See Also¶
- Callbacks - Full callback reference
- Code Generation -
__RUN_CB__,__VIRTUAL__, literate macros - Defines - Node list defines