Skip to content

TouchOSC Snippets

  • PUBLISHED: 2024-2-8
  • UPDATED: 2024-2-17

A collection of my code snippets for Touch OSC.

Debugging

Debug Frame
function debugFrame(obj)
  print(obj.name .. ' ( ' .. obj.frame.x .. ', ' .. obj.frame.y .. ', ' .. obj.frame.w .. ', ' .. obj.frame.h .. ')')
end
Debug Lua Table
function debugTableInternal(tableName, table)
  local s = "TABLE: " .. tableName .. " {" 
  for k, v in pairs(table) do
    if(type(v) == "table") then
      local sDeep = debugTable(tostring(k), v)
      if (sDeep ~= nil) then
        s = s .. sDeep 
      end

    end
    s = s .. k .. ": " .. tostring(v) .. ", "
  end
  s = string.sub(s, 1, -3)
  s = s .. "}"
  return s
end
function debugTable(tableName, table)
  print(debugTableInternal(tableName, table))
end

Per Frame Updates

update()
Update Callback
function update()
  print(self.name, 'update') 
end

Values

onValueChanged()
function onValueChanged(key)
  if (key == "x") then

  end
  if (key == "touch") then

  end
  if (key == "x" and self.values.touch) then

  end
end
function onValueChanged(key)
  if key == "touch" and self.values.touch then

  end
end
function onValueChanged(key)
  if key == "x" and self.values.touch then

  end
end
function onValueChanged(key)
  print(key, self.values[key])
end
Set Value
self.parent.values.x = 1

Notify

onReceiveNotify()
function onReceiveNotify(key, value)
  if key == "" then

  end
end
function onReceiveNotify(key, value)
  print(self.name, 'onReceiveNotify')
  print('\t key   =', key)
  print('\t value =', value)
end
control:notify()
self.parent:notify("update", 1)
self.parent:notify("update", {obj=self, value=1})

OSC

onReceiveOSC()
OSC Callback - Single Value
function onReceiveOSC(message, connections)
  local path = message[1]
  local arguments = message[2]
  if path=="/" then
    local v = arguments[1].value

  end
end
OSC Callback - Loop Values
function onReceiveOSC(message, connections)
  local path = message[1]
  local arguments = message[2]
  if path=="/" then
    for i=1,#arguments do
      local tag = arguments[i].tag
      local v = arguments[i].value
    end
  end
end
function onReceiveOSC(message, connections)
  print(self.name, 'onReceiveOSC')
  local path = message[1]
  local arguments = message[2]
  print('\t path        =', path)
  for i=1,#arguments do
    print('\t argument    =', arguments[i].tag, arguments[i].value)
  end
  print('\t connections =', table.unpack(connections))
end
sendOSC()
-- -----------------------------------------
-- Send simple OSC messages
--
-- arguments are auto-converted to
-- boolean, float or string (not integer!)
-- -----------------------------------------

-- send on all configured connections (1-5)
sendOSC('/simple')
sendOSC('/ping', 'pong')
sendOSC('/on', true)
sendOSC('/1/fader1', 0.5)
sendOSC('/3/xy1', 0.25, 0.75)
sendOSC('/mixedarguments', 'Hello', 1, true, 'World')

-- send only on connections 1 and 2
sendOSC('/1/fader1', 0.5, { true, true })

-- send only on connections 1 and 3
sendOSC('/3/xy1', 0.25, 0.75, { true, false, true })

-- send only on connections 1 and 5
sendOSC('/mixedarguments', 'Hello', 1, true, 'World', { true, false, false, false, true })
-- -----------------------------------------
-- Send complex OSC messages
-- with argument type tags
-- -----------------------------------------

sendOSC(
  -- message
  {
    -- path
    '/complex',

    -- argument list
    {
      { tag = 'T' },                                     -- true
      { tag = 'F' },                                     -- false
      { tag = 'N' },                                     -- nil
      { tag = 'I' },                                     -- infinitum
      { tag = 'i', value = 42 },                         -- int32
      { tag = 'f', value = 3.14 },                       -- float32
      { tag = 's', value = 'Goodbye Cruel World' },      -- string
      { tag = 'b', value = { 0xC0, 0x00, 0x10, 0xFF } }  -- blob
    }
  },
  -- connections
  {
    true, -- 1
    true, -- 2
    true, -- 3
    true, -- 4
    true  -- 5
  }
)

Math

Map: Remap a value to a different range
function map(value, oldMin, oldMax, newMin, newMax)
  return (((value - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin
end

Tables

Deep Table Clear
function deepClear(t)
  for k, v in pairs(t) do
    if type(v) == "table" then
      deepClear(v)
    end
    t[k] = nil
  end
end

-- Example usage:
myTable = {
  a = {
    b = {
      c = "value"
    }
  },
  d = "another value"
}

deepClear(myTable)
Find nearest value in table
function findClosestValue(table_index, value)
  local value_dif = 20000
  local num_items = #table_index
  local lowest_index = 0
  for index, table_value in pairs(table_index) do
    local dif = math.abs(table_value - value)

    if(dif < value_dif) then
      value_dif = dif
      lowest_index = index
    end
  end

  return lowest_index
end

Finding Objects

All Object Based On Tag
local t = self.parent:findAllByProperty('tag', '3/6', true)
print(#t)
for i=1, #t do
  print(t[i].name)
  print(t[i].parent.name)
end
Find All Objects Based on Tag With Full Path
local objs = root:findAllByProperty("tag", "3/5", true)
-- print all object names and their path to root
for i, obj in ipairs(objs) do
  print(obj.name .. " " .. getPathToRoot(obj))
end

function getPathToRoot(obj)
  local path = obj.name
  local parent = obj.parent
  while parent ~= nil do
    path = parent.name .. "/" .. path
    parent = parent.parent
  end
  return path
end
Find Objects via Table of Names
--Deep Search
local obj = {"A", "B","C","D"}
for key, name in ipairs(names) do 
  local obj = self.parent:findByName(name, true)
end
--one level search
local obj = {"A", "B","C","D"}
for key, name in ipairs(names) do 
  local obj = self.parent:findByName(name, false)
end
--Loop Thru objects
local obj = {"A", "B","C","D"}
for key, name in ipairs(names) do 
  local obj = self.parent.children[name]
end

Object Layouts

Object Layout - Even vertical spacing top to bottom
function layout()
local spacing = 15
local coiunt = 10
for index=led_count, 1, -1 do
    local box = "box" .. index

    self.children[box].frame.y = index * - spacing + led_count*spacing
  end
end
layout()

Pointers

Translate x/y To ScreenSpace
function translateToScreenSpace(obj, localX, localY)
    if obj.parent == nil then
        return localX + obj.x, localY + obj.y
    else
        local parentX, parentY = translateToScreenSpace(obj.parent, localX, localY)
        return parentX + obj.x, parentY + obj.y
    end
end

Timers

Control Double-tap
local delay = 300
local last = 0

function onValueChanged()
  if(not self.values.touch) then
    local now = getMillis()
    if(now - last < delay) then
      print('double tap!')
      last = 0
    else
      last = now
    end
  end
end
Send Periodic Message
local delay = 1000 -- every 1000ms = 1s
local last = 0

function update()
  local now = getMillis()
  if(now - last > delay) then
    last = now
    sendOSC('/ping')
  end
end

Accelerometer

Get accelerometer Data
if(hasAccelerometer()) then
  update = function()
    local values = getAccelerometer()
    sendOSC('/accxyz', table.unpack(values))
  end
end