Renoise api questions

Hi,

I am confused about how I should access the pre- and also post-pannings and -volumes via lua. track:device(1) seems to be not always a “TrackVolPan” device, also the last one (track:device(#track.devices)) neither always is a “SendTrackVolPan” device…

What am I am doing wrong here?

1 Like

ok, found it with track.postfx_panning and track.postfx_volume etc.

Next question:

Is there an easy way to convert the CDATA saved in ParameterChunk into binary data?

… Is it just an base64 encoded string after the “<![CDATA[” ?

Ah yes.

Are there builtin zippy functions?

Nope!

1 Like

I am using this xml library: GitHub - manoelcampos/xml2lua: XML Parser written entirely in Lua that works for Lua 5.1+. Convert XML to and from Lua Tables 🌖💱

Trying to create such a structure:

<Devices>
  <Vst2Plugin />
  <Vst3Plugin />
  <Vst2Plugin />
</Devices>

What would be the table representation for this?
maybe the lib isn’t capable for this?

Try yourself:

local objects = {}
objects[#objects + 1] = {
        Vst2Plugin = {}
}
objects[#objects + 1] = {
        Vst3Plugin = {}
}
objects[#objects + 1] = {
        Vst2Plugin = {}
}
local xml2lua = require("xml2lua")
oprint(xml2lua.toXml({ Devices = objects }))

It gives me:

<Devices>
  <Vst2Plugin />
</Devices>
<Devices>
  <Vst3Plugin />
</Devices>
<Devices>
  <Vst2Plugin />
</Devices>

Not an answer (sorry), but is there a reason you’re not using Renoise’s native Document API?

It has no support for attributes AFAIK.

I am using now an ugly workaround:

xmlString = string.gsub(xmlString, "</Devices>([ \t\r\n]+)<Devices>", "")

I wonder if these mixed types of nodes actually break the XML standard… I tried now the opposite way, the library can back convert it, but then it’s not possible to keep the actual node order. Seems to be a flaw in the current dawproject definition. Do you think such mixed node types are standard in XML?

1 Like

Internal zippy functionality would be indeed very nice… Since Renoise itself certainly uses ZIP for multiple purposes. This would save io.exec calls to system os specific zippy tools…

Is there a way to save an instrument as xrni via api? Can’t find… aaah Application - Renoise Scripting

I don’t think there’s anything wrong with how Renoise uses XML. But the Document functions do appear to have limitations—which is understandable if a bit frustrating, as they’re not intended to be a full XML serializer library.

Ah, I am using an external library. Didn’t use Renoise Document, due to lack of XML attributes support.

Can I somehow suppress the status bar messaging while using renoise.app():save_instrument()?

Can I load an vst3 .vstpreset into an empty instrument slot using lua api? It should be able to detect the plugin by the identifier written into the file header… The preset loading icon though is disabled if there is no instrument yet.

Is there a reason you don’t detect it yourself and load the instrument first?

1 Like

So how do I load an specific plugin via plugin path id or so? Ah ok, I did that myself already haha

1 Like

Ah no, you can’t load a specific VSTi it seems, there is no

Song.selected_instrument:insert_device_at(‘Audio/Instrument/VST3/’…ReduxVST3Identifier)

or similar…

You’re looking for renoise.InstrumentPluginProperties:load_plugin(). The API docs have a nice search feature, you know. :wink:

Oh nice :slight_smile:

Ah yes, this works:

Song.instruments[Song.selected_instrument_index].plugin_properties:load_plugin(‘Audio/Generators/VST3/’ …
ReduxVST3Identifier)

But now I seem to have to build an instrument xml by myself, injecting base64-encoded active_preset_data… I imagined I could “simply” load the preset now instead… Like

Song.instruments[Song.selected_instrument_index].load_preset(path)

This does not seem to work either:

  local stringPresetData = DawProject:convertInstrumentToRedux(Song.selected_instrument, TempDir .. "/plugins/_temp")
  Song.instruments[Song.selected_instrument_index].plugin_properties:load_plugin('Audio/Generators/VST3/' ..
    ReduxVST3Identifier)
  Song.instruments[Song.selected_instrument_index].plugin_properties.plugin_device.active_preset_data =
      Helpers:stringToBase64(stringPresetData)

Did you happen to try printing active_preset_data to see what Renoise expects to be there? I had a go at it:

<FilterDevicePreset doc_version="14">
  <DeviceSlot type="AudioPluginDevice">
    <IsMaximized>true</IsMaximized>
    <ActiveProgram>-1</ActiveProgram>
    <PluginType>VST3</PluginType>
    <PluginIdentifier>ABCDEF019182FAEB566D624153675854</PluginIdentifier>
    <PluginDisplayName>VST3: Surge Synth Team: Surge XT</PluginDisplayName>
    <PluginShortDisplayName>Surge XT</PluginShortDisplayName>
    <PluginEditorWindowPosition>-1,-1</PluginEditorWindowPosition>
    <ParameterChunkType>Chunk</ParameterChunkType>
    <ParameterChunk><![CDATA[...]]></ParameterChunk>
  </DeviceSlot>
</FilterDevicePreset>

The ... was a bunch of Base64 data. Decoding that gave me a full .vstpreset, header and all.

1 Like

Ah, this now works :slight_smile:

Song = renoise.song()
      local stringPresetData = DawProject:convertInstrumentToRedux(Song.selected_instrument, TempDir .. "/plugins/_temp")
      Song.instruments[Song.selected_instrument_index].plugin_properties:load_plugin('Audio/Generators/VST3/' ..
        ReduxVST3Identifier)
      local activePresetData = Helpers:readFile('./templates/redux_instrument.xml')
      activePresetData = string.gsub(activePresetData, 'CHUNKDATA', Helpers:stringToBase64(stringPresetData))
      local name = Song.instruments[Song.selected_instrument_index].name
      Song.instruments[Song.selected_instrument_index]:clear()
      Song.instruments[Song.selected_instrument_index].name = name
      Song.instruments[Song.selected_instrument_index].plugin_properties.plugin_device.active_preset_data =
          activePresetData
1 Like

the base64 decoder that @OopsIFly has made available is really important for this.

i’ve used it to inject data into a Renoise Convolver.

what i would propose is first generating a xml you can inject via a script to the plugin, then work out how to dynamically replace the <ParameterChunk>.