How To Utilize Available_Track_Devices +Plugin List?

Hi. This is a bit of a question really.
I became aware of the API allowing for these two:

  
rprint (renoise.song().selected_track.available_devices)  
rprint (renoise.song().selected_instrument.plugin_properties.available_plugins)  
  

And that plugins and trackDSP devices can be loaded
like for instance like this:

  
renoise.song().selected_instrument.plugin_properties:load_plugin("Audio/Generators/VST/Absynth 4")  
renoise.song().selected_instrument.plugin_properties.plugin_device.external_editor_visible=true  
  

and

  
renoise.song().selected_track:insert_device_at("Audio/Effects/ Native/EQ 10", 2  
  

as an example.
Now, this is really cool! Being able to create keyboard shortcuts for your VST/AU/Native choices. Really neat!

But the possibility of listing all VST/AU/Native Track DSP devices and the possibility of listing all VST/AU plugins available begs a few questions (oh no, here we go :panic: )

  1. Is it possible to “capture” either of the lists and to display them as a drop-down menu in a window dialog?
  2. Is it possible to define, say, 16 Track DSP “slots” in a window dialog so that the user can drop-down menu his “16 favourite Track DSP devices” onto the interface, then they are magically saved or looked up by shortcut requests (i.e. Once the user defines his/her 16 fave VSTs and 16 fave VSTinstruments, for instance - they can call them with their 16+16 shortcuts).

I realize that’s a pretty tall order. Well… It can be complex or simple. I think at it’s simplest it’d be a customized window which has a bunch of buttons which start up functions. A kind of a “API function button template”. How would I go about doing something like this?

  
 local mylist = renoise.song().selected_instrument.plugin_properties.available_plugins  
  
 for t = 1,#mylist do  
 print (mylist[t])  
 end  
--Depending on what id you gave to your popup, assumed is "popup" like in the ExampleToolGui:  
 vb.popup.items = mylist  
  

Assuming your list of choices is called “popup_two” and you have a button with a “>” character in it to indicate the user can push his favorite into the next list:

  
 vb:button {  
 text = ">",  
 width = 30,  
 pressed = function()  
 --Add the current selected item from list one to the current selected slot in list two  
 vb.popup_two.items[vb.popup_two.value] = vb.popup.items[vb.popup.value]   
 end,  
 }  
  

Well, I did look at ExampleToolGui and got lost in the “show all functions” (function available_controls() ).
I did find a popup:

-- popup   
 local popup_row = vb:row {  
 vb:text {  
 width = TEXT_ROW_WIDTH,  
 text = "vb:popup"  
 },  
 vb:popup {  
 id = "popup",  
 width = 100,  
 value = 2,  
 items = {"First", "Second", "Third"},  
 notifier = function(new_index)  
 local popup = vb.views.popup  
 show_status(("popup value changed to '%s'"):  
 format(popup.items[new_index]))  
 end  
 }  
 }  

However, since available_controls is such a smorgasbord of things, I’m not exactly sure how to mash what you wrote and what ExampleToolGui has together while retaining functionality :)

I forgot the views part in the object tree (vb.views.xxx)

All GUI objects are placed in the renoise.viewbuilder() object.
the simple vb = renoise.viewbuilder() simply creates an alias for renoise.viewbuilder()
You can address an object by giving it a unique ID in its definition.
whenever you set id = “my_object_id”, the way to address an object then becomes:
vb.views.myobject_id
Whatever property is attached to it, you can then easily change.
In your snippet you can see that the id = “popup” has been set for the popup object. That refers to how i approach it in my example.
It looks a bit confusing as the word has been plastered all over the example, also on places where it doesn’t really have a big influence on functionality of the object.

Here’s a snippet that does the listing:

  
--[[============================================================================  
main.lua  
============================================================================]]--  
  
-- Placeholder for the dialog  
local dialog = nil  
  
-- Placeholder to expose the ViewBuilder outside the show_dialog() function  
local vb = nil  
  
-- Reload the script whenever this file is saved.   
-- Additionally, execute the attached function.  
_AUTO_RELOAD_DEBUG = function()  
  
end  
  
-- Read from the manifest.xml file.  
class "RenoiseScriptingTool" (renoise.Document.DocumentNode)  
 function RenoiseScriptingTool:__init()   
 renoise.Document.DocumentNode.__init(self)   
 self:add_property("Name", "Untitled Tool")  
 self:add_property("Id", "Unknown Id")  
 end  
  
local manifest = RenoiseScriptingTool()  
local ok,err = manifest:load_from("manifest.xml")  
local tool_name = manifest:property("Name").value  
local tool_id = manifest:property("Id").value  
  
  
--------------------------------------------------------------------------------  
-- GUI  
--------------------------------------------------------------------------------  
  
local function show_dialog()  
  
 -- This block makes sure a non-modal dialog is shown once.  
 -- If the dialog is already opened, it will be focused.  
 if dialog and dialog.visible then  
 dialog:show()  
 return  
 end  
  
 -- The ViewBuilder is the basis  
 vb = renoise.ViewBuilder()  
 local mylist = renoise.song().selected_instrument.plugin_properties.available_plugins  
 local favorites = {}  
 -- The content of the dialog, built with the ViewBuilder.  
 local content = vb:row {  
 margin = 10,  
 vb:popup {  
 id = "popup",  
 width = 400,  
 value = 1,  
 items = mylist,  
 notifier = function(new_index)  
 end  
 } ,  
 vb:button {  
 -- buttons can also have custom text/back colors  
 text = ">",  
 width = 30,  
 pressed = function()  
 local choice = vb.views.popup.items[vb.views.popup.value]  
 favorites[#favorites+1] = choice  
 vb.views.popup_two.items = favorites  
 end,  
 },  
 vb:popup {  
 id = "popup_two",  
 width = 400,  
 value = 1,  
 items = {"one","two"},  
 notifier = function(new_index)  
 end  
 }   
 }   
  
 -- A custom dialog is non-modal and displays a user designed  
 -- layout built with the ViewBuilder.   
 dialog = renoise.app():show_custom_dialog(tool_name, content)   
  
  
end  
  
  
--------------------------------------------------------------------------------  
-- Menu entries  
--------------------------------------------------------------------------------  
  
renoise.tool():add_menu_entry {  
 name = "Main Menu:Tools:"..tool_name.."...",  
 invoke = show_dialog   
}  
  
  
  

When you also want to store the values, you have to save the information using the renoise.document API.
There are various snippets around that store information into and retreive info from an xml file. (createtool for instance)

Thanks vV for the snippet, I did finally check it out and see what it does. I’ll just have to comprehend it a bit more before I can start modifying it.
Here’s where I’m at now:

What I don’t get is the new_index thing, a function defines a new_index, but where is that written to / read from?