hey! great q’s.
OSC is supported, it’s just up to the script to state how it’d like to handle OSC messages (since each script defines its interactions with controllers – grids, MIDI, OSC, arc, HID, etc).
this raises a different question, though – why don’t more scripts support OSC control out the box? from my understanding, OSC messages aren’t always standardized the way MIDI messages are, since they can be customized and totally arbitrary. it seems that Connection Kit has decided on a particular style, but perhaps the wide variance of approaches contributes to a lack of built-in support in scripts? there’s probably some work to do on the norns documentation, as well – clearer API would help make OSC easier to add.
for now, the OSC-centric norns study is a good place to start unpacking how to work with OSC + norns: https://monome.org/docs/norns/study-5/#numbers-through-air
pretty much, yeah.
using molly as an example, MIDI input is defined starting on line 153.
molly's MIDI input code
-- MIDI input
local function midi_event(data)
local msg = midi.to_msg(data)
local channel_param = params:get("midi_channel")
if channel_param == 1 or (channel_param > 1 and msg.ch == channel_param - 1) then
-- Note off
if msg.type == "note_off" then
-- Note on
elseif msg.type == "note_on" then
note_on(msg.note, msg.vel / 127)
-- Key pressure
elseif msg.type == "key_pressure" then
set_pressure(msg.note, msg.val / 127)
-- Channel pressure
elseif msg.type == "channel_pressure" then
set_pressure_all(msg.val / 127)
-- Pitch bend
elseif msg.type == "pitchbend" then
local bend_st = (util.round(msg.val / 2)) / 8192 * 2 -1 -- Convert to -1 to 1
local bend_range = params:get("bend_range")
set_pitch_bend_all(bend_st * bend_range)
elseif msg.type == "cc" then
-- Mod wheel
if msg.cc == 1 then
set_timbre_all(msg.val / 127)
using the OSC study + your sample OSC messages as an example, you could add a parallel
osc_event function under that
midi_event function which connects received OSC messages with the script’s defined
example code (not tested or totally comprehensive, but should get you started):
function osc_in(path, args, from)
if path == "/Note1" then
osc_note = args
elseif path == "/Velocity1" then
osc_vel = args
if osc_vel > 0 then
osc.event = osc_in
hopefully this helps get you going? lmk!