Make Navigation keys (left, down, right, up) MIDI mappable

I have my MIDI controller set up in such a way that I use the actual computer keyboard as little as possible. One of the things that I seem to constantly come back to using the keyboard for is for the functionality of the arrow keys (left, down, right, up) to navigate in the pattern editor.

Since there is a lot of similar functionality already available in the MIDI mapping (such as next/previous column), would it also be possible to make it so that you can map keys on your midi controller to do these basic navigation functions?

Control of the cursor would be possible to support via the GlobalMidiActions (scripting).

Basically you would take a copy of the file - located in the preferences folder > Scripts (see Help > Show the Preferences folder), paste it into the Renoise application data folder (ā€œ%appdata%/Renoise/V3.1.0/Scriptsā€ on my windows system) and then modify it to taste.

I could create these mappings for you, or you could give it a shot yourself?

If I were to create them, I would want it to be 1:1 with the actual keyboard navigation, meaning that going down one line will eventually make the cursor appear at the top of the pattern - unless the continuous movement option was enabled, in which case it would head into the first line of the next pattern.

One of the things that I seem to constantly come back to using the keyboard for is for the functionality of the arrow keys (left, down, right, up) to navigate in the pattern editor.

Since you want this ā€œhands-offā€ type navigation, perhaps there are other things that you miss in particular?

Let me chew on this and get back to you. FWIW I have no real experience hacking on Renoise, so bear with me.

Hey danoise,

Iā€™d actually really like to learn a little bit of thisā€¦ itā€™s a teach a man to fish versus a catch him a fish sort of thing. Is there anything you can help me to get started? Like documentation about the file formats or any kind of scripting stuff I should learn. I see Lua mentioned a lot in conjunction with Renoise. Always wanted to learn thatā€¦

Thanks.

Navigation in the pattern editor is a perfectly reasonable thing to have built-in as MIDI mappings.

Renoise could (should) arrive with such mappings, ready-to-use. So, instead of learning to ā€œangle with luaā€, let me just do it for you!

But there are plenty of starting points for learning lua scripting in Renoise.

Most importantly, how to configure Renoise for scripting is mentioned on our github page:

https://github.com/renoise/xrnx

Once you have enabled the scripting console you can evaluate code directly from there - makes it really easy to paste a few lines in and see if it works or breaks, and to consult the documentation for the whole Renoise API.

Also, this one about how to program with lua (difference from other languages):

https://forum.renoise.com/t/new-to-lua-but-not-to-programming/29196

In this particular case, I am going to work on a special lua file which defines the Renoise MIDI mappings

https://github.com/renoise/xrnx/blob/master/GlobalMidiActions.lua

Editing this file is a bit special: if you change it you will have to hit the ā€˜reloadā€™ button in the MIDI mapping dialog to apply the changes.

Thanks a lot for your help. Is there some configuration file you created that I need to replace?

Iā€™d like to look more into Lua scripting so I appreciate your guidance on that as well.

OK, here are mappings for next/previous pattern-row that works exactly like the Renoise counterpart (including wrapped edit mode)

I also took time to add the ā€œjump to quarter of patternā€ which are so useful on the QWERTY (F9-F12)

As for next/previous column - those mappings already exist, search for ā€œcolumnā€ in the MIDI-mappings dialog

(they are as fine-grained as the Renoise API currently allows - no character-by-character navigation is possible yet)

Thanks a lot for your help. Is there some configuration file you created that I need to replace?

Yep, the file called GlobalMidiActions.lua. See my previous post where to find it.

First, find this file and open it in a text editor (the Renoise scripting console can be used for this purpose).

Then, to insert it a the right spot, search for a part with the text ā€œ-- Navigationā€ (without quotes), and paste the code below before that text

Finally, save the document and hit the reload button in the MIDI mapping dialog :slight_smile:

-- Navigation:Pattern Rows

add_action("Navigation:Columns:Jump To First Quarter Row [Trigger]",
function(message)
  if message:is_trigger() then
    song().selected_line_index = 1
  end
end)

add_action("Navigation:Columns:Jump To Second Quarter Row [Trigger]",
function(message)
  if message:is_trigger() then
    song().selected_line_index = 1 + song().selected_pattern.number_of_lines/4*1
  end
end)

add_action("Navigation:Columns:Jump To Third Quarter Row [Trigger]",
function(message)
  if message:is_trigger() then
    song().selected_line_index = 1 + song().selected_pattern.number_of_lines/4*2
  end
end)

add_action("Navigation:Columns:Jump To Fourth Quarter Row [Trigger]",
function(message)
  if message:is_trigger() then
    song().selected_line_index = 1 + song().selected_pattern.number_of_lines/4*3
  end
end)

add_action("Navigation:Columns:Move To Next Pattern Row [Trigger]",
function(message)
  if message:is_trigger() then    
    local pattern = song().selected_pattern
    local line_idx = song().selected_line_index
    line_idx = math.min(pattern.number_of_lines,line_idx+1)
    local wrapped_edit = song().transport.wrapped_pattern_edit
    if (line_idx == song().selected_line_index) then
      local seq_length = #song().sequencer.pattern_sequence
      local new_seq_idx = song().selected_sequence_index  
      local new_line_idx = song().selected_line_index
      local last_pattern_in_song = (song().selected_sequence_index == seq_length)
      if last_pattern_in_song then
        if not wrapped_edit then
          new_line_idx = 1
        end
      else
        new_seq_idx = wrapped_edit and new_seq_idx + 1 or new_seq_idx
        song().selected_line_index = 1
      end
      song().selected_sequence_index = new_seq_idx
      song().selected_line_index = new_line_idx
    else
      song().selected_line_index = line_idx
    end
  end
end)

add_action("Navigation:Columns:Move To Previous Pattern Row [Trigger]",
function(message)
  if message:is_trigger() then
    local line_idx = song().selected_line_index
    line_idx = math.max(1,line_idx-1)
    local wrapped_edit = song().transport.wrapped_pattern_edit
    if (line_idx == song().selected_line_index) then
      local first_pattern_in_song = (song().selected_sequence_index == 1)
      local new_seq_idx = song().selected_sequence_index  
      local new_line_idx = song().selected_line_index
      if first_pattern_in_song then
        if not wrapped_edit then
          local pattern_idx = song().sequencer.pattern_sequence[song().selected_sequence_index]
          new_line_idx = song().patterns[pattern_idx].number_of_lines
        end
      else
        new_seq_idx = wrapped_edit and new_seq_idx - 1 or new_seq_idx
        local pattern_idx = song().sequencer.pattern_sequence[new_seq_idx]
        new_line_idx = song().patterns[pattern_idx].number_of_lines
      end
      song().selected_sequence_index = new_seq_idx
      song().selected_line_index = line_idx
    else
      song().selected_line_index = line_idx
    end
  end
end)

Hey,

Sorry I havenā€™t been good at keeping up with this thread. Iā€™m going to try this out now and Iā€™ll let you know how it goes. Also thanks for doing this and giving me the code. This is a cool example to see how Renoise can be extended. Thanks for all your help.

EDIT

Maybe I misunderstood you. I see on Github where you have GlobalMidiActions.lua, however in my Preferences folder under scripts I donā€™t see an existing GlobalMidiActions.lua. I see what looks like things for Renoise plugins/extensions that I already installed. Am I supposed to just drop the modified file from Github in that Scripts directory, or is there somewhere else I should be looking for an existing file to modify?

EDIT 2

Sorry to spam the same postā€¦ tried it out and it worked like a charm!!! Thank you so much!!!

tried it out and it worked like a charm!!! Thank you so much!!!

Great, thatā€™s good to hear.

I include related code for jump into patterns (works fine in R3.1):

function tool_02_CH01_5B()--JUMP NEXT PATTERN
  local song = renoise.song()
  local pos = song.transport.playback_pos
  --print("pos.sequence:", pos.sequence)
  pos.sequence = pos.sequence + 1
  local seq_length = #song.sequencer.pattern_sequence
  --print("number of patterns:", seq_length)
  if (pos.sequence <= seq_length) then
    song.transport.playback_pos = pos
  end
end

function tool_02_CH01_6B()--JUMP PREVIOUS PATTERN
  local song = renoise.song()
  local pos = song.transport.playback_pos
  --print("pos.sequence:", pos.sequence)
  pos.sequence = pos.sequence - 1
  if (pos.sequence >= 1) then
    song.transport.playback_pos = pos
  end
end

function tool_02_CH01_7B()--JUMP NEXT 4 PATTERNS
  local song = renoise.song()
  local pos = song.transport.playback_pos
  --print("pos.sequence:", pos.sequence)
  pos.sequence = pos.sequence + 4
  local seq_length = #song.sequencer.pattern_sequence
  --print("number of patterns:", seq_length)
  if (pos.sequence <= seq_length) then
    song.transport.playback_pos = pos
  end
end

function tool_02_CH01_8B()--JUMP PREVIOUS 4 PATTERNS
  local song = renoise.song()
  local pos = song.transport.playback_pos
  --print("pos.sequence:", pos.sequence)
  pos.sequence = pos.sequence - 4
  if (pos.sequence >= 1) then
    song.transport.playback_pos = pos
  end
end

Also includes condition ā€œIfā€ with numbers to avoid mistakesā€¦

Thanks for the code published in this post. It has served me for my tool.

Hello everybody,

just like our fellowgolfervrsboxer I was looking for a method to MIDI map a few functions and avoid moving my hands from my controller to my keyboard, back and forth.
Thanks to danoise I fixed half of my problem, but actually I need something more: Iā€™d like to map the ā€œINSā€ and ā€œBACKā€ keys in order to insert and delete rows via MIDI.

Do you guys think it should be possible to implement?

Thanks, byebye :walkman:

Insert/delete row in column/track/pattern?

Should be absolutely doable, but perhaps better as a standalone tool. We donā€™t wanna bloat GlobalMidiActions too much :slight_smile:

Yes, actually I was thinking about inserting/deleting rows in a track!
Hopefully this is going to be the kickstart for someone to program the tool I need :slight_smile:

I wish a lot more things were midi mappable. The disk browser, effects browser ā€¦ a la Maschine, everything in the advanced pattern editor, etc. It would be cool to have an entire workflow through controllers.

1 Like