Adding Notifier On Renoise.Song().Selected_Line_Index

Hi

I’m just getting started with lua, due to this thread

Basically I’m trying to send to current position of renoise over OSC. So far I have the following:

  
renoise.song().selected_pattern_index_observable:add_notifier(function()  
 print("selected_pattern_index:"..renoise.song().selected_pattern_index)  
end)  
  
renoise.song().selected_sequence_index_observable:add_notifier(function()  
 print("selected_sequence_index:"..renoise.song().selected_sequence_index)  
end)  
  
renoise.song().selected_line_index:add_notifier(function()  
 print("line updated")  
end)  

The first two work just fine, however loading the script with the third hook throws this error:

  
*** main.lua:161: attempt to index field 'selected_line_index' (a number value)  
*** stack traceback:  
*** main.lua:161: in main chunk  

On http://code.google.com/p/xrnx/source/browse/trunk/Documentation/Renoise.Song.API.lua?r=876 lines 250-262 I see the properties I’m trying to access, the only difference is the lack of “_observable” after the renoise.song().selected_line_index property. What am I doing wrong?

Additional observations/questions:

  1. I tripped over a typo in the documentation found in the “Scripting Terminal & Editor” in renoise: !introduction.txt, line 218 should have add_notifier (and not “addnotifier”)

which leads me to:

  1. Where is the most up-to-date documentation on the lua API?

Thanks in advance!

The lack of “_observable” means that the property isn’t observable. Not everything is “Observable” in the API.

Have a look at this post for a similar code snippet and ideas.

Thanks, will be fixed.

In SVN.

Why not? I mean, what’s it good for, API-wise, then?

I looked at it, but can’t figure out how to make it do what I try to do, sorry. I’m pretty sure I understand what’s going on in the example, but… It seems the add_line_notifier only kicks in when something is changed in the pattern’s line, so I guess I should be looking for something else. Could you give a few more hints to how I should approach this?

Sorry for asking such dumb questions :(

I also looked at how things are done in de.cie-online.StepSequencer.xrnx, but that doesn’t really work :frowning:

  
local lineNB = 0  
  
local last_idle_time = os.clock()  
  
renoise.tool().app_idle_observable:add_notifier(function()  
 handle_app_idle_notification()  
end)  
  
function handle_app_idle_notification()  
 if (renoise.song().transport.playing) then  
 if os.clock() - last_idle_time >=0.001 then   
  
 lineNB = renoise.song().transport.playback_pos.line  
 print("line:"..lineNB)  
 last_idle_time = os.clock();  
 end  
 end  
end  
  

The problem is that it’s not notified, but called “every once in a while”, so for instance setting Lines/Beat to 16 at 120BPM makes it miss some lines. And I can only imagine the imprecise nature of these polled observations, since they happen way to seldom…

Just thought I’d mention what other directions I tried…

Also tried something ugly: sleeping. The ugly part is that it seems (according to google) lua doesn’t have an non-busy wait/sleep function.

This means I’d have to go for something like this:

  
function sleep(n) -- seconds  
 os.execute("sleep " .. tonumber(n))  
end  
  
while true do  
 if (not renoise.song().transport.playback_pos.line == lineNB) then  
 lineNB = renoise.song().transport.playback_pos.line  
 print("line:"..lineNB)  
 end  
 sleep(1)   
end  
  

First of all it’s not portable to all platforms, but although it’s non-busy wait (at least in principle, but then not really), it hogs renoise and ask me after a while if I want to kill the script.

I can’t speak about implementation, but I imagine making everything the Observer Pattern would be a performance hog, and just generally a bad idea. Edit: I dunno though, i’m mostly speaking out of my arse here. Ping Taktik.

I haven’t looked at your code snippets with enough dedication to give you any practical advice. That said, might I suggest instead of sending individual notes to PD, you design your app in a way that sends chunks of notes with timestamps? Or have PD poll Renoise for data?

Good times.

I’m heading for another strategy ATM: Sending OSC updates of bpm and a message at start/stop + at every new pattern. I’m hoping a free wheeling PD won’t run significantly out of sync between pattern changes (I guess every couple of seconds). I have things communicating fine, hope to implement some real tests tonight, will let you know how it goes…

Scripts are right now NOT running in realtime, not in the player, but in Renoises UI. They are running in the user’s thread where stuff is drawn, user input (keyboard, mouse, bla) is handled.

“selected_line_index” is changed all the time in the realtime thread by the player while playback. The GUI just follows it as often as it needs to, can do.

So, IF there would be an “_observable”, it would do basically what you do in on_idle() as well. IMHO its actually a good thing that it’s right now not observable, cause ou then are forced to be aware of this. Would make no sense to bomb clients with update messages in this case, cause it can anyway not display/handle them in realtime.

Until we do have scripts which directly run in the player (this is a topic on its own) then th elast proposed idea (BPM + pattern changes) is the only way to go.

Couldn’t you mix this solution with the idle notifiers in the de.cie-online.StepSequencer.xrnx example to make a working solution?

example:

  
local lineNB = 0  
  
renoise.tool().app_idle_observable:add_notifier(function()  
 handle_app_idle_notification()  
end)  
  
function handle_app_idle_notification()  
 if (not renoise.song().transport.playback_pos.line == lineNB) then  
 lineNB = renoise.song().transport.playback_pos.line  
 print("line:"..lineNB)  
 end  
end  
  

Wasn’t that effectively what I listed in post #4?

Not completely.

In #4 the time checker is os.time() so you will print at a given time interval instead of at each line.

Edit:
I am aware as you pointed out in #4 that polled requests can fail and these checks will do so with little cpu, complex dsp and high bpm. But a direct check of the variable you want to output will greatly outperform timed interval checks and printing the output variable each time. I thought it might do.

Ok I tried it, first it should be

if not (renoise.song().transport.playback_pos.line == lineNB) then  

and not

if (not renoise.song().transport.playback_pos.line == lineNB) then  

The difference is if the not is before renoise.song().transport.playback_pos.line it doesn’t negate the boolean evaluation but the expression “renoise.song().transport.playback_pos.line” (surprise to me, I’m not used to negate an integer…).

Next the outcome is exactly the same. It’s imprecise and misses some lines. I even tried dropping the prints (they are in some contexts quite slow) and replaced them with sending OSC, and received those in PD. Am pretty sure it’s a dead end…

I didn’t go all the way, but did a quick patch in PD with a blinking [bang] on every beat. The imprecision is great enough to be observed just looking at the [bang]. Sometimes it flashes two times quickly when the new patternNB is received over OSC. I’m pretty sure that if it’s visible it’s unbearably untight to listen to…

A quite noob question (but I just never touched this) is this: Is it possible to send midi notes from a track out from renoise (I’m on linux, if it matters)? If so, a final pragmatic hack I could try ((much) later) would be to use note-on’s from renoise to sync PD…

Why would it not be? But if you would be using Midi to broadcast timing standards, why then not use Renoise as MIDI Master and simply send SPP data to PD?

How do I do that (have renoise send the notes on a track out to be read by some other midi-reading app) then? And, yes I looked in the manual, but I must be blind…

Not sure it was in chuck or PD (I think PD), but I had trouble syncing to midi clock (or was that in fact generating midi clock in PD) last time tried. Maybe I should give it another shot, you’re right it’s the right thing to do…

http://tutorials.ren…MIDI_Properties
Either use a virtual cable like Midi Yoke or CopperLan for that, to route note data to PD.

If you use Renoise as a MIDI slave, a slave-clock will appear next to the bpm option.
If you enable it, synchronisation should work correctly, if the master sends spp data.