probable fix https://github.com/monome/norns/pull/1011

I’m playing with devices - so if I change devices and then change which device is in a specific vport, then my things table (devices names in this case) is no longer accurate when I select something with that param action.

Maybe I need to refresh the vports in that action?

That sounds like the right direction…

Is it possible to params:set() the options in an option type?

If the device list changes after the script has run, my parameter option list for device selection becomes incorrect and I’d like to update it. Just not sure how.

FWIW - I hacked this by using params.params[1].options = devicelist but this is less than ideal.

if you’re changing the options it’s likely a fragile usecase and possibly not advised. consider that psets store the number position of the option selected. if the number of options changes, then psets will be an invalid state based on dynamic options changing at runtime.

re: device list, are you trying to replicate some vport stuff inside of the param menu?

I am attempting to provide a param to switch between attached devices for the current script. (see Grid Test) Currently if the devices change after the script loads (new device added, device changes vport position), the param options list will be incorrect. Thus I was attempting to bullet-proof the param listing.

In this particular case, the options list size wont change since it’s mirroring the vports, but I see your point about psets (although I’m not saving state in this script).

Does the Lua environment have a TCP/IP client library? There are a couple of servers I would like to run on my Norns in order to bridge to certain USB devices – e.g. http://openpixelcontrol.org protocol talking to the Fadecandy Server to send visualization data to Neopixel LEDs.

1 Like

not installed by default but you can get it with luarocks install luasocket

https://luarocks.org/modules/luasocket/luasocket

2 Likes

Have you tried Fennel in the meantime? I’m interested too!

I’ve had a bit of a look around here and the docs and can’t seem to see if there is a command to list all the parameters of a script? I’m having a bit of a toy around with an op-z style external ui over OSC and was going to start with mapping some params.

Edit: I did some source digging and found params.params :slight_smile:

I’ve written a little toy to line up hex values common in trackers (like my beloved Adlib Tracker II) with rhythmic counting devices like

  • ta ka di mi
    or
  • 1 e & a 2 e & a 3 e … …

I’m just not sure it’s worthy of a library post?

the code is a little rough, but I'm proud of it and think it might be useful to some!
-- tracker tool
-- ttool
--
-- easy to use rulers for
-- all sorts of tracking
--      scenarios
--
-- TODO: add params
--       for which counts
--       are displayed
--      rather than all at once
--
-- TODO: add custom rulers
--       maybe chord progs
--       ill hardcode some first
--
-- TODO: split counts off into 
--       a little lib
--       so i can store 
--       a default instance 
--       in a var
-- 
-- ---idea:
-- local n = {},{},{}
-- counts = require lib/counts
-- 
-- function init()
--   for i=1,3 do
--     n[i] = counts.newBlank()
--   end
-- 
-- ---lib/counts--------
-- function newBlank()
--   local t = {}
--   local mt = { 
--     __index = function (t, k) 
--       return "---" 
--     end }
--   t = setmetatable(
--     counts.blank, mt)
--   return t
-- end

engine.name = "TestSine"

counts = {
  blank = {},
  hex = {}, -- see hex_mt
  four_four={ 
    
    quarter={
      [1]="one",[5]="two",[9]="three",[13]="four"
    },
  
    eigth={
      [1]="one",[5]="two",[9]="three",[13]="four", 
      [3]="and",[7]="and",[11]="and",[15]="and"
    },
  
    sixteenth={
      [1]="1",[5]="2",[9]="3",[13]="4", 
      [2]="e",[6]="e",[10]="e",[14]="e",
      [3]="&",[7]="&",[11]="&",[15]="&",
      [4]="a",[8]="a",[12]="a",[16]="a"
    },
  
    takadimi={
      "ta", "ka", "di", "mi",
      "ta", "ka", "di", "mi",
      "ta", "ka", "di", "mi",
      "ta", "ka", "di", "mi"
    }
  }
}

local counts_mt = { __index = function (t, k) return "---" end }

local hex_mt = {
  __index = function (t,k) 
    return string.format('%02x', k-1)
  end
}

function counts_metatables()
  -- TODO: apply metatable to each counts.x.y table for x,y
  counts.blank = setmetatable(
    counts.blank, counts_mt)
  counts.four_four.quarter = setmetatable(
    counts.four_four.quarter, counts_mt)
  counts.four_four.eigth = setmetatable(
    counts.four_four.eigth, counts_mt)
  counts.four_four.sixteenth = setmetatable(
    counts.four_four.sixteenth, counts_mt)
  counts.hex = setmetatable(
    counts.hex, hex_mt)
end

function init()
  counts_metatables() 
  
  re=metro.init()
  re=metro.init()
	re.time = 1.0/15
	re.event = function()
	  redraw()
	end
	
	screen_init()
	re:start()
end

function screen_init()
  screen.aa(1)
end

local scroll = 0
local column_positions = {2, 16, 30, 46, 58, 72, 88, 98, 112}
local c_p_hl= { 2, 3, 5, 6, 8, 9 }
local row_offset = 6
local hx,hy = 1,1

function redraw()
  screen.clear()
  
  screen.level(10)
  screen.font_face(1)
  screen.font_size(8)
  
  for i=1,16 do
    
    -- COL 1 -- HEX
    fx_move(
      column_positions[1],
      row_offset*(i-scroll)) -- start @ 2
    screen.text(counts.hex[i])
    
    -- COL 2 -- NOTE 1
    fx_move(
      column_positions[2],
      row_offset*(i-scroll)) -- n1 = start + 14
    screen.text(counts.blank[i])
    
    -- COL 3 -- FX 1
    fx_move(
      column_positions[3],
      row_offset*(i-scroll)) -- f1 = n1 + 14
    screen.text(counts.blank[i])
    
    -- COL 4 -- RULER 1
    fx_move(
      column_positions[4],
      row_offset*(i-scroll)) -- r1 = f1 + 16
    screen.text(
      counts.four_four.takadimi[i])
    
    -- COL 5 -- NOTE 2
    fx_move(
      column_positions[5],
      row_offset*(i-scroll)) -- n2 = r1 + 12
    screen.text(counts.blank[i])
    
    -- COL 6 -- FX 2
    fx_move(
      column_positions[6],
      row_offset*(i-scroll)) -- f2 = n2 + 14
    screen.text(counts.blank[i])
    
    -- COL 7 -- RULER 2
    fx_move(
      column_positions[7],
      row_offset*(i-scroll)) -- r2 = f2 + 16
    screen.text(
      counts.four_four.sixteenth[i])
    
    -- COL 8 -- NOTE 3
    fx_move(
      column_positions[8],
      row_offset*(i-scroll)) -- n3 = r2 + 10
    screen.text(counts.blank[i])
    
    -- COL 9 -- FX 3
    fx_move(
      column_positions[9],
      row_offset*(i-scroll)) -- f3 = n3 + 14
    screen.text(counts.blank[i])
  end 
  
  -- OPERATIONS THAT USE THIS RECTANGLE
  -- AS THEIR TARGERT
  -- NEED TO OPEPRATE ON Y+SCROLL
  screen.level(6)
  fx_rect(
    column_positions[c_p_hl[math.floor(hx)]], 
    row_offset*(math.floor(hy)-1),
    12, row_offset)
  screen.stroke()
  
  screen.update()
end


function fx_move(x,y,fx)
  local xscale,yscale = 1,1
  -- TODO: what if i made everything wiggle by doing something fun in here
  screen.move(x*xscale,y*yscale) 
end

function fx_rect(x,y,w,h)
  local xscale,yscale = 1,1
  -- TODO: what if i made rectangles move around by doing something fun in here
  screen.rect(x*xscale,y*yscale,w,h) 
end

function enc(n,d)
  if n == 1 then
    scroll = util.clamp((scroll + d), 0, 6)
  elseif n == 2 then
    hx = util.clamp((hx + d*0.2), 1,6)
  elseif n == 3 then
    hy = util.clamp((hy + d*0.4), 1,16)
  end
end

Recommendations?

Update: i’ve got the bug. This turned into a tracker using softcut as it’s sampler and it will be finished and released as soon as I can manage it. If anyone wants to help build or test I’m slightly in over my head but having a great time!

4 Likes

pulling a bit of stupid tonight and can’t quite figure this out…

I have a redraw function for the OLED, with a gridredraw inside, and when I do a K1 to go to the menu or params screens, the grid leds stop updating

redraw() is getting called from a beatclock step event

any help?

function gridredraw()
  grid_device:all(0)
  -- function to set grid leds here
  grid_device:refresh()
end 

function redraw()
  gridredraw()
  -- oled update stuff here
end

menu steals the redraw function

call gridredraw separately

1 Like

… or can I just rename redraw()?

put oled stuff in redraw(). if you don’t put it in redraw() it will splatter over the menu screen when you go to the menu.

don’t put non-oled stuff in redraw(). or more generally, anything you want to keep happening while in menu mode

2 Likes

make a grid redraw function on a metro, use dirty flags. this pattern is demonstrated in many scripts.

Thanks!

Was tired, apparently looking at the wrong things, and didn’t find a simple reference to remind myself how to do this.

1 Like

Are there any gentle introductions to using lua/lib/pattern_time.lua for pattern recording? I’m interested in implementing a recorder in one of my scripts, but studying examples makes me feel like it’s still above my head somewhat. No worries if there ain’t…happy to keep studying :sweat_smile:

1 Like

i haven’t used it personally, but it seems rasonably straightforward. i’m looking at earthsea as an example.

each pattern maintains:

  • a list of time-deltas,
  • a matching list of “events”, each of which can be any table,
  • a metro for playback
  • a process function which is called for each event on playback.

e.g. in the case of earthsea, each event includes fields x, y, id, which correspond to grid position and note ID, but these could just as easily be midi events with (msg, channel, data1, data2) or whatever.

usage goes like:

  • p = pattern_time.new makes a new pattern
  • p.process = function(event)...end - set the event handler function
  • p:watch(event) - record the event and its timing, but only if p is in “recording” state
  • p:start(), :stop(), :rec_start(), :rec_stop() - manipulate state
  • p.rec, p.play - check state flags
7 Likes

As always, :bowing_man: This is really approachable.

1 Like