Save Tool State With Song?

Hello

Would it be possible to store the state for a tool along with the song?

You know, just like with a VSTi;

If i create a song, add some VSTi synth, make a synth sound, save the song, close and reopen the song then the sound is where I left it.

What mechanism is doing that, and can I achieve something like that for my tool (Guru)? If so how?

(This is an idea I came up with myself, not saying it’s a good idea, but anyway; I can hook on to events like when a song is loaded and saved, right? So when a song is saved I could let my tool secretly store something, like a document, and when the song is loaded again I could load what I stored away. Maybe with the song filename as key to what is stored, but then if the song is moved or renamed then this would not work, but maybe there is some unique id available?)

Later
CB

Tools like the Marks tool or my Clip Arranger tool do this using a dummy instrument. In that dummy instrument they use the name of the first sample to store arbitrary strings (the length of sample names, according to someones tests, are not limited). This is a big hack if you ask me, but it seems to work reasonably well if handle it with care.

Here is some code from my Tool, which originally came from the Marks tool:

  
 CLIPARR_INSTRUMENT_NAME = "NO ACCESS: ClipArranger Data"  
  
 -- Much thanks for this to aklt [anders AT bladre.dk] and his fabulous Marks tool!  
 function get_instr ()  
 for i, instrument in ripairs (renoise.song ().instruments) do  
 if instrument.name == CLIPARR_INSTRUMENT_NAME then  
 return instrument.samples[1]  
 end  
 end  
  
 local index = #renoise.song ().instruments + 1  
 renoise.song ():insert_instrument_at (index)  
 local instrument = renoise.song ().instruments[index]  
 instrument.name = CLIPARR_INSTRUMENT_NAME  
  
 return instrument.samples[1]  
 end  
  

Usage looks like this:

  
 -- Loading your data:  
 data = deserialize_with_something (get_instr ().name)  
  
 -- Storing your data:  
 get_instr ().name = serialize_with_something (data)  
  

Haha, now that’s what i call a hack!

Lets hope the developers come up with a LUA API extension for this in the next version. That would be quite great!

Yeah

But also, give my idea some thought. See here:

  
-- Invoked each time a new document (song) is created or loaded, aka each time  
-- the result of renoise.song() is changed. Also called when the script gets  
-- reloaded (only happens with the auto_reload debugging tools), in order  
-- to connect the new script instance to the already running document.  
renoise.tool().app_new_document_observable  
 -> [renoise.Document.Observable object]  
  
-- invoked each time the app's document (song) is successfully saved.  
-- renoise.song().file_name will point to the filename that it was saved to.  
renoise.tool().app_saved_document_observable  
 -> [renoise.Document.Observable object]  
  

If the renoise.Document.Observable happen contain something unique (filename will do…) then you can use this to store away a renoise.Document in a sub folder below the tool, containing anything you like. As soon as a song is loaded check if you have something stored that matches this. Moving the song to another computer wouldn’t work though without copying the document in the tool subfolder

yes. +INF

Simply pick some song aspects (song name + first pattern contents and instrument names) and pull that through an MD5 hash, you could store the MD5 key with the settings.
There is an MD5 library, but the MD5 library has to be integrated:
http://www.keplerpro…/md5/index.html

There is also a Lua-only source that requires the bitlib (renoise has bitwise operator support so with a few adjustments, it could be used):
http://equi4.com/md5/md5calc.lua

I would like to note that both of these solutions look like hacks and I’d love to see the ability to store tool info within a song bundle:

  1. If you store information within an instrument, you have confusing data. The user is not sure what to do with it or how he is allowed to touch it (is it ok to move the instrument etc.) – But at least we store the data with the song and not the tool.

  2. If you store information within the tool, it will not be joint with the song. So if you overwrite/update the tool, you will have lost settings for songs. Same goes if you send the song or store it for later use (unless you send/store it with a copy of the tool), you will loose settings for the tool and even knowledge about this song using a tool.

I think the currently best solution is:
3) Using a separate file, using the song name and location with a different file ending (like some tools do, sry can’t remember any examples atm.). This will store the settings in a distinct file beside your song file, you can then check for this file within your tool. This can be done easily with the LUA io.write and io.read functions. (This means an extra file for each tool used in a song – a bit excessive but quite user friendly imo)

A while back I was testing out putting this settings file for a tool by force within the xrns. I was modifying the “Export Tool Tool” to zip an xrns file containing the contents of the original xrns with the added file. But I believe this is not possible as Renoise seems to overwrite the loaded xrns file on loading. So the xrns is stripped of external data when loaded and the tool will never be able to access the file in time to save it. Correct me if I’m wrong here, these tests where performed a while back.

I think it would be nice if Renoise tools had access directly to the xrns contents, and could write whatever files it wanted. Just an idea to the developers, maybe to not strip external data when loading an xrns would suffice.

Anyhow, I recommend saving the settings to an external file located beside the song’s xrns file.

One more thing if you use vV’s method (included in tool) or the 3rd method (external file).

Adding a token to the song’s info can be good method to verify the existence of associated song settings.

For example if we add “Uses Guru” to the song comments, this is our token. Then on loading if a song contains “Uses Guru” within the song comments but we do not find the associated song settings we can display an error message; “Song settings for Guru not found.” – However the user can modify the comment and remove the token (as with all song data that tools can access). But as the data is not stored in the token we can still check for the data (in the tool or external file) even if the token does not exist, so functionality does not rely on the token. The token is used when the token exists but there is no data/settings then display an error, the token is used for the error only and does not affect checking for available settings.

The Md5 method also has one very minor disadvantage, if the song or its content is altered outside Renoise, the hash changes and the song no longer will be recognized.

You can store a lot of stuff in the song info. The generic .ini method is:
[section]
param1=value1
param2=value2
param3=value3

You could simply use this style:
[com.user.toolname.xrnx]
param1=value1
param2=value2
param3=value3

The tool can lookup its own section and fetch its parameters.
If the tool isn’t installed, nothing is done with the data.

Yo!

Storing temporary Guru patches and settings in .xml files and some key in the song comments maybe is the best idea yet.

Sorry, what exactly do you mean by this? “song info”? “.ini method”?

CB

step by step!
1 he means the song comments section probably. to be honest, if i wouldn’t have downloaded compo entries in xrns format, i could’ve used renoise for years without knowing you can save your artist name, track name, and some story in the song comments section (accessible in the view menu)
2, he means, that is a very human readable, and generally used a lot, format for saving config stuff. i do however recommend looking at padsynth’s method for doing this, making the config string a lua table on one line is a bit less human readable but code readable much more (one loadstring command gets your vars / prefs for you)

ps i don’t like shift key

Yeah, after some thinking i realized this :stuck_out_tongue:

I agree, a table is probably better. Thing is, all i need is a key to look for and a value that serves as a unique identifier, so GuruPrefs=128376812736 for example will do, and then I store everything I want to store in a xml doc with the corresponging filename, 128376812736.xml

CB

I’ve made a cool proof of concept.

I have a renoise.Document, that I call “state document”.

On renoise.tool().app_new_document_observable I check if a line in renoise.song().comments starting with “Guru_state_key:” exists.

If not; I create the key from current date/time “20120110214503” and add it to the last row of the comments, “Guru_state_key:20120110214503”. (So when the song is saved so is the key in the comments with it…)

If the key did exist: i try to load the state document using the key as filename “20120110214503.xml”

On renoise.tool().app_saved_document_observable I save the state document using the state key…

So, I tried starting a song, launching a few guru synths, save the song, and later loading it, the synths are launched again as when i left it.

Only I have quite some work to do to make it work as I would like with the guru patches and windows…

One drawback is that when you create a new song it is always marked as changed because of the comment added…

Neveretheless a really cool solution. If you would find the need you can extremely simply copy/move the state from one song to another, or restore on another computer without too much hassle…

CB

Wooh,

I’ve created a util class for saving settings for the tool with the song.

http://code.google.com/p/stepbrother/source/browse/trunk/Guru%20xrnx/com.cornbeast.Guru.xrnx/class_songtoolsettings.lua

Read the description in the file comments… too tired to write anything right now.

Later
CB

Looks like a pretty rad routine. I would add some kind of author-ID to the key. In the very rare case people are loading their song on another Renoise installation where a guru configuration was saved at the exact same moment. ;)

Yeah, but you know, that could very well accidently create a mega hit song, so I’ll leave it there :wink:

I’ve been experimenting a bit with this as well, using some of mxb’s code as a starting point.
My aim is a bit different: I’d prefer the serialized string to become embedded directly in the song comments, instead of being referenced as an external file.

@Cornbeast: Any particular technical reason you chose to use external files for storing the information?

Well, not really, except that it seemed less hacky, less addition to the song, simpler to read/move/transfer, but for me I think the main reason is I already use a lot of files for Guru, for saving patches and preferences for the synth definitions. And saving the state for Guru means saving temporary patches which is one or more quite big xml-file(s) anyway. There’s just too much and complex data, a synth could have hundreds, maybe thousands of parameters whose value is saved as renoise xml docs.

CB

Yeah, absolutely makes sense in that context. Perhaps what I’m asking (a standard method) isn’t realistic - perhaps it’s just too dependent on the goal/purpose. For instance, we have agreed that using the song comments for extra data is both obvious and non-intrusive - but then comes something like ReSynth/Cells, which make it clear that storing information in other places (instruments) is a valid approach too. Well, I guess that as long as we don’t end up breaking each others scripts, everything’s possible :slight_smile:

P.S: I noticed that elmex has also created a nice, generic serializer class for the ClipArranger. I have made some tests, and it’s a pretty solid performer.