lk.Patch
:findCode (url)
local lib = {type='lk.Patch'} lib.__index = lib lk.Patch = lib local private = {}
Lubyk.mimas_quit_on_close = false
-- PRIVATE local ALLOWED_KEYS = { nodes = true, x = true, y = true, w = true, h = true, hue = true, name = true, }
-- PUBLIC
setmetatable(lib, { -- new method __call = function(lib, name) local self = { name = name, nodes = {}, pending_nodes = {}, on_notify = setmetatable({}, {__mode = 'k'}), } sched.patch = name setmetatable(self, lib)
return self end})
-- When we load from morph, we must set file loader to be the -- remote morph server. (find code) self.is_process = true
-- Create processes watch before loading code (to resolve remote -- processes). -- --- Watch for other processes on the network and create -- lk.RemoteProcess proxies when needed. self.process_watch = lk.ProcessWatch():addDelegate(self) end
--print(string.format("================================= lk.Patch %s\n%s", self.name, yaml.dump(definitions))) --print("================================= lk.Patch ]") for k, v in pairs(definitions) do if k == 'nodes' then private.setNodes(self, v) elseif ALLOWED_KEYS[k] then self[k] = v end end if self.need_cleanup then self.need_cleanup = nil collectgarbage('collect') collectgarbage('collect') end end
--- Create a pending inlet from an url relative to this process (nearly the same -- as editor.Process.pendingInlet). local inlet_url = lk.absToRel(inlet_abs_url, self:url()) -- inlet_url example: -- node/in/slot local parts = lk.split(inlet_url, '/') local node_name, inlet_name if parts == 3 and parts[2] == 'in' then node_name, inlet_name = parts[1], parts[3] else return nil, string.format("Invalid pendingInlet url '%s'.") end
local node = self.nodes[node_name] local inlet = nil if node then -- inlet not created yet inlet = lk.Inlet(inlet_abs_url, inlet_name) node.pending_inlets[inlet_name] = inlet else -- node not created yet local pending_node = self.pending_nodes[node_name] if not pending_node then pending_node = {} self.pending_nodes[node_name] = pending_node end inlet = pending_node[inlet_name] if not inlet then -- We pass absolute url so that the inlet can answer 'url()' requests. inlet = lk.Inlet(inlet_abs_url, inlet_name) pending_node[inlet_name] = inlet end end return inlet end
-- Find an element from an url. An url -- is something like -- /process name/[parent node name]/node name/in/inlet name -- or /process name/[parent node name]/node name -- or [parent node name]/node name -- -- ALSO USED BY editor.Process -- TODO: cache result by full url ? -- not greedy regexp local process_name, path = string.match(url, '^/([^/])/(.*)$')
local process if process_name then process = self:findProcess(process_name) else process = self path = url end
local res = process:findByPath(path) local res_mt = getmetatable(res) if res and mt and mt ~= res_mt then local msg = '' if mt.type and res_mt.type then msg = string.format('expected %s, found %s', mt.type, res_mt.type) elseif res.__tostring then msg = string.format('found %s', res:to__string()) elseif not res then msg = 'found nil' else msg = 'found ?' end return false, string.format("Invalid object at '%s' (%s).", url, msg) else return res end end
-- ALSO USED BY editor.Process local parts = lk.split(path, '/') -- current object local c = self local c_next = 'node'
for i, name in ipairs(parts) do if c_next == 'node' then -- Find node if name == 'in' then c, c_next = c.inlets, 'slot' elseif name == 'out' then c, c_next = c.outlets, 'slot' else -- sub-node 'a/b' lives in nodes.a.nodes.b c = c.nodes[name] end elseif c_next == 'slot' then -- slot list c, c_type = c[name], nil else -- error c = nil end if c == nil then return nil, string.format("Cannot find '%s' while resolving '%s'.", name, path) end end return c end
--- Serialize current patch as a lua table. If a -- data table is provided, only dump parts that contain -- keys in the table. local res = {nodes = {}} for k, _ in pairs(ALLOWED_KEYS) do if k == 'nodes' then local nodes = {} res.nodes = nodes for k, node in pairs(self.nodes) do nodes[k] = node:dump() end else local v = self[k] if v then res[k] = v end end end return res end
--- Serialize part of the current patch as a lua table by only returning -- data for parts that contain keys in the given table. local res = {} local nodes = self.nodes for k, v in pairs(data) do if k == 'nodes' then res.nodes = {} local res_nodes = res.nodes for k, node_data in pairs(v) do local node = nodes[k] if node then res_nodes[k] = node:partialDump(node_data) else res_nodes[k] = false end end elseif ALLOWED_KEYS[k] then res[k] = self[k] end end return res end
--- Find source code for the node at the given url (patch_name/[parent_node/]node_name). --[[
Path organization (local filesystem or remote on Mnémosyne server):
... <== base project directory. This is the current dir for the process .../A <== Everything for process with role "A" .../A/_patch.yml <== Patch for process with role "A" .../B <== Everything for process with role "B" .../B/_patch.yml <== Patch for process with role "B" .../B/foo.lua or ...[node:url()].lua <== Code for node 'foo' in process 'B' .../lib <== searched for required code
TODO make async
:findClass (class_name)
TODO MISSING DOCUMENTATION
TODO make async ?
:callback (url, ...)
TODO MISSING DOCUMENTATION
FIXME This is an ugly hack related to post-linking. We notify only
:error (...)
TODO MISSING DOCUMENTATION
TODO notify error
:notify (...)
TODO MISSING DOCUMENTATION
:onNotify (key, callback)
TODO MISSING DOCUMENTATION
:setParam (lubyk, p, param_name, value)
Set a single parameter
:control (url, value)
Set a parameter from a relative url like "metro/@tempo".
FIXME Is this used ?
:findProcess (name)
TODO MISSING DOCUMENTATION
TODO better error handling
:url ()
nodes.
:setMorph (process)
TODO MISSING DOCUMENTATION
:sync ()
TODO MISSING DOCUMENTATION
:processConnected (remote_process)
Callback on found process in ProcessWatch. Not used for the moment.
:processDisconnected (remote_process)
Callback on removed process in ProcessWatch. Not used for the moment.
TODO
#findCodeTODO make async
#findClassTODO MISSING DOCUMENTATION
#findClassTODO make async ?
#callbackTODO MISSING DOCUMENTATION
#errorTODO MISSING DOCUMENTATION
#errorTODO notify error
#notifyTODO MISSING DOCUMENTATION
#onNotifyTODO MISSING DOCUMENTATION
#findProcessTODO MISSING DOCUMENTATION
#findProcessTODO better error handling
#setMorphTODO MISSING DOCUMENTATION
#syncTODO MISSING DOCUMENTATION
FIXME
#callbackFIXME This is an ugly hack related to post-linking. We notify only
#controlFIXME Is this used ?