Old 10-18-2020, 09:13 AM   #1
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
Default LUA: Metatables and loading data as code

I'm trying to store some information in a file in such a format that it can be loaded in as a function. But I'm unclear how to set the metatables... I'm still fuzzy on metatables....

The basic idea is here: https://stackoverflow.com/questions/...other-lua-file

A sample data file looks like this:

Code:
return {   name = kontakt, params = {A2 = Chorus,A1 = Reverb},
    banks = {favorites = { hue = 120, sat = 0.05, params = {A5 = Wah},
               presets = {"Ice Bell", "OB pad" }
            },
             pianos = { hue = 10, sat = 0.09, params = {A1 = Reverb},
               presets = {"Black", "Grandeur" }
            }
    }
}
It is loading and creating a table, but the object is lacking its metatable.

Here's what the constructor looks like:
Code:
function Plugin.new(vstName)
    local self = setmetatable({}, Plugin)
    self.name = vstName
    self.params = {}
    self.banks = {}
    return self
end
Replicating the effect of that first line with the data loaded from file is what I can't figure out....

full code available if needed. But I think I can just create a method to set the metatable on the loaded data and it should work ???


EDIT: okay, for completeness, here's the code to create and load the file. I'm getting a table back, but I can't seem to access any fields in it.
Code:
local Bank = {}
Bank.__index = Bank
function Bank:__tostring()
    rtnStr = '    '..self.name..' = { '.. 'hue = '..self.hue..', sat = '..self.sat..', ' 
    ..getParamStr(self.params)..'\n'
    ..'            presets = {\"'..table.concat (self.presets,'\", \"')..'\" }\n'
    ..'        }'
    return rtnStr
end
function Bank.new(name,hue,sat,preset)
    local self = setmetatable({}, Bank) 
    self.name = name
    self.hue = hue or 0
    self.sat = sat or 0
    self.params = {}
    self.presets = {preset} or {}
    return self
end

function Bank:addPreset(name)
    table.insert(self.presets,name)
end

function Bank:setParam(control,name)
    self.params[control]=name
end

function Bank:getParam(control)
    return self.params.name
end

function getParamStr(params)
    paramT= {}
    paramStr = 'params = {'
    for control,param in pairs(params) do
        table.insert(paramT,control..' = '..param)
    end
    paramStr = paramStr..table.concat(paramT,',')..'},'
    return paramStr
end

local   Plugin = {}
Plugin.__index = Plugin

function Plugin:__tostring() 
    bankT = {}
    plugStr = 'return {\n'..'name = '..self.name..', '    
    bankPre = '\n    banks = {\n    '
    for bankName in pairs(self.banks) do 
        table.insert(bankT,tostring(self.banks[bankName]))
    end
    return plugStr..getParamStr(self.params)..bankPre..table.concat(bankT,',\n    ')..'\n    }\n'..'}'  
end

function Plugin.new(vstName)
    local self = setmetatable({}, Plugin)
    self.name = vstName
    self.params = {}
    self.banks = {}
    return self
end


function Plugin:getPresetList()
    return table.sort(self.presets)
end

function Plugin:addBank(bankName,hue,sat,preset)
    --just quietly overwrite any existing bank?  for now...
    self.banks[bankName] = Bank.new(bankName,hue,sat,preset)
end

function Plugin:addPresetToBank(bankName,preset)    
    self.banks[bankName]:addPreset(preset)
end

function Plugin:getBank(bank)
    return self.banks[bank]
end

function Plugin:setColor(hue,sat)
    self.hue = hue
    self.sat = sat
end

function Plugin:getColor(level)
    return 'hue: '..self.hue..' and sat: '..self.sat
end

function Plugin:setParam(control,name)
    self.params[control]=name   
end

function Plugin:getParam(control)
    --print(self.params.control)
    return self.params[control]
end

function Bank.init(data)
    self = setmetatable({data},Bank)
    print(self)
    return self

end

function Plugin.init(data)
    data.setmetatable(data,Plugin)
    print(data)
    --for table in pairs(data.banks) do
        --table.setmetatable({table},Bank)
    --end
    return self
end

plug = Plugin.new('kontakt')
plug:setColor(120,.08)
plug:setParam('A1','Reverb')
plug:setParam('A2','Chorus')
plug:addBank('favorites',120,.05,'Ice Bell')
plug:addBank('pianos',10,.09,'Black')
plug:addPresetToBank('pianos','Grandeur')
plug:addPresetToBank('favorites','OB pad')

curBank = plug:getBank('favorites')
curBank:setParam('A5','Wah')
plug:getBank('pianos'):setParam('A1','Reverb')
filename = 'c:\\lua\\test.lua'
bankfile = io.open(filename,'w')
bankfile:write(tostring(plug))
bankfile:close()  
--bankfile = io.open(filename,'r')
local f = assert(loadfile(filename))
plugData = f()
print(plugData.name)
--newPlug = Plugin.init(plugData)
--print(newPlug)


--test:getBank('pianos'):getParam('A1')
__________________
eric moon
Very Stable Genius
https://gogolab.com/

Last edited by woodslanding; 10-18-2020 at 09:55 AM.
woodslanding is offline   Reply With Quote
Old 10-22-2020, 02:47 PM   #2
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
Default

Well, a bunch of things wrong, but here's working code, in case anyone else wants to do something similar someday...

Code:
function esc(str) return ("%q"):format(str) end

local Bank = {}
Bank.__index = Bank

function Bank.new(name,hue,sat,preset)
    local self = setmetatable({}, Bank) 
    self.name = name
    self.hue = hue or 0
    self.sat = sat or 0
    self.params = {}
    self.presets = {preset} or {}
    return self
end

function Bank:addPreset(name)
    table.insert(self.presets,name)
end

function Bank:setParam(control,name)
    self.params[control]=name
end

function Bank:getParam(control)
    return self.params.name
end

function getParamStr(params)
    paramT= {}
    paramStr = 'params = {'
    for control,param in pairs(params) do
        table.insert(paramT,control..' = '..esc(param))
    end
    paramStr = paramStr..table.concat(paramT,',')..'},'
    return paramStr
end

local   Plugin = {}
Plugin.__index = Plugin

function Plugin:__tostring() 
    bankT = {}
    plugStr = 'return {\n'..'name = '..esc(self.name)..', emptyPreset = '..esc(self.emptyPreset)..', '  
    bankPre = '\n    banks = {\n    '
    for bankName in pairs(self.banks) do 
        table.insert(bankT,tostring(self.banks[bankName]))
    end
    return plugStr..getParamStr(self.params)..bankPre..table.concat(bankT,',\n    ')..'\n    }\n'..'}'  
end
function Bank:__tostring()
    rtnStr = '    '..self.name..' = { '..'name = '..esc(self.name)..', hue = '..self.hue..', sat = '..self.sat..', ' 
    ..getParamStr(self.params)..'\n'
    ..'            presets = {\"'..table.concat (self.presets,'\", \"')..'\" }\n'
    ..'        }'
    return rtnStr
end

function Plugin.new(vstName)
    local self = setmetatable({}, Plugin)
    self.name = vstName
    self.params = {}
    self.banks = {}
    self.emptyPreset = ''
    return self
end

function Plugin:getPresetList()
    return table.sort(self.presets)
end

function Plugin:addBank(bankName,hue,sat,preset)
    --just quietly overwrite any existing bank?  for now...
    self.banks[bankName] = Bank.new(bankName,hue,sat,preset)
end

function Plugin:addPresetToBank(bankName,preset)    
    self.banks[bankName]:addPreset(preset)
end

function Plugin:getBank(bank)
    return self.banks[bank]
end

function Plugin:setParam(control,name)
    self.params[control]=name   
end

function Plugin:getParam(control)
    return self.params[control]
end

function Bank.init(data)
    local self = setmetatable(data,Bank)
    return self
end

function Plugin.load(filename)
    local f = assert(loadfile('c:\\lua\\'..filename..'.lua'))
    data = f()
    local self = setmetatable(data,Plugin)   
    for bankName,table in pairs(self.banks) do
        self.banks[bankName] = Bank.init(table)
    end
    return self
end
function Plugin:save()
    filename = 'c:\\lua\\'..self.name..'.lua'
    local file = io.open(filename,'w')
    file:write(tostring(self))
    file:close() 
end

function Plugin.test(name)
    plug = Plugin.new(name)
    plug.emptyPreset = 'not found'
    plug:setParam('A1','Reverb')
    plug:setParam('A2','Chorus')
    plug:addBank('favorites',120,.05,'Ice Bell')
    plug:addBank('pianos',10,.09,'Black')
    plug:addPresetToBank('pianos','Grandeur')
    plug:addPresetToBank('favorites','OB pad')
    curBank = plug:getBank('favorites')
    curBank:setParam('A5','Wah')
    plug:getBank('pianos'):setParam('A1','Reverb')
    return plug
end

plugName = 'test'
plug = Plugin.test(plugName)
plug:save()
plug2 = Plugin.load(plugName)
print(plug2)
plug2.name = 'test2'
plug2:save()
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 10-22-2020, 04:36 PM   #3
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

If you use Ultraschall-API and have the entire data encapsulated within a function, you can export and import that function via these two Ultraschall-API-functions:

Convert into a base64-string:
https://mespotin.uber.space/Ultrasch...ToBase64String

Convert the Base64-string back into a Lua-function:
https://mespotin.uber.space/Ultrasch...omBase64String
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - Donate, if you wish

On vacation for the time being...
Meo-Ada Mespotine is offline   Reply With Quote
Old 10-22-2020, 07:19 PM   #4
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
Default

That's interesting. What is meant by a 64base string? Would it buy me some functionality I don't have?

Of course I use your API, it's invaluable. (and also vast!)
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Old 10-22-2020, 07:45 PM   #5
Meo-Ada Mespotine
Human being with feelings
 
Meo-Ada Mespotine's Avatar
 
Join Date: May 2017
Location: Leipzig
Posts: 6,621
Default

It means you can save the string somewhere and when you want to reload the function, you read the base64-string and pass it to the function.
It will convert the string back to the original function.

It's really nice. You can pass functions between scripts via extstates using base64-strings.

Base64 is a way to store binary data in a readable string.
You could even post these strings in this forum and others can reuse them.
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - Donate, if you wish

On vacation for the time being...
Meo-Ada Mespotine is offline   Reply With Quote
Old 10-22-2020, 08:44 PM   #6
woodslanding
Human being with feelings
 
woodslanding's Avatar
 
Join Date: Mar 2007
Location: Denver, CO
Posts: 633
Default

wow, I will have to think about how to use that....
__________________
eric moon
Very Stable Genius
https://gogolab.com/
woodslanding is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:17 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.