Jump to content


Photo

Programming Newbie Question: Make an Observer for Selection in Pattern


  • Please log in to reply
3 replies to this topic

#1 cupcake

cupcake

    Member

  • Normal Members
  • PipPip
  • 51 posts

Posted 13 August 2015 - 13:09

Hi,

 

I'm trying to make a simple tool to print to the status bar the number of lines selected in the pattern editor.

 

 

I've got it working like this so far:

 

num_lines = renoise.song().selection_in_pattern["end_line"] - renoise.song().selection_in_pattern["start_line"] + 1

 
renoise.app():show_status(string.format("Lines Selected: %d", num_lines))
 
 
Does exactly what i want it to, but i have to trigger the script to execute each time i need it to show the result.
 
How can i make it aware of the selection being changed, so that it will trigger itself whenever it spots a change?
 
 
 


#2 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6330 posts
  • Gender:Male
  • Interests:wildlife + urban trekking

Posted 13 August 2015 - 18:20

How can i make it aware of the selection being changed, so that it will trigger itself whenever it spots a change?

 

A quick look at the API docs reveals that we have no selection_in_pattern_observable

Usually, the ability for a script to get notified when a value has changes is indicated by the presence of an accompanying variable with the _observable suffix.

 

The alternative is a bit messy, but entirely do-able. It would basically involve hooking your script onto an idle notifier, and use this to check (several times per second) if the selection has changed:

-- Invoked periodically in the background, more often when the work load
-- is low. less often when Renoises work load is high.
-- The exact interval is not defined and can not be relied on, but will be
-- around 10 times per sec.
-- You can do stuff in the background without blocking the application here.
-- Be gentle and don't do CPU heavy stuff in your notifier!
renoise.tool().app_idle_observable:add_notifier(function()
  handle_app_idle_notification()
end)

Source: https://xrnx.googlec...l.xrnx/main.lua

 

Note that even if the code above says "don't do CPU intensive stuff", lua is pretty damn efficient :-)

Checking for a changed selection would not add much overhead at all - just make sure your code is relatively efficient, and you will be fine. 

 

Finally, I'd suggest that you add this (that the selection becomes observable) to our API wishlist thread.

 

 

 

 

 

 

 


Tracking with Stuff. API wishlist | Soundcloud


#3 cupcake

cupcake

    Member

  • Normal Members
  • PipPip
  • 51 posts

Posted 13 August 2015 - 23:31

Hey danoise,

 

Thanks for the quick reply. I'll try it out the way you mentioned.

 

 

 

Also, would be good to have an observer settable in a future update, will make a request!



#4 cupcake

cupcake

    Member

  • Normal Members
  • PipPip
  • 51 posts

Posted 30 August 2015 - 13:55

Hi,

 

So i've got this little tool working using the method danoise suggested by calling the function on the idle routine. But, as it gets called very frequently, it tends to over-write any other messages that are displayed in the status bar.

 

Is there any kind of way to make it run only once when it needs to display the changed number of lines, and then stop re-writing to the status bar?

 

Basically so far i've dealt with this by having empty handlers on the conditions where the selection is nil (which is the case when Renoise first opens), or 1 line (which is the case if you're just mousing around in the pattern). It works ok, but i get the feeling that this is a kind of inelegant and slightly sloppy way to deal with this situation.

 

This is my code so far:


renoise.tool().app_idle_observable:add_notifier(function()
  show_line_num()
end)


local num_lines


function show_line_num()
    
      if renoise.song().selection_in_pattern == nil then
      
      elseif renoise.song().selection_in_pattern["end_line"] - renoise.song().selection_in_pattern["start_line"] > 0 then
    
        num_lines = renoise.song().selection_in_pattern["end_line"] - renoise.song().selection_in_pattern["start_line"] + 1
        
        --print(num_lines)
        
        renoise.app():show_status(string.format("Lines Selected: %d", num_lines))
      
      elseif renoise.song().selection_in_pattern["end_line"] - renoise.song().selection_in_pattern["start_line"] == 0 then

        
      end
  
end