Welcome to the Renoise scripting Guide. In all the various "Documention" files, we will give you an overview on how to write tools for Renoise; how to debug them, what's possible to "script", what's not, and much more. Please read this introduction carefully to get an idea on how to get started, and to avoid common pitfalls and FAQs.
By default Renoise has all scripting utilities hidden; to keep things as easy as possible for those who don't want to mess around with code. If you want to write scripts, then the first thing you have to do is enable the hidden development tools that are built into Renoise. This can be done by:
Launching the Renoise executable with the argument "--scripting-dev"
Opening Renoise's config.xml file from the preferences folder, and setting the
Enabling scripting will add a new main menu entry "Tools" (or add new entries there if it already exists).
In the "Tools" menu you will find:
Reload All Tools: This will force a reload of all installed and running scripting tools. This can be handy when adding new tools by hand or when changing them.
Scripting Console & Editor: This is the main developing scripting tool. It allows you to:
Show Example Tools that target script developers.
Right now (in this Renoise release), you can make use of scripts in the following places:
Run scripts and commands via a terminal in realtime using the "Scripting Console & Editor".
Create tools: Add new and custom functionality to Renoise. Tools are small file bundles with Lua script(s) and a description file (manifest.xml) that make use of the Renoise API. Tools can be distributed and installed via drag and drop (by bundling them and hiding the code). This way, not only developers can use scripts, but also users who don't want to mess around with technical details. We'll describe these types bundles later on...
Some examples of what you can do with Renoise Tools:
New context menu entries and keyboard shortcuts. Think "My Improved Pattern Jump", "My Bypass all DSP Devices in Track", "My Generate Chip Sound Sample" commands, and so on.
Custom graphical user interface elements with the look and feel of Renoise itself. Perfectly integrate your tools into Renoise, and make them easy to use for other users.
Manipulate Renoise's main window or song (patterns, tracks, instruments, anything that makes up a song). Generate, filter, or process song data in any way you can think of. E.g. for algorithmic composition, instrument creation, automation, etc. The sky is the limit.
Nibbles ;)
MIDI controller scripting: Create bidirectional MIDI or OSC implementations for any controller hardware:
For example, make your Launchpad or Monome behave exactly how you want them to, and share your settings with others. Tools like these can be a simple auto mapping of your MIDI controller, like plug & play support for Mackie Control, Behringer MIDI Mixers, and so on.
To make this easier, Renoise offers a tool called "Duplex" which already has support for several MIDI/OSC controllers. Duplex is a very flexible, object-oriented approach to handling MIDI controllers in Renoise, and also offers virtual UIs for the MIDI controllers that are supported by Duplex. This way you can virtually test and use such controllers in Renoise without even owning them. ;)
NB: You don't have to use Duplex to write MIDI/OSC controller scripts in Renoise, but it is a nice (and supported) framework that makes this type of development easier.
Create, configure, or override Renoise's default MIDI/OSC bindings: Renoise has a default set of MIDI mappings that can be assigned manually by the user. These can be inherited, extended and tweaked to fit your needs. Renoise also has a default OSC implementation which can tweaked and overriden to do "your stuff."
What's NOT possible with Renoise tools:
Change Renoise's existing behaviour. Like, you can't make all C-4s in the pattern editor yellow instead of white. You can write your own pattern editor, but not change the existing one.
Realtime access. Except for OSC and MIDI IO, you can't write scripts that run in the audio player. In other words, you can not script new realtime DSPs - yet. But you can, for example, write a tool that creates samples or manipulates existing samples. This limitation might change in the future. For now you can make a VST, AudioUnit, or LADSPA/DSSI plug-in.
The XXX.API files in this documentation folder will list all available Lua functions and classes that can be accessed from scripts in Renoise. If you are familiar with Renoise, the names of the classes, functions and properties should be self explanitory.
Here is a small overview of what the API exposes:
Renoise.API
Renoise API version number and some global accessors like "song", "app" are here.
Renoise.Application.API
Access to the main Renoise application and window, main user interface.
Renoise.Song.API
Access to the song and all its components (instruments, samples, tracks...)
Renoise.Document.API
Generic "observer pattern" document creation and access, used by the
song/app and to create persistent data (preferences, presets).
Renoise.ScriptingTool.API
Available to XRNX tools only: Interact with Renoise; create menus, keybindings.
Renoise.Socket.API
Inter-process and network communication functions and classes.
Renoise.OSC.API
Tools to generate and receive OSC messages, bundles over the network.
Renoise.Midi.API
"Raw" MIDI device interaction (send, receive MIDI messages from any devices.)
A note about the general API design:
Whatever you do with the API, you should never be able to fatally crash Renoise. If you manage to do this, then please file a bug report in our forums so we can fix it. All errors, as stupid they might be, should always result in a clean error message from Lua.
The Renoise Lua API also allows global File IO and external program execution (via os.execute()) which can obviously be hazardous. Please be careful with these, as you would with programming in general...
Some notes about the documentation, and a couple of tips:
All classes, functions in the API, are nested in the namespace (Lua table) "renoise". E.g: to get the application object, you will have to type "renoise.app()"
The API is object-oriented, and thus split into classes. The references will first note the class name (e.g. 'renoise.Application'), then list its Constants, Properties, Functions and Operators. All properties and functions are always listed with their full path to make it clear where they belong and how to access them.
Return values (or arguments / types of properties) are listed in brackets. "-> [string]" means that a string is returned. When no brackets are listed, the function will not return anything.
Nearly all functions are actually "methods", so you have to invoke them via the colon operator ":" E.g. 'renoise.app():show_status("Status Message")' If you're new to Lua, this takes a while to get used to. Don't worry, it'll make sense sooner or later. ;)
Properties are syntactic sugar for get/set functions. "song().comments" will invoke a function which returns "comments". But not all properties have setters, and thus can only be used as read-only "getters". Those are marked as "[read-only, type]". Again mind the colon; which you don't need when accessing properties!
All exposed "objects" are read-only (you can not add new fields, properties).
In contrast, the "classes" are not. This means you can extend the API classes
with your own helper functions, if needed, but can not add new properties to
objects. Objects, like for example the result of "song()", are read-only to
make it easier to catch typos. song().transport.bmp = 80
will fire an error,
because there is no such property 'bmp.' You probably meant
song().transport.bpm = 80
here. If you need to store data somewhere,
do it in your own tables, objects instead of using the Renoise API objects.
"some_property, _observable" means, that there is also an observer object available for the property. An observable object allows you to attach notifiers (global functions or methods) that will be called as soon as a value has changed. Please see Renoise.Document.API for more info about observables and related classes.
A small example using bpm:
renoise.song().transport.bpm_observable:add_notifier(function() print("bpm changed") end) -- will print "bpm changed", but only if the bpm was not 120 before renoise.song().transport.bpm = 120
The above notifier is called when anything changes the bpm, including your script, other scripts, or anything else in Renoise (you've automated the BPM in the song, entered a new BPM value in Renoise's GUI, whatever...)
Lists like "renoise.song().tracks[]" can also have notifiers. But these will only fire when the list layout has changed: an element was added, removed or elements in the list changed their order. They will not fire when the list values changed. Attach notifiers to the list elements to get such notifications.
Can't remember what the name of function XYZ was? In the scripting terminal
you can list all methods/properties of API objects (or your own class objects)
via the global function oprint(some_object)
- e.g. oprint(renoise.song())
.
To dump the renoise module/class layout, use rprint(renoise)
.
Developing XRNX tools: As previously mentioned, Renoise tools are file bundles with an XRNX extension. Tools have the following layout:
You can import other Lua files into "main.lua" via Lua's "require" function if appropriate, and also include resource files (icons, bitmaps, text files, or executables) into your bundles as needed.
For a detailed description of the bundle layout and the main.lua, manifest.lua specifications, have a look at the "com.renoise.Example.xrnx" tool please.
Distributing XRNX tools: To share your tools with others, you can create Zip files out of your bundles, which can then simply be dragged and dropped into Renoise by the user. To do so, zip all the bundle's content (the !content!, not the bundle folder itself), and rename this Zip file to "SomeName.xrnx". Renoise will accept such XRNX zips as drag and drop targets, copy, install and activate the tool automatically.
If you want to add support for your MIDI controller into Duplex, or help extend the Duplex framework, have a look at the Duplex XRNX tool.
In the XRNX bundle you'll find some information about the Duplex API and how to create new controller mappings.
The Duplex code can also be viewed online in the XRNX repository at: https://github.com/renoise/xrnx/tree/master/Tools/com.renoise.Duplex.xrnx
More information can be found in Duplex manual, available here: https://github.com/renoise/xrnx/blob/master/Tools/com.renoise.Duplex.xrnx/Docs/GettingStarted.md
If tracing/debugging in the console with print, oprint and rprint isn't enough, you can try attaching a command-line based debugger to your scripts. Have a look at the Debugging document for more information and a small tutorial.
Enjoy extending, customizing and automating Renoise ;)