Sng.selected_track.devices_observable:add_notifier() targetobject?


if I use the observer


the event gives back an table, and table.type is the event type string. But where is the target object (or at least the position and path)? Also, I seem to be unable to find the according info in the documentation here.

I want to observe the removal of a specific device.

I think this is the most simple way to do it. It’s not the way I would have done it perhaps, but it’s crude and simple :slight_smile: There’s no problem after swapping tracks or devices either.

I’ve structured it in a way that should, hopefully, be easy to reuse.

function add_device_notifier(track, device_idx, banger_func)

  local device = track:device(device_idx)

  local notifier_func = function(event)
    if event.type == "remove" then

      local exists = false
      for idx, obj in ipairs(track.devices) do
        exists = exists or rawequal(obj, device)
      if not exists then



--- test

local was_removed_func = function()
  print("the device was removed")

local track_obj =
local device_index = 2

add_device_notifier(track_obj, device_index, was_removed_func)

EDIT: I forgot that you may want it to react to the track being removed as well, but maybe you’ll manage to add this on your own. Just use a similar approach for tracks and renoise.Song.tracks_observable.

Thank you, but I do not know the device position and track before destruction in my case, so I need it in the event.

The device position is in the event table under the key “index”.

How to best fetch the track or track index depends a bit on how you ‘structure the scopes’ in your particular case. Somewhere along the way you have the track object, and you can always pass it further and check with rawequal and track iteration what the track index is.

Or exchange the track_obj in my code with track index and reuse that in the banger_func(). As you might understand, it depends a bit on how you need/want to structure your code from the start.

Neat, thanks. That already works. I then can use selected_track.

1 Like

Just remember to make things work even after tracks or devices are swapped. Pass objects and not indexes when needed.

…Still a “target_object” would be much more elegant.

Sorry, but I have to reopen this.

It turns out that there is a problem now which make a solution for me impossible: The removed device actually is already destroyed in that event. So the event.index has no use at all, it seems.

I need the device-path of the removed device, too.

@taktik Is there already a solution here? If not, is it possible that you add a “before_remove” event, too, that optimally could reference the affected object?

Also, if an object was removed by a script and not by the user, current_track might not work…

I don’t get it. The most obvious way is to save it in a variable.

If that’s not enough and you want to be fancy about it, you can even ‘overload’ (extend) the API with a custom observable that will return your own class object with all information from the old object. But it’s better to keep it as simple as possible.

If you have problems keeping track of the track index of the device, you can overload the device with a track_object property upon creation, and thereby get the track index with iteration+rawequal.

Pretty much anything is possible. I once made an extended line notifier that included the old data in the event table…

But yeah, all observables having a separate before and after variant is a pretty neat idea.

No, this is really cumbersome and not a good concept.

The common event API standard consists of the “target object” in the event, almost in any language and API. Except here. It would save a ton of code lines and also processing load, if target_object was the standard in the Renoise API.

I will now add a looping over all tracks and all devices, just for adding individual remove observers. This makes me feel like I was coding in an ugly basic, bah.

Or maybe I’ll simply leave it, so the tool is not perfect, who cares :smile:

Yeah. But I get why all observables bang after the actual ‘event’. It’s what you want most of the time. The other way around is more of a special case.

But it’s a damn good idea having both, if it could be implemented in a non-confusing and easily documented manner.

Sorry, again I disagree. It is just a special case for you, but not for me :smile: I actually would say the other way around.

Anyway… if you want I can help you achieve what you need this weekend. You will get a perfect API compliant syntax free of charge, adding any optional data that has been “removed” inside the event table :wink:


It’s pretty easy as long as you just want to save static values (like device_path) and don’t have to use tons of observables to update the cache with every single parameter.

1 Like

Thanks for offering your help. I decided now to leave it like it is. Please do not do any effort here.

1 Like