Patterns_obs vs. selected_pattern_index_obs

I was having a bug in one of my tools that took a while to pinpoint. Either I was stupid or the API behavior is a bit unexpected:

It seems that renoise.Song.selected_pattern_index_observable is always banging before renoise.Song.patterns_observable (e g, when inserting a new pattern and both are banging). This is a bit unexpected to me, as I would expect a list to be updated before the “active position” is changed.

(In practice, this was bugging me since I have an internal Document that is updating to reflect the current pattern list - while my GUI is updating on any changes of selected_pattern_index. Hence, I’ll get “attempt to index a nil value” when trying to access my Document in the brief time between those bangs.)

An ugly and non-failsafe workaround would be to wrap the index bang in a timer. But maybe the order of banging should/could be changed here, @taktik?

-- NB: the order of the two calls below does not matter

renoise.song().patterns_observable:add_notifier(
  function() print("pattern list bang") end
)

renoise.song().selected_pattern_index_observable:add_notifier(
  function() print("pattern index bang") end
) -- seems to always bang first. possible lack of integrity :)

EDIT: The same thing goes for renoise.song().sequencer.pattern_sequence_observable I suppose. It should fire before selected_pattern_index_observable and not after when clicking on the “insert new pattern” button.

These issues are probably possible to circumvent by using pattern_sequence_observable (and a lot of custom code to mimic the event table that patterns_observable would give. I’m a bit sad!)

1 Like

They can’t both fire at the same time, so they have to fire sequentially. And since the selected pattern observable actually depends on the selected pattern index, it always fires after the index changes. As long as this behaviour is consistent, I think this is fine.

In doubt, use only one of them, maybe just patterns_observable. It will also fire if the list has changed but the index hasn’t.

1 Like

OK. I have to use both to cover all cases and actions, but will solve it with some ad-hoc if statements then. Best would be if any list was updated before any reference to the list was changed (e.g patterns banging before selected_pattern_index).

This might be related by the way, and should be an inconsistency (?)

index_vs_patterns

renoise.song().selected_pattern_index_observable:add_notifier(
  function()
    print("Entries in song().patterns: " .. #renoise.song().patterns)
  end
)

This won’t work when deleting items at the end while the selected index points to the end too, because then existing indices to the list are invalid while the list fires its notifiers.

Apart from that, those notifiers are not only used for Lua, but everywhere in Renoise internally too. Such a fundamental change will basically break everything in Renoise then.

Thanks for clarifying! I’ll wrap what I want to do with the selected_pattern_index_observable in a oneshot timer then. I assume it’s unlikely to break!

(PS. Can’t quite wrap my head around how the current scheme won’t create the potential for even more edge cases than what I suggested… but I get if it’s some compromise due to pointers or whatnot)

I attached the case if it’s of any interest. selected_pattern_index_observable will later update a GUI.

joule.no0b.bugtest.xrnx (1.3 KB)