I see is that you are using a a global “previously_observed” that could change before the observer does anything. So you could, in theory, be halfway through a function and previously_observed changes from 1 to 2. I’m not sure this is the best approach. Maybe stack everything in a table and do a foreach() instead?
Another suggestion is to get ideas by looking at my grid pie’s Bootsauce routine.
-=-=-
Some things to look for:
-
Encapsulate your “…_observable:add_notifier()” in “…_observable:has_notifier()” This is done at “init” and “teardown”, not on the fly
.
-
The “function tracks_changed(notification)” and “function idler(notificiation)” and friends has “notification” as a magic/auto-passed parameter. Maybe you could use this as extra info to make a conditional decision?
-
Most of the work is done in “(renoise.tool().app_idle_observable:has_notifier(idler))”. Every time Renoise has a spare cycle I do some work. I don’t try dynamically attach notifiers to everything and juggle conflicts.
-=-=-
From what I see you are trying to chain together a bunch of Pattern/Tracks so that, when you change something, the change is propagated. Personally, I would take a different approach and do most of the work in an idler().
I would create a table that holds info. How this table is created, naming conventions, nesting, and whatever, I leave it up to you. Example:
my_chain["p1t1"] = false
my_chain["p2t3"] = false
my_chain["p10t4"] = false
This is a table of linked patterns. False means no change. If something changes, i’d do:
if my_chain["p10t4"] ~= nil then my_chain[p10t4] = true end
Then in my idler() routine:
-- Look for "true" in my_chain
local is_changed = table.find(my_chain, true)
if (is_changed ~= nil) then
-- Parse is_changed, which contains 'p10t4'
local p1 = string.match(is_changed, "p(%d+)")
local t1 = string.match(is_changed, "t(%d+)")
-- Propagate changes
for k,v in pairs(my_chain) do
local p2 = string.match(k, "p(%d+)")
local t2 = string.match(k, "t(%d+)")
if p2 ~= p1 and t2 ~= t1 then
renoise.song().patterns[p2].tracks[t2]:copy_from(renoise.song().patterns[p1].tracks[t1])
end
my_chain[k] = false
end
end
And so on.
Anyway. not trying to say my way is correct. Maybe this will make things worse. Just throwing out ideas.