-
Hello there, I searched left and right these discussions and the original forum (I gave up to that really quick as I can't create a new account to download files apparently). But I can't seem to find an answer to my question. I'm trying to think how to save and load presets of my panels in a way that might work for standalone or VST instances. A way to save a file externally that has the information of all the modulator values. This file can then be loaded in my restricted instance to set the values of all my modulators. I know how to set a value by LUA. Still did not find a way to get a value using LUA (having issues in #661), pleas help me with this too. The way I was picturing it is by saving a string of vstIndex=value in a txt file divided by spaces that can be read and saved easily with a for loop. Does anybody know a way to do what I need to do? If there is already a discussion on this I might've missed please let me know, I might've not found it due to a difference in terminology for example. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 8 replies
-
I invite you to take a look at available panels on ctrlr.org who are labelled as librarian like the ms2000 or Novation x station orJD990 : They have everything under the hood to learn how to deal with valueTree, XML and the JUCE File class. hope it helps |
Beta Was this translation helpful? Give feedback.
-
JSON is the way to go! |
Beta Was this translation helpful? Give feedback.
-
Ok, this is how I save them for other people coming here. I will post the one for the panel with only 10 values, but I used the same approach for another one that has 162 modulators. First of all you need a function to get the panel data:
If from the modulator list you export a csv, you can ask copilot or chat gpt to help you code this, just write the first line and ask AI to expand the code for the other modulators (you can paste them)
For getting the data the thinfs are a bit more complicated. When you read the file you will have an hex string, so first of all let's do a function that converts this hex string to a table for easy recall:
And this is the code needed to set the panel data
Lastly, the load preset function, I'll probably expand it to handle more error, but this works fine, I force the open dialog to only open kvlk files:
Hopefully this helps people approaching Ctrlr and have not a strong programming background. Copilot helped me a lot in doing what I didn't know how to, especially since I never touched lua before :) |
Beta Was this translation helpful? Give feedback.
-
Here is how I would do that. The JSON code is much simpler, although I acknowlege it's yet another thing to knowledge, but if you have a straight one dimensional hash/value table as below, it's actually much simpler and you don’t really need to know what JSON is! -- -- Called when a mouse is down on this component -- loadPreset = function(--[[ CtrlrComponent --]] comp --[[ MouseEvent --]], event) -- File open dialog local jsonfile = utils.openFileWindow( "Select Volca Kick preset...", File.getSpecialLocation(File.userHomeDirectory), "*.kvlk", true ) if jsonfile:existsAsFile() then local str = jsonfile:loadFileAsString() obj = json.decode(str) end if type(obj) ~= "table" then return end -- bail out if something's not right for k, v in pairs(obj) do if data[k] then -- safeguard against non existent keys panel:getModulatorByName(k):setModulatorValue(v, false, true, false) end end end -- -- Called when a mouse is down on this component -- savePreset = function(--[[ CtrlrComponent --]] comp --[[ MouseEvent --]], event) tmp = {} -- this table will converted to JSON and saved to file for key in pairs(data) do -- assign values to each item tmp[key] = panel:getModulatorByName(key):getModulatorValue() end -- Default filename local cPresName = "preset" -- File to save local jsonfile = utils.saveFileWindow("Save Volca Kick preset to file...", File(cPresName), "*.kvlk", true) -- Writing data to the file jsonfile:replaceWithText(json.encode(tmp), true, true) end data = { Pulse_Colour=true, Pulse_Level=true, Amp_Attack=true, Amp_Decay=true, Drive=true, Tone=true, Resonator_Pitch=true, Resonator_Bend=true, Resonator_Time=true, Accent=true, } -- just add new modulators to this list (truth set) -- if your modulator name contains a space or funny character -- surround by [''] e.g. ['Pulse Level']=true, |
Beta Was this translation helpful? Give feedback.
-
Oh no, it's not horrible from a programming perspective and if it works then it's fine. I just think when you come back to it (which you may or may not) it might be harder to unravel what was going on, or maybe not. - so if it works then great! Spending too much time on Ctrlr? It's the story of my life ! :) |
Beta Was this translation helpful? Give feedback.
-
I looked at your binary file version. There are a couple of improvements that can be made. You don't need that fancy hex_to_table() function, because MemoryBlock contains a method to do just that toLuaTable() - and also I would keep all access to getting/setting the modulators in one indexed table modulator={}: -- create a global table for all reference to modulators -- DRY principle modulator = { "Pulse_Colour", "Pulse_Level", "Amp_Attack", "Amp_Decay", "Drive", "Tone", "Resonator_Pitch", "Resonator_Bend", "Resonator_Time", "Accent", } function getPanelData() local t = {} for i,v in ipairs(modulator) do table.insert(t,panel:getComponent(v):getValue()) end -- Populate the data table return t end function savePreset() -- Default filename local cPresName = "preset" -- File to save local file = utils.saveFileWindow("Save Volca Kick preset to file...", File(cPresName), "*.kvlk", true) -- Writing data to the file file:replaceWithData(MemoryBlock(getPanelData())) end function loadPreset() -- File open dialog local file = utils.openFileWindow( "Select Volca Kick preset...", File.getSpecialLocation(File.userHomeDirectory), "*.kvlk", true ) -- MemoryBlock has a method for converting binary strings to lua table -- hexData:toLuaTable(t) local hexData = MemoryBlock() local t={} -- If file exists, then proceed if file:existsAsFile() then hexData = MemoryBlock(file:getSize()) file:loadFileAsData(hexData) else return end -- If the file is too big than there is a mistake if (file:getSize() > 10) then utils.warnWindow("Warning", "Wrong file size, operation cancelled") else -- Convert hex data into table hexData:toLuaTable(t) -- Convert hex to decimal number for i, v in ipairs(t) do -- Call function to set values in the VST panel:getModulatorByName(modulator[i]):setModulatorValue(v,false,true,false) end end -- Get filename and change extension filename = string.gsub(file:getFileName(), "(.+)%.%w+$", "%1") -- Set filename in the LCD screen panel:getLabelComponent("Preset_Name"):setText(filename) |
Beta Was this translation helpful? Give feedback.
Ok, this is how I save them for other people coming here. I will post the one for the panel with only 10 values, but I used the same approach for another one that has 162 modulators.
First of all you need a function to get the panel data: