[fixed] VST effect preset error

Tried to make a script for this.
4375 com.kmaki.VstPresetShortcuts_Rns280_V0.1.xrnx

What I’m trying to do, basically, is get the number of presets availlable for the active track effect plugin and then set the next or previous one based on that info.

I’m running into a weird error:

  
*** std::logic_error: 'invalid preset index '1'. valid values are (1 to 326).'  
*** stack traceback:  
*** [C]: in function 'preset'  
*** main.lua:34: in function 'get_track_device_data'  
*** main.lua:53: in function <48><br>
<br>```

<br>
<br>
Note the 'invalid' preset index I tried to set, and the valid values returned.<br>
<br>
This seems to happen at least with some Melda Productions VST plugs. This particular error dialog came up with MCompressor (using the free, non-upgraded version here).<br>
<br>
What I dun goofed now?<br>
<br>
Here's the code for those interested, but not enough to install.<br>

[details="Click to view contents"]

<br>

```<br><br>
--[[============================================================================<br>
main.lua<br>
============================================================================]]--<br>
<br>
-- Placeholder for the dialog<br>
local dialog = nil<br>
<br>
-- Placeholder to expose the ViewBuilder outside the show_dialog() function<br>
local vb = nil<br>
<br>
-- Reload the script whenever this file is saved. <br>
-- Additionally, execute the attached function.<br>
_AUTO_RELOAD_DEBUG = function()<br>
  <br>
end<br>
<br>
local function get_track_device_data()<br>
    --[[<br>
    A common helper for next/prev trackdevice preset functions<br>
    --]]<br>
    local this_device = renoise.song().selected_device<br>
    if this_device == nil then<br>
        --no device selected<br>
        return false<br>
    end<br>
    local p_nr = #this_device.presets<br>
    renoise.app():show_status("nr of presets for this device:"..p_nr)<br>
    if p_nr == 0 then<br>
        --no presets for this device<br>
        return false<br>
    end<br>
    --[[<br>
    if p_nr == 1 then<br>
        --test for a special case<br>
        local p_name = this_device:preset(1)<br>
        if p_name == 'empty' then<br>
            return false<br>
        end<br>
    end<br>
    --]]<br>
    local p_current = this_device.active_preset<br>
    if p_current == 0 then<br>
        --modified preset<br>
        renoise.app():show_status("No preset selected!")<br>
        return false<br>
    end<br>
    return true, this_device, p_nr, p_current<br>
end<br>
<br>
local function select_next()<br>
    --[[<br>
    Selects next TRACK DEVICE VST preset<br>
    --]]<br>
    <br>
    local success, this_device, p_nr, p_current = get_track_device_data()<br>
    if success == false then<br>
        --Failed for some reason<br>
        return false<br>
    end<br>
    --Roll fwd<br>
    p_current = p_current + 1<br>
    if p_current &gt; p_nr then<br>
        p_current = 1<br>
    end<br>
    this_device.active_preset = p_current<br>
<br>
    return true<br>
end<br>
<br>
local function select_prev()<br>
    --[[<br>
    Selects previous TRACK DEVICE VST preset<br>
    --]]<br>
    <br>
    local success, this_device, p_nr, p_current = get_track_device_data()<br>
    if success == false then<br>
        --Failed for some reason<br>
        return false<br>
    end<br>
    --Roll fwd<br>
    p_current = p_current - 1<br>
    if p_current == 0 then<br>
        p_current = p_nr<br>
    end<br>
    this_device.active_preset = p_current<br>
<br>
    return true<br>
end<br>
<br>
--------------------------------------------------------------------------------<br>
-- Key Binding<br>
--------------------------------------------------------------------------------<br>
<br>
renoise.tool():add_keybinding {<br>
  name = "Global:Tools:Next VST preset",<br>
  invoke = select_next<br>
}<br>
<br>
renoise.tool():add_keybinding {<br>
  name = "Global:Tools:Prev. VST preset",<br>
  invoke = select_prev<br>
}<br>
<br>
--------------------------------------------------------------------------------<br>
-- MIDI Mapping<br>
--------------------------------------------------------------------------------<br>
<br>
--[[<br>
renoise.tool():add_midi_mapping {<br>
  name = tool_id..":Show Dialog...",<br>
  invoke = show_dialog<br>
}<br>
--]]<br>
<br>
<br>```

<br>

[/details]

</48>

You declare a lot of local variables inside functions.
I suspect the garbage collection is removing the content as soon as the function closes.
Specially objects involving renoise.song() you should be careful with returning variables that you have attached Renoise objects to them locally because you only have cloned the address of the renoise.song() object.

I think it is better to declare this:
local this_device = renoise.song().selected_device

in every function where you use it. Also be sure that the Renoise object you want to change allows to be changed (not being read-only)

Na, this is perfectly fine.


There was a bug in the preset handling when a plugin had no presets at all. #presets returned 1 then, but did not allowed to select preset number 1. Fixed that now.
There was also a bug in the error handler for some extra confusion. Should have been: std::logic_error: ‘invalid preset index ‘1’. no preset’s are available.’ Fixed that too.

Thanks for reporting.

I used to think so in some cases but got surprised now and then.