The following code will crash renoise completely. The necessary components of the crash are
add a new pattern to the sequencer
render the new pattern (or a portion of it)
delete the pattern that was just rendered
There seems to be something going on with the :delete_sequence_at() method aswell where the sequence indexes are not properly updated so the next line of code doesn`t work in some cases. I will try to post back a snippet for that too.
--song
local song = renoise.song()
--final pattern index
local final_pattern = #song.sequencer.pattern_sequence
--add a temporary pattern
local pat = song.sequencer:insert_new_pattern_at(final_pattern + 1)
--insert a c-4 in new pattern
-----------------------------
song:pattern(pat):track(1):line(1):note_column(1).note_string = "C-4"
--render newly created pattern
------------------------------------------
--renoise.SongPos objects for render range
------------------------------------------
local start_pos = renoise.SongPos()
local end_pos = renoise.SongPos()
start_pos.line = 1
start_pos.sequence = final_pattern + 1
end_pos.line = 16
end_pos.sequence = final_pattern + 1
--update options table
----------------------
local options = {}
options["start_pos"] = start_pos
options["end_pos"] = end_pos
--prompt user for path
local file_path = renoise.app():prompt_for_filename_to_write("wav", "Save Wav")
--render
--------
song:render(options,file_path,function()end)
--delete new pattern
---------------------
song.sequencer:delete_sequence_at(#song.sequencer.pattern_sequence)
-- Rendering job will be done in the background and the call will return
-- back immediately, but the Renoise GUI will be blocked during rendering.
In a way I’m not too surprised with a crash here Ledger. I kinda naturally would of waited before performing any change of state to the song until the ‘done callback’ is called. Ah, pulling the rug out from under Renoise feet while background rendering
So would the following be best practice, or is there a way to ‘pause’ the code temporarily to keep things more linear?
--callback delete new pattern
-------------------------------
local function delete_pattern()
-------------------------------
local song = renoise.song()
song.sequencer:delete_sequence_at(#song.sequencer.pattern_sequence)
end
--render
song:render(options,file_path,delete_pattern)
Yes that should work now Ledger. Putting the delete pattern call in the ‘done’ callback. I would imagine that Renoise gets miffed if you (for example) start deleting instruments while it is rendering? (I’ve never tried it mind you.) As for ‘pausing’, for ‘cheap & quick’ small renders I’d just go into a forever while loop or something waiting for a ‘render done’ flag that becomes true (which is set in the ‘render done’ callback function.) But I’m not sure what would happen for larger renders that happen over a longer period of time with that system (remember you have that 10 second timer ‘watchdog’ going.) Maybe Idle notifier setup, start render and in the idle notifier you are testing to see if a ‘render done’ flag is true. Something like that maybe. Can get complicated
Unfortunately the while loop seems to hang renoise for about 10 seconds, so it looks like I’ll have to use the callback function to contain the rest code. Here’s the while loop I was using:
--flag
local render_complete = false
--render callback flag function
---------------------------------
local function completed_render()
---------------------------------
render_complete = true
end
--render
song:render(options,file_path,completed_render)
--loop
while 1 do
-- print(render_complete)
if render_complete == true then
break
end
end
song.sequencer:delete_sequence_at(#song.sequencer.pattern_sequence)
print("done")
Yes, unfortunately Ledge you can’t do the while loop pause (you can’t lock up your ‘main thread’, it’ll never start the render. Pity.) You’ve got to use say an idle notifier to keep checking your render flag (do other things not associated with changing Renoise song state) then when render_complete flag becomes true, you can safely delete the pattern
The other I forgot to mention Ledger is that you don’t really need to define your own render_complete flag. There is one in the API:
-- See renoise.song():render(). Returns true while rendering is in progress.
renoise.song().rendering
-> [read-only, boolean]
Yes, gone with the ‘put the rest of the function in the callback’ route for this one. If I was doing multiple renders I may have had to used the idle function.
Thanks for the help and the tip on the rendering flag!