Observe "unobservable" values with the Observer class

Hello folks!

I wrote a small class that might be useful for some of you.

Since I need to observe some values, which aren’t observable by default, I needed something, that helps me out.

Using loadstring() might not be very efficient, and in general, using the app_idle_observable should be used wisely, but I couldn’t find a more efficient way to make this happen using a universal class.

One difficulty is, that you cannot pass references of renoise values, which is why I used loadstring() to get the current value to periodically check for changes.

Have fun!

EDIT: added if statement to remove_notifier() and simplified has_notifier(). thanks for your eyes and fingers brain, mxb. ;)

[details=“Click to view contents”] ```

– Observer class

– makes unobservable values observable, using app_idle_observable

– functions:

– add_notifier(Function hook, String observed)
– example:
– my_instance:add_notifier(function(value) my_hook(value) end, “renoise.song().transport.loop_block_range_coeff”)

– remove_notifier(Function hook)

– has_notifier(Function hook)

class “Observer”

function Observer:__init()
self._hooks = {}
end

function Observer:add_notifier(hook, observed)
assert(hook, “hook not defined or invalid”)
assert(type(hook) == “function”, “expected hook to be a function”)
assert(observed, “observed value not defined or invalid”)
assert(type(observed) == “string”, “expected observed value to be a string”)

local internal_hook = function()
local current_value = loadstring("return "…self._hooks[hook].observed)
if current_value() ~= self._hooks[hook].value then
self._hooks[hook].value = current_value()
self._hooks[hook].hook(current_value())
end
end

local value = loadstring("return "…observed)

self._hooks[hook] = {
hook = hook,
observed = observed,
value = value(),
internal_hook = internal_hook,
}

renoise.tool().app_idle_observable:add_notifier(internal_hook)
end

function Observer:remove_notifier(hook)
assert(hook, “hook not defined or invalid”)
assert(type(hook) == “function”, “expected hook to be a function”)

if self.has_notifier(hook) then
renoise.tool().app_idle_observable:remove_notifier(self._hooks[hook].internal_hook)
self._hooks[hook] = nil
end
end

function Observer:has_notifier(hook)
assert(hook, “hook not defined or invalid”)
assert(type(hook) == “function”, “expected hook to be a function”)

if self._hooks[hook] then
return true
else
return false
end
end

:D

nice idea. hacking the rules ;)