-- midi-daemon Lua stdlib — loaded into every route before its script.
-- All symbols defined here are globals available without any require/dofile.
--
-- OSC subscribe/unsubscribe/heartbeat/param-dispatch is handled automatically
-- by Rust when a route declares osc.params in its init() return table:
--
-- function init()
-- return {
-- inputs = {"midi"}, outputs = {"midi"},
-- osc = {
-- receive = 9000,
-- params = {
-- bpm = { set = function(v) set_bpm(v) end, get = get_bpm },
-- mute = { set = function(v) muted = (v ~= 0) end,
-- get = function() return muted and 1 or 0 end },
-- stop = { set = function() running = false end },
-- },
-- },
-- }
-- end
--
-- With params declared this way, the Rust event loop:
-- • handles /route/subscribe, /route/unsubscribe, /route/heartbeat
-- • dispatches /route/<param> to the appropriate set/get callback
-- • sends /route/heartbeat to subscribers every 5 s
-- • evicts expired subscribers automatically
--
-- on_osc (if defined) still fires for every OSC message after param dispatch.
-- on_tick (if defined) still fires on every timer tick after the heartbeat tick.