Clip Launcher à la Bitwig/Ableton, Launchpad, Maschine…

Probably an obvious idea but not finding a post about it, here. Anyone has a script doing the kind of clip launching as done in Bitwig Studio or Ableton Live? The same principle is applied to Remixlive and Ampify Launchpad on iOS, not to mention 8x8 grid-based instrument like the Novation Launchpad, Native Instruments Maschine, and Ableton Push.
Shouldn’t be too hard to emulate the basic functionality. Should even work with the ROLI Lightpad Block. A challenge could be to time everything together, but SPi has what’s needed to make that work.
Remember some examples of people on the list doing Techno jukebox kind of thing, with an interface using OSC. Thinking more of: you setup a folder of clips, run the script, and you can launch clips from a MIDI device. Easy as Pi.
Thoughts?

This was my TouchOSC jukebox controller, but it largely uses a script external to Sonic Pi. https://rbnrpi.wordpress.com/a-touchosc-jukebox-for-sonicpi/
(Has a link to a video at the bottom)
As you say, should be possible to do something within Sonic Pi, detecting a midi input (midi-cc>) and using it to trigger clips to play using run_file or run_code.

Had a little play and got this. As you say syncing could be a bit tricky. Here 11 code clips each paly a diffferent scale. One midi rotary on my keyboard (controls control_change 10) selects the clip and a button the the keyboard (control_change 25) starts it playing. You can overlap “plays” as the code runs in a thread.

#testing run_code clips

codelist  = []
11.times do |x| #generate some code clips
  codelist[x]="use_synth :tri;play_pattern_timed scale(48+"+x.to_s+",:major),0.2,release: 0.2"
  puts x,codelist[x]
end

set :codelist,codelist #store the clip array



live_loop :select do #select the clip id to play (0->10)
  use_real_time
  n= sync "/midi/*/*/*/control_change"
  if n[0]==10
    v=(n[1].to_f/127*10).to_i
    puts "value #{v} selected"
    set :v,v #store required ID in :v
  end
end

live_loop :clip_start do #play the selected clip
  use_real_time
  n= sync "/midi/*/*/*/control_change"
  if n[0]==25 and n[1]==127 #triggers when button pressed (output 127)
    cl=get(:codelist) #get array of clips
    in_thread do #play in thread so that more than one can be triggered at once
      run_code cl[get(:v)] #play the required clip using run_code
    end
  end
end

Had a further play. added scales going up and down, and a heartbeat live_loop to enable playback sync to the nearest note (they are spaced 0.2 apart).
Here is the code:

#testing run_code clips

codelist  = []
11.times do |x| #generate some code clips. see the code in the printout on the log screen
  codelist[x]="use_synth :tri;sync :heartbeat;n=scale(48+"+x.to_s+",:major,num_octaves: 2);n=n.reverse if "+x.to_s+"%2==1;play_pattern_timed n,0.2,release: 0.2"
  puts x,codelist[x]
end

set :codelist,codelist #store the clip array

live_loop :heartbeat do #heartbdat used to give sync cues
  sleep 0.2
end


live_loop :select do #select the clip id to play (0->10)
  use_real_time
  n= sync "/midi/*/*/*/control_change"
  if n[0]==10
    v=(n[1].to_f/127*10).to_i
    puts "value #{v} selected"
    set :v,v #store required ID in :v
  end
end

live_loop :clip_start do #play the selected clip
  use_real_time
  n= sync "/midi/*/*/*/control_change"
  if n[0]==25 and n[1]==127 #triggers when button pressed (output 127)
    cl=get(:codelist) #get array of clips
    in_thread do #play in thread so that more than one can be triggered at once
      run_code cl[get(:v)] #play the required clip using run_code
    end
  end
end

here is a recording of multiple overlapping “plays” of different clips. When a clip is started it syncs to the next note pulse.
https://drive.google.com/open?id=1N7E914Rh0PuLZgQCWLHMiyq1wS_EWE4q