Capture_Nearest_Instrument_From_Pattern

Oh well I really don’t like to make a topic about this problem (probably a very silly one).

I’ve been stuck for a couple of days with capture_nearest_instrument_from_pattern :(
I’m really confused - how is it supposed to work or what should it return?
Only thing I can get out of it is nil if I run this

captured_instrument = renoise.song():capture_nearest_instrument_from_pattern()  
print(captured_instrument)  

If someone could post a simple example of how it works I’d be really grateful.

Hi eeter.

capture_nearest_instrument_from_pattern is a “method” which is shown by the colon after renoise.song(). It will do something and not necessarily return something to print.

If you run what you have posted in the test pad, you will see that on execution renoise will capture the nearest instrument from the pattern in the instrument list (presuming there is a song and instruments there etc.). It works as though you had used the renoise feature yourself [pressed shift+return] in a song.

according to the documentation, this function does not return anything: it should only perform the operation of capturing the instrument. It would be indeed reasonable to return the captured instrumet

It would be comfortable, but ain’t necessary.
Once you have executed that function, simply call the routine to fetch the currently selected instrument and you are done.
renoise.song().selected_instrument_index

Perhaps, you need to add a notifier that watches instrument selection changes meanwhile, just for security reasons.
renoise.song().selected_instrument_index_notifier:add_observable(changed_instrument)

Thanks guys!
According to this false bug-report https://forum.renoise.com/t/auto-capture-instrument/29561 the Ledgers AutoCaptureFromFirstNote script was preventing the capture_nearest_instrument_from_pattern method to take effect. - And that’s why I was so confused in the first place.

But I got it now. Hmm… That makes things a bit bit more complicated for me. Would be great if there was a method to just get the nearest instrument index from anywhere you want and not depending on where’s the cursor at and not changing the selected instrument.

This may help, just paste into testpad and execute. It should print the index you want but not capture the instrument i.e. returns the selected instrument to the initial one:

   
local current_instrument = renoise.song().selected_instrument_index --get current index  
  
renoise.song():capture_nearest_instrument_from_pattern() --capture  
  
local captured_index = renoise.song().selected_instrument_index --get captured index  
  
 print(captured_index)  
 renoise.song().selected_instrument_index = current_instrument --return to initial instrument  
  

Edit: though I am not quite sure what you mean by “not depending on where’s the cursor at” as the capture depends on this? i.e. how would it know what instrument you are after?

edit 2: if you mean to work similarly to my autocapture script, then you need to do this with a track iterator.

I think he rather means that the instrument is not selected but simply an instrument index is returned.

In that case you indeed need to create your own instrument catcher by simply scanning the lines around the cursor using a track-iterator.

Indeed. But the snippet he gave was really useful though.
To accomplish what I’m up to I guess I have to just scan the whole song line by line, pattern by pattern, track by track and column by column and then collect all the instrument data to a table… Let’s see. I hope it won’t become too slow. I just wished there was a better way to do it.

The whole song?
I believe even the internal routine does not scan further than the current pattern…
If it would have to extent song-wise, i would go no further than the current track.
Also don’t forget to check if a subcolumn is visible or hidden. Note-data in hidden subcolumns are still readable by scripts and may cause confusion if you don’t know that the script has processed hidden data.

@ eeter is it possible to say exactly what you are trying to achieve with your script or is it something you do not wish to disclose?

it could be easier to point you in a useful direction and save you a bit (or maybe a lot) of time.

Sorry it took so long to reply.
Here’s the core of what I wanted to do. It finds and stores all the instrument indexes which are used on a track from whole song. Beginner as I am this code really sucks and it’s slow. So better test it on some shorter song ;)
There’s also a bug which I haven’t figured out yet how to avoid it - when there’s no note data on the first pattern on a track it just adds the selected instrument index.

renoise.app():show_status("Processing... Please wait...")  
  
local tracks = renoise.song().tracks  
local track_count = table.getn(tracks)  
local instruments = renoise.song().instruments  
local patterns = renoise.song().patterns  
local current_track = renoise.song().selected_track_index  
local current_instrument = renoise.song().selected_instrument_index  
local current_note_column = renoise.song().selected_note_column_index  
local current_pattern = renoise.song().selected_pattern_index  
local current_line = renoise.song().selected_line_index  
  
local line_step = 4  
  
local tracks_and_instruments = {}  
  
for i, v in ipairs(tracks) do  
 if tracks[i].visible_note_columns > 0 then   
 renoise.song().selected_track_index = i   
 table.insert(tracks_and_instruments, i)  
 tracks_and_instruments[i] = {}  
  
 for i, v in ipairs(patterns) do  
 renoise.song().selected_pattern_index = i  
  
 for i=1, renoise.song().selected_track.visible_note_columns, 1 do  
 renoise.song().selected_note_column_index = i  
  
 for i=1, renoise.song().selected_pattern.number_of_lines, 2 do -- line step = 2  
 renoise.song().selected_line_index = i  
  
---################## Collecting data to tracks_and_instruments  
  
 renoise.song():capture_nearest_instrument_from_pattern()  
  
 local selected_instrument = renoise.song().selected_instrument_index  
 local instrument_belongs_to_track_already = false  
 local no_instruments_found_yet = true  
  
-- detecting if instrument belongs to the track already, to avoid adding it twice  
 for i=0, table.getn(tracks_and_instruments[renoise.song().selected_track_index]) , 1 do  
 if instrument_belongs_to_track_already == false then  
  
 if tracks_and_instruments[renoise.song().selected_track_index][i] == selected_instrument then  
 instrument_belongs_to_track_already = true  
 end  
  
 end  
 end  
  
-- Adding a new entry to table tracks_and_instruments if the instrument doesn't belong to the track  
 if instrument_belongs_to_track_already == false then  
 table.insert(tracks_and_instruments[renoise.song().selected_track_index], selected_instrument)  
 end  
  
---################### End of collecting data to tracks_and_instruments  
  
 end  
 end   
 end   
 end  
end  
  
-- Restoring the position  
  
renoise.song().selected_track_index = current_track  
renoise.song().selected_instrument_index = current_instrument  
renoise.song().selected_note_column_index = current_note_column  
renoise.song().selected_pattern_index = current_pattern  
renoise.song().selected_line_index = current_line  
  
rprint(tracks_and_instruments)  
  
renoise.app():show_status("Done!")  

I hope you guys have some ideas and can help me out a bit here.
And make sure you tell me if I’m doing something terribly wrong :)

Well for starters you could replace this line:
local current_instrument = renoise.song().selected_instrument_index
for
local current_instrument = -1

Then when you are working with your routines, you need to insert conditions to check if the current instrument is actually filled in or not before processing any specific data.
If you don’t use these conditions, you get errors pretty quickly but these errors allow you to get some insight on what goes exactly wrong where in your code.