Simple (!?!) Sequencer Setup - part 1 of?

Mahalo Sonic Pilots!
Thought that I would report in on my current progress with an Idea I had to program a simple sequencer with Sonic Pi and my 8x8 Monome.

The end goal was to be able to program some beats from here (apologies for profanity in the url - not mine):

with this in mind I wanted the top 2 rows to be an “sample select” the next 2 to be an indicator of where the current step is and the next 2 rows to toggle the step on or off.

Results below - I can successfully program a basic “Boots and cats” 16 bar beat using the 3 sample and add more trivially.

Clearly none of this would have been possible without the amazing (and much more fully featured libraries) shared by @Martin here that I grokked my way through and lifted large sections of:

# Welcome to Sonic Pi

use_osc "localhost", 11117

#Initialise Variables to Hold Monome and track state
pages = []
page0 = [ [0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]]
pages.push(page0)

#Lookup to convert button index to BCD
lookup = [1,2,4,8,16,32,64,128]

set :pages, pages
set :active_sound, 0

#Update Grid Lights with active sound selection, step number and sequence value
define :update_grid do
  active = get :active_sound
  ##| pages = get :pages
  p = pages[0]
  #Clear entire Monome before resetting
  osc "/monome/grid/led/all",0
  #Show active Sample
  x,y = n2c(active)
  #Rows 4 and 5 to show sequence steps that are active
  row1 = p[active][0]
  row2 = p[active][1]
  #Very ugly conversion from array values to row values
  puts p[active][0].to_s(2).rjust(8,'0').reverse + p[active][1].to_s(2).rjust(8,'0').reverse
  puts (bools (p[active][0].to_s(2).rjust(8,'0').reverse + p[active][1].to_s(2).rjust(8,'0').reverse).chars)
  osc "/monome/grid/led/set",x,y,1
  osc "/monome/grid/led/row",0,4,row1
  osc "/monome/grid/led/row",0,5,row2
  
end

define :page_set do | sound, line, s, page = 0 |
  p = pages[page]
  p[sound][line] = s
  pages[page] = p
  puts "---------------------- Page: #{p} --------------"
  puts "---------------------- Pages: #{pages} --------------"
  set :pages, pages
end

define :page_all do | s, page = 0 |
  p = []
  15.times do
    p.push(s)
  end
  pages[page] = p
  set :pages, pages
end

define :pages_print do
  get(:pages).length.times do | p |
    row = ""
    puts "Page #{p}: ----------------"
    get(:pages)[0].length.times do | y |
      row += get(:pages)[p][y].to_s
      puts get(:pages)[p][y].to_s
    end
    puts "------------------------"
  end
end

define :c2n do | x, y |
  num = x.to_i + 8 * y.to_i
  return num
end

define :n2c do | n |
  x = n % 8
  y = n / 8
  coords = [x.to_i, y.to_i]
  return coords
end

live_loop :listen_monome do
  use_real_time
  x, y, s = sync "/osc:127.0.0.1:11117/monome/grid/key"
  pressed = c2n(x, y)
  if s == 1
    case pressed
    
    when 0
      page_init(0)
    when 1..15
      set :active_sound, pressed
      update_grid
    when 32..39
      value = lookup[x]
      active = get(:active_sound)
      p = pages[0]
      puts p
      old_value = p[active][0]
      puts old_value
      puts "Bitwise:  " + (old_value & value).to_s
      if (old_value & value) == 0
        puts "ADDED !!!"
        page_set(active,0,old_value+value)
        pages[0] =p
        set :pages, pages
        puts pages_print
        update_grid
      else
        puts "REMOVED !!!"
        page_set(active,0,old_value-value)
        pages[0] =p
        set :pages, pages
        puts pages_print
        update_grid
      end
      
    when 40..47
      value = lookup[x]
      active = get(:active_sound)
      puts value
      p = pages[0]
      puts p
      old_value = p[active][1]
      puts old_value
      puts "Bitwise:  " + (old_value & value).to_s
      if (old_value & value) == 0
        puts "ADDED !!!"
        page_set(active,1,old_value+value)
        puts pages_print
        update_grid
      else
        puts "REMOVED !!!"
        page_set(active,1,old_value-value)
        puts pages_print
        update_grid
      end
    end
  end
end

define :pattern do |pattern|
  return pattern.ring.look == "1"
end

live_loop :play_stuff do
  #Play the samples if the patterns are active
  x,y = n2c(look)
  patterns = []
  get(:pages).length.times do | p |
    get(:pages)[0].length.times do | y |
      patterns.push(get(:pages)[p][y][0].to_s(2).rjust(8,'0').reverse + get(:pages)[p][y][1].to_s(2).rjust(8,'0').reverse)
    end
  end
  
  sample :drum_bass_hard if pattern patterns[2]
  sample :sn_generic if pattern patterns[3]
  sample :hat_snap if pattern patterns[4]
  
  
  osc "/monome/grid/led/set",x,y+2,1
  
  if look == 15
    tick_reset
  end
  tick
  sleep 0.125
  
  
  osc "/monome/grid/led/set",x,y+2,0
end