├── docs ├── API │ ├── builtins.md │ ├── modules.md │ ├── builtins │ │ ├── any.md │ │ ├── unknown.md │ │ ├── integer.md │ │ ├── function.md │ │ ├── table.md │ │ ├── number.md │ │ ├── string.md │ │ ├── userdata.md │ │ ├── lightuserdata.md │ │ ├── boolean.md │ │ ├── nil.md │ │ └── self.md │ ├── renoise │ │ ├── renoise.Views.md │ │ ├── renoise.SongPos.md │ │ ├── renoise.Document.Serializable.md │ │ ├── renoise.Osc.Bundle.md │ │ ├── renoise.Dialog.md │ │ ├── renoise.Midi.MidiDevice.md │ │ ├── renoise.Midi.MidiInputDevice.md │ │ ├── renoise.ScriptingTool.MidiMessage.md │ │ ├── renoise.Socket.SocketBase.md │ │ ├── renoise.EffectColumn.md │ │ ├── renoise.Midi.MidiOutputDevice.md │ │ ├── renoise.InstrumentMacroMapping.md │ │ ├── renoise.InstrumentMidiInputProperties.md │ │ ├── renoise.Document.Observable.md │ │ ├── renoise.InstrumentMacro.md │ │ ├── renoise.Document.ObservableBang.md │ │ ├── renoise.Socket.md │ │ ├── renoise.InstrumentPluginDevice.md │ │ ├── renoise.InstrumentDevice.md │ │ ├── renoise.Document.ObservableNumber.md │ │ ├── renoise.Document.ObservableString.md │ │ ├── renoise.Document.ObservableBoolean.md │ │ ├── renoise.PatternLine.md │ │ ├── renoise.Document.ObservableList.md │ │ ├── renoise.InstrumentPhraseMapping.md │ │ ├── renoise.SampleMapping.md │ │ ├── renoise.Osc.Message.md │ │ ├── renoise.NoteColumn.md │ │ ├── renoise.DeviceParameter.md │ │ ├── renoise.InstrumentMidiOutputProperties.md │ │ ├── renoise.AudioDevice.md │ │ ├── renoise.SampleDeviceChain.md │ │ ├── renoise.Midi.md │ │ ├── renoise.Document.ObservableNumberList.md │ │ ├── renoise.Document.ObservableStringList.md │ │ ├── renoise.Document.ObservableBooleanList.md │ │ ├── renoise.Osc.md │ │ ├── renoise.PatternTrack.md │ │ ├── renoise.InstrumentTriggerOptions.md │ │ └── renoise.SampleOperandModulationDevice.md │ ├── modules │ │ ├── debug.md │ │ ├── math.md │ │ ├── io.md │ │ ├── os.md │ │ ├── table.md │ │ └── global.md │ ├── renoise.md │ └── README.md ├── guide │ ├── README.md │ ├── sqlite.md │ ├── files&bits.md │ ├── observables.md │ ├── classes.md │ ├── midi.md │ └── osc.md ├── styles.css └── start │ ├── README.md │ ├── installing.md │ ├── distribution.md │ ├── development.md │ └── possibilities.md ├── Cargo.toml ├── .gitmodules ├── .gitignore ├── .vscode ├── settings.json ├── tasks.json └── launch.json ├── tools ├── com.renoise.ExampleToolGui.xrnx │ ├── Bitmaps │ │ ├── MiniPiano.bmp │ │ ├── RenoiseLua.bmp │ │ └── RenoiseLua.png │ └── manifest.xml ├── DragOntoRenoiseToInstall.txt ├── com.renoise.ExampleToolSlicedProcess.xrnx │ ├── manifest.xml │ ├── process_slicer.lua │ └── main.lua └── com.renoise.ExampleTool.xrnx │ └── manifest.xml ├── tests ├── README.md ├── all.lua ├── app_window.lua ├── class.lua ├── parameters.lua ├── osc.lua ├── notifiers.lua ├── track_device_chain.lua ├── transport.lua └── sample_device_chain.lua ├── generate ├── Cargo.toml ├── src │ └── main.rs └── README.md ├── justfile ├── book.toml ├── BUILD.md ├── LICENSE ├── .github └── workflows │ ├── archive.yml │ └── pages.yml └── README.md /docs/API/builtins.md: -------------------------------------------------------------------------------- 1 | # Lua Builtin Types -------------------------------------------------------------------------------- /docs/API/modules.md: -------------------------------------------------------------------------------- 1 | # Lua Module Extensions -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "generate", 5 | ] 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "definitions"] 2 | path = definitions 3 | url = git@github.com:renoise/definitions 4 | branch = master 5 | -------------------------------------------------------------------------------- /docs/API/builtins/any.md: -------------------------------------------------------------------------------- 1 | # any 2 | > A type for a dynamic argument, it can be anything at run-time. 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | /book/ 3 | /dist/ 4 | /generate/Cargo.lock 5 | /generate/target/ 6 | /generate/lua-language-server/ 7 | /target/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Lua.workspace.library": ["./definitions"], 3 | "Lua.runtime.plugin": "./definitions/plugin.lua" 4 | } 5 | -------------------------------------------------------------------------------- /docs/API/builtins/unknown.md: -------------------------------------------------------------------------------- 1 | # unknown 2 | > A dummy type for something that cannot be inferred before run-time. 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/integer.md: -------------------------------------------------------------------------------- 1 | # integer 2 | > A helper type that represents whole numbers, a subset of [number](number.md) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Views.md: -------------------------------------------------------------------------------- 1 | # renoise.Views 2 | > Namespace for renoise view widgets. 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/MiniPiano.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renoise/xrnx/HEAD/tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/MiniPiano.bmp -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/RenoiseLua.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renoise/xrnx/HEAD/tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/RenoiseLua.bmp -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/RenoiseLua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renoise/xrnx/HEAD/tools/com.renoise.ExampleToolGui.xrnx/Bitmaps/RenoiseLua.png -------------------------------------------------------------------------------- /docs/API/builtins/function.md: -------------------------------------------------------------------------------- 1 | # function 2 | > A built-in type representing functions, [see details](https://www.lua.org/pil/2.6.html) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/table.md: -------------------------------------------------------------------------------- 1 | # table 2 | > A built-in type representing associative arrays, [see details](https://www.lua.org/pil/2.5.html) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/number.md: -------------------------------------------------------------------------------- 1 | # number 2 | > A built-in type representing floating point numbers, [see details](https://www.lua.org/pil/2.3.html) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/string.md: -------------------------------------------------------------------------------- 1 | # string 2 | > A built-in type representing a string of characters, [see details](https://www.lua.org/pil/2.4.html) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/userdata.md: -------------------------------------------------------------------------------- 1 | # userdata 2 | > A built-in type representing array values, [see details](https://www.lua.org/pil/28.1.html). 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/lightuserdata.md: -------------------------------------------------------------------------------- 1 | # lightuserdata 2 | > A built-in type representing a pointer, [see details](https://www.lua.org/pil/28.5.html) 3 | 4 | -------------------------------------------------------------------------------- /docs/API/builtins/boolean.md: -------------------------------------------------------------------------------- 1 | # boolean 2 | > A built-in type representing a boolean (true or false) value, [see details](https://www.lua.org/pil/2.2.html) 3 | 4 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | ## Renoise API Tests 2 | 3 | This is a set of basic tests for the renoise Lua API, which need to be invoked within Renoise's scripting terminal. 4 | 5 | Use all.lua to run all of them in a batch. 6 | -------------------------------------------------------------------------------- /docs/API/builtins/nil.md: -------------------------------------------------------------------------------- 1 | # nil 2 | > A built-in type representing a non-existant value, [see details](https://www.lua.org/pil/2.1.html). When you see `?` at the end of types, it means they can be nil. 3 | 4 | -------------------------------------------------------------------------------- /generate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generate-api-docs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | # luals-docs-gen = { path = "../../Crates/luals-docs-gen" } 8 | luals-docs-gen = { git = "https://github.com/emuell/luals-docs-gen", tag = "v0.2.2" } 9 | -------------------------------------------------------------------------------- /docs/API/builtins/self.md: -------------------------------------------------------------------------------- 1 | # self 2 | > A type that represents an instance that you call a function on. When you see a function signature starting with this type, you should use `:` to call the function on the instance, this way you can omit this first argument. 3 | > ```lua 4 | > local object = SomeClass() 5 | > object:do_something(123) 6 | > ``` 7 | 8 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Guides to the Renoise API 2 | 3 | Welcome to the guides for the Renoise Scripting API. 4 | 5 | In this section, you can learn about different aspects of the API through practical examples and explanations. These guides assume you have already read the chapters in our [introduction](../start/development.md) and are familiar with how to package and install tools. 6 | -------------------------------------------------------------------------------- /tools/DragOntoRenoiseToInstall.txt: -------------------------------------------------------------------------------- 1 | To try out the example tools you have to install them first. 2 | 3 | This can be done by dragging the com.renoise.ExampleTool.xrnx and 4 | com.renoise.ExampleToolGui.xrnx folders onto the running Renoise window. 5 | 6 | The installed tools will create two menu entries in Renoises "Tool" menu: 7 | "Tools -> Example Tool" and 8 | "Tools -> Example Tool GUI" 9 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | # These are just commands: https://github.com/casey/just 2 | 3 | default: docs-serve 4 | 5 | install-mdbook: 6 | cargo binstall -y mdbook mdbook-linkcheck mdbook-toc mdbook-alerts 7 | 8 | update-definitions: 9 | cd definitions && git checkout master 10 | 11 | docs-generate-api: 12 | cargo run 13 | 14 | docs-build: docs-generate-api 15 | mdbook build 16 | 17 | docs-serve: docs-generate-api 18 | mdbook serve 19 | -------------------------------------------------------------------------------- /docs/API/modules/debug.md: -------------------------------------------------------------------------------- 1 | # debug 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### `start()` 9 | > Shortcut to remdebug.session.start(), which starts a debug session: 10 | > launches the debugger controller and breaks script execution. See 11 | > "Debugging.md" in the documentation root folder for more info. 12 | ### `stop()` 13 | > Shortcut to remdebug.session.stop: stops a running debug session 14 | 15 | -------------------------------------------------------------------------------- /docs/styles.css: -------------------------------------------------------------------------------- 1 | blockquote { 2 | margin: 10px 0; 3 | padding-left: 10px; 4 | padding-right: 10px; 5 | background-color: transparent; 6 | border-block-start: .1em solid transparent; 7 | border-block-end: .1em solid transparent; 8 | } 9 | 10 | blockquote > p { 11 | color: var(--icons); 12 | padding: 0 0 10px 0; 13 | margin: 0 0 0 10px; 14 | } 15 | 16 | hr { 17 | height: 2px; 18 | background-color: var(--quote-border); 19 | border: none; 20 | } -------------------------------------------------------------------------------- /docs/API/renoise/renoise.SongPos.md: -------------------------------------------------------------------------------- 1 | # renoise.SongPos 2 | > Helper class used in Transport and Song, representing a position in the song. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Properties 9 | ### sequence : [`integer`](../../API/builtins/integer.md) 10 | > Position in the pattern sequence. 11 | 12 | ### line : [`integer`](../../API/builtins/integer.md) 13 | > Position in the pattern at the given pattern sequence. 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /generate/src/main.rs: -------------------------------------------------------------------------------- 1 | use luals_docs_gen::*; 2 | 3 | fn main() -> Result<(), Error> { 4 | // run from the `generate` dir 5 | std::env::set_current_dir(env!("CARGO_MANIFEST_DIR"))?; 6 | // set option and generate... 7 | let options = Options { 8 | library: "../definitions/library".into(), 9 | output: "../docs".into(), 10 | excluded_classes: vec![], 11 | order: OutputOrder::ByClass, 12 | namespace: "renoise".into(), 13 | }; 14 | generate_docs(&options) 15 | } 16 | -------------------------------------------------------------------------------- /generate/README.md: -------------------------------------------------------------------------------- 1 | # Renoise API Documentation Generator 2 | 3 | This app generates the API definition chapters in the [Renoise XRNX book](https://renoise.github.io/xrnx/) from the [Renoise API definition](https://github.com/renoise/definitions) files using [luals-docs-gen](https://github.com/emuell/luals-docs-gen). 4 | 5 | ## Requirements 6 | 7 | [Rust](https://www.rust-lang.org/tools/install) v1.78 or higher 8 | 9 | ## Building 10 | 11 | To create or update the API definitions chapter, simply build and run the app via `cargo run`. -------------------------------------------------------------------------------- /docs/start/README.md: -------------------------------------------------------------------------------- 1 | Renoise 2 | 3 | ## Welcome 4 | ... to the Renoise Lua Scripting Guide! This book is intended for developers who want to write their own scripts & tools for [Renoise](http://www.renoise.com/). 5 | 6 | If you are only interested in downloading tools for Renoise and not in developing your own tools, please have a look at the [Renoise Tools Page](http://www.renoise.com/tools). 7 | 8 | If you want to develop your own tools for Renoise, just keep reading. 9 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["renoise"] 3 | language = "en" 4 | multilingual = false 5 | src = "docs" 6 | title = "Renoise Scripting" 7 | 8 | [build] 9 | create-missing = false 10 | 11 | [output.html] 12 | default-theme = "dark" 13 | preferred-dark-theme = "ayu" 14 | git-repository-url = "https://github.com/renoise/xrnx" 15 | git-repository-icon = "fa-github" 16 | edit-url-template = "https://github.com/renoise/xrnx/edit/master/{path}" 17 | additional-css = [ "docs/styles.css" ] 18 | 19 | [output.linkcheck] 20 | warning-policy = "ignore" 21 | 22 | [preprocessor.toc] 23 | [preprocessor.alerts] -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cargo", 6 | "command": "run", 7 | "problemMatcher": [ 8 | "$rustc" 9 | ], 10 | "group": "build", 11 | "label": "build: API docs" 12 | }, 13 | { 14 | "type": "shell", 15 | "command": "mdbook", 16 | "args": [ 17 | "build" 18 | ], 19 | "group": "build", 20 | "label": "build: book", 21 | }, 22 | { 23 | "type": "shell", 24 | "command": "mdbook", 25 | "args": [ 26 | "serve" 27 | ], 28 | "group": "build", 29 | "label": "serve: book", 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolSlicedProcess.xrnx/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6.2 4 | com.renoise.ExampleToolSlicedProcess 5 | 1.2 6 | taktik [taktik@renoise.com] 7 | Renoise Tool Processing Example 8 | Development 9 | Example tool that shows how to use coroutines to slice up processing functions. 10 | MIT 11 | http://scripting.renoise.com 12 | 13 | -------------------------------------------------------------------------------- /docs/start/installing.md: -------------------------------------------------------------------------------- 1 | # Installing tools 2 | 3 | You can install any tool by dragging its folder (or a zip file with the `.xrnx` extension and the tool's contents) onto Renoise. You can also copy the folder manually into your Tools folder. 4 | 5 | > [!NOTE] 6 | > When creating a zip file you should only zip the **contents** of the folder, not the folder itself 7 | 8 | 9 | 10 | 11 | After you've installed a tool, it will be activated automatically. When in doubt, click the *Tools / Reload All Tools*. -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.Serializable.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.Serializable 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### to_string([*self*](../../API/builtins/self.md)) 9 | `->`[`string`](../../API/builtins/string.md) 10 | 11 | > Serialize an object to a string. 12 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 13 | `->`[`string`](../../API/builtins/string.md) 14 | 15 | > Assign the object's value from a string - when possible. Errors are 16 | > silently ignored. 17 | 18 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug 'Generate API'", 11 | "cargo": { 12 | "args": [ 13 | "build", 14 | ], 15 | "filter": { 16 | "kind": "bin" 17 | } 18 | }, 19 | }, 20 | ] 21 | } -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | ## Documentation Development 2 | 3 | ### Requirements 4 | 5 | The docs are generated using [mdBook](https://github.com/rust-lang/mdBook). To preview the pages locally you will need [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to install mdbook, mdbook-linkcheck and mdbook-toc. 6 | 7 | ```sh 8 | # or `binstall`, to fetch latest binaries 9 | cargo install mdbook mdbook-linkcheck mdbook-toc mdbook-alerts 10 | ``` 11 | 12 | ### Building 13 | 14 | Afterwards you can serve the docs at `localhost:3000` using mdbook, this will automatically refresh the browser tab whenever you change markdown files. 15 | 16 | ```sh 17 | mdbook serve --open 18 | ``` 19 | 20 | ### Generate API reference 21 | 22 | See [generate/README.md](./generate/README.md) -------------------------------------------------------------------------------- /tests/all.lua: -------------------------------------------------------------------------------- 1 | local failed_tests = 0 2 | 3 | -- run all tests except midi_actions which already executes a lot of sub tests 4 | local ignored_files = table.create{ "all.lua", "midi_actions.lua" } 5 | 6 | -- run all in current directory 7 | for _, file in pairs(os.filenames(os.currentdir(), { "*.lua" })) do 8 | if ignored_files:find(file) == nil then 9 | local file_chunk = assert(loadfile(os.currentdir() .. file, "t")) 10 | print("Running '" .. file .. "' tests...") 11 | local result, error = pcall(file_chunk) 12 | if result == false then 13 | print("\tTest FAILED:\n" .. error) 14 | failed_tests = failed_tests + 1 15 | end 16 | end 17 | end 18 | 19 | assert(failed_tests == 0, 20 | "One or more test failed. See output for details...") 21 | 22 | -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolGui.xrnx/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6.2 4 | com.renoise.ExampleToolGui 5 | 1.2 6 | taktik [taktik@renoise.com] 7 | Renoise ViewBuilder API Example 8 | Development 9 | Example tool which describes step by step how to create custom GUIs for your Renoise XRNX tools. Please have a look at the source files of this tool (manifest.xml and main.lua) for more info. Also creates a new menu 'Example Tool GUI' in the global 'Tools' menu. 10 | MIT 11 | http://scripting.renoise.com 12 | 13 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Osc.Bundle.md: -------------------------------------------------------------------------------- 1 | # renoise.Osc.Bundle 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### timetag : [`number`](../../API/builtins/number.md) 9 | > **READ-ONLY** Time value of the bundle. 10 | 11 | ### elements : [`renoise.Osc.Bundle`](../../API/renoise/renoise.Osc.Bundle.md) | [`renoise.Osc.Message`](../../API/renoise/renoise.Osc.Message.md)[] 12 | > **READ-ONLY** Access to the bundle elements (table of messages or bundles) 13 | 14 | ### binary_data : [`string`](../../API/builtins/string.md) 15 | > **READ-ONLY** Raw binary representation of the bundle, as needed when e.g. 16 | > sending the message over the network through sockets. 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tools/com.renoise.ExampleTool.xrnx/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6.2 4 | com.renoise.ExampleTool 5 | 1.2 6 | taktik [taktik@renoise.com] 7 | Renoise Scripting Tool Example 8 | Development 9 | Example tool which describes step by step and in depth how to create Renoise XRNX tools. Please have a look at the source files of this tool (manifest.xml and main.lua) for more info. Also creates a new menu 'Example Tool' in the global 'Tools' menu. 10 | http://scripting.renoise.com 11 | MIT 12 | Windows, Mac, Linux 13 | 14 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Dialog.md: -------------------------------------------------------------------------------- 1 | # renoise.Dialog 2 | > A custom dialog created via the scripting API. Dialogs can be created 3 | > via `renoise.app():show_custom_dialog`. 4 | > 5 | > See `create custom views` on top of the renoise.ViewBuilder docs on how to 6 | > create views for the dialog. 7 | 8 | 9 | 10 | 11 | --- 12 | ## Properties 13 | ### visible : [`boolean`](../../API/builtins/boolean.md) 14 | > **READ-ONLY** Check if a dialog is alive and visible. 15 | 16 | ### focused : [`boolean`](../../API/builtins/boolean.md) 17 | > **READ-ONLY** Check if a dialog is visible and is the key window. 18 | 19 | 20 | 21 | --- 22 | ## Functions 23 | ### show([*self*](../../API/builtins/self.md)) 24 | > Bring an already visible dialog to front and make it the key window. 25 | ### close([*self*](../../API/builtins/self.md)) 26 | > Close a visible dialog. 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 by the renoise authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Midi.MidiDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.Midi.MidiDevice 2 | > Baseclass of renoise.Midi.MidiIn/OutDevice with common properties for MIDI 3 | > input and output devices. 4 | 5 | 6 | 7 | 8 | --- 9 | ## Properties 10 | ### is_open : [`boolean`](../../API/builtins/boolean.md) 11 | > Returns true while the device is open (ready to send or receive messages). 12 | > Your device refs will never be auto-closed, "is_open" will only be false if 13 | > you explicitly call "midi_device:close()" to release a device. 14 | 15 | ### name : [`string`](../../API/builtins/string.md) 16 | > The name of a device. This is the name you create a device with via 17 | > `renoise.Midi.create_input_device` or `renoise.Midi.create_output_device`. 18 | 19 | 20 | 21 | --- 22 | ## Functions 23 | ### close([*self*](../../API/builtins/self.md)) 24 | > Close a running MIDI device. When no other client is using a device, Renoise 25 | > will also shut off the device driver so that, for example, Windows OS other 26 | > applications can use the device again. This is automatically done when 27 | > scripts are closed or your device objects are garbage collected. 28 | 29 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Midi.MidiInputDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.Midi.MidiInputDevice 2 | > Midi device interface for receiving MIDI messages. 3 | > Instances are created via `renoise.Midi.create_input_device` 4 | 5 | 6 | 7 | 8 | --- 9 | ## Properties 10 | ### is_open : [`boolean`](../../API/builtins/boolean.md) 11 | > Returns true while the device is open (ready to send or receive messages). 12 | > Your device refs will never be auto-closed, "is_open" will only be false if 13 | > you explicitly call "midi_device:close()" to release a device. 14 | 15 | ### name : [`string`](../../API/builtins/string.md) 16 | > The name of a device. This is the name you create a device with via 17 | > `renoise.Midi.create_input_device` or `renoise.Midi.create_output_device`. 18 | 19 | 20 | 21 | --- 22 | ## Functions 23 | ### close([*self*](../../API/builtins/self.md)) 24 | > Close a running MIDI device. When no other client is using a device, Renoise 25 | > will also shut off the device driver so that, for example, Windows OS other 26 | > applications can use the device again. This is automatically done when 27 | > scripts are closed or your device objects are garbage collected. 28 | 29 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.ScriptingTool.MidiMessage.md: -------------------------------------------------------------------------------- 1 | # renoise.ScriptingTool.MidiMessage 2 | > MIDI message as passed to the `invoke` callback in tool midi_mappings. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Properties 9 | ### int_value : [`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 10 | > Range: (0S - 127) for abs values, Range: (-63 - 63) for relative values 11 | > valid when `is_rel_value()` or `is_abs_value()` returns true, else undefined 12 | 13 | ### boolean_value : [`boolean`](../../API/builtins/boolean.md)[`?`](../../API/builtins/nil.md) 14 | > valid [true OR false] when `is_switch()` returns true, else undefined 15 | 16 | 17 | 18 | --- 19 | ## Functions 20 | ### is_trigger([*self*](../../API/builtins/self.md)) 21 | > returns if action should be invoked 22 | ### is_switch([*self*](../../API/builtins/self.md)) 23 | > check if the boolean_value property is valid 24 | ### is_rel_value([*self*](../../API/builtins/self.md)) 25 | `->`[`boolean`](../../API/builtins/boolean.md) 26 | 27 | > check if the int_value property is valid 28 | ### is_abs_value([*self*](../../API/builtins/self.md)) 29 | `->`[`boolean`](../../API/builtins/boolean.md) 30 | 31 | > check if the int_value property is valid 32 | 33 | -------------------------------------------------------------------------------- /docs/guide/sqlite.md: -------------------------------------------------------------------------------- 1 | # SQLite Databases 2 | 3 | The Renoise API allows you to create or load [SQLite databases](https://sqlite.org). This can be used to either efficiently deal with large data blobs within your tools or to read existing database files from other applications. 4 | 5 | See [`renoise.SQLite`](../API/renoise/renoise.SQLite.md) for more info. 6 | 7 | A quick example on how to open and read from an existing database file: 8 | 9 | ```lua 10 | -- create a new database (rwc = read/write/create) 11 | local db, status, error = renoise.SQLite.open("./some_test.db", "rwc") 12 | -- NB: use renoise.SQLite.open() to create a in-memory db instead 13 | print("Create:", db.is_open, db.error_code, db.error_message) 14 | 15 | local sql = [[ 16 | CREATE TABLE numbers(num1,num2,str); 17 | INSERT INTO numbers VALUES(1,11,"ABC"); 18 | INSERT INTO numbers VALUES(2,22,"DEF"); 19 | INSERT INTO numbers VALUES(3,33,"UVW"); 20 | INSERT INTO numbers VALUES(4,44,"XYZ"); 21 | ]] 22 | 23 | print("Exec:", db:execute(sql)) 24 | print("Changes:", db.changes, db.total_changes, db.error_message) 25 | 26 | -- read from an existing db using a prepared statement 27 | local db, status, error = renoise.SQLite.open("./test.db", "ro") -- read-only 28 | print("Open:", db.is_open, db.error_code, db.error_message) 29 | 30 | local stm = db:prepare("SELECT * from numbers") 31 | print("Read:", stm.columns, stm.unames) 32 | 33 | for k in stm:rows() do 34 | rprint(k) 35 | end 36 | ``` -------------------------------------------------------------------------------- /.github/workflows/archive.yml: -------------------------------------------------------------------------------- 1 | name: Build and Archive XRNX_Starter_Pack.zip 2 | 3 | on: 4 | pull_request: 5 | branches: [ "master" ] 6 | push: 7 | branches: 8 | - master 9 | 10 | env: 11 | CARGO_TERM_COLOR: always 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | with: 20 | submodules: recursive 21 | 22 | - name: Install Rust 23 | uses: actions-rust-lang/setup-rust-toolchain@v1 24 | with: 25 | cache-workspaces: "docs" 26 | cache-key: "renoise-xrnx" 27 | 28 | - name: Install mdbook 29 | run: cargo install mdbook@0.4.51 mdbook-linkcheck@0.7.5 mdbook-toc@0.14.2 mdbook-alerts@0.8.0 30 | 31 | - name: Build the API 32 | run: cargo run 33 | 34 | - name: Build the book 35 | run: mdbook build 36 | 37 | - name: Create XRNX_Starter_Pack 38 | run: | 39 | mkdir dist 40 | cp -rf definitions dist/definitions 41 | cp -rf book/html dist/docs 42 | cp -rf tools dist/tools 43 | rm -rf dist/*/.git dist/*/.gitignore 44 | echo -e '\n\n\n\n' > dist/docs.html 45 | 46 | - name: Archive 47 | uses: actions/upload-artifact@v4 48 | with: 49 | name: XRNX_Starter_Pack 50 | path: dist 51 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Socket.SocketBase.md: -------------------------------------------------------------------------------- 1 | # renoise.Socket.SocketBase 2 | > SocketBase is the base class for socket clients and servers. All 3 | > SocketBase properties and functions are available for servers and clients. 4 | 5 | 6 | 7 | 8 | --- 9 | ## Properties 10 | ### is_open : [`boolean`](../../API/builtins/boolean.md) 11 | > **READ-ONLY** Returns true when the socket object is valid and connected. 12 | > Sockets can manually be closed (see socket:close()). Client sockets can also 13 | > actively be closed/refused by the server. In this case the client:receive() 14 | > calls will fail and return an error. 15 | 16 | ### local_address : [`string`](../../API/builtins/string.md) 17 | > **READ-ONLY** The socket's resolved local address (for example "127.0.0.1" 18 | > when a socket is bound to "localhost") 19 | 20 | ### local_port : [`integer`](../../API/builtins/integer.md) 21 | > **READ-ONLY** The socket's local port number, as specified when instantiated. 22 | 23 | 24 | 25 | --- 26 | ## Functions 27 | ### close([*self*](../../API/builtins/self.md)) 28 | > Closes the socket connection and releases all resources. This will make 29 | > the socket useless, so any properties, calls to the socket will result in 30 | > errors. Can be useful to explicitly release a connection without waiting for 31 | > the dead object to be garbage collected, or if you want to actively refuse a 32 | > connection. 33 | 34 | -------------------------------------------------------------------------------- /docs/start/distribution.md: -------------------------------------------------------------------------------- 1 | # Distribution 2 | 3 | Eventually you might want to share your work with others, in this case you will have to use the zipped format. 4 | 5 | * First, we recommend sharing your tool on the [Tools section of the forum](https://forum.renoise.com/c/renoise-tools) to get some feedback and early testing done. If you create a topic there, you can also use it to notify users about updates or discuss potential improvements. 6 | * Later on, you might want to [submit your tool](https://www.renoise.com/tools/submit) to the official [Tool library](https://www.renoise.com/tools) so that users can find it easier and have automatic updates. 7 | 8 | 9 | # Community channels 10 | 11 | If you have further questions or just want to discuss tools with fellow devs you can reach out over the following channels 12 | 13 | * [The official Renoise forum has a dedicated topic](https://forum.renoise.com/c/renoise-tool-development) 14 | * [The Discord server has a room for scripting](https://discord.com/invite/uDNJpQ8awR) 15 | * [Enter the Matrix at Renoise space](https://matrix.to/#/#renoise-space:hacklab.fi) on [Matrix](https://joinmatrix.org/) 16 | * [Post on Reddit](https://www.reddit.com/r/renoise/) 17 | * [Join the Facebook Group](https://www.facebook.com/groups/109911655710325/) 18 | * [Find community channels on the Renoise site](https://www.renoise.com/community) 19 | 20 | Now that you can write, package and test your tool, you are ready to explore the depths of the API and start implementing your ideas. 21 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.EffectColumn.md: -------------------------------------------------------------------------------- 1 | # renoise.EffectColumn 2 | > A single effect column in a pattern line. 3 | > 4 | > Access effect column properties either by values (numbers) or by strings. 5 | > The string representation uses exactly the same notation as you see 6 | > them in Renoise's pattern or phrase editor. 7 | 8 | 9 | 10 | 11 | --- 12 | ## Properties 13 | ### is_empty : [`boolean`](../../API/builtins/boolean.md) 14 | > **READ-ONLY** True, when all effect column properties are empty. 15 | 16 | ### is_selected : [`boolean`](../../API/builtins/boolean.md) 17 | > **READ-ONLY** True, when this column is selected in the pattern or phrase editor. 18 | 19 | ### number_value : [`integer`](../../API/builtins/integer.md) 20 | > 0-65535 in the form 0x0000xxyy where xx=effect char 1 and yy=effect char 2 21 | 22 | ### number_string : [`string`](../../API/builtins/string.md) 23 | > Range: ('00' - 'ZZ') 24 | 25 | ### amount_value : [`integer`](../../API/builtins/integer.md) 26 | > Range: (0 - 255) 27 | 28 | ### amount_string : [`string`](../../API/builtins/string.md) 29 | > Range: ('00' - 'FF') 30 | 31 | 32 | 33 | --- 34 | ## Functions 35 | ### clear([*self*](../../API/builtins/self.md)) 36 | > Clear the effect column. 37 | ### copy_from([*self*](../../API/builtins/self.md), other : [`renoise.EffectColumn`](../../API/renoise/renoise.EffectColumn.md)) 38 | > Copy the column's content from another column. 39 | 40 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Midi.MidiOutputDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.Midi.MidiOutputDevice 2 | > Midi device interface for sending MIDI messages. 3 | > Instances are created via `renoise.Midi.create_output_device` 4 | 5 | 6 | 7 | 8 | --- 9 | ## Properties 10 | ### is_open : [`boolean`](../../API/builtins/boolean.md) 11 | > Returns true while the device is open (ready to send or receive messages). 12 | > Your device refs will never be auto-closed, "is_open" will only be false if 13 | > you explicitly call "midi_device:close()" to release a device. 14 | 15 | ### name : [`string`](../../API/builtins/string.md) 16 | > The name of a device. This is the name you create a device with via 17 | > `renoise.Midi.create_input_device` or `renoise.Midi.create_output_device`. 18 | 19 | 20 | 21 | --- 22 | ## Functions 23 | ### close([*self*](../../API/builtins/self.md)) 24 | > Close a running MIDI device. When no other client is using a device, Renoise 25 | > will also shut off the device driver so that, for example, Windows OS other 26 | > applications can use the device again. This is automatically done when 27 | > scripts are closed or your device objects are garbage collected. 28 | ### send([*self*](../../API/builtins/self.md), message : [`integer`](../../API/builtins/integer.md)[]) 29 | > Send raw 1-3 byte MIDI messages or sysex messages. Message is expected 30 | > to be an array of numbers. It must not be empty and can only contain 31 | > numbers >= 0 and <= 0xFF (bytes). Sysex messages must be sent in one block, 32 | > and must start with 0xF0, and end with 0xF7. 33 | 34 | -------------------------------------------------------------------------------- /tests/app_window.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestAppWindow.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | 15 | -- shortcuts 16 | 17 | local window = renoise.app().window 18 | 19 | 20 | ---------------------------------------------------------------------------- 21 | -- upper frame 22 | 23 | local notification_count = 0 24 | function disk_browser_is_visible_changed() 25 | notification_count = notification_count + 1 26 | end 27 | 28 | window.disk_browser_is_visible = false 29 | 30 | window.disk_browser_is_visible_observable:add_notifier( 31 | disk_browser_is_visible_changed) 32 | 33 | window.disk_browser_is_visible = true 34 | assert(window.disk_browser_is_visible == true) 35 | assert(notification_count == 1) 36 | 37 | window.disk_browser_is_visible = false 38 | assert(window.disk_browser_is_visible == false) 39 | assert(notification_count == 2) 40 | 41 | window.disk_browser_is_visible_observable:remove_notifier( 42 | disk_browser_is_visible_changed) 43 | 44 | end 45 | 46 | 47 | ------------------------------------------------------------------------------ 48 | -- test finalizers 49 | 50 | collectgarbage() 51 | 52 | 53 | --[[-------------------------------------------------------------------------- 54 | --------------------------------------------------------------------------]]-- 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy mdBook 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | with: 15 | submodules: recursive 16 | 17 | - name: Install Rust 18 | uses: actions-rust-lang/setup-rust-toolchain@v1 19 | with: 20 | cache-workspaces: "docs" 21 | cache-key: "renoise-xrnx" 22 | 23 | - name: Install mdbook 24 | run: cargo install mdbook@0.4.51 mdbook-linkcheck@0.7.5 mdbook-toc@0.14.2 mdbook-alerts@0.8.0 25 | 26 | - name: Build the API 27 | run: cargo run 28 | 29 | - name: Build the book 30 | run: mdbook build 31 | 32 | - name: Upload 33 | uses: actions/upload-pages-artifact@v3 34 | with: 35 | name: github-pages 36 | path: ./book/html 37 | 38 | deploy: 39 | # Add a dependency to the build job 40 | needs: build 41 | 42 | # Grant GITHUB_TOKEN the permissions required to make a Pages deployment 43 | permissions: 44 | pages: write # to deploy to Pages 45 | id-token: write # to verify the deployment originates from an appropriate source 46 | 47 | # Deploy to the github-pages environment 48 | environment: 49 | name: github-pages 50 | url: ${{ steps.deployment.outputs.page_url }} 51 | 52 | # Specify runner + deployment step 53 | runs-on: ubuntu-latest 54 | steps: 55 | - name: Deploy to GitHub Pages 56 | id: deployment 57 | uses: actions/deploy-pages@v4 # or specific "vX.X.X" version tag for this action 58 | -------------------------------------------------------------------------------- /docs/guide/files&bits.md: -------------------------------------------------------------------------------- 1 | # File IO & Bits 2 | 3 | The Renoise API uses Lua's standard [io library](https://www.lua.org/pil/21.html) to read or write external files. 4 | 5 | To access the raw bits and bytes of some data, for example, to read or write binary file streams, you can use the `bit` library. It's built into the Renoise API, so there's no need to `require` it. 6 | 7 | See the [LuaJIT bit library documentation](https://bitop.luajit.org/api.html) for more info and examples. 8 | 9 | ```lua 10 | -- Reading integer numbers or raw bytes from a file 11 | 12 | local function read_word(file) 13 | local bytes = file:read(2) 14 | if (not bytes or #bytes < 2) then 15 | return nil 16 | else 17 | -- little-endian 18 | return bit.bor(bytes:byte(1), 19 | bit.lshift(bytes:byte(2), 8)) 20 | end 21 | end 22 | 23 | local function read_dword(file) 24 | local bytes = file:read(4) 25 | if (not bytes or #bytes < 4) then 26 | return nil 27 | else 28 | -- little-endian 29 | return bit.bor(bytes:byte(1), 30 | bit.lshift(bytes:byte(2), 8), 31 | bit.lshift(bytes:byte(3), 16), 32 | bit.lshift(bytes:byte(4), 24)) 33 | end 34 | end 35 | 36 | -- and so on (adapt as needed to deal with endianness!) ... 37 | 38 | local file, err = io.open("some_binary_file.bin", "rb") 39 | if not file then 40 | print("Could not open file: " .. tostring(err)) 41 | return 42 | end 43 | 44 | local bytes = file:read(512) 45 | 46 | if (not bytes or #bytes < 512) then 47 | print("unexpected end of file") 48 | else 49 | for i = 1, #bytes do 50 | print(bytes:byte(i)) 51 | end 52 | end 53 | 54 | print(read_word(file) or "unexpected end of file") 55 | print(read_dword(file) or "unexpected end of file") 56 | 57 | file:close() 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/API/modules/math.md: -------------------------------------------------------------------------------- 1 | # math 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### lin2db(n : [`number`](../../API/builtins/number.md)) 9 | `->`[`number`](../../API/builtins/number.md) 10 | 11 | > Converts a linear value to a db value. db values will be clipped to 12 | > math.infdb. 13 | > #### examples: 14 | > ```lua 15 | > print(math.lin2db(1.0)) --> 0 16 | > print(math.lin2db(0.0)) --> -200 (math.infdb) 17 | > ``` 18 | ### db2lin(n : [`number`](../../API/builtins/number.md)) 19 | `->`[`number`](../../API/builtins/number.md) 20 | 21 | > Converts a dB value to a linear value. 22 | > #### examples: 23 | > ```lua 24 | > print(math.db2lin(math.infdb)) --> 0 25 | > print(math.db2lin(6.0)) --> 1.9952623149689 26 | > ``` 27 | ### db2fader(min_dB : [`number`](../../API/builtins/number.md), max_dB : [`number`](../../API/builtins/number.md), dB_to_convert : [`number`](../../API/builtins/number.md)) 28 | `->`[`number`](../../API/builtins/number.md) 29 | 30 | > Converts a dB value to a normalized linear fader value between 0-1 within 31 | > the given dB range. 32 | > #### examples: 33 | > ```lua 34 | > print(math.db2fader(-96, 0, 1)) --> 0 35 | > print(math.db2fader(-48, 6, 0)) --> 0.73879611492157 36 | > ``` 37 | ### fader2db(min_dB : [`number`](../../API/builtins/number.md), max_dB : [`number`](../../API/builtins/number.md), fader_value : [`number`](../../API/builtins/number.md)) 38 | `->`[`number`](../../API/builtins/number.md) 39 | 40 | > Converts a normalized linear mixer fader value to a db value within 41 | > the given dB range. 42 | > #### examples: 43 | > ```lua 44 | > print(math.fader2db(-96, 0, 1)) --> 0 45 | > print(math.fader2db(-96, 0, 0)) --> -96 46 | > ``` 47 | 48 | -------------------------------------------------------------------------------- /docs/API/renoise.md: -------------------------------------------------------------------------------- 1 | # renoise 2 | > Holds all renoise related API functions and classes. 3 | 4 | 5 | 6 | ## Constants 7 | 8 | ### API_VERSION : [`number`](../API/builtins/number.md) 9 | > Currently 6.2. Any changes in the API which are not backwards compatible, 10 | > will increase the internal API's major version number (e.g. from 1.4 -> 2.0). 11 | > All other backwards compatible changes, like new functionality, new functions 12 | > and classes which do not break existing scripts, will increase only the minor 13 | > version number (e.g. 1.0 -> 1.1). 14 | 15 | ### RENOISE_VERSION : [`string`](../API/builtins/string.md) 16 | > Renoise Version "Major.Minor.Revision[AlphaBetaRcVersion][Demo]" 17 | 18 | 19 | --- 20 | ## Functions 21 | ### `ViewBuilder()` 22 | `->`[`renoise.ViewBuilder`](../API/renoise/renoise.ViewBuilder.md) 23 | 24 | > Construct a new viewbuilder instance you can use to create views. 25 | ### `app()` 26 | `->`[`renoise.Application`](../API/renoise/renoise.Application.md) 27 | 28 | > Global access to the Renoise Application. 29 | ### `song()` 30 | `->`[`renoise.Song`](../API/renoise/renoise.Song.md)[`?`](../API/builtins/nil.md) 31 | 32 | > Global access to the Renoise Song. 33 | > 34 | > NB: The song instance changes when a new song is loaded or created in Renoise, 35 | > so tools can not memorize the song instance globally once, but must instead 36 | > react on the application's `new_document_observable` 37 | > observable. 38 | ### `tool()` 39 | `->`[`renoise.ScriptingTool`](../API/renoise/renoise.ScriptingTool.md) 40 | 41 | > Global access to the Renoise Scripting Tool (your XRNX tool). 42 | > 43 | > This is only valid when getting called from a tool and not when e.g. using the 44 | > scripting terminal and editor in Renoise. 45 | 46 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentMacroMapping.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentMacroMapping 2 | 3 | 4 | 5 | ## Constants 6 | ### Scaling 7 | > ```lua 8 | > { 9 | > SCALING_LOG_FAST: integer = 1, 10 | > SCALING_LOG_SLOW: integer = 2, 11 | > SCALING_LINEAR: integer = 3, 12 | > SCALING_EXP_SLOW: integer = 4, 13 | > SCALING_EXP_FAST: integer = 5, 14 | > } 15 | > ``` 16 | 17 | 18 | --- 19 | ## Properties 20 | ### parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 21 | > **READ-ONLY** Linked parameter. 22 | > Can be a sample FX- or modulation parameter. Never nil. 23 | 24 | ### parameter_min : [`number`](../../API/builtins/number.md) 25 | > Range: (0 - 1) 26 | 27 | ### parameter_min_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 28 | > Track changes to document properties or general states by attaching listener 29 | > functions to it. 30 | 31 | ### parameter_max : [`number`](../../API/builtins/number.md) 32 | > Range: (0 - 1) 33 | 34 | ### parameter_max_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 35 | > Track changes to document properties or general states by attaching listener 36 | > functions to it. 37 | 38 | ### parameter_scaling : [`renoise.InstrumentMacroMapping.Scaling`](renoise.InstrumentMacroMapping.md#Scaling) 39 | > Scaling which gets applied within the min/max range to set the dest value. 40 | 41 | ### parameter_scaling_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 42 | > Track changes to document properties or general states by attaching listener 43 | > functions to it. 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentMidiInputProperties.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentMidiInputProperties 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### device_name : [`string`](../../API/builtins/string.md) 9 | > When setting new devices, device names must be one of 10 | > `renoise.Midi.available_input_devices()` or "Renoise OSC Device". 11 | > To close a device and disconnect it from the instrument, assign 12 | > an empty string. 13 | 14 | ### device_name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 15 | > Track changes to document properties or general states by attaching listener 16 | > functions to it. 17 | 18 | ### channel : [`integer`](../../API/builtins/integer.md) 19 | > Range: (1 - 16) 0 = Omni 20 | 21 | ### channel_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 22 | > Track changes to document properties or general states by attaching listener 23 | > functions to it. 24 | 25 | ### note_range : [`integer`](../../API/builtins/integer.md)[] 26 | > Table of two numbers in range (0-119) where C-4 is 48 27 | 28 | ### note_range_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 29 | > Track changes to document properties or general states by attaching listener 30 | > functions to it. 31 | 32 | ### assigned_track : [`integer`](../../API/builtins/integer.md) 33 | > Range: (1 - song.sequencer_track_count) 0 = Current track 34 | 35 | ### assigned_track_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 36 | > Track changes to document properties or general states by attaching listener 37 | > functions to it. 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Renoise 2 | 3 | ## Renoise Scripting Development 4 | 5 | Welcome to the Renoise Lua Scripting Repository! This site is for developers who want to write their own scripts & tools for [Renoise](http://www.renoise.com/). If you are only interested in downloading tools for Renoise and not in developing your own, please have a look at the [Renoise Tools Page](http://renoise.com/tools). 6 | 7 | ### Documentation & Guides 8 | 9 | Read the [Renoise Scripting Development Book](https://renoise.github.io/xrnx). 10 | 11 | This book is highly recommended for anyone who wants to get into all this Renoise scripting. Please read it first to get an overview of what's needed to develop tools for Renoise. It contains an introduction, some guides and the full API documentation. 12 | 13 | ### Example Tools 14 | 15 | In addition to the documentation, this repository also contains some sample tools in the [tools folder](./tools) that are intended for new tool developers only. You can download them, install them, and read them as an interactive tutorial. The example tools are also included in the XRNX Starter pack (see below). 16 | 17 | See [github.com/renoise/tools](https://github.com/renoise/tools) for tools created by the Renoise team that actually do something. 18 | 19 | ### Starter Pack 20 | 21 | The scripting development book, API definition and example tools, can also be downloaded as a "starter pack" bundle file from the [releases page](https://github.com/renoise/xrnx/releases). 22 | 23 | ### Need more help? 24 | 25 | For any questions regarding the Lua API or this repository, please have a look at the [Renoise Scripting Development Forum](https://forum.renoise.com/c/renoise-tool-development). 26 | 27 | *Have fun scripting and hacking Renoise!* 28 | 29 | ### Contribute 30 | 31 | Contributions such as typo fixes, new user guides, and other forms of documentation improvement are welcome! 32 | 33 | Please report issues [here](https://github.com/renoise/xrnx/issues) or fork the latest git repository and create a feature or bugfix branch. 34 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.Observable.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.Observable 2 | > Track changes to document properties or general states by attaching listener 3 | > functions to it. 4 | 5 | 6 | 7 | 8 | --- 9 | ## Functions 10 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 11 | `->`[`boolean`](../../API/builtins/boolean.md) 12 | 13 | > Checks if the given function, method was already registered as notifier. 14 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 15 | > Register a function or method as a notifier, which will be called as soon as 16 | > the observable's value changed. The passed notifier can either be a function 17 | > or a table with a function and some context (an "object") -> method. 18 | > #### examples: 19 | > ```lua 20 | > renoise.song().transport.bpm_observable:add_notifier(function() 21 | > print("BPM changed") 22 | > end) 23 | > 24 | > local my_context = { bpm_changes = 0, something_else = "bla" } 25 | > renoise.song().transport.bpm_observable:add_notifier({ 26 | > my_context, 27 | > function(context) 28 | > context.bpm_changes = context.bpm_changes + 1; 29 | > print(("#BPM changes: %s"):format(context.bpm_changes)); 30 | > end 31 | > }) 32 | > ``` 33 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction) | [`NotifierMemberContext`](#NotifierMemberContext)) 34 | > Unregister a previously registered notifier. When only passing an object, 35 | > all notifier functions that match the given object will be removed. 36 | > This will not fire errors when no methods for the given object are attached. 37 | > Trying to unregister a function or method which wasn't registered, will resolve 38 | > into an error. 39 | 40 | 41 | 42 | --- 43 | ## Aliases 44 | ### NotifierFunction 45 | fun() 46 | 47 | 48 | ### NotifierMemberContext 49 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentMacro.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentMacro 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### name : [`string`](../../API/builtins/string.md) 9 | > Macro name as visible in the GUI when mappings are presents. 10 | 11 | ### name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 12 | > Track changes to document properties or general states by attaching listener 13 | > functions to it. 14 | 15 | ### value : [`number`](../../API/builtins/number.md) 16 | > Range: (0 - 1) 17 | 18 | ### value_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 19 | > Track changes to document properties or general states by attaching listener 20 | > functions to it. 21 | 22 | ### value_string : [`string`](../../API/builtins/string.md) 23 | > Range: (0 - 100) 24 | 25 | ### value_string_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 26 | > Track changes to document properties or general states by attaching listener 27 | > functions to it. 28 | 29 | ### mappings : [`renoise.InstrumentMacroMapping`](../../API/renoise/renoise.InstrumentMacroMapping.md)[] 30 | > **READ-ONLY** Macro mappings, target parameters 31 | 32 | ### mappings_observable : [`renoise.Document.ObservableList`](../../API/renoise/renoise.Document.ObservableList.md) 33 | > Track changes to document lists by attaching listener functions to it. 34 | > NB: Notifiers will not broadcast changes made to list items, but only changes 35 | > to the lists **layout** (items got added, removed, swapped). 36 | 37 | 38 | 39 | --- 40 | ## Functions 41 | ### mapping([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 42 | `->`[`renoise.InstrumentMacroMapping`](../../API/renoise/renoise.InstrumentMacroMapping.md) 43 | 44 | > Access to a single attached parameter mapping by index. Use property 45 | > 'mappings' to query mapping count. 46 | 47 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableBang.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableBang 2 | > Observable without a value which sends out notifications when "banging" it. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Functions 9 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 10 | `->`[`boolean`](../../API/builtins/boolean.md) 11 | 12 | > Checks if the given function, method was already registered as notifier. 13 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 14 | > Register a function or method as a notifier, which will be called as soon as 15 | > the observable's value changed. The passed notifier can either be a function 16 | > or a table with a function and some context (an "object") -> method. 17 | > #### examples: 18 | > ```lua 19 | > renoise.song().transport.bpm_observable:add_notifier(function() 20 | > print("BPM changed") 21 | > end) 22 | > 23 | > local my_context = { bpm_changes = 0, something_else = "bla" } 24 | > renoise.song().transport.bpm_observable:add_notifier({ 25 | > my_context, 26 | > function(context) 27 | > context.bpm_changes = context.bpm_changes + 1; 28 | > print(("#BPM changes: %s"):format(context.bpm_changes)); 29 | > end 30 | > }) 31 | > ``` 32 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction) | [`NotifierMemberContext`](#NotifierMemberContext)) 33 | > Unregister a previously registered notifier. When only passing an object, 34 | > all notifier functions that match the given object will be removed. 35 | > This will not fire errors when no methods for the given object are attached. 36 | > Trying to unregister a function or method which wasn't registered, will resolve 37 | > into an error. 38 | ### bang([*self*](../../API/builtins/self.md)) 39 | > fire a notification, calling all registered notifiers. 40 | 41 | 42 | 43 | --- 44 | ## Aliases 45 | ### NotifierFunction 46 | fun() 47 | 48 | 49 | ### NotifierMemberContext 50 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/guide/observables.md: -------------------------------------------------------------------------------- 1 | # Observables 2 | 3 | The Renoise API makes extensive use of the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern). In short, many values are wrapped in "Observable" objects. You can register "notifier" functions on these objects, which will be called whenever the underlying value changes. This is a powerful way to react to changes in the application state without constantly polling and comparing values. 4 | 5 | When browsing the [API documentation](../API/README.md), you will find many properties with an `_observable` suffix. Let's see how to use this feature by attaching a notifier that runs when the user loads a new song. 6 | 7 | ```lua 8 | local function on_new_document() 9 | renoise.app():show_message("Loaded a new song!") 10 | end 11 | 12 | -- Get the tool's new_document observable and add our function as a notifier. 13 | renoise.tool().app_new_document_observable:add_notifier(on_new_document) 14 | ``` 15 | 16 | A common pattern is to attach notifiers to song-specific properties inside the `app_new_document_observable` notifier. This ensures that your notifiers are re-attached whenever a new song is loaded. To listen for changes on a specific value, you typically add `_observable` to the property name and add a notifier to it. 17 | 18 | Let's extend the previous snippet to also fire a message whenever the name of the song changes. 19 | 20 | ```lua 21 | local function on_song_name_changed() 22 | local song_name = renoise.song().name 23 | renoise.app():show_message("New name was set!\nName: " .. song_name) 24 | end 25 | 26 | local function on_new_document() 27 | renoise.app():show_message("Loaded a new song!") 28 | -- When a new song is loaded, attach a notifier to its name_observable 29 | renoise.song().name_observable:add_notifier(on_song_name_changed) 30 | end 31 | 32 | renoise.tool().app_new_document_observable:add_notifier(on_new_document) 33 | ``` 34 | 35 | Now, try changing the song title in the "Song Settings" tab to see your message pop up. 36 | 37 | With this technique, you can listen to all sorts of events, which is very useful when you want your tool to react to user actions like selecting a new instrument, track, or sample. 38 | 39 | There are different Observables for each primitive type, such as `ObservableBoolean`, `ObservableNumber`, or `ObservableString`, as well as list types like `ObservableBooleanList`. You can explore the entire [Observables API](../API/renoise/renoise.Document.Observable.md) to see them all. 40 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Socket.md: -------------------------------------------------------------------------------- 1 | # renoise.Socket 2 | > Interfaces for built-in socket support for Lua scripts in Renoise. 3 | > 4 | > Right now UDP and TCP protocols are supported. The class interfaces for UDP 5 | > and TCP sockets behave exactly the same. That is, they don't depend on the 6 | > protocol, so both are easily interchangeable when needed. 7 | 8 | 9 | 10 | ## Constants 11 | ### Protocol 12 | > ```lua 13 | > { 14 | > PROTOCOL_TCP: integer = 1, 15 | > PROTOCOL_UDP: integer = 2, 16 | > } 17 | > ``` 18 | 19 | 20 | --- 21 | ## Functions 22 | ### create_server(server_address : [`string`](../../API/builtins/string.md), server_port : [`integer`](../../API/builtins/integer.md), protocol : [`renoise.Socket.Protocol`](renoise.Socket.md#Protocol)[`?`](../../API/builtins/nil.md)) 23 | `->`[`renoise.Socket.SocketServer`](../../API/renoise/renoise.Socket.SocketServer.md)[`?`](../../API/builtins/nil.md), [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md) 24 | 25 | > Creates a connected UPD or TCP server object. Use "localhost" to use your 26 | > system's default network address. Protocol can be `renoise.Socket.PROTOCOL_TCP` 27 | > or `renoise.Socket.PROTOCOL_UDP` (by default TCP). 28 | > When instantiation and connection succeed, a valid server object is 29 | > returned, otherwise "error" is set and the server object is nil. 30 | > Using the create function with no server_address allows you to create a 31 | > server which allows connections to any address (for example localhost 32 | > and some IP) 33 | ### create_client(server_address : [`string`](../../API/builtins/string.md), server_port : [`integer`](../../API/builtins/integer.md), protocol : [`renoise.Socket.Protocol`](renoise.Socket.md#Protocol)[`?`](../../API/builtins/nil.md), timeout : [`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md)) 34 | `->`client : [`renoise.Socket.SocketClient`](../../API/renoise/renoise.Socket.SocketClient.md)[`?`](../../API/builtins/nil.md), error : [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md) 35 | 36 | > Create a connected UPD or TCP client. 37 | > `protocol` can be `renoise.Socket.PROTOCOL_TCP` or 38 | > `renoise.Socket.PROTOCOL_UDP` (by default TCP). 39 | > `timeout` is the time in ms to wait until the connection is established 40 | > (1000 ms by default). When instantiation and connection succeed, a valid client 41 | > object is returned, otherwise "error" is set and the client object is nil 42 | 43 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentPluginDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentPluginDevice 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### name : [`string`](../../API/builtins/string.md) 9 | > **READ-ONLY** Device name. 10 | 11 | ### short_name : [`string`](../../API/builtins/string.md) 12 | > **READ-ONLY** 13 | 14 | ### presets : [`string`](../../API/builtins/string.md)[] 15 | > **READ-ONLY** 16 | 17 | ### active_preset : [`integer`](../../API/builtins/integer.md) 18 | > Preset handling. 0 when when none is active (or available) 19 | 20 | ### active_preset_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 21 | > Track changes to document properties or general states by attaching listener 22 | > functions to it. 23 | 24 | ### active_preset_data : [`string`](../../API/builtins/string.md) 25 | > raw XML data of the active preset 26 | 27 | ### parameters : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)[] 28 | > **READ-ONLY** 29 | 30 | ### external_editor_available : [`boolean`](../../API/builtins/boolean.md) 31 | > **READ-ONLY** Returns whether or not the plugin provides its own custom GUI. 32 | 33 | ### external_editor_visible : [`boolean`](../../API/builtins/boolean.md) 34 | > When the plugin has no custom GUI, Renoise will create a dummy editor for it which 35 | > lists the plugin parameters. 36 | > set to true to show the editor, false to close it 37 | 38 | ### device_path : [`string`](../../API/builtins/string.md) 39 | > **READ-ONLY** Returns a string that uniquely identifies the plugin 40 | > The string can be passed into: renoise.InstrumentPluginProperties:load_plugin() 41 | 42 | 43 | 44 | --- 45 | ## Functions 46 | ### preset([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 47 | `->`[`string`](../../API/builtins/string.md) 48 | 49 | > Access to a single preset name by index. Use properties 'presets' to iterate 50 | > over all presets and to query the presets count. 51 | ### parameter([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 52 | `->`[`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 53 | 54 | > Access to a single parameter by index. Use properties 'parameters' to iterate 55 | > over all parameters and to query the parameter count. 56 | 57 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentDevice 2 | > **Deprecated.** Use `renoise.InstrumentPluginDevice` instead. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Properties 9 | ### name : [`string`](../../API/builtins/string.md) 10 | > **READ-ONLY** Device name. 11 | 12 | ### short_name : [`string`](../../API/builtins/string.md) 13 | > **READ-ONLY** 14 | 15 | ### presets : [`string`](../../API/builtins/string.md)[] 16 | > **READ-ONLY** 17 | 18 | ### active_preset : [`integer`](../../API/builtins/integer.md) 19 | > Preset handling. 0 when when none is active (or available) 20 | 21 | ### active_preset_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 22 | > Track changes to document properties or general states by attaching listener 23 | > functions to it. 24 | 25 | ### active_preset_data : [`string`](../../API/builtins/string.md) 26 | > raw XML data of the active preset 27 | 28 | ### parameters : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)[] 29 | > **READ-ONLY** 30 | 31 | ### external_editor_available : [`boolean`](../../API/builtins/boolean.md) 32 | > **READ-ONLY** Returns whether or not the plugin provides its own custom GUI. 33 | 34 | ### external_editor_visible : [`boolean`](../../API/builtins/boolean.md) 35 | > When the plugin has no custom GUI, Renoise will create a dummy editor for it which 36 | > lists the plugin parameters. 37 | > set to true to show the editor, false to close it 38 | 39 | ### device_path : [`string`](../../API/builtins/string.md) 40 | > **READ-ONLY** Returns a string that uniquely identifies the plugin 41 | > The string can be passed into: renoise.InstrumentPluginProperties:load_plugin() 42 | 43 | 44 | 45 | --- 46 | ## Functions 47 | ### preset([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 48 | `->`[`string`](../../API/builtins/string.md) 49 | 50 | > Access to a single preset name by index. Use properties 'presets' to iterate 51 | > over all presets and to query the presets count. 52 | ### parameter([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 53 | `->`[`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 54 | 55 | > Access to a single parameter by index. Use properties 'parameters' to iterate 56 | > over all parameters and to query the parameter count. 57 | 58 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableNumber.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableNumber 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### value : [`number`](../../API/builtins/number.md) 9 | > Read/write access to the value of an Observable. 10 | 11 | 12 | 13 | --- 14 | ## Functions 15 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 16 | `->`[`boolean`](../../API/builtins/boolean.md) 17 | 18 | > Checks if the given function, method was already registered as notifier. 19 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 20 | > Register a function or method as a notifier, which will be called as soon as 21 | > the observable's value changed. The passed notifier can either be a function 22 | > or a table with a function and some context (an "object") -> method. 23 | > #### examples: 24 | > ```lua 25 | > renoise.song().transport.bpm_observable:add_notifier(function() 26 | > print("BPM changed") 27 | > end) 28 | > 29 | > local my_context = { bpm_changes = 0, something_else = "bla" } 30 | > renoise.song().transport.bpm_observable:add_notifier({ 31 | > my_context, 32 | > function(context) 33 | > context.bpm_changes = context.bpm_changes + 1; 34 | > print(("#BPM changes: %s"):format(context.bpm_changes)); 35 | > end 36 | > }) 37 | > ``` 38 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction) | [`NotifierMemberContext`](#NotifierMemberContext)) 39 | > Unregister a previously registered notifier. When only passing an object, 40 | > all notifier functions that match the given object will be removed. 41 | > This will not fire errors when no methods for the given object are attached. 42 | > Trying to unregister a function or method which wasn't registered, will resolve 43 | > into an error. 44 | ### to_string([*self*](../../API/builtins/self.md)) 45 | `->`[`string`](../../API/builtins/string.md) 46 | 47 | > Serialize an object to a string. 48 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 49 | `->`[`string`](../../API/builtins/string.md) 50 | 51 | > Assign the object's value from a string - when possible. Errors are 52 | > silently ignored. 53 | 54 | 55 | 56 | --- 57 | ## Aliases 58 | ### NotifierFunction 59 | fun() 60 | 61 | 62 | ### NotifierMemberContext 63 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableString.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableString 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### value : [`string`](../../API/builtins/string.md) 9 | > Read/write access to the value of an Observable. 10 | 11 | 12 | 13 | --- 14 | ## Functions 15 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 16 | `->`[`boolean`](../../API/builtins/boolean.md) 17 | 18 | > Checks if the given function, method was already registered as notifier. 19 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 20 | > Register a function or method as a notifier, which will be called as soon as 21 | > the observable's value changed. The passed notifier can either be a function 22 | > or a table with a function and some context (an "object") -> method. 23 | > #### examples: 24 | > ```lua 25 | > renoise.song().transport.bpm_observable:add_notifier(function() 26 | > print("BPM changed") 27 | > end) 28 | > 29 | > local my_context = { bpm_changes = 0, something_else = "bla" } 30 | > renoise.song().transport.bpm_observable:add_notifier({ 31 | > my_context, 32 | > function(context) 33 | > context.bpm_changes = context.bpm_changes + 1; 34 | > print(("#BPM changes: %s"):format(context.bpm_changes)); 35 | > end 36 | > }) 37 | > ``` 38 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction) | [`NotifierMemberContext`](#NotifierMemberContext)) 39 | > Unregister a previously registered notifier. When only passing an object, 40 | > all notifier functions that match the given object will be removed. 41 | > This will not fire errors when no methods for the given object are attached. 42 | > Trying to unregister a function or method which wasn't registered, will resolve 43 | > into an error. 44 | ### to_string([*self*](../../API/builtins/self.md)) 45 | `->`[`string`](../../API/builtins/string.md) 46 | 47 | > Serialize an object to a string. 48 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 49 | `->`[`string`](../../API/builtins/string.md) 50 | 51 | > Assign the object's value from a string - when possible. Errors are 52 | > silently ignored. 53 | 54 | 55 | 56 | --- 57 | ## Aliases 58 | ### NotifierFunction 59 | fun() 60 | 61 | 62 | ### NotifierMemberContext 63 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableBoolean.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableBoolean 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### value : [`boolean`](../../API/builtins/boolean.md) 9 | > Read/write access to the value of an observable. 10 | 11 | 12 | 13 | --- 14 | ## Functions 15 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 16 | `->`[`boolean`](../../API/builtins/boolean.md) 17 | 18 | > Checks if the given function, method was already registered as notifier. 19 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction)) 20 | > Register a function or method as a notifier, which will be called as soon as 21 | > the observable's value changed. The passed notifier can either be a function 22 | > or a table with a function and some context (an "object") -> method. 23 | > #### examples: 24 | > ```lua 25 | > renoise.song().transport.bpm_observable:add_notifier(function() 26 | > print("BPM changed") 27 | > end) 28 | > 29 | > local my_context = { bpm_changes = 0, something_else = "bla" } 30 | > renoise.song().transport.bpm_observable:add_notifier({ 31 | > my_context, 32 | > function(context) 33 | > context.bpm_changes = context.bpm_changes + 1; 34 | > print(("#BPM changes: %s"):format(context.bpm_changes)); 35 | > end 36 | > }) 37 | > ``` 38 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`NotifierFunction`](#NotifierFunction) | [`NotifierMemberContext`](#NotifierMemberContext)) 39 | > Unregister a previously registered notifier. When only passing an object, 40 | > all notifier functions that match the given object will be removed. 41 | > This will not fire errors when no methods for the given object are attached. 42 | > Trying to unregister a function or method which wasn't registered, will resolve 43 | > into an error. 44 | ### to_string([*self*](../../API/builtins/self.md)) 45 | `->`[`string`](../../API/builtins/string.md) 46 | 47 | > Serialize an object to a string. 48 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 49 | `->`[`string`](../../API/builtins/string.md) 50 | 51 | > Assign the object's value from a string - when possible. Errors are 52 | > silently ignored. 53 | 54 | 55 | 56 | --- 57 | ## Aliases 58 | ### NotifierFunction 59 | fun() 60 | 61 | 62 | ### NotifierMemberContext 63 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.PatternLine.md: -------------------------------------------------------------------------------- 1 | # renoise.PatternLine 2 | 3 | 4 | 5 | ## Constants 6 | 7 | ### EMPTY_NOTE : [`integer`](../../API/builtins/integer.md) 8 | ### NOTE_OFF : [`integer`](../../API/builtins/integer.md) 9 | ### EMPTY_INSTRUMENT : [`integer`](../../API/builtins/integer.md) 10 | ### EMPTY_VOLUME : [`integer`](../../API/builtins/integer.md) 11 | ### EMPTY_PANNING : [`integer`](../../API/builtins/integer.md) 12 | ### EMPTY_DELAY : [`integer`](../../API/builtins/integer.md) 13 | ### EMPTY_EFFECT_NUMBER : [`integer`](../../API/builtins/integer.md) 14 | ### EMPTY_EFFECT_AMOUNT : [`integer`](../../API/builtins/integer.md) 15 | 16 | --- 17 | ## Properties 18 | ### is_empty : [`boolean`](../../API/builtins/boolean.md) 19 | > **READ-ONLY** 20 | 21 | ### note_columns : [`renoise.NoteColumn`](../../API/renoise/renoise.NoteColumn.md)[] 22 | > **READ-ONLY** 23 | 24 | ### effect_columns : [`renoise.EffectColumn`](../../API/renoise/renoise.EffectColumn.md)[] 25 | > **READ-ONLY** 26 | 27 | 28 | 29 | --- 30 | ## Functions 31 | ### clear([*self*](../../API/builtins/self.md)) 32 | > Clear all note and effect columns. 33 | ### copy_from([*self*](../../API/builtins/self.md), other : [`renoise.PatternLine`](../../API/renoise/renoise.PatternLine.md)) 34 | > Copy contents from other_line, trashing column content. 35 | ### note_column([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 36 | `->`[`renoise.NoteColumn`](../../API/renoise/renoise.NoteColumn.md) 37 | 38 | > Access to a single note column by index. Use properties 'note_columns' 39 | > to iterate over all note columns and to query the note_column count. 40 | > This is a !lot! more efficient than calling the property: 41 | > note_columns[index] to randomly access columns. When iterating over all 42 | > columns, use pairs(note_columns). 43 | ### effect_column([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 44 | `->`[`renoise.EffectColumn`](../../API/renoise/renoise.EffectColumn.md) 45 | 46 | > Access to a single effect column by index. Use properties 'effect_columns' 47 | > to iterate over all effect columns and to query the effect_column count. 48 | > This is a !lot! more efficient than calling the property: 49 | > effect_columns[index] to randomly access columns. When iterating over all 50 | > columns, use pairs(effect_columns). 51 | 52 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableList.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableList 2 | > Track changes to document lists by attaching listener functions to it. 3 | > NB: Notifiers will not broadcast changes made to list items, but only changes 4 | > to the lists **layout** (items got added, removed, swapped). 5 | 6 | 7 | 8 | 9 | --- 10 | ## Functions 11 | ### size([*self*](../../API/builtins/self.md)) 12 | `->`[`integer`](../../API/builtins/integer.md) 13 | 14 | > Returns the number of entries of the list. 15 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 16 | > Checks if the given function, method was already registered as notifier. 17 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 18 | > Register a function or method as a notifier, which will be called as soon as 19 | > the observable lists layout changed. The passed notifier can either be a function 20 | > or a table with a function and some context (an "object") -> method. 21 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction) | [`ListNotifierMemberContext`](#ListNotifierMemberContext)) 22 | > Unregister a previously registered list notifier. When only passing an object, 23 | > all notifier functions that match the given object will be removed. 24 | > This will not fire errors when no methods for the given object are attached. 25 | > Trying to unregister a function or method which wasn't registered, will resolve 26 | > into an error. 27 | 28 | 29 | 30 | --- 31 | ## Aliases 32 | ### ListElementAdded 33 | { index : [`integer`](../../API/builtins/integer.md), type : `"insert"` } 34 | 35 | 36 | ### ListElementChange 37 | [`ListElementAdded`](#ListElementAdded) | [`ListElementRemoved`](#ListElementRemoved) | [`ListElementsSwapped`](#ListElementsSwapped) 38 | 39 | 40 | ### ListElementRemoved 41 | { index : [`integer`](../../API/builtins/integer.md), type : `"remove"` } 42 | 43 | 44 | ### ListElementsSwapped 45 | { index1 : [`integer`](../../API/builtins/integer.md), index2 : [`integer`](../../API/builtins/integer.md), type : `"swap"` } 46 | 47 | 48 | ### ListNotifierFunction 49 | (change : [`ListElementChange`](#ListElementChange)) 50 | 51 | 52 | ### ListNotifierMemberContext 53 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /docs/guide/classes.md: -------------------------------------------------------------------------------- 1 | # Classes 2 | 3 | The Lua language does not have a built-in `class` construct. However, the Renoise Lua API provides simple object-oriented programming support via a global `class()` function. All Renoise API objects use such classes, and you can use them in your tools as well. 4 | 5 | See the [luabind documentation](https://www.rasterbar.com/products/luabind/docs.html#defining-classes-in-lua) for more technical information, and the examples below for how to use them. 6 | 7 | ## Examples 8 | 9 | ```lua 10 | -- abstract class 11 | class 'Animal' 12 | 13 | function Animal:__init(name) 14 | self.name = name 15 | self.can_fly = nil 16 | end 17 | 18 | function Animal:__tostring() 19 | assert(self.can_fly ~= nil, "I don't know if I can fly or not") 20 | 21 | return ("I am a %s (%s) and I %s"):format(self.name, type(self), 22 | (self.can_fly and "can fly" or "cannot fly")) 23 | end 24 | 25 | 26 | -- derived classes 27 | 28 | -- MAMMAL 29 | class 'Mammal' (Animal) 30 | 31 | function Mammal:__init(str) 32 | Animal.__init(self, str) 33 | self.can_fly = false 34 | end 35 | 36 | -- BIRD 37 | class 'Bird' (Animal) 38 | 39 | function Bird:__init(str) 40 | Animal.__init(self, str) 41 | self.can_fly = true 42 | end 43 | 44 | -- FISH 45 | class 'Fish' (Animal) 46 | 47 | function Fish:__init(str) 48 | Animal.__init(self, str) 49 | self.can_fly = false 50 | end 51 | 52 | 53 | -- run 54 | 55 | local farm = {} 56 | 57 | table.insert(farm, Mammal("cow")) 58 | table.insert(farm, Bird("sparrow")) 59 | table.insert(farm, Fish("bass")) 60 | 61 | print(("type(Mammal('cow')) -> %s"):format(type(Mammal("cow")))) 62 | print(("type(Mammal) -> %s"):format(type(Mammal))) 63 | 64 | for _,animal in ipairs(farm) do 65 | print(animal) 66 | end 67 | ``` 68 | 69 | Something to keep in mind: 70 | 71 | * A constructor, `function MyClass:__init(args)`, must be defined for each class, or the class cannot be used to instantiate objects. 72 | * Class definitions are always global, so even locally defined classes will be registered globally. 73 | 74 | 75 | ## Class operators 76 | 77 | You can overload most operators in Lua for your classes. You do this by simply declaring a member function with the same name as an operator's corresponding metamethod in Lua. 78 | 79 | The operators you can overload are: 80 | 81 | * `__add` (addition) 82 | * `__sub` (subtraction) 83 | * `__mul` (multiplication) 84 | * `__div` (division) 85 | * `__pow` (exponentiation) 86 | * `__lt` (less than) 87 | * `__le` (less than or equal to) 88 | * `__eq` (equality) 89 | * `__call` (function call) 90 | * `__unm` (unary minus) 91 | * `__tostring` (serialization) 92 | * `__len` (length operator `#`) 93 | 94 | Note: `__tostring` isn't really an operator, but it's the metamethod that is called by the standard library's `tostring()` function. 95 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentPhraseMapping.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentPhraseMapping 2 | 3 | 4 | 5 | ## Constants 6 | ### KeyTrackingMode 7 | > ```lua 8 | > { 9 | > KEY_TRACKING_NONE: integer = 1, 10 | > KEY_TRACKING_TRANSPOSE: integer = 2, 11 | > KEY_TRACKING_OFFSET: integer = 3, 12 | > } 13 | > ``` 14 | 15 | 16 | --- 17 | ## Properties 18 | ### phrase : [`renoise.InstrumentPhrase`](../../API/renoise/renoise.InstrumentPhrase.md) 19 | > Linked phrase. 20 | 21 | ### key_tracking : [`renoise.InstrumentPhraseMapping.KeyTrackingMode`](renoise.InstrumentPhraseMapping.md#KeyTrackingMode) 22 | > Phrase's key-tracking mode. 23 | 24 | ### key_tracking_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 25 | > Track changes to document properties or general states by attaching listener 26 | > functions to it. 27 | 28 | ### base_note : [`integer`](../../API/builtins/integer.md) 29 | > Range: (0 - 119) where C-4 is 48 30 | 31 | ### base_note_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 32 | > Track changes to document properties or general states by attaching listener 33 | > functions to it. 34 | 35 | ### note_range : [`integer`](../../API/builtins/integer.md)[] 36 | > Range: (0 - 119) where C-4 is 48 37 | 38 | ### note_range_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 39 | > Track changes to document properties or general states by attaching listener 40 | > functions to it. 41 | 42 | ### looping : [`boolean`](../../API/builtins/boolean.md) 43 | > Loop mode. The phrase plays as one-shot when disabled. 44 | 45 | ### looping_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 46 | > Track changes to document properties or general states by attaching listener 47 | > functions to it. 48 | 49 | ### loop_start : [`integer`](../../API/builtins/integer.md) 50 | ### loop_start_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 51 | > Track changes to document properties or general states by attaching listener 52 | > functions to it. 53 | 54 | ### loop_end : [`integer`](../../API/builtins/integer.md) 55 | ### loop_end_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 56 | > Track changes to document properties or general states by attaching listener 57 | > functions to it. 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /tests/class.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestClass.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | -- GlobalBaseClass 6 | 7 | class "GlobalBaseClass" 8 | 9 | function GlobalBaseClass:__init(str) 10 | self.__str = str 11 | end 12 | 13 | function GlobalBaseClass:__tostring() 14 | return self.__str 15 | end 16 | 17 | 18 | -- GlobalMyClass 19 | 20 | class "GlobalMyClass"(GlobalBaseClass) 21 | 22 | function GlobalMyClass:__init(str) 23 | GlobalBaseClass.__init(self, str) 24 | end 25 | 26 | 27 | -- namespace 28 | 29 | namespace = { } 30 | 31 | 32 | -- namespace.BaseClass 33 | 34 | class (namespace, "BaseClass") 35 | 36 | function namespace.BaseClass:__init(str) 37 | self.__str = str 38 | end 39 | 40 | function namespace.BaseClass:__tostring() 41 | return self.__str 42 | end 43 | 44 | 45 | -- namespace.MyClass(BaseClass) 46 | 47 | class (namespace, "MyClass")(namespace.BaseClass) 48 | 49 | function namespace.MyClass:__init(str) 50 | namespace.BaseClass.__init(self, str) 51 | end 52 | 53 | 54 | ------------------------------------------------------------------------------ 55 | -- test 56 | 57 | do 58 | 59 | -- tools 60 | 61 | local function assert_error(statement) 62 | assert(pcall(statement) == false, "expected function error") 63 | end 64 | 65 | 66 | -- test class namespaces 67 | 68 | assert_error(function() 69 | assert(tostring(MyClass("Olla")) == "Olla") 70 | end) 71 | 72 | assert(tostring(namespace.MyClass("Olla")) == "Olla") 73 | 74 | assert(type(GlobalBaseClass) == "GlobalBaseClass class") 75 | assert(type(GlobalBaseClass()) == "GlobalBaseClass") 76 | 77 | assert(type(GlobalMyClass) == "GlobalMyClass class") 78 | assert(type(GlobalMyClass()) == "GlobalMyClass") 79 | 80 | assert(type(namespace.BaseClass) == "BaseClass class") 81 | assert(type(namespace.BaseClass()) == "BaseClass") 82 | 83 | assert(type(namespace.MyClass) == "MyClass class") 84 | assert(type(namespace.MyClass()) == "MyClass") 85 | 86 | assert(type(renoise.song()) == "Song") 87 | assert(type(renoise.Song) == "Song class") 88 | 89 | -- rprint(namespace) 90 | -- oprint(GlobalMyClass()) 91 | -- oprint(namespace.MyClass()) 92 | 93 | 94 | -- test class object comparison 95 | 96 | local obj1 = GlobalMyClass() 97 | local obj2 = GlobalMyClass() 98 | 99 | assert(rawequal(obj1, obj1)) 100 | assert(not rawequal(obj1, obj2)) 101 | 102 | assert(rawequal(renoise.song(), renoise.song())) 103 | assert(rawequal(renoise.song().tracks[1], renoise.song().tracks[1])) 104 | assert(not rawequal(renoise.song().tracks[1], renoise.song().tracks[2])) 105 | assert(not rawequal(renoise.song().tracks[1], renoise.song().instruments[1])) 106 | assert(not rawequal(renoise.song().tracks[1], obj1)) 107 | 108 | end 109 | 110 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.SampleMapping.md: -------------------------------------------------------------------------------- 1 | # renoise.SampleMapping 2 | > General remarks: Sample mappings of sliced samples are read-only: can not be 3 | > modified. See `sample_mappings[].read_only` 4 | 5 | 6 | 7 | 8 | --- 9 | ## Properties 10 | ### read_only : [`boolean`](../../API/builtins/boolean.md) 11 | > **READ-ONLY** True for sliced instruments. No sample mapping properties are 12 | > allowed to be modified, but can be read. 13 | 14 | ### sample : [`renoise.Sample`](../../API/renoise/renoise.Sample.md) 15 | > Linked sample. 16 | 17 | ### layer : [`renoise.Instrument.Layer`](renoise.Instrument.md#Layer) 18 | > Mapping's layer (triggered via Note-Ons or Note-Offs?). 19 | 20 | ### layer_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 21 | > Track changes to document properties or general states by attaching listener 22 | > functions to it. 23 | 24 | ### map_velocity_to_volume : [`boolean`](../../API/builtins/boolean.md) 25 | > Mappings velocity->volume and key->pitch options. 26 | 27 | ### map_velocity_to_volume_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 28 | > Track changes to document properties or general states by attaching listener 29 | > functions to it. 30 | 31 | ### map_key_to_pitch : [`boolean`](../../API/builtins/boolean.md) 32 | ### map_key_to_pitch_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 33 | > Track changes to document properties or general states by attaching listener 34 | > functions to it. 35 | 36 | ### base_note : [`integer`](../../API/builtins/integer.md) 37 | > Range: (0-119, c-4=48)] 38 | 39 | ### base_note_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 40 | > Track changes to document properties or general states by attaching listener 41 | > functions to it. 42 | 43 | ### note_range : [`integer`](../../API/builtins/integer.md)[] 44 | > Range: (0 - 119) where C-4 is 48 45 | 46 | ### note_range_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 47 | > Track changes to document properties or general states by attaching listener 48 | > functions to it. 49 | 50 | ### velocity_range : [`integer`](../../API/builtins/integer.md)[] 51 | > Range: (0 - 127) 52 | 53 | ### velocity_range_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 54 | > Track changes to document properties or general states by attaching listener 55 | > functions to it. 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /docs/API/modules/io.md: -------------------------------------------------------------------------------- 1 | # io 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### exists(filename : [`string`](../../API/builtins/string.md)) 9 | `->`[`boolean`](../../API/builtins/boolean.md) 10 | 11 | > Returns true when a file, folder or link at the given path and name exists 12 | ### stat(filename : [`string`](../../API/builtins/string.md)) 13 | `->`result : [`Stat`](#stat)[`?`](../../API/builtins/nil.md), error : [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md), error_code : [`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 14 | 15 | > Returns a table with status info about the file, folder or link at the given 16 | > path and name, else nil the error and the error code is returned. 17 | ### chmod(filename : [`string`](../../API/builtins/string.md), mode : [`integer`](../../API/builtins/integer.md)) 18 | `->`result : [`boolean`](../../API/builtins/boolean.md), error : [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md), error_code : [`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 19 | 20 | > Change permissions of a file, folder or link. mode is a unix permission 21 | > styled octal number (like 755 - WITHOUT a leading octal 0). Executable, 22 | > group and others flags are ignored on windows and won't fire errors 23 | 24 | 25 | 26 | --- 27 | ## Structs 28 | # Stat 29 | > return value for io.stat 30 | 31 | --- 32 | ## Properties 33 | ### dev : [`integer`](../../API/builtins/integer.md) 34 | > device number of filesystem 35 | 36 | ### ino : [`integer`](../../API/builtins/integer.md) 37 | > inode number 38 | 39 | ### mode : [`integer`](../../API/builtins/integer.md) 40 | > unix styled file permissions 41 | 42 | ### type : `"file"` | `"directory"` | `"link"` | `"socket"` | `"named pipe"` | `"char device"` | `"block device"` 43 | ### nlink : [`integer`](../../API/builtins/integer.md) 44 | > number of (hard) links to the file 45 | 46 | ### uid : [`integer`](../../API/builtins/integer.md) 47 | > numeric user ID of file's owner 48 | 49 | ### gid : [`integer`](../../API/builtins/integer.md) 50 | > numeric group ID of file's owner 51 | 52 | ### rdev : [`integer`](../../API/builtins/integer.md) 53 | > the device identifier (special files only) 54 | 55 | ### size : [`integer`](../../API/builtins/integer.md) 56 | > total size of file, in bytes 57 | 58 | ### atime : [`integer`](../../API/builtins/integer.md) 59 | > last access time in seconds since the epoch 60 | 61 | ### mtime : [`integer`](../../API/builtins/integer.md) 62 | > last modify time in seconds since the epoch 63 | 64 | ### ctime : [`integer`](../../API/builtins/integer.md) 65 | > inode change time (NOT creation time!) in seconds 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /tests/parameters.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestParameters.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- shortcuts 9 | 10 | local song = renoise.song() 11 | local selected_track = song.tracks[song.selected_track_index] 12 | 13 | 14 | ---------------------------------------------------------------------------- 15 | -- default track parameters & device parameter iteration 16 | 17 | local found_prefx_volume_parameter = false 18 | local found_prefx_panning_parameter = false 19 | local found_prefx_width_parameter = false 20 | local found_postfx_volume_parameter = false 21 | local found_postfx_panning_parameter = false 22 | 23 | local track_device_parameters = selected_track.devices[1].parameters 24 | 25 | for _,param in ipairs(track_device_parameters) do 26 | 27 | if param.name == selected_track.prefx_volume.name then 28 | found_prefx_volume_parameter = true 29 | 30 | elseif param.name == selected_track.prefx_panning.name then 31 | found_prefx_panning_parameter = true 32 | 33 | elseif param.name == selected_track.prefx_width.name then 34 | found_prefx_width_parameter = true 35 | 36 | elseif param.name == selected_track.postfx_volume.name then 37 | found_postfx_volume_parameter = true 38 | 39 | elseif param.name == selected_track.postfx_panning.name then 40 | found_postfx_panning_parameter = true 41 | end 42 | 43 | end 44 | 45 | assert(found_prefx_volume_parameter) 46 | assert(found_prefx_panning_parameter) 47 | assert(found_prefx_width_parameter) 48 | assert(found_postfx_volume_parameter) 49 | assert(found_postfx_panning_parameter) 50 | 51 | 52 | ---------------------------------------------------------------------------- 53 | -- parameter ranges & values 54 | 55 | assert(selected_track.prefx_volume.value_min < 56 | selected_track.prefx_volume.value_max) 57 | 58 | local new_value = math.random(selected_track.prefx_width.value_min, 59 | selected_track.prefx_width.value_max) 60 | 61 | selected_track.prefx_width.value = new_value 62 | assert(selected_track.prefx_width.value == new_value) 63 | 64 | selected_track.prefx_volume.value_string = "1.0 dB" 65 | assert(selected_track.prefx_volume.value_string == "1.000 dB") 66 | 67 | selected_track.postfx_volume.value_string = "3.0 dB" 68 | 69 | 70 | ---------------------------------------------------------------------------- 71 | -- parameter automation flags 72 | 73 | assert(selected_track.prefx_volume.is_automatable) 74 | assert(not selected_track.postfx_volume.is_automatable) 75 | 76 | end 77 | 78 | 79 | ------------------------------------------------------------------------------ 80 | -- test finalizers 81 | 82 | collectgarbage() 83 | 84 | 85 | --[[-------------------------------------------------------------------------- 86 | --------------------------------------------------------------------------]]-- 87 | -------------------------------------------------------------------------------- /tests/osc.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestOsc.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | local OscMessage = renoise.Osc.Message 15 | local OscBundle = renoise.Osc.Bundle 16 | 17 | 18 | -- create & access messages 19 | 20 | local message = OscMessage("/test/message") 21 | 22 | message = OscMessage("/test/message", { 23 | {tag="s", value="string"}, 24 | {tag="i", value=12}, 25 | {tag="b", value="blob"} 26 | }) 27 | 28 | assert(message.pattern == "/test/message") 29 | assert(message.binary_data:find("/test/message") == 1) 30 | assert(#message.binary_data > #message.pattern) 31 | 32 | assert(#message.arguments == 3) 33 | assert(message.arguments[1].tag == "s") 34 | assert(message.arguments[1].value == "string") 35 | assert(message.arguments[2].tag == "i") 36 | assert(message.arguments[2].value == 12) 37 | assert(message.arguments[3].tag == "b") 38 | assert(message.arguments[3].value == "blob") 39 | 40 | -- unknown tag 41 | assert_error(function() 42 | OscMessage("/test/message", { {tag="X"} }) 43 | end) 44 | -- missing tag value 45 | assert_error(function() 46 | OscMessage("/test/message", { {tag="i"} }) 47 | end) 48 | -- bogus tag value 49 | assert_error(function() 50 | OscMessage("/test/message", { {tag="i", value="string"} }) 51 | end) 52 | 53 | 54 | -- create & access bundles 55 | 56 | local timetag = 99 57 | local bundle = OscBundle(timetag, message) 58 | assert(#bundle.elements == 1) 59 | 60 | bundle = OscBundle(timetag, {OscMessage("/bla"), message}) 61 | assert(#bundle.elements == 2) 62 | assert(type(bundle.elements[1]) == "Message") 63 | assert(type(bundle.elements[2]) == "Message") 64 | assert(bundle.elements[2].arguments[2].tag == "i") 65 | assert(bundle.elements[2].arguments[2].value == 12) 66 | 67 | 68 | -- binary data -> bundles or messages 69 | 70 | local result, error = renoise.Osc.from_binary_data("garbage") 71 | assert(not result and error) 72 | 73 | result, error = renoise.Osc.from_binary_data(bundle.binary_data) 74 | assert(result and not error) 75 | assert(type(result) == "Bundle") 76 | assert(result.timetag == bundle.timetag) 77 | assert(result.elements[2].arguments[2].tag == "i") 78 | assert(result.elements[2].arguments[2].value == 12) 79 | 80 | 81 | result, error = renoise.Osc.from_binary_data(message.binary_data) 82 | assert(result and not error) 83 | assert(type(result) == "Message") 84 | assert(result.arguments[2].tag == "i") 85 | assert(result.arguments[2].value == 12) 86 | 87 | end 88 | 89 | 90 | ------------------------------------------------------------------------------ 91 | -- test finalizers 92 | 93 | collectgarbage() 94 | 95 | 96 | --[[-------------------------------------------------------------------------- 97 | --------------------------------------------------------------------------]]-- 98 | 99 | -------------------------------------------------------------------------------- /docs/start/development.md: -------------------------------------------------------------------------------- 1 | # Setting up your development environment 2 | 3 | To start developing Scripts in Renoise, use the following two menu entries inside the `Tools` menu on the top bar. 4 | 5 | * `Scripting Terminal & Editor` - This will open the debugging console used to test things and see your tool's output 6 | * `Reload All Tools` - This will force a reload of all installed and running tools. It can be useful when adding new tools by hand or when changing them. 7 | 8 | > [!NOTE] 9 | > In previous versions of Renoise it was necessary to launch the Renoise executable with the `--scripting-dev` argument to see the above mentioned menue entries. 10 | 11 | ## Lua 12 | 13 | Tools in Renoise are written using the [Lua programming language](https://www.lua.org/). Lua is a dynamic language with a friendly syntax and good performance. While Renoise itself is written in C++, it has an [API](https://en.wikipedia.org/wiki/API) layer that exposes all sorts of aspects of the tracker so that tools can implement new functionality without the dangers of crashing Renoise itself or having to worry about low level programming challenges. 14 | 15 | > [!NOTE] 16 | > Teaching you programming is out of the scope of this guide but you can check out the book [Programming in Lua](https://www.lua.org/pil/contents.html) to get a complete overview of the language. That said, you will probably be able to pick up a lot of things just by reading through this guide and checking out the examples. If you are the kind of person who learns best by doing stuff, getting straight into tinkering might be right up your alley. 17 | 18 | ### Language Server 19 | 20 | Luckily Lua has a language server called [LuaLS](https://github.com/LuaLS/lua-language-server) which - when paired with the [definitions for the Renoise API](https://github.com/renoise/definitions/) - can help you write code by providing useful hints about functions and variables, autocompletion and code diagnostics. You can even annotate your own code to keep things more explicit and well documented. While you can absolutely write Lua and create tools without any of this, we highly recommend setting it up. 21 | 22 | If you are using [VSCode](https://code.visualstudio.com/) you will have to do three things 23 | 24 | * Install the [Lua extension by sumneko](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) 25 | * Download the [Renoise API definitions from Github](https://github.com/renoise/definitions/) 26 | * Configure VSCode so that LuaLS knows where to find the definition files. For this you will have to either put this into your [workspace's settings](https://code.visualstudio.com/docs/editor/workspaces#_singlefolder-workspace-settings) in your project folder (as `.vscode/settings.json`), or the global *User Settings JSON* file. Make sure to fill the paths below according to where you've extracted the previously downloaded definitions. 27 | 28 | ```json 29 | { 30 | "Lua.workspace.library": [ "PATH/TO/RENOISE_DEFINITION_FOLDER" ], 31 | "Lua.runtime.plugin": "PATH/TO/RENOISE_DEFINITION_FOLDER/plugin.lua" 32 | } 33 | ``` 34 | 35 | > For configuring other editors, you can check out the [official docs about installation](https://luals.github.io/#install) 36 | -------------------------------------------------------------------------------- /docs/API/modules/os.md: -------------------------------------------------------------------------------- 1 | # os 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### `platform()` 9 | `->``"LINUX"` | `"MACINTOSH"` | `"WINDOWS"` 10 | 11 | > Returns the platform the script is running on: 12 | > 13 | > ```lua 14 | > return #1: 15 | > | "WINDOWS" 16 | > | "MACINTOSH" 17 | > | "LINUX" 18 | > ``` 19 | ### `currentdir()` 20 | `->`path : [`string`](../../API/builtins/string.md) 21 | 22 | > Returns the current working dir. Will always be the scripts directory 23 | > when executing a script from a file 24 | ### dirnames(path : [`any`](../../API/builtins/any.md)) 25 | `->`paths : [`string`](../../API/builtins/string.md)[] 26 | 27 | > Returns a list of directory names (names, not full paths) for the given 28 | > parent directory. Passed directory must be valid, or an error will be thrown. 29 | ### filenames(path : [`string`](../../API/builtins/string.md), file_extensions : [`string`](../../API/builtins/string.md)[][`?`](../../API/builtins/nil.md)) 30 | `->`paths : [`string`](../../API/builtins/string.md)[] 31 | 32 | > Returns a list file names (names, not full paths) for the given 33 | > parent directory. Second optional argument is a list of file extensions that 34 | > should be searched for, like {"*.wav", "*.txt"}. By default all files are 35 | > matched. The passed directory must be valid, or an error will be thrown. 36 | ### mkdir(path : [`string`](../../API/builtins/string.md)) 37 | `->`[`boolean`](../../API/builtins/boolean.md)[`?`](../../API/builtins/nil.md), [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md) 38 | 39 | > Creates a new directory. mkdir can only create one new sub directory at the 40 | > same time. If you need to create more than one sub dir, call mkdir multiple 41 | > times. Returns true if the operation was successful; in case of error, it 42 | > returns nil plus an error string. 43 | ### move(src : [`string`](../../API/builtins/string.md), dest : [`string`](../../API/builtins/string.md)) 44 | `->`[`boolean`](../../API/builtins/boolean.md)[`?`](../../API/builtins/nil.md), [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md) 45 | 46 | > Moves a file or a directory from path 'src' to 'dest'. Unlike 'os.rename' 47 | > this also supports moving a file from one file system to another one. Returns 48 | > true if the operation was successful; in case of error, it returns nil plus 49 | > an error string. 50 | ### tmpname(extension : [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md)) 51 | `->`[`string`](../../API/builtins/string.md) 52 | 53 | > Returns a string with a file name that can be used for a temporary file. 54 | > 55 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-os.tmpname) 56 | ### `clock()` 57 | `->`[`number`](../../API/builtins/number.md) 58 | 59 | > Returns an approximation of the amount in seconds of CPU time used by the program. 60 | > 61 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-os.clock) 62 | ### `exit()` 63 | > Calls the ISO C function `exit` to terminate the host program. 64 | > 65 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-os.exit) 66 | 67 | -------------------------------------------------------------------------------- /docs/API/modules/table.md: -------------------------------------------------------------------------------- 1 | # table 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### create(t : [`table`](../../API/builtins/table.md)[`?`](../../API/builtins/nil.md)) 9 | `->`[`table`](../../API/builtins/table.md) | tablelib 10 | 11 | > Create a new, or convert an exiting table to an object that uses the global 12 | > 'table.XXX' functions as methods, just like strings in Lua do. 13 | > #### examples: 14 | > ```lua 15 | > t = table.create(); t:insert("a"); rprint(t) -> [1] = a; 16 | > t = table.create{1,2,3}; print(t:concat("|")); -> "1|2|3"; 17 | > ``` 18 | ### is_empty(t : [`table`](../../API/builtins/table.md)) 19 | `->`[`boolean`](../../API/builtins/boolean.md) 20 | 21 | > Returns true when the table is empty, else false and will also work 22 | > for non indexed tables 23 | > #### examples: 24 | > ```lua 25 | > t = {}; print(table.is_empty(t)); -> true; 26 | > t = {66}; print(table.is_empty(t)); -> false; 27 | > t = {["a"] = 1}; print(table.is_empty(t)); -> false; 28 | ### count(t : [`table`](../../API/builtins/table.md)) 29 | > Count the number of items of a table, also works for non index 30 | > based tables (using pairs). 31 | > #### examples: 32 | > ```lua 33 | > t = {["a"]=1, ["b"]=1}; print(table.count(t)) --> 2 34 | > ``` 35 | ### find(t : [`table`](../../API/builtins/table.md), value : [`any`](../../API/builtins/any.md), start_index : [`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md)) 36 | `->`key_or_nil : [`string`](../../API/builtins/string.md) | [`number`](../../API/builtins/number.md)[`?`](../../API/builtins/nil.md) 37 | 38 | > Find first match of *value* in the given table, starting from element 39 | > number *start_index*.
40 | > Returns the first *key* that matches the value or nil 41 | > #### examples: 42 | > ```lua 43 | > t = {"a", "b"}; table.find(t, "a") --> 1 44 | > t = {a=1, b=2}; table.find(t, 2) --> "b" 45 | > t = {"a", "b", "a"}; table.find(t, "a", 2) --> "3" 46 | > t = {"a", "b"}; table.find(t, "c") --> nil 47 | > ``` 48 | ### keys(t : [`table`](../../API/builtins/table.md)) 49 | `->`[`table`](../../API/builtins/table.md) 50 | 51 | > Return an indexed table of all keys that are used in the table. 52 | > #### examples: 53 | > ```lua 54 | > t = {a="aa", b="bb"}; rprint(table.keys(t)); --> "a", "b" 55 | > t = {"a", "b"}; rprint(table.keys(t)); --> 1, 2 56 | > ``` 57 | ### values(t : [`table`](../../API/builtins/table.md)) 58 | `->`[`table`](../../API/builtins/table.md) 59 | 60 | > Return an indexed table of all values that are used in the table 61 | > #### examples: 62 | > ```lua 63 | > t = {a="aa", b="bb"}; rprint(table.values(t)); --> "aa", "bb" 64 | > t = {"a", "b"}; rprint(table.values(t)); --> "a", "b" 65 | > ``` 66 | ### copy(t : [`table`](../../API/builtins/table.md)) 67 | `->`[`table`](../../API/builtins/table.md) 68 | 69 | > Copy the metatable and all first level elements of the given table into a 70 | > new table. Use table.rcopy to do a recursive copy of all elements 71 | ### rcopy(t : [`table`](../../API/builtins/table.md)) 72 | `->`[`table`](../../API/builtins/table.md) 73 | 74 | > Deeply copy the metatable and all elements of the given table recursively 75 | > into a new table - create a clone with unique references. 76 | ### clear(t : [`table`](../../API/builtins/table.md)) 77 | > Recursively clears and removes all table elements. 78 | 79 | -------------------------------------------------------------------------------- /docs/guide/midi.md: -------------------------------------------------------------------------------- 1 | # MIDI 2 | 3 | The Renoise API allows you to access raw MIDI input and output devices from within your tool. You can use this to add features like bi-directional MIDI controller support. 4 | 5 | See the [`renoise.Midi`](../API/renoise/renoise.Midi.md) API for more details. 6 | 7 | ## MIDI Input Listener (Function Callback) 8 | 9 | ```lua 10 | -- NOTE: The MIDI device will be closed when this local variable gets garbage 11 | -- collected. Make it global or assign it to a table that is held globally 12 | -- to keep it active. 13 | local midi_device = nil 14 | 15 | local inputs = renoise.Midi.available_input_devices() 16 | if not table.is_empty(inputs) then 17 | -- Use the first available device in this example 18 | local device_name = inputs[1] 19 | 20 | local function midi_callback(message) 21 | assert(#message == 3) 22 | assert(message[1] >= 0 and message[1] <= 0xff) 23 | assert(message[2] >= 0 and message[2] <= 0xff) 24 | assert(message[3] >= 0 and message[3] <= 0xff) 25 | 26 | print(("%s: got MIDI %X %X %X"):format(device_name, 27 | message[1], message[2], message[3])) 28 | end 29 | 30 | -- The sysex callback is an optional second argument. 31 | midi_device = renoise.Midi.create_input_device( 32 | device_name, midi_callback) 33 | 34 | -- To stop listening, call: midi_device:close() 35 | end 36 | ``` 37 | 38 | ## MIDI Input and SysEx Listener (Class Callbacks) 39 | 40 | ```lua 41 | class "MidiDumper" 42 | function MidiDumper:__init(device_name) 43 | self.device_name = device_name 44 | self.device = nil 45 | end 46 | 47 | function MidiDumper:start() 48 | self.device = renoise.Midi.create_input_device( 49 | self.device_name, 50 | { self, self.midi_callback }, 51 | { self, self.sysex_callback } 52 | ) 53 | end 54 | 55 | function MidiDumper:stop() 56 | if self.device then 57 | self.device:close() 58 | self.device = nil 59 | end 60 | end 61 | 62 | function MidiDumper:midi_callback(message) 63 | print(("%s: MidiDumper got MIDI %X %X %X"):format( 64 | self.device_name, message[1], message[2], message[3])) 65 | end 66 | 67 | function MidiDumper:sysex_callback(message) 68 | print(("%s: MidiDumper got SYSEX with %d bytes"):format( 69 | self.device_name, #message)) 70 | end 71 | 72 | -- NOTE: The MIDI device will be closed when this dumper object gets garbage 73 | -- collected. Make it global or assign it to a table that is held globally 74 | -- to keep it active. 75 | local midi_dumper = nil 76 | 77 | local inputs = renoise.Midi.available_input_devices() 78 | 79 | if not table.is_empty(inputs) then 80 | -- Use the first available device in this example 81 | local device_name = inputs[1] 82 | 83 | midi_dumper = MidiDumper(device_name) 84 | -- This will dump MIDI messages until midi_dumper:stop() is called 85 | -- or the MidiDumper object is garbage collected. 86 | midi_dumper:start() 87 | end 88 | ``` 89 | 90 | ## MIDI Output 91 | 92 | ```lua 93 | local outputs = renoise.Midi.available_output_devices() 94 | if not table.is_empty(outputs) then 95 | local device_name = outputs[1] 96 | local midi_device = renoise.Midi.create_output_device(device_name) 97 | 98 | -- Note On 99 | midi_device:send({ 0x90, 0x10, 0x7F }) 100 | -- SysEx (MMC Start) 101 | midi_device:send({ 0xF0, 0x7F, 0x00, 0x06, 0x02, 0xF7 }) 102 | 103 | -- We no longer need the device in this example, so close it. 104 | midi_device:close() 105 | end 106 | ``` 107 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Osc.Message.md: -------------------------------------------------------------------------------- 1 | # renoise.Osc.Message 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### pattern : [`string`](../../API/builtins/string.md) 9 | > **READ-ONLY** The message pattern (e.g. "/renoise/transport/start") 10 | 11 | ### arguments : [`OscValue`](#oscvalue)[] 12 | > **READ-ONLY** Table of `{tag="X", value=SomeValue}` that represents the 13 | > message arguments. See `renoise.Osc.Message.create` for more info. 14 | 15 | ### binary_data : [`string`](../../API/builtins/string.md) 16 | > **READ-ONLY** Raw binary representation of the message, as needed when e.g. 17 | > sending the message over the network through sockets. 18 | 19 | 20 | 21 | 22 | 23 | --- 24 | ## Structs 25 | # OscValue 26 | > `tag` is a standard OSC type tag. `value` is the arguments value expressed 27 | > by a Lua type. The value must be convertible to the specified tag, which 28 | > means, you cannot for example specify an "i" (integer) as type and then pass 29 | > a string as the value. Use a number value instead. Not all tags require a 30 | > value, like the T,F boolean tags. Then a `value` field should not be 31 | > specified. For more info, see: http://opensoundcontrol.org/spec-1_0 32 | 33 | --- 34 | ## Properties 35 | ### tag : [`OscTag`](#OscTag) 36 | ### value : [`boolean`](../../API/builtins/boolean.md) | [`string`](../../API/builtins/string.md) | [`number`](../../API/builtins/number.md) 37 | 38 | 39 | 40 | 41 | --- 42 | ## Aliases 43 | ### OscTag 44 | `"F"` | `"I"` | `"N"` | `"S"` | `"T"` | `"b"` | `"c"` | `"d"` | `"f"` | `"h"` | `"i"` | `"m"` | `"r"` | `"s"` | `"t"` 45 | > ```lua 46 | > OscTag: 47 | > | "i" -- int32 48 | > | "f" -- float32 49 | > | "s" -- OSC-string 50 | > | "b" -- OSC-blob (raw string) 51 | > | "h" -- 64 bit big-endian two's complement integer 52 | > | "t" -- OSC-timetag 53 | > | "d" -- 64 bit ("double") IEEE 754 floating point number 54 | > | "S" -- Alternate type represented as an OSC-string 55 | > | "c" -- An ascii character, sent as 32 bits 56 | > | "r" -- 32 bit RGBA color 57 | > | "m" -- 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 58 | > | "T" -- True. No value needs to be specified. 59 | > | "F" -- False. No value needs to be specified. 60 | > | "N" -- Nil. No value needs to be specified. 61 | > | "I" -- Infinitum. No value needs to be specified. 62 | > ``` 63 | 64 | 65 | 66 | 67 | 68 | 69 | --- 70 | ## Aliases 71 | ### OscTag 72 | `"F"` | `"I"` | `"N"` | `"S"` | `"T"` | `"b"` | `"c"` | `"d"` | `"f"` | `"h"` | `"i"` | `"m"` | `"r"` | `"s"` | `"t"` 73 | > ```lua 74 | > OscTag: 75 | > | "i" -- int32 76 | > | "f" -- float32 77 | > | "s" -- OSC-string 78 | > | "b" -- OSC-blob (raw string) 79 | > | "h" -- 64 bit big-endian two's complement integer 80 | > | "t" -- OSC-timetag 81 | > | "d" -- 64 bit ("double") IEEE 754 floating point number 82 | > | "S" -- Alternate type represented as an OSC-string 83 | > | "c" -- An ascii character, sent as 32 bits 84 | > | "r" -- 32 bit RGBA color 85 | > | "m" -- 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 86 | > | "T" -- True. No value needs to be specified. 87 | > | "F" -- False. No value needs to be specified. 88 | > | "N" -- Nil. No value needs to be specified. 89 | > | "I" -- Infinitum. No value needs to be specified. 90 | > ``` 91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.NoteColumn.md: -------------------------------------------------------------------------------- 1 | # renoise.NoteColumn 2 | > A single note column in a pattern line. 3 | > 4 | > General remarks: instrument columns are available for lines in phrases 5 | > but are ignored. See renoise.InstrumentPhrase for detail. 6 | > 7 | > Access note column properties either by values (numbers) or by strings. 8 | > The string representation uses exactly the same notation as you see 9 | > them in Renoise's pattern or phrase editor. 10 | 11 | 12 | 13 | 14 | --- 15 | ## Properties 16 | ### is_empty : [`boolean`](../../API/builtins/boolean.md) 17 | > **READ-ONLY** True, when all note column properties are empty. 18 | 19 | ### is_selected : [`boolean`](../../API/builtins/boolean.md) 20 | > **READ-ONLY** True, when this column is selected in the pattern or phrase 21 | > editors current pattern. 22 | 23 | ### note_value : [`integer`](../../API/builtins/integer.md) 24 | > Range: (0-119) or 120=Off or 121=Empty 25 | 26 | ### note_string : [`string`](../../API/builtins/string.md) 27 | > Range: (\'C-0\'-\'G-9\') or \'OFF\' or \'---\' 28 | 29 | ### instrument_value : [`integer`](../../API/builtins/integer.md) 30 | > Range: (0-254), 255==Empty 31 | 32 | ### instrument_string : [`string`](../../API/builtins/string.md) 33 | > Range: (\'00\'-\'FE\') or \'..\' 34 | 35 | ### volume_value : [`integer`](../../API/builtins/integer.md) 36 | > Range: (0-127) or 255==Empty when column value is <= 0x80 or is 0xFF, 37 | > i.e. to specify a volume value. 38 | > 39 | > Range: (0-65535) in the form 0x0000xxyy where xx=effect char 1 and yy=effect char 2, 40 | > when column value is > 0x80, i.e. to specify an effect. 41 | 42 | ### volume_string : [`string`](../../API/builtins/string.md) 43 | > Range(\'00\'-\'ZF\') or \'..\' 44 | 45 | ### panning_value : [`integer`](../../API/builtins/integer.md) 46 | > Range: (0-127) or 255==Empty when column value is <= 0x80 or is 0xFF, 47 | > i.e. to specify a pan value. 48 | > 49 | > Range: (0-65535) in the form 0x0000xxyy where xx=effect char 1 and yy=effect char 2, 50 | > when column value is > 0x80, i.e. to specify an effect. 51 | 52 | ### panning_string : [`string`](../../API/builtins/string.md) 53 | > Range: (\'00'-\'ZF\') or \'..\' 54 | 55 | ### delay_value : [`integer`](../../API/builtins/integer.md) 56 | > Range: (0-255) 57 | 58 | ### delay_string : [`string`](../../API/builtins/string.md) 59 | > Range: (\'00'-\'FF\') or \'..\' 60 | 61 | ### effect_number_value : [`integer`](../../API/builtins/integer.md) 62 | > Range: (0-65535) in the form 0x0000xxyy where xx=effect char 1 and yy=effect char 2 63 | 64 | ### effect_number_string : [`string`](../../API/builtins/string.md) 65 | > Range: (\'00\'-\'ZZ\') 66 | 67 | ### effect_amount_value : [`integer`](../../API/builtins/integer.md) 68 | > Range: (0-255) 69 | 70 | ### effect_amount_string : [`string`](../../API/builtins/string.md) 71 | > Range: (\'00\' - \'FF\') 72 | 73 | 74 | 75 | --- 76 | ## Functions 77 | ### clear([*self*](../../API/builtins/self.md)) 78 | > Clear the note column. 79 | ### copy_from([*self*](../../API/builtins/self.md), other : [`renoise.NoteColumn`](../../API/renoise/renoise.NoteColumn.md)) 80 | > Copy the column's content from another column. 81 | 82 | -------------------------------------------------------------------------------- /tests/notifiers.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestNotifiers.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | 15 | ---------------------------------------------------------------------------- 16 | -- setup 17 | 18 | -- SomeClass 19 | 20 | class "SomeClass" 21 | function SomeClass:__init(name) 22 | self.name = name 23 | end 24 | 25 | function SomeClass:BpmNotifier() 26 | local bpm = renoise.song().transport.bpm 27 | notifier_print("BPM changed to " .. bpm .. 28 | " in Object: '" .. self.name .. "'") 29 | end 30 | 31 | 32 | -- function 33 | 34 | local function BpmNotifierFunction() 35 | local bpm = renoise.song().transport.bpm 36 | notifier_print("BPM changed to " .. bpm .. 37 | " in global Function") 38 | end 39 | 40 | 41 | -- setup 42 | 43 | local bpm_observable = renoise.song().transport.bpm_observable 44 | local tpl_observable = renoise.song().transport.tpl_observable 45 | 46 | local obj1 = SomeClass("Obj1") 47 | local obj2 = SomeClass("Obj2") 48 | 49 | 50 | ---------------------------------------------------------------------------- 51 | -- expect notifications 52 | 53 | notifier_print = function (message) --[[ do nothing --]] end 54 | 55 | bpm_observable:add_notifier(SomeClass.BpmNotifier, obj1) 56 | bpm_observable:add_notifier(SomeClass.BpmNotifier, obj2) 57 | bpm_observable:add_notifier(BpmNotifierFunction) 58 | 59 | assert(bpm_observable:has_notifier(SomeClass.BpmNotifier, obj1)) 60 | assert(bpm_observable:has_notifier(obj2, SomeClass.BpmNotifier)) 61 | assert(bpm_observable:has_notifier(BpmNotifierFunction)) 62 | assert(not bpm_observable:has_notifier(function() end)) 63 | 64 | tpl_observable:add_notifier(BpmNotifierFunction) 65 | tpl_observable:remove_notifier(BpmNotifierFunction) 66 | 67 | -- already added notifier 68 | assert_error(function() 69 | bpm_observable:add_notifier(SomeClass.BpmNotifier, obj1) 70 | end) 71 | assert_error(function() 72 | bpm_observable:add_notifier(BpmNotifierFunction) 73 | end) 74 | 75 | local transport = renoise.song().transport 76 | local old_bpm = transport.bpm 77 | if transport.bpm == 999 then 78 | transport.bpm = transport.bpm - 1 79 | else 80 | transport.bpm = transport.bpm + 1 81 | end 82 | 83 | 84 | ---------------------------------------------------------------------------- 85 | -- expect no notifications 86 | 87 | notifier_print = function (message) error(message) end 88 | 89 | bpm_observable:remove_notifier(SomeClass.BpmNotifier, obj1) 90 | bpm_observable:remove_notifier(SomeClass.BpmNotifier, obj2) 91 | bpm_observable:remove_notifier(BpmNotifierFunction) 92 | 93 | -- already removed notifiers 94 | assert_error(function() 95 | bpm_observable:remove_notifier(SomeClass.BpmNotifier, obj1) 96 | end) 97 | assert_error(function() 98 | bpm_observable:remove_notifier(BpmNotifierFunction) 99 | end) 100 | 101 | transport.bpm = old_bpm 102 | 103 | end 104 | 105 | 106 | ------------------------------------------------------------------------------ 107 | -- test finalizers 108 | 109 | collectgarbage() 110 | 111 | 112 | --[[-------------------------------------------------------------------------- 113 | --------------------------------------------------------------------------]]-- 114 | 115 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.DeviceParameter.md: -------------------------------------------------------------------------------- 1 | # renoise.DeviceParameter 2 | > A single parameter within an audio DSP effect (renoise.AudioDevice) 3 | 4 | 5 | 6 | ## Constants 7 | ### Polarity 8 | > ```lua 9 | > { 10 | > POLARITY_UNIPOLAR: integer = 1, 11 | > POLARITY_BIPOLAR: integer = 2, 12 | > } 13 | > ``` 14 | 15 | 16 | --- 17 | ## Properties 18 | ### name : [`string`](../../API/builtins/string.md) 19 | > **READ-ONLY** 20 | 21 | ### name_observable : [`renoise.Document.ObservableString`](../../API/renoise/renoise.Document.ObservableString.md) 22 | ### polarity : [`renoise.DeviceParameter.Polarity`](renoise.DeviceParameter.md#Polarity) 23 | > **READ-ONLY** 24 | 25 | ### value_min : [`number`](../../API/builtins/number.md) 26 | > **READ-ONLY** 27 | 28 | ### value_max : [`number`](../../API/builtins/number.md) 29 | > **READ-ONLY** 30 | 31 | ### value_quantum : [`number`](../../API/builtins/number.md) 32 | > **READ-ONLY** 33 | 34 | ### value_default : [`number`](../../API/builtins/number.md) 35 | > **READ-ONLY** 36 | 37 | ### time_quantum : [`number`](../../API/builtins/number.md) 38 | > **READ-ONLY** 39 | 40 | ### is_automatable : [`boolean`](../../API/builtins/boolean.md) 41 | > **READ-ONLY** 42 | 43 | ### is_automated : [`boolean`](../../API/builtins/boolean.md) 44 | > **READ-ONLY** Is automated. Not valid for parameters of instrument devices. 45 | 46 | ### is_automated_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 47 | > Track changes to document properties or general states by attaching listener 48 | > functions to it. 49 | 50 | ### is_midi_mapped : [`boolean`](../../API/builtins/boolean.md) 51 | > **READ-ONLY** Parameter has a custom MIDI mapping in the current song. 52 | 53 | ### is_midi_mapped_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 54 | > Track changes to document properties or general states by attaching listener 55 | > functions to it. 56 | 57 | ### show_in_mixer : [`boolean`](../../API/builtins/boolean.md) 58 | > Show in mixer. Not valid for parameters of instrument devices. 59 | 60 | ### show_in_mixer_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 61 | > Track changes to document properties or general states by attaching listener 62 | > functions to it. 63 | 64 | ### value : [`number`](../../API/builtins/number.md) 65 | > value in Range: (value_min - value_max) 66 | 67 | ### value_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 68 | > Track changes to document properties or general states by attaching listener 69 | > functions to it. 70 | 71 | ### value_string : [`string`](../../API/builtins/string.md) 72 | ### value_string_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 73 | > Track changes to document properties or general states by attaching listener 74 | > functions to it. 75 | 76 | 77 | 78 | --- 79 | ## Functions 80 | ### record_value([*self*](../../API/builtins/self.md), value : [`number`](../../API/builtins/number.md)) 81 | > Set a new value and write automation when the MIDI mapping 82 | > "record to automation" option is set. Only works for parameters 83 | > of track devices, not for instrument devices. 84 | 85 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentMidiOutputProperties.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentMidiOutputProperties 2 | 3 | 4 | 5 | ## Constants 6 | ### Type 7 | > ```lua 8 | > { 9 | > TYPE_EXTERNAL: integer = 1, 10 | > TYPE_LINE_IN_RET: integer = 2, 11 | > TYPE_INTERNAL: integer = 3, 12 | > } 13 | > ``` 14 | 15 | 16 | --- 17 | ## Properties 18 | ### instrument_type : [`renoise.InstrumentMidiOutputProperties.Type`](renoise.InstrumentMidiOutputProperties.md#Type) 19 | > Note: ReWire device always start with "ReWire: " in the device_name and 20 | > will always ignore the instrument_type and channel properties. MIDI 21 | > channels are not configurable for ReWire MIDI, and instrument_type will 22 | > always be "TYPE_INTERNAL" for ReWire devices. 23 | 24 | ### instrument_type_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 25 | > Track changes to document properties or general states by attaching listener 26 | > functions to it. 27 | 28 | ### device_name : [`string`](../../API/builtins/string.md) 29 | > When setting new devices, device names must be one of: 30 | > renoise.Midi.available_output_devices. 31 | > Devices are automatically opened when needed. To close a device, set its name 32 | > to "", e.g. an empty string. 33 | 34 | ### device_name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 35 | > Track changes to document properties or general states by attaching listener 36 | > functions to it. 37 | 38 | ### channel : [`integer`](../../API/builtins/integer.md) 39 | > Range: (1 - 16) 40 | 41 | ### channel_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 42 | > Track changes to document properties or general states by attaching listener 43 | > functions to it. 44 | 45 | ### transpose : [`integer`](../../API/builtins/integer.md) 46 | > Range: (-120 - 120) 47 | 48 | ### transpose_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 49 | > Track changes to document properties or general states by attaching listener 50 | > functions to it. 51 | 52 | ### program : [`integer`](../../API/builtins/integer.md) 53 | > Range: (1 - 128) 0 = OFF 54 | 55 | ### program_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 56 | > Track changes to document properties or general states by attaching listener 57 | > functions to it. 58 | 59 | ### bank : [`integer`](../../API/builtins/integer.md) 60 | > Range: (1 - 65536) 0 = OFF 61 | 62 | ### bank_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 63 | > Track changes to document properties or general states by attaching listener 64 | > functions to it. 65 | 66 | ### delay : [`integer`](../../API/builtins/integer.md) 67 | > Range: (0 - 100) 68 | 69 | ### delay_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 70 | > Track changes to document properties or general states by attaching listener 71 | > functions to it. 72 | 73 | ### duration : [`integer`](../../API/builtins/integer.md) 74 | > Range: (1 - 8000) 8000 = INF 75 | 76 | ### duration_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 77 | > Track changes to document properties or general states by attaching listener 78 | > functions to it. 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/API/README.md: -------------------------------------------------------------------------------- 1 | # Renoise Lua API Overview 2 | 3 | The 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. 4 | 5 | A note about the general API design: 6 | 7 | - 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. 8 | 9 | - 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... 10 | 11 | Some notes about the documentation, and a couple of tips: 12 | 13 | - 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()` 14 | 15 | - 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. 16 | 17 | - 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. ;) 18 | 19 | - 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**`. 20 | 21 | - 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. 22 | 23 | - *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. 24 | 25 | A small example using bpm: 26 | ```lua 27 | renoise.song().transport.bpm_observable:add_notifier(function() 28 | print("bpm changed") 29 | end) 30 | 31 | -- will print "bpm changed", but only if the bpm was not 120 before 32 | renoise.song().transport.bpm = 120 33 | ``` 34 | 35 | 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...) 36 | 37 | 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. 38 | 39 | - 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)`. -------------------------------------------------------------------------------- /docs/guide/osc.md: -------------------------------------------------------------------------------- 1 | # OSC 2 | 3 | The Renoise API allows you to create sockets and provides tools to send and receive Open Sound Control (OSC) data. This enables you to connect your tools to other OSC servers and clients, offering an alternative to MIDI for controlling and interacting with devices like a [monome](https://monome.org/docs/serialosc/osc). 4 | 5 | See the [`renoise.Osc`](../API/renoise/renoise.Osc.md) and [`renoise.Socket`](../API/renoise/renoise.Socket.md) APIs for more details. 6 | 7 | > [!NOTE] 8 | > Using TCP instead of UDP as the socket protocol would likely require manual [SLIP encoding/decoding](https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol) of OSC message data. This is not handled automatically, so the examples below will only work with UDP servers/clients. 9 | 10 | ## OSC Server (Receiving OSC) 11 | 12 | This example creates a UDP server that listens for OSC messages on port 8008. 13 | 14 | ```lua 15 | -- Create some shortcuts 16 | local OscMessage = renoise.Osc.Message 17 | local OscBundle = renoise.Osc.Bundle 18 | 19 | -- Open a socket connection to listen for messages 20 | local server, socket_error = renoise.Socket.create_server( 21 | "localhost", 8008, renoise.Socket.PROTOCOL_UDP) 22 | 23 | if (socket_error) then 24 | renoise.app():show_warning(("Failed to start the " .. 25 | "OSC server. Error: '%s'"):format(socket_error)) 26 | return 27 | end 28 | 29 | server:run { 30 | socket_message = function(socket, data) 31 | -- Decode the binary data to an OSC message or bundle 32 | local message_or_bundle, osc_error = renoise.Osc.from_binary_data(data) 33 | 34 | -- Show what we've got 35 | if (message_or_bundle) then 36 | if (type(message_or_bundle) == "Message") then 37 | print(("Got OSC message: '%s'"):format(tostring(message_or_bundle))) 38 | 39 | elseif (type(message_or_bundle) == "Bundle") then 40 | print(("Got OSC bundle: '%s'"):format(tostring(message_or_bundle))) 41 | end 42 | 43 | -- Send a reply back to the client 44 | local reply_message = OscMessage("/renoise/reply", { 45 | { tag = "s", value = "Thank you for the message!" } 46 | }) 47 | socket:send(reply_message:to_binary_data()) 48 | 49 | else 50 | print(("Got invalid OSC data, or data which is not " .. 51 | "OSC data at all. Error: '%s'"):format(osc_error)) 52 | end 53 | end 54 | } 55 | 56 | -- To shut down the server at any time, call: 57 | -- server:close() 58 | ``` 59 | 60 | ## OSC Client (Sending OSC) 61 | 62 | This example creates a UDP client to send OSC messages to a server on port 8008. 63 | 64 | ```lua 65 | -- Create some shortcuts 66 | local OscMessage = renoise.Osc.Message 67 | local OscBundle = renoise.Osc.Bundle 68 | 69 | -- Create a client to send messages to the server 70 | local client, socket_error = renoise.Socket.create_client( 71 | "localhost", 8008, renoise.Socket.PROTOCOL_UDP) 72 | 73 | if (socket_error) then 74 | renoise.app():show_warning(("Failed to start the " .. 75 | "OSC client. Error: '%s'"):format(socket_error)) 76 | return 77 | end 78 | 79 | -- Construct and send a simple message 80 | client:send( 81 | OscMessage("/transport/start"):to_binary_data() 82 | ) 83 | 84 | -- Construct and send a message with arguments 85 | client:send( 86 | OscMessage("/transport/bpm", { 87 | { tag = "f", value = 127.5 } 88 | }):to_binary_data() 89 | ) 90 | 91 | -- Construct and send a bundle of messages 92 | local message1 = OscMessage("/some/message") 93 | local message2 = OscMessage("/another/one", { 94 | { tag = "b", value = "with some blob data" }, 95 | { tag = "s", value = "and a string" } 96 | }) 97 | 98 | client:send( 99 | OscBundle(os.clock(), { message1, message2 }):to_binary_data() 100 | ) 101 | 102 | -- Close the client when done 103 | client:close() 104 | ``` 105 | -------------------------------------------------------------------------------- /docs/start/possibilities.md: -------------------------------------------------------------------------------- 1 | # Possibilities 2 | 3 | Before you delve into writing your own scripts and tools, it worth considering what is even possible to do with them. In general, you can automate and manage different aspects Renoise, add or modify song data using algorithms or create interfaces to connect with other software or hardware. You can see some examples below about what you can access inside Renoise, for a complete reference, check out the [API Definitions](../API/README.md). 4 | 5 | ### Process song data 6 | * Generate, modify or filter notes, patterns or phrases 7 | * Access volume, delays and panning values 8 | * Write effect commands and automation 9 | * Rearrange the pattern matrix and more 10 | 11 | ### Manage tracks and instruments 12 | * Create and modify instruments or tracks 13 | * Add built-in DSP devices to tracks or FX chains and set their parameters 14 | * Generate modulation chains on instruments 15 | * Load samples and configure them 16 | * Manage slices and keyzones 17 | 18 | ### Sample generation and mangling 19 | * Generate new samples and change existing ones 20 | * Chop samples and create slices and intruments based on custom rules 21 | * Implement offline audio effects 22 | 23 | ### Custom graphical interfaces 24 | * Use built-in sliders, buttons, switches and more to compose a GUI 25 | * Listen to keyboard and mouse events to define custom behaviour 26 | * Use bitmaps to create unique buttons 27 | * Hook up the interface to the rest of your tool 28 | 29 | ### Controller support 30 | * Write logic for bidirectional communication between Renoise and MIDI controllers 31 | * Implement custom functionality for MIDI control surfaces 32 | * Control Renoise via customized [OSC](https://en.wikipedia.org/wiki/Open_Sound_Control) messages 33 | * Exchange information with other software like VJ tools or web services 34 | 35 | ### Interactions 36 | 37 | There are a few ways tool creators can make the functionality they provide available for users, below is a brief summary of the most used methods. 38 | 39 | * [Define keybindings](../guide/tool.md#keybindings) that can be assigned to shortcuts and executed from certain contexts in Renoise 40 | * [Add new entries to menus](../guide/tool.md#menu-entries) like the *Tools* menu or one of the right-click context menus 41 | * [Create custom views](../guide/tool.md#custom-guis) that do things on button presses, slider drags and so on 42 | * Listen to [MIDI](../guide/midi.md), [OSC](../guide/osc.md) or [WebSocket messages](../guide/sockets.md) to execute actions 43 | * [React to events inside Renoise](../guide/observables.md) like "do something any time a new song is loaded" 44 | 45 | 46 | ## Limitations 47 | 48 | Finally, let's look at what is **not** possible via tools. 49 | 50 | * You cannot override the existing behaviour of Renoise. You can add functionality *on top* of what's already there, but you can't disable or change how the built-in features work. 51 | For example, you can create a completely custom GUI to compose patterns in a novel way but you cannot change how the built-in pattern editor works or looks like. Similarly, you can add a new shortcut that does something extra to the selected sample block or places new slices but you can't modify how the built-in autoslicing works. 52 | 53 | * You cannot write real-time DSP code like synths, effects or modulators (except for scripts inside the [Formula device](https://tutorials.renoise.com/wiki/Meta_Devices#*Formula)), which is not using the Renoise Tool API. If you want to design your own synths and effects you should look into plugin development (using [DISTRHO](https://distrho.kx.studio/), [nih-plug](https://github.com/robbert-vdh/nih-plug) etc.), you could also use existing plugins that allow you to build your own DSP patches (like [plugdata](https://plugdata.org/) or [Cardinal](https://cardinal.kx.studio/)). Of course you can [generate and modify samples](../guide/song.md#samples) using your tool, but it will have to be implemented as offline rendering instead of real-time processing. 54 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.AudioDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.AudioDevice 2 | > Audio DSP device in tracks or sample device chains. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Properties 9 | ### name : [`string`](../../API/builtins/string.md) 10 | > **READ-ONLY** 11 | 12 | ### short_name : [`string`](../../API/builtins/string.md) 13 | > **READ-ONLY** 14 | 15 | ### display_name : [`string`](../../API/builtins/string.md) 16 | > Configurable device display name. When empty `name` is displayed. 17 | 18 | ### display_name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 19 | > Track changes to document properties or general states by attaching listener 20 | > functions to it. 21 | 22 | ### is_active : [`boolean`](../../API/builtins/boolean.md) 23 | > !active = bypassed 24 | 25 | ### is_active_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 26 | > Track changes to document properties or general states by attaching listener 27 | > functions to it. 28 | 29 | ### is_maximized : [`boolean`](../../API/builtins/boolean.md) 30 | > Maximize state in DSP chain. 31 | 32 | ### is_maximized_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 33 | > Track changes to document properties or general states by attaching listener 34 | > functions to it. 35 | 36 | ### active_preset : [`integer`](../../API/builtins/integer.md) 37 | > 0 when none is active or available 38 | 39 | ### active_preset_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 40 | > Track changes to document properties or general states by attaching listener 41 | > functions to it. 42 | 43 | ### active_preset_data : [`string`](../../API/builtins/string.md) 44 | > raw serialized data in XML format of the active preset 45 | 46 | ### presets : [`string`](../../API/builtins/string.md)[] 47 | > **READ-ONLY** preset names 48 | 49 | ### is_active_parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 50 | > **READ-ONLY** 51 | 52 | ### parameters : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)[] 53 | > **READ-ONLY** 54 | 55 | ### external_editor_available : [`boolean`](../../API/builtins/boolean.md) 56 | > **READ-ONLY** Returns whether or not the device provides its own custom GUI 57 | > (only available for some plugin devices) 58 | 59 | ### external_editor_visible : [`boolean`](../../API/builtins/boolean.md) 60 | > true to show the editor, false to close it 61 | 62 | ### device_path : [`string`](../../API/builtins/string.md) 63 | > **READ-ONLY** Returns a string that uniquely identifies the device, from 64 | > `available_devices`. The string can be passed into: 65 | > `renoise.song().tracks[]:insert_device_at()` 66 | 67 | 68 | 69 | --- 70 | ## Functions 71 | ### preset([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 72 | `->`preset_name : [`string`](../../API/builtins/string.md) 73 | 74 | > Access to a single preset name by index. Use properties 'presets' to iterate 75 | > over all presets and to query the presets count. 76 | > comment 77 | ### parameter([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 78 | `->`[`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 79 | 80 | > Access to a single parameter by index. Use properties 'parameters' to iterate 81 | > over all parameters and to query the parameter count. 82 | 83 | -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolSlicedProcess.xrnx/process_slicer.lua: -------------------------------------------------------------------------------- 1 | --[[============================================================================ 2 | process_slicer.lua 3 | ============================================================================]]-- 4 | 5 | --[[ 6 | 7 | ProcessSlicer allows you to slice up a function which takes a lot of 8 | processing time into multiple calls via Lua coroutines. 9 | 10 | * Example usage: 11 | 12 | local slicer = ProcessSlicer(my_process_func, argument1, argumentX) 13 | 14 | -- This starts calling 'my_process_func' in idle, passing all arguments 15 | -- you've specified in the ProcessSlicer constructor. 16 | slicer:start() 17 | 18 | -- To abort a running sliced process, you can call "stop" at any time 19 | -- from within your processing function of outside of it in the main thread. 20 | -- As soon as your process function returns, the slicer is automatically 21 | -- stopped. 22 | slicer:stop() 23 | 24 | -- To give processing time back to Renoise, call 'coroutine.yield()' 25 | -- anywhere in your process function to temporarily yield back to Renoise: 26 | function my_process_func() 27 | for j=1,100 do 28 | -- do something that needs a lot of time, and periodically call 29 | -- "coroutine.yield()" to give processing time back to Renoise. Renoise 30 | -- will switch back to this point of the function as soon as has done 31 | -- "its" job: 32 | coroutine.yield() 33 | end 34 | end 35 | 36 | 37 | * Drawbacks: 38 | 39 | By slicing your processing function, you will also slice any changes that are 40 | done to the Renoise song into multiple undo actions (one action per slice/yield). 41 | 42 | Modal dialogs will block the slicer, cause on_idle notifications are not fired then. 43 | It will even block your own process GUI when trying to show it modal. 44 | 45 | ]] 46 | 47 | class "ProcessSlicer" 48 | 49 | function ProcessSlicer:__init(process_func, ...) 50 | assert(type(process_func) == "function", 51 | "expected a function as first argument") 52 | 53 | self.__process_func = process_func 54 | self.__process_func_args = { ... } 55 | self.__process_thread = nil 56 | end 57 | 58 | -------------------------------------------------------------------------------- 59 | -- returns true when the current process currently is running 60 | 61 | function ProcessSlicer:running() 62 | return (self.__process_thread ~= nil) 63 | end 64 | 65 | -------------------------------------------------------------------------------- 66 | -- start a process 67 | 68 | function ProcessSlicer:start() 69 | assert(not self:running(), "process already running") 70 | 71 | self.__process_thread = coroutine.create(self.__process_func) 72 | 73 | renoise.tool().app_idle_observable:add_notifier( 74 | { ProcessSlicer.__on_idle, self }) 75 | end 76 | 77 | -------------------------------------------------------------------------------- 78 | -- stop a running process 79 | 80 | function ProcessSlicer:stop() 81 | assert(self:running(), "process not running") 82 | 83 | renoise.tool().app_idle_observable:remove_notifier( 84 | { ProcessSlicer.__on_idle, self }) 85 | 86 | self.__process_thread = nil 87 | end 88 | 89 | -------------------------------------------------------------------------------- 90 | 91 | -- function that gets called from Renoise to do idle stuff. switches back 92 | -- into the processing function or detaches the thread 93 | 94 | function ProcessSlicer:__on_idle() 95 | assert(self.__process_thread ~= nil, "ProcessSlicer internal error: " .. 96 | "expected no idle call with no thread running") 97 | 98 | -- continue or start the process while its still active 99 | if (coroutine.status(self.__process_thread) == 'suspended') then 100 | local succeeded, error_message = coroutine.resume( 101 | self.__process_thread, table.unpack(self.__process_func_args)) 102 | 103 | if (not succeeded) then 104 | -- stop the process on errors 105 | self:stop() 106 | -- and forward the error to the main thread 107 | error(error_message) 108 | end 109 | 110 | -- stop when the process function completed 111 | elseif (coroutine.status(self.__process_thread) == 'dead') then 112 | self:stop() 113 | end 114 | end 115 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.SampleDeviceChain.md: -------------------------------------------------------------------------------- 1 | # renoise.SampleDeviceChain 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### name : [`string`](../../API/builtins/string.md) 9 | > Name of the audio effect chain. 10 | 11 | ### name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 12 | > Track changes to document properties or general states by attaching listener 13 | > functions to it. 14 | 15 | ### available_devices : [`string`](../../API/builtins/string.md)[] 16 | > **READ-ONLY** Allowed, available devices for 'insert_device_at'. 17 | 18 | ### available_device_infos : [`AudioDeviceInfo`](#audiodeviceinfo)[] 19 | > **READ-ONLY** Returns a list of tables containing more information about 20 | > the devices. 21 | 22 | ### devices : [`renoise.AudioDevice`](../../API/renoise/renoise.AudioDevice.md)[] 23 | > **READ-ONLY** Device access. 24 | 25 | ### devices_observable : [`renoise.Document.ObservableList`](../../API/renoise/renoise.Document.ObservableList.md) 26 | > Track changes to document lists by attaching listener functions to it. 27 | > NB: Notifiers will not broadcast changes made to list items, but only changes 28 | > to the lists **layout** (items got added, removed, swapped). 29 | 30 | ### available_output_routings : [`string`](../../API/builtins/string.md)[] 31 | > **READ-ONLY** Output routing. 32 | 33 | ### output_routing : [`string`](../../API/builtins/string.md) 34 | > One of 'available_output_routings' 35 | 36 | ### output_routing_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 37 | > Track changes to document properties or general states by attaching listener 38 | > functions to it. 39 | 40 | 41 | 42 | --- 43 | ## Functions 44 | ### insert_device_at([*self*](../../API/builtins/self.md), device_path : [`string`](../../API/builtins/string.md), index : [`integer`](../../API/builtins/integer.md)) 45 | `->`new_device : [`renoise.AudioDevice`](../../API/renoise/renoise.AudioDevice.md) 46 | 47 | > Insert a new device at the given position. "device_path" must be an available device 48 | > See: `renoise.SampleDeviceChain.available_devices` 49 | ### delete_device_at([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 50 | > Delete an existing device from a chain. The mixer device at index 1 can not 51 | > be deleted. 52 | ### swap_devices_at([*self*](../../API/builtins/self.md), index1 : [`integer`](../../API/builtins/integer.md), index2 : [`integer`](../../API/builtins/integer.md)) 53 | > Swap the positions of two devices in the device chain. The mixer device at 54 | > index 1 can not be swapped or moved. 55 | ### device([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 56 | `->`[`renoise.AudioDevice`](../../API/renoise/renoise.AudioDevice.md) 57 | 58 | > Access to a single device in the chain. 59 | 60 | 61 | 62 | --- 63 | ## Structs 64 | # AudioDeviceInfo 65 | > Audio device info 66 | 67 | --- 68 | ## Properties 69 | ### path : [`string`](../../API/builtins/string.md) 70 | > The device's path used by `renoise.Track:insert_device_at` 71 | 72 | ### name : [`string`](../../API/builtins/string.md) 73 | > The device's name 74 | 75 | ### short_name : [`string`](../../API/builtins/string.md) 76 | > The device's name as displayed in shortened lists 77 | 78 | ### favorite_name : [`string`](../../API/builtins/string.md) 79 | > The device's name as displayed in favorites 80 | 81 | ### is_favorite : [`boolean`](../../API/builtins/boolean.md) 82 | > true if the device is a favorite 83 | 84 | ### is_bridged : [`boolean`](../../API/builtins/boolean.md) 85 | > true if the device is a bridged plugin 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/API/modules/global.md: -------------------------------------------------------------------------------- 1 | # Global 2 | 3 | 4 | 5 | 6 | --- 7 | ## Functions 8 | ### tostring(pattern_line : [`renoise.PatternLine`](../../API/renoise/renoise.PatternLine.md)) 9 | `->`[`string`](../../API/builtins/string.md) 10 | 11 | > Receives a value of any type and converts it to a string in a human-readable format. 12 | > 13 | > If the metatable of `v` has a `__tostring` field, then `tostring` calls the corresponding value with `v` as argument, and uses the result of the call as its result. Otherwise, if the metatable of `v` has a `__name` field with a string value, `tostring` may use that string in its final result. 14 | > 15 | > For complete control of how numbers are converted, use [string.format](http://www.lua.org/manual/5.4/manual.html#pdf-string.format). 16 | > 17 | > 18 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-tostring) 19 | ### ripairs(table : ) 20 | `->`fun(table: [], i?: integer):integer, , , i : [`integer`](../../API/builtins/integer.md) 21 | 22 | > An iterator like ipairs, but in reverse order. 23 | > #### examples: 24 | > ```lua 25 | > t = {"a", "b", "c"} 26 | > for k,v in ripairs(t) do print(k, v) end -> "3 c, 2 b, 1 a" 27 | > ``` 28 | ### objinfo(object : [`userdata`](../../API/builtins/userdata.md)) 29 | `->`[`string`](../../API/builtins/string.md)[] 30 | 31 | > Return a string which lists properties and methods of class objects. 32 | ### oprint(object : [`userdata`](../../API/builtins/userdata.md)) 33 | > Dumps properties and methods of class objects (like renoise.app()). 34 | ### rprint(value : [`any`](../../API/builtins/any.md)) 35 | > Recursively dumps a table and all its members to the std out (console). 36 | > This works for standard Lua types and class objects as well. 37 | ### class(name : [`string`](../../API/builtins/string.md)) 38 | `->`[`function`](../../API/builtins/function.md) 39 | 40 | > Luabind "class" registration. Registers a global class object and returns a 41 | > closure to optionally set the base class. 42 | > 43 | > See also [Luabind class](https://luabind.sourceforge.net/docs.html#class_lua) 44 | > 45 | > #### examples 46 | > ```lua 47 | > ---@class Animal 48 | > -- Construct a new animal with the given name. 49 | > ---@overload fun(string): Animal 50 | > Animal = {} 51 | > class 'Animal' 52 | > ---@param name string 53 | > function Animal:__init(name) 54 | > self.name = name 55 | > self.can_fly = nil 56 | > end 57 | > function Animal:show() 58 | > return ("I am a %s (%s) and I %s fly"):format(self.name, type(self), 59 | > (self.can_fly and "can fly" or "can not fly")) 60 | > end 61 | > 62 | > -- Mammal class (inherits Animal functions and members) 63 | > ---@class Mammal : Animal 64 | > -- Construct a new mamal with the given name. 65 | > ---@overload fun(string): Mammal 66 | > Mammal = {} 67 | > class 'Mammal' (Animal) 68 | > ---@param name string 69 | > function Mammal:__init(name) 70 | > Animal.__init(self, name) 71 | > self.can_fly = false 72 | > end 73 | > 74 | > -- show() function and base member are available for Mammal too 75 | > local mamal = Mammal("Cow") 76 | > mamal:show() 77 | > ``` 78 | ### type(value : [`any`](../../API/builtins/any.md)) 79 | `->`[`string`](../../API/builtins/string.md) 80 | 81 | > Returns the type of its only argument, coded as a string. The possible results of this function are `"nil"` (a string, not the value `nil`), `"number"`, `"string"`, `"boolean"`, `"table"`, `"function"`, `"thread"`, and `"userdata"`. 82 | > 83 | > 84 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-type) 85 | > 86 | > 87 | > ```lua 88 | > type: 89 | > | "nil" 90 | > | "number" 91 | > | "string" 92 | > | "boolean" 93 | > | "table" 94 | > | "function" 95 | > | "thread" 96 | > | "userdata" 97 | > ``` 98 | ### rawequal(obj1 : [`any`](../../API/builtins/any.md), obj2 : [`any`](../../API/builtins/any.md)) 99 | > Checks whether v1 is equal to v2, without invoking the `__eq` metamethod. 100 | > 101 | > [View documents](http://www.lua.org/manual/5.4/manual.html#pdf-rawequal) 102 | 103 | -------------------------------------------------------------------------------- /tests/track_device_chain.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestTrackDeviceChain.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | 15 | -- shortcuts 16 | 17 | local song = renoise.song() 18 | 19 | song.selected_track_index = 1 -- make sure its a player track 20 | local selected_track = song.tracks[song.selected_track_index] 21 | 22 | 23 | ---------------------------------------------------------------------------- 24 | -- insert/delete/swap 25 | 26 | local avail_devices = selected_track.available_devices 27 | 28 | local new_device_path, new_device_path2 29 | 30 | repeat 31 | new_device_path = avail_devices[math.random(1, #avail_devices)] 32 | new_device_path2 = avail_devices[math.random(1, #avail_devices)] 33 | until 34 | -- avoid plugins, cause they may fail to load and pop up dialogs 35 | not string.find(new_device_path, "VST") and 36 | not string.find(new_device_path, "AU") and 37 | not string.find(new_device_path2, "VST") and 38 | not string.find(new_device_path2, "AU") 39 | 40 | assert_error(function() 41 | selected_track:insert_device_at("InvalidDeviceName#234", #selected_track.devices + 1) 42 | end) 43 | 44 | assert_error(function() 45 | selected_track:insert_device_at(new_device_path, 1) 46 | end) 47 | 48 | assert_error(function() 49 | selected_track:delete_device_at(1) 50 | end) 51 | 52 | local device_count = #selected_track.devices 53 | 54 | local new_device = selected_track:insert_device_at(new_device_path, 2) 55 | device_count = device_count + 1 56 | assert(device_count == #selected_track.devices) 57 | 58 | local found_device = false 59 | 60 | local found_device_path = false 61 | 62 | for _,device in ipairs(selected_track.devices) do 63 | if device.name == new_device.name then 64 | found_device = true 65 | end 66 | if device.device_path == new_device_path then 67 | found_device_path = true 68 | end 69 | end 70 | 71 | assert(found_device) 72 | 73 | assert(found_device_path) 74 | 75 | selected_track:delete_device_at(2) 76 | device_count = device_count - 1 77 | assert(device_count == #selected_track.devices) 78 | 79 | selected_track:insert_device_at(new_device_path, 80 | #selected_track.devices + 1) 81 | 82 | selected_track:insert_device_at(new_device_path2, 83 | #selected_track.devices + 1) 84 | 85 | device_count = device_count + 2 86 | assert(device_count == #selected_track.devices) 87 | 88 | 89 | selected_track:swap_devices_at( 90 | #selected_track.devices, 91 | #selected_track.devices - 1) 92 | 93 | assert(device_count == #selected_track.devices) 94 | 95 | 96 | selected_track:delete_device_at(2) 97 | selected_track:delete_device_at(2) 98 | 99 | device_count = device_count - 2 100 | assert(device_count == #selected_track.devices) 101 | 102 | 103 | -- preset handing 104 | 105 | local trackvolpan = selected_track.devices[1] 106 | assert(#trackvolpan.presets == 1) -- init 107 | 108 | selected_track:insert_device_at(new_device_path, 109 | #selected_track.devices + 1) 110 | 111 | local new_device = selected_track.devices[#selected_track.devices] 112 | 113 | assert(#new_device.presets >= 1) 114 | assert(new_device.active_preset >= 1) 115 | 116 | local new_preset = math.random(#new_device.presets) 117 | new_device.active_preset = new_preset 118 | assert(new_device.active_preset == new_preset) 119 | 120 | assert_error(function() 121 | new_device.active_preset = 0 122 | end) 123 | assert_error(function() 124 | new_device.active_preset = #new_device.presets + 1 125 | end) 126 | 127 | end 128 | 129 | 130 | ------------------------------------------------------------------------------ 131 | -- test finalizers 132 | 133 | collectgarbage() 134 | 135 | 136 | --[[-------------------------------------------------------------------------- 137 | --------------------------------------------------------------------------]]-- 138 | -------------------------------------------------------------------------------- /tests/transport.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestTransport.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | 15 | -- shortcuts 16 | 17 | local transport = renoise.song().transport 18 | 19 | 20 | ---------------------------------------------------------------------------- 21 | -- SongPos 22 | 23 | local some_str = tostring(transport.edit_pos) 24 | transport.edit_pos = renoise.SongPos(1, 1) 25 | local new_pos = transport.edit_pos 26 | 27 | assert_error(function() 28 | new_pos.does_not_exist = "Foo!" 29 | end) 30 | 31 | --[[ TODO: 32 | assert_error(function() 33 | new_pos.sequence = 2 34 | end) 35 | assert_error(function() 36 | new_pos.line = 1 37 | end) 38 | --]] 39 | 40 | transport.loop_range = {renoise.SongPos(1, 1), renoise.SongPos(1, 17)} 41 | 42 | assert(transport.loop_start == transport.loop_range[1]) 43 | assert(transport.loop_end == transport.loop_range[2]) 44 | 45 | assert(transport.loop_start < transport.loop_end) 46 | assert(transport.loop_start <= transport.loop_end) 47 | assert(transport.loop_end > transport.loop_start) 48 | assert(transport.loop_end >= transport.loop_start) 49 | 50 | assert(transport.loop_start == renoise.SongPos(1, 1)) 51 | assert(transport.loop_start ~= renoise.SongPos(2, 1)) 52 | 53 | 54 | 55 | ---------------------------------------------------------------------------- 56 | -- Track Headroom 57 | 58 | function track_headroom_changed() 59 | print("track headroom changed: " .. transport.track_headroom) 60 | end 61 | 62 | transport.track_headroom_observable:add_notifier(track_headroom_changed) 63 | 64 | transport.track_headroom = math.db2lin(-6.0) 65 | 66 | assert_error(function() 67 | transport.track_headroom = math.db2lin(1.5) 68 | end) 69 | 70 | transport.track_headroom_observable:remove_notifier(track_headroom_changed) 71 | 72 | 73 | ---------------------------------------------------------------------------- 74 | -- Computer Keyboard Velocity 75 | 76 | transport.keyboard_velocity_enabled = false 77 | transport.keyboard_velocity = 127 78 | 79 | local num_keyboard_velocity_changes = 0 80 | function keyboard_velocity_changed() 81 | num_keyboard_velocity_changes = num_keyboard_velocity_changes + 1 82 | end 83 | 84 | local num_keyboard_velocity_enabled_changes = 0 85 | function keyboard_velocity_enabled_changed() 86 | num_keyboard_velocity_enabled_changes = 87 | num_keyboard_velocity_enabled_changes + 1 88 | end 89 | 90 | transport.keyboard_velocity_observable:add_notifier( 91 | keyboard_velocity_changed) 92 | transport.keyboard_velocity_enabled_observable:add_notifier( 93 | keyboard_velocity_enabled_changed) 94 | 95 | transport.keyboard_velocity_enabled = true 96 | assert(transport.keyboard_velocity_enabled == true) 97 | 98 | transport.keyboard_velocity = 1 99 | assert(transport.keyboard_velocity == 1) 100 | 101 | transport.keyboard_velocity = 64 102 | assert(transport.keyboard_velocity == 64) 103 | 104 | assert_error(function() 105 | transport.keyboard_velocity = 128 106 | end) 107 | 108 | transport.keyboard_velocity_enabled = false 109 | assert(transport.keyboard_velocity_enabled ~= true) 110 | 111 | -- Should always return max 127 when disabled 112 | assert(transport.keyboard_velocity == 127) 113 | 114 | assert(num_keyboard_velocity_changes == 2) 115 | assert(num_keyboard_velocity_enabled_changes == 2) 116 | 117 | transport.keyboard_velocity_observable:remove_notifier( 118 | keyboard_velocity_changed) 119 | 120 | transport.keyboard_velocity_enabled_observable:remove_notifier( 121 | keyboard_velocity_enabled_changed) 122 | 123 | end 124 | 125 | 126 | ------------------------------------------------------------------------------ 127 | -- test finalizers 128 | 129 | collectgarbage() 130 | 131 | 132 | --[[-------------------------------------------------------------------------- 133 | --------------------------------------------------------------------------]]-- 134 | 135 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Midi.md: -------------------------------------------------------------------------------- 1 | # renoise.Midi 2 | > Raw MIDI IO support for scripts in Renoise; the ability to send and receive 3 | > MIDI data. 4 | 5 | 6 | 7 | 8 | --- 9 | ## Functions 10 | ### `available_input_devices()` 11 | `->`[`string`](../../API/builtins/string.md)[] 12 | 13 | > Return a list of strings with currently available MIDI input devices. 14 | > This list can change when devices are hot-plugged. 15 | > See `renoise.Midi.devices_changed_observable` 16 | ### `available_output_devices()` 17 | `->`[`string`](../../API/builtins/string.md)[] 18 | 19 | > Return a list of strings with currently available MIDI output devices. 20 | > This list can change when devices are hot-plugged. 21 | > See `renoise.Midi.devices_changed_observable` 22 | ### `devices_changed_observable()` 23 | `->`[`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 24 | 25 | > Fire notifications as soon as new devices become active or a previously 26 | > added device gets removed/unplugged. 27 | > This will only happen on Linux and OSX with real devices. On Windows this 28 | > may happen when using ReWire slaves. ReWire adds virtual MIDI devices to 29 | > Renoise. 30 | > Already opened references to devices which are no longer available will 31 | > do nothing: you can use them as before and they will not fire any errors. 32 | > The messages will simply go into the void... 33 | ### create_input_device(device_name : [`string`](../../API/builtins/string.md), callback : [`MidiMessageFunction`](#MidiMessageFunction) | [`MidiMessageMethod1`](#MidiMessageMethod1) | [`MidiMessageMethod2`](#MidiMessageMethod2)[`?`](../../API/builtins/nil.md), sysex_callback : [`MidiMessageFunction`](#MidiMessageFunction) | [`MidiMessageMethod1`](#MidiMessageMethod1) | [`MidiMessageMethod2`](#MidiMessageMethod2)[`?`](../../API/builtins/nil.md)) 34 | `->`[`renoise.Midi.MidiInputDevice`](../../API/renoise/renoise.Midi.MidiInputDevice.md) 35 | 36 | > Listen to incoming MIDI data: opens access to a MIDI input device by 37 | > specifying a device name. 38 | > Name must be one of `renoise.Midi.available_input_devices()`. 39 | > 40 | > One or both callbacks should be valid, and should either point to a function 41 | > with one parameter `function (message: number[]) end`, or a table with an object 42 | > and class `{context, function(context, message: number[]) end}` -> a method. 43 | > 44 | > All MIDI messages except active sensing will be forwarded to the callbacks. 45 | > When Renoise is already listening to this device, your callback *and* Renoise 46 | > (or even other scripts) will handle the message. 47 | > 48 | > Messages are received until the device reference is manually closed (see 49 | > renoise.Midi.MidiDevice:close()) or until the MidiInputDevice object gets garbage 50 | > collected. 51 | ### create_output_device(device_name : [`string`](../../API/builtins/string.md)) 52 | `->`[`renoise.Midi.MidiOutputDevice`](../../API/renoise/renoise.Midi.MidiOutputDevice.md) 53 | 54 | > Open access to a MIDI device by specifying the device name. 55 | > Name must be one of `renoise.Midi.available_input_devices()`. 56 | > All other device names will fire an error. 57 | > 58 | > The real device driver gets automatically closed when the MidiOutputDevice 59 | > object gets garbage collected or when the device is explicitly closed 60 | > via midi_device:close() and nothing else references it. 61 | 62 | 63 | 64 | --- 65 | ## Aliases 66 | ### MidiMessage 67 | [`integer`](../../API/builtins/integer.md)[] 68 | 69 | 70 | ### MidiMessageFunction 71 | (message : [`MidiMessage`](#MidiMessage)) 72 | 73 | 74 | ### MidiMessageMemberContext 75 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 76 | 77 | 78 | ### MidiMessageMemberFunction 79 | (self : [`MidiMessageMemberContext`](#MidiMessageMemberContext), message : [`MidiMessage`](#MidiMessage)) 80 | 81 | 82 | ### MidiMessageMethod1 83 | { 1 : [`MidiMessageMemberContext`](#MidiMessageMemberContext), 2 : [`MidiMessageMemberFunction`](#MidiMessageMemberFunction) } 84 | 85 | 86 | ### MidiMessageMethod2 87 | { 1 : [`MidiMessageMemberFunction`](#MidiMessageMemberFunction), 2 : [`MidiMessageMemberContext`](#MidiMessageMemberContext) } 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /tools/com.renoise.ExampleToolSlicedProcess.xrnx/main.lua: -------------------------------------------------------------------------------- 1 | --[[============================================================================ 2 | main.lua 3 | ============================================================================]]-- 4 | 5 | --[[ 6 | 7 | This tool shows how to slice up a function which takes a lot of processing 8 | time into multiple calls via Lua coroutines. 9 | 10 | This mainly is useful to: 11 | - show the current progress of your processing function 12 | - allow users to abort the progress at any time 13 | - avoids that Renoise asks to kill your process function cause it assumes 14 | its frozen when taking more than 10 seconds 15 | 16 | Please have a look at "process_slicer.lua" for more info. This file basically 17 | just shows how to create a GUI for the ProcessSlicer class. 18 | 19 | ]] 20 | 21 | require "process_slicer" 22 | 23 | 24 | -------------------------------------------------------------------------------- 25 | 26 | -- main: dummy example for sliced working function which needs a lot of time 27 | 28 | function main(update_progress_func) 29 | local i = 0 30 | 31 | local num_iterations = 1000 32 | for j=1,num_iterations do 33 | i = i + 1 34 | 35 | -- waste time (your tool would do something useful here) 36 | for k=1,1000000 do 37 | local a = 12/12*3434 38 | end 39 | 40 | -- show the progress in the GUI 41 | update_progress_func(i / num_iterations) 42 | 43 | -- and periodically give time back to renoise 44 | coroutine.yield() 45 | end 46 | end 47 | 48 | 49 | -------------------------------------------------------------------------------- 50 | 51 | -- creates a dialog which starts stops and visualizes a sliced progress 52 | 53 | local function create_gui() 54 | 55 | local dialog, process 56 | local vb = renoise.ViewBuilder() 57 | 58 | -- Note: we allow multiple dialogs and processes in this example. If you 59 | -- only want one dialog to be shown and only one process running, make 60 | -- 'dialog' and 'process' global, and check if if the dialog is visible 61 | -- here. If your dialog and viewbuilder is global, you also don't have to 62 | -- pass an "update_progress_func" to the processing function, but can call 63 | -- it directly. 64 | 65 | ----- process GUI functions (callbacks): 66 | 67 | local function update_progress(progress) 68 | if (not dialog or not dialog.visible) then 69 | -- abort processing when the dialog was closed 70 | process:stop() 71 | return 72 | end 73 | 74 | -- else update the progress text 75 | if (progress == 1.0) then 76 | vb.views.start_button.text = "Start" 77 | vb.views.progress_text.text = "Done!" 78 | else 79 | vb.views.progress_text.text = string.format( 80 | "Working hard (%d%% done)...", progress * 100) 81 | end 82 | end 83 | 84 | local function start_stop_process() 85 | if (not process or not process:running()) then 86 | -- start running 87 | vb.views.start_button.text = "Stop" 88 | process = ProcessSlicer(main, update_progress) 89 | process:start() 90 | 91 | elseif (process and process:running()) then 92 | -- stop running 93 | vb.views.start_button.text = "Start" 94 | vb.views.progress_text.text = "Process Aborted!" 95 | process:stop() 96 | end 97 | end 98 | 99 | 100 | ---- process GUI 101 | 102 | local DEFAULT_DIALOG_MARGIN = 103 | renoise.ViewBuilder.DEFAULT_DIALOG_MARGIN 104 | 105 | local DEFAULT_CONTROL_SPACING = 106 | renoise.ViewBuilder.DEFAULT_CONTROL_SPACING 107 | 108 | local DEFAULT_DIALOG_BUTTON_HEIGHT = 109 | renoise.ViewBuilder.DEFAULT_DIALOG_BUTTON_HEIGHT 110 | 111 | local dialog_content = vb:column { 112 | uniform = false, 113 | margin = DEFAULT_DIALOG_MARGIN, 114 | spacing = DEFAULT_CONTROL_SPACING, 115 | 116 | -- (add some content here) 117 | 118 | vb:text { 119 | id = "progress_text", 120 | text = "Hit 'Start' to begin a sliced process:" 121 | }, 122 | 123 | vb:button { 124 | id = "start_button", 125 | text = "Start", 126 | height = DEFAULT_DIALOG_BUTTON_HEIGHT, 127 | width = 80, 128 | notifier = start_stop_process 129 | } 130 | } 131 | 132 | dialog = renoise.app():show_custom_dialog( 133 | "Sliced Process Example", dialog_content) 134 | end 135 | 136 | 137 | -------------------------------------------------------------------------------- 138 | 139 | renoise.tool():add_menu_entry{ 140 | name = "Main Menu:Tools:Example Tool Sliced Process...", 141 | invoke = function() 142 | create_gui() 143 | end 144 | } 145 | 146 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableNumberList.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableNumberList 2 | > A observable list of number values. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Functions 9 | ### to_string([*self*](../../API/builtins/self.md)) 10 | `->`[`string`](../../API/builtins/string.md) 11 | 12 | > Serialize an object to a string. 13 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 14 | `->`[`string`](../../API/builtins/string.md) 15 | 16 | > Assign the object's value from a string - when possible. Errors are 17 | > silently ignored. 18 | ### size([*self*](../../API/builtins/self.md)) 19 | `->`[`integer`](../../API/builtins/integer.md) 20 | 21 | > Returns the number of entries of the list. 22 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 23 | > Checks if the given function, method was already registered as notifier. 24 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 25 | > Register a function or method as a notifier, which will be called as soon as 26 | > the observable lists layout changed. The passed notifier can either be a function 27 | > or a table with a function and some context (an "object") -> method. 28 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction) | [`ListNotifierMemberContext`](#ListNotifierMemberContext)) 29 | > Unregister a previously registered list notifier. When only passing an object, 30 | > all notifier functions that match the given object will be removed. 31 | > This will not fire errors when no methods for the given object are attached. 32 | > Trying to unregister a function or method which wasn't registered, will resolve 33 | > into an error. 34 | ### property([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 35 | `->`[`renoise.Document.ObservableNumber`](../../API/renoise/renoise.Document.ObservableNumber.md)[`?`](../../API/builtins/nil.md) 36 | 37 | > List item access by index. returns nil for non existing items. 38 | ### find([*self*](../../API/builtins/self.md), start_pos : [`integer`](../../API/builtins/integer.md), value : [`number`](../../API/builtins/number.md)) 39 | `->`[`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 40 | 41 | > Find a value in the list by comparing the list values with the passed 42 | > value. The first successful match is returned. When no match is found, nil 43 | > is returned. 44 | ### insert([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md), value : [`number`](../../API/builtins/number.md)) 45 | `->`[`renoise.Document.ObservableNumber`](../../API/renoise/renoise.Document.ObservableNumber.md) 46 | 47 | > Insert a new item to the end of the list when no position is specified, or 48 | > at the specified position. Returns the newly created and inserted Observable. 49 | ### remove([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md)) 50 | > Removes an item (or the last one if no index is specified) from the list. 51 | ### swap([*self*](../../API/builtins/self.md), pos1 : [`integer`](../../API/builtins/integer.md), pos2 : [`integer`](../../API/builtins/integer.md)) 52 | > Swaps the positions of two items without adding/removing the items. 53 | > With a series of swaps you can move the item from/to any position. 54 | 55 | 56 | 57 | --- 58 | ## Aliases 59 | ### ListElementAdded 60 | { index : [`integer`](../../API/builtins/integer.md), type : `"insert"` } 61 | 62 | 63 | ### ListElementChange 64 | [`ListElementAdded`](#ListElementAdded) | [`ListElementRemoved`](#ListElementRemoved) | [`ListElementsSwapped`](#ListElementsSwapped) 65 | 66 | 67 | ### ListElementRemoved 68 | { index : [`integer`](../../API/builtins/integer.md), type : `"remove"` } 69 | 70 | 71 | ### ListElementsSwapped 72 | { index1 : [`integer`](../../API/builtins/integer.md), index2 : [`integer`](../../API/builtins/integer.md), type : `"swap"` } 73 | 74 | 75 | ### ListNotifierFunction 76 | (change : [`ListElementChange`](#ListElementChange)) 77 | 78 | 79 | ### ListNotifierMemberContext 80 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableStringList.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableStringList 2 | > A observable list of string values. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Functions 9 | ### to_string([*self*](../../API/builtins/self.md)) 10 | `->`[`string`](../../API/builtins/string.md) 11 | 12 | > Serialize an object to a string. 13 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 14 | `->`[`string`](../../API/builtins/string.md) 15 | 16 | > Assign the object's value from a string - when possible. Errors are 17 | > silently ignored. 18 | ### size([*self*](../../API/builtins/self.md)) 19 | `->`[`integer`](../../API/builtins/integer.md) 20 | 21 | > Returns the number of entries of the list. 22 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 23 | > Checks if the given function, method was already registered as notifier. 24 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 25 | > Register a function or method as a notifier, which will be called as soon as 26 | > the observable lists layout changed. The passed notifier can either be a function 27 | > or a table with a function and some context (an "object") -> method. 28 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction) | [`ListNotifierMemberContext`](#ListNotifierMemberContext)) 29 | > Unregister a previously registered list notifier. When only passing an object, 30 | > all notifier functions that match the given object will be removed. 31 | > This will not fire errors when no methods for the given object are attached. 32 | > Trying to unregister a function or method which wasn't registered, will resolve 33 | > into an error. 34 | ### property([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 35 | `->`[`renoise.Document.ObservableString`](../../API/renoise/renoise.Document.ObservableString.md)[`?`](../../API/builtins/nil.md) 36 | 37 | > List item access by index. returns nil for non existing items. 38 | ### find([*self*](../../API/builtins/self.md), start_pos : [`integer`](../../API/builtins/integer.md), value : [`number`](../../API/builtins/number.md)) 39 | `->`[`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 40 | 41 | > Find a value in the list by comparing the list values with the passed 42 | > value. The first successful match is returned. When no match is found, nil 43 | > is returned. 44 | ### insert([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md), value : [`number`](../../API/builtins/number.md)) 45 | `->`[`renoise.Document.ObservableString`](../../API/renoise/renoise.Document.ObservableString.md) 46 | 47 | > Insert a new item to the end of the list when no position is specified, or 48 | > at the specified position. Returns the newly created and inserted Observable. 49 | ### remove([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md)) 50 | > Removes an item (or the last one if no index is specified) from the list. 51 | ### swap([*self*](../../API/builtins/self.md), pos1 : [`integer`](../../API/builtins/integer.md), pos2 : [`integer`](../../API/builtins/integer.md)) 52 | > Swaps the positions of two items without adding/removing the items. 53 | > With a series of swaps you can move the item from/to any position. 54 | 55 | 56 | 57 | --- 58 | ## Aliases 59 | ### ListElementAdded 60 | { index : [`integer`](../../API/builtins/integer.md), type : `"insert"` } 61 | 62 | 63 | ### ListElementChange 64 | [`ListElementAdded`](#ListElementAdded) | [`ListElementRemoved`](#ListElementRemoved) | [`ListElementsSwapped`](#ListElementsSwapped) 65 | 66 | 67 | ### ListElementRemoved 68 | { index : [`integer`](../../API/builtins/integer.md), type : `"remove"` } 69 | 70 | 71 | ### ListElementsSwapped 72 | { index1 : [`integer`](../../API/builtins/integer.md), index2 : [`integer`](../../API/builtins/integer.md), type : `"swap"` } 73 | 74 | 75 | ### ListNotifierFunction 76 | (change : [`ListElementChange`](#ListElementChange)) 77 | 78 | 79 | ### ListNotifierMemberContext 80 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Document.ObservableBooleanList.md: -------------------------------------------------------------------------------- 1 | # renoise.Document.ObservableBooleanList 2 | > A observable list of boolean values. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Functions 9 | ### to_string([*self*](../../API/builtins/self.md)) 10 | `->`[`string`](../../API/builtins/string.md) 11 | 12 | > Serialize an object to a string. 13 | ### from_string([*self*](../../API/builtins/self.md), string : [`any`](../../API/builtins/any.md)) 14 | `->`[`string`](../../API/builtins/string.md) 15 | 16 | > Assign the object's value from a string - when possible. Errors are 17 | > silently ignored. 18 | ### size([*self*](../../API/builtins/self.md)) 19 | `->`[`integer`](../../API/builtins/integer.md) 20 | 21 | > Returns the number of entries of the list. 22 | ### has_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 23 | > Checks if the given function, method was already registered as notifier. 24 | ### add_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction)) 25 | > Register a function or method as a notifier, which will be called as soon as 26 | > the observable lists layout changed. The passed notifier can either be a function 27 | > or a table with a function and some context (an "object") -> method. 28 | ### remove_notifier([*self*](../../API/builtins/self.md), notifier : [`ListNotifierFunction`](#ListNotifierFunction) | [`ListNotifierMemberContext`](#ListNotifierMemberContext)) 29 | > Unregister a previously registered list notifier. When only passing an object, 30 | > all notifier functions that match the given object will be removed. 31 | > This will not fire errors when no methods for the given object are attached. 32 | > Trying to unregister a function or method which wasn't registered, will resolve 33 | > into an error. 34 | ### property([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 35 | `->`[`renoise.Document.ObservableBoolean`](../../API/renoise/renoise.Document.ObservableBoolean.md)[`?`](../../API/builtins/nil.md) 36 | 37 | > List item access by index. returns nil for non existing items. 38 | ### find([*self*](../../API/builtins/self.md), start_pos : [`integer`](../../API/builtins/integer.md), value : [`boolean`](../../API/builtins/boolean.md)) 39 | `->`[`integer`](../../API/builtins/integer.md)[`?`](../../API/builtins/nil.md) 40 | 41 | > Find a value in the list by comparing the list values with the passed 42 | > value. The first successful match is returned. When no match is found, nil 43 | > is returned. 44 | ### insert([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md), value : [`boolean`](../../API/builtins/boolean.md)) 45 | `->`[`renoise.Document.ObservableBoolean`](../../API/renoise/renoise.Document.ObservableBoolean.md) 46 | 47 | > Insert a new item to the end of the list when no position is specified, or 48 | > at the specified position. Returns the newly created and inserted Observable. 49 | ### remove([*self*](../../API/builtins/self.md), pos : [`integer`](../../API/builtins/integer.md)) 50 | > Removes an item (or the last one if no index is specified) from the list. 51 | ### swap([*self*](../../API/builtins/self.md), pos1 : [`integer`](../../API/builtins/integer.md), pos2 : [`integer`](../../API/builtins/integer.md)) 52 | > Swaps the positions of two items without adding/removing the items. 53 | > 54 | > With a series of swaps you can move the item from/to any position. 55 | 56 | 57 | 58 | --- 59 | ## Aliases 60 | ### ListElementAdded 61 | { index : [`integer`](../../API/builtins/integer.md), type : `"insert"` } 62 | 63 | 64 | ### ListElementChange 65 | [`ListElementAdded`](#ListElementAdded) | [`ListElementRemoved`](#ListElementRemoved) | [`ListElementsSwapped`](#ListElementsSwapped) 66 | 67 | 68 | ### ListElementRemoved 69 | { index : [`integer`](../../API/builtins/integer.md), type : `"remove"` } 70 | 71 | 72 | ### ListElementsSwapped 73 | { index1 : [`integer`](../../API/builtins/integer.md), index2 : [`integer`](../../API/builtins/integer.md), type : `"swap"` } 74 | 75 | 76 | ### ListNotifierFunction 77 | (change : [`ListElementChange`](#ListElementChange)) 78 | 79 | 80 | ### ListNotifierMemberContext 81 | [`table`](../../API/builtins/table.md) | [`userdata`](../../API/builtins/userdata.md) 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.Osc.md: -------------------------------------------------------------------------------- 1 | # renoise.Osc 2 | > OSC (Open Sound Control) support for Lua scripts in Renoise. 3 | 4 | 5 | 6 | 7 | --- 8 | ## Functions 9 | ### from_binary_data(binary_data : [`string`](../../API/builtins/string.md)) 10 | `->`[`renoise.Osc.Bundle`](../../API/renoise/renoise.Osc.Bundle.md) | [`renoise.Osc.Message`](../../API/renoise/renoise.Osc.Message.md)[`?`](../../API/builtins/nil.md), [`string`](../../API/builtins/string.md)[`?`](../../API/builtins/nil.md) 11 | 12 | > De-packetizing raw (socket) data to OSC messages or bundles: 13 | > Converts the binary data to an OSC message or bundle. If the data does not 14 | > look like an OSC message, or the message contains errors, nil is returned 15 | > as first argument and the second return value will contain the error. 16 | > If de-packetizing was successful, either a renoise.Osc.Bundle or Message 17 | > object is returned. Bundles may contain multiple messages or nested bundles. 18 | ### Message(pattern : [`string`](../../API/builtins/string.md), arguments : [`OscValue`](#oscvalue)[][`?`](../../API/builtins/nil.md)) 19 | `->`[`renoise.Osc.Message`](../../API/renoise/renoise.Osc.Message.md) 20 | 21 | > Create a new OSC message with the given pattern and optional arguments. 22 | ### Bundle(time : [`integer`](../../API/builtins/integer.md), arguments : [`renoise.Osc.Message`](../../API/renoise/renoise.Osc.Message.md) | [`renoise.Osc.Message`](../../API/renoise/renoise.Osc.Message.md)[]) 23 | `->`[`renoise.Osc.Bundle`](../../API/renoise/renoise.Osc.Bundle.md) 24 | 25 | > Create a new bundle by specifying a time-tag and one or more messages. 26 | > If you do not know what to do with the time-tag, use `os.clock()`, 27 | > which simply means "now". Messages must be renoise.Osc.Message objects. 28 | > Nested bundles (bundles in bundles) are right now not supported. 29 | 30 | 31 | 32 | --- 33 | ## Structs 34 | # OscValue 35 | > `tag` is a standard OSC type tag. `value` is the arguments value expressed 36 | > by a Lua type. The value must be convertible to the specified tag, which 37 | > means, you cannot for example specify an "i" (integer) as type and then pass 38 | > a string as the value. Use a number value instead. Not all tags require a 39 | > value, like the T,F boolean tags. Then a `value` field should not be 40 | > specified. For more info, see: http://opensoundcontrol.org/spec-1_0 41 | 42 | --- 43 | ## Properties 44 | ### tag : [`OscTag`](#OscTag) 45 | ### value : [`boolean`](../../API/builtins/boolean.md) | [`string`](../../API/builtins/string.md) | [`number`](../../API/builtins/number.md) 46 | 47 | 48 | 49 | 50 | --- 51 | ## Aliases 52 | ### OscTag 53 | `"F"` | `"I"` | `"N"` | `"S"` | `"T"` | `"b"` | `"c"` | `"d"` | `"f"` | `"h"` | `"i"` | `"m"` | `"r"` | `"s"` | `"t"` 54 | > ```lua 55 | > OscTag: 56 | > | "i" -- int32 57 | > | "f" -- float32 58 | > | "s" -- OSC-string 59 | > | "b" -- OSC-blob (raw string) 60 | > | "h" -- 64 bit big-endian two's complement integer 61 | > | "t" -- OSC-timetag 62 | > | "d" -- 64 bit ("double") IEEE 754 floating point number 63 | > | "S" -- Alternate type represented as an OSC-string 64 | > | "c" -- An ascii character, sent as 32 bits 65 | > | "r" -- 32 bit RGBA color 66 | > | "m" -- 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 67 | > | "T" -- True. No value needs to be specified. 68 | > | "F" -- False. No value needs to be specified. 69 | > | "N" -- Nil. No value needs to be specified. 70 | > | "I" -- Infinitum. No value needs to be specified. 71 | > ``` 72 | 73 | 74 | 75 | 76 | 77 | 78 | --- 79 | ## Aliases 80 | ### OscTag 81 | `"F"` | `"I"` | `"N"` | `"S"` | `"T"` | `"b"` | `"c"` | `"d"` | `"f"` | `"h"` | `"i"` | `"m"` | `"r"` | `"s"` | `"t"` 82 | > ```lua 83 | > OscTag: 84 | > | "i" -- int32 85 | > | "f" -- float32 86 | > | "s" -- OSC-string 87 | > | "b" -- OSC-blob (raw string) 88 | > | "h" -- 64 bit big-endian two's complement integer 89 | > | "t" -- OSC-timetag 90 | > | "d" -- 64 bit ("double") IEEE 754 floating point number 91 | > | "S" -- Alternate type represented as an OSC-string 92 | > | "c" -- An ascii character, sent as 32 bits 93 | > | "r" -- 32 bit RGBA color 94 | > | "m" -- 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 95 | > | "T" -- True. No value needs to be specified. 96 | > | "F" -- False. No value needs to be specified. 97 | > | "N" -- Nil. No value needs to be specified. 98 | > | "I" -- Infinitum. No value needs to be specified. 99 | > ``` 100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.PatternTrack.md: -------------------------------------------------------------------------------- 1 | # renoise.PatternTrack 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### is_alias : [`boolean`](../../API/builtins/boolean.md) 9 | > **READ-ONLY** 10 | 11 | ### alias_pattern_index : [`integer`](../../API/builtins/integer.md) 12 | > index or 0 when no alias is present 13 | 14 | ### alias_pattern_index_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 15 | > Track changes to document properties or general states by attaching listener 16 | > functions to it. 17 | 18 | ### color : [`RGBColor`](#RGBColor)[`?`](../../API/builtins/nil.md) 19 | > slot color of the pattern in the matrix, nil when no slot color is set 20 | 21 | ### color_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 22 | > Track changes to document properties or general states by attaching listener 23 | > functions to it. 24 | 25 | ### is_empty : [`boolean`](../../API/builtins/boolean.md) 26 | > Returns true when all the track lines are empty. Does not look at automation. 27 | 28 | ### is_empty_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 29 | > Track changes to document properties or general states by attaching listener 30 | > functions to it. 31 | 32 | ### lines : [`renoise.PatternLine`](../../API/renoise/renoise.PatternLine.md)[] 33 | > **READ-ONLY** Get all lines in range [1, number_of_lines_in_pattern]. 34 | > Use `renoise.Pattern:add/remove_line_notifier` for change notifications. 35 | 36 | ### automation : [`renoise.PatternTrackAutomation`](../../API/renoise/renoise.PatternTrackAutomation.md)[] 37 | > Automation. 38 | 39 | ### automation_observable : [`renoise.Document.ObservableList`](../../API/renoise/renoise.Document.ObservableList.md) 40 | > Track changes to document lists by attaching listener functions to it. 41 | > NB: Notifiers will not broadcast changes made to list items, but only changes 42 | > to the lists **layout** (items got added, removed, swapped). 43 | 44 | 45 | 46 | --- 47 | ## Functions 48 | ### clear([*self*](../../API/builtins/self.md)) 49 | > Deletes all lines & automation. 50 | ### copy_from([*self*](../../API/builtins/self.md), other : [`renoise.PatternTrack`](../../API/renoise/renoise.PatternTrack.md)) 51 | > Copy contents from other pattern tracks, including automation when possible. 52 | ### line([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 53 | `->`[`renoise.PatternLine`](../../API/renoise/renoise.PatternLine.md) 54 | 55 | > Access to a single line by index. Line must be in Range: (1 - MAX_NUMBER_OF_LINES). 56 | > This is a !lot! more efficient than calling the property: lines[index] to 57 | > randomly access lines. 58 | ### lines_in_range([*self*](../../API/builtins/self.md), index_from : [`integer`](../../API/builtins/integer.md), index_to : [`integer`](../../API/builtins/integer.md)) 59 | `->`[`renoise.PatternLine`](../../API/renoise/renoise.PatternLine.md)[] 60 | 61 | > Get a specific line range. Index must be Range: (1 - Pattern.MAX_NUMBER_OF_LINES) 62 | ### find_automation([*self*](../../API/builtins/self.md), parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)) 63 | `->`[`renoise.PatternTrackAutomation`](../../API/renoise/renoise.PatternTrackAutomation.md)[`?`](../../API/builtins/nil.md) 64 | 65 | > Returns the automation for the given device parameter or nil when there is 66 | > none. 67 | ### create_automation([*self*](../../API/builtins/self.md), parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)) 68 | `->`[`renoise.PatternTrackAutomation`](../../API/renoise/renoise.PatternTrackAutomation.md) 69 | 70 | > Creates a new automation for the given device parameter. 71 | > Fires an error when an automation for the given parameter already exists. 72 | > Returns the newly created automation. Passed parameter must be automatable, 73 | > which can be tested with 'parameter.is_automatable'. 74 | ### delete_automation([*self*](../../API/builtins/self.md), parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)) 75 | > Remove an existing automation the given device parameter. Automation 76 | > must exist. 77 | 78 | 79 | 80 | --- 81 | ## Aliases 82 | ### RGBColor 83 | { 1 : [`integer`](../../API/builtins/integer.md), 2 : [`integer`](../../API/builtins/integer.md), 3 : [`integer`](../../API/builtins/integer.md) } 84 | > A table of 3 bytes (ranging from 0 to 255) 85 | > representing the red, green and blue channels of a color. 86 | > {0xFF, 0xFF, 0xFF} is white 87 | > {165, 73, 35} is the red from the Renoise logo 88 | 89 | 90 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.InstrumentTriggerOptions.md: -------------------------------------------------------------------------------- 1 | # renoise.InstrumentTriggerOptions 2 | 3 | 4 | 5 | ## Constants 6 | ### QuantizeMode 7 | > ```lua 8 | > { 9 | > QUANTIZE_NONE: integer = 1, 10 | > QUANTIZE_LINE: integer = 2, 11 | > QUANTIZE_BEAT: integer = 3, 12 | > QUANTIZE_BAR: integer = 4, 13 | > } 14 | > ``` 15 | 16 | 17 | --- 18 | ## Properties 19 | ### available_scale_modes : [`string`](../../API/builtins/string.md)[] 20 | > **READ-ONLY** List of all available scale modes. 21 | 22 | ### scale_mode : [`string`](../../API/builtins/string.md) 23 | > one of 'available_scales'] 24 | 25 | ### scale_mode_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 26 | > Track changes to document properties or general states by attaching listener 27 | > functions to it. 28 | 29 | ### scale_key : [`integer`](../../API/builtins/integer.md) 30 | > Scale-key to use when transposing (1=C, 2=C#, 3=D, ...) 31 | 32 | ### scale_key_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 33 | > Track changes to document properties or general states by attaching listener 34 | > functions to it. 35 | 36 | ### mts_esp_tuning : [`boolean`](../../API/builtins/boolean.md) 37 | > When true, act as MTS ESP client. Disables custom tunings. 38 | 39 | ### mts_esp_tuning_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 40 | > Track changes to document properties or general states by attaching listener 41 | > functions to it. 42 | 43 | ### tuning : [`number`](../../API/builtins/number.md)[] 44 | > Array of custom pitch values relative to 1/1, used as custom tuning values for 45 | > instrument sample playback. The root key is assumed to be middle C (48 in Renoise), 46 | > The scale will be repeated, so only one octave of values should be defined. An 47 | > octave may contain more or less than 12 notes. 48 | > 49 | > When set mts_esp_tuning is disabled. Set an empty table to disable custom tuning 50 | > using default 12-TET tuning instead. 51 | > 52 | > Use property `tuning_name` to give your custom tuning a name. 53 | > 54 | > #### examples: 55 | > ```lua 56 | > -- Andreas Werckmeister's temperament III (the most famous one, 1681) 57 | > local well_tempered_tuning = { 58 | > 256/243, 1.117403, 32/27, 1.252827, 4/3, 1024/729, 59 | > 1.494927, 128/81, 1.670436, 16/9, 1.879241, 2/1 60 | > } 61 | > instrument.tuning = well_tempered_tuning 62 | > ``` 63 | 64 | ### tuning_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 65 | > Track changes to document properties or general states by attaching listener 66 | > functions to it. 67 | 68 | ### tuning_name : [`string`](../../API/builtins/string.md) 69 | > Name, as displayed in the UI for a custom tuning or a tuning loaded from a file. 70 | 71 | ### tuning_name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 72 | > Track changes to document properties or general states by attaching listener 73 | > functions to it. 74 | 75 | ### quantize : [`renoise.InstrumentTriggerOptions.QuantizeMode`](renoise.InstrumentTriggerOptions.md#QuantizeMode) 76 | > Trigger quantization mode. 77 | 78 | ### quantize_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 79 | > Track changes to document properties or general states by attaching listener 80 | > functions to it. 81 | 82 | ### monophonic : [`boolean`](../../API/builtins/boolean.md) 83 | > Mono/Poly mode. 84 | 85 | ### monophonic_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 86 | > Track changes to document properties or general states by attaching listener 87 | > functions to it. 88 | 89 | ### monophonic_glide : [`integer`](../../API/builtins/integer.md) 90 | > Glide amount when monophonic. 0 == off, 255 = instant 91 | 92 | ### monophonic_glide_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 93 | > Track changes to document properties or general states by attaching listener 94 | > functions to it. 95 | 96 | 97 | 98 | --- 99 | ## Functions 100 | ### load_tuning([*self*](../../API/builtins/self.md), filename : [`string`](../../API/builtins/string.md)) 101 | `->`success : [`boolean`](../../API/builtins/boolean.md) 102 | 103 | > Load and apply a scala tuning file as custom tuning. Disables `mts_esp_tuning`. 104 | > Any errors during the export are shown to the user. 105 | 106 | -------------------------------------------------------------------------------- /tests/sample_device_chain.lua: -------------------------------------------------------------------------------- 1 | --[[-------------------------------------------------------------------------- 2 | TestSampleDeviceChain.lua 3 | --------------------------------------------------------------------------]]-- 4 | 5 | do 6 | 7 | ---------------------------------------------------------------------------- 8 | -- tools 9 | 10 | local function assert_error(statement) 11 | assert(pcall(statement) == false, "expected function error") 12 | end 13 | 14 | 15 | -- shortcuts 16 | 17 | local song = renoise.song() 18 | local selected_instrument = song.selected_instrument 19 | 20 | 21 | ---------------------------------------------------------------------------- 22 | -- device chain insert/delete/swap 23 | ---------------------------------------------------------------------------- 24 | 25 | selected_instrument:insert_sample_device_chain_at(1) 26 | 27 | while (#selected_instrument.sample_device_chains > 0) do 28 | selected_instrument:delete_sample_device_chain_at(1) 29 | end 30 | 31 | assert(#selected_instrument.sample_device_chains == 0) 32 | 33 | new_chain1 = selected_instrument:insert_sample_device_chain_at(1) 34 | assert(type(new_chain1) == "SampleDeviceChain") 35 | new_chain1.name = "Wurst" 36 | 37 | new_chain2 = selected_instrument:insert_sample_device_chain_at(2) 38 | assert(type(new_chain2) == "SampleDeviceChain") 39 | new_chain2.name = "Hose" 40 | 41 | selected_instrument:swap_sample_device_chains_at(1, 2) 42 | assert(selected_instrument.sample_device_chains[1].name == "Hose") 43 | assert(selected_instrument.sample_device_chains[2].name == "Wurst") 44 | 45 | 46 | ---------------------------------------------------------------------------- 47 | -- device insert/delete/swap 48 | ---------------------------------------------------------------------------- 49 | 50 | local avail_devices = 51 | selected_instrument.sample_device_chains[1].available_devices 52 | 53 | local new_device_path 54 | repeat 55 | new_device_path = avail_devices[math.random(1, #avail_devices)] 56 | until 57 | -- avoid plugins, cause they may fail to load and pop up dialogs 58 | not string.find(new_device_path, "VST") and 59 | not string.find(new_device_path, "AU") 60 | 61 | 62 | assert_error(function() 63 | new_chain1:insert_device_at("InvalidDeviceName#234", 64 | #new_chain1.devices + 1) 65 | end) 66 | 67 | -- mixer device tests 68 | assert_error(function() 69 | new_chain1:insert_device_at(new_device_path, 1) 70 | end) 71 | 72 | assert_error(function() 73 | new_chain1:delete_device_at(1) 74 | end) 75 | 76 | local device_count = #new_chain1.devices 77 | 78 | local new_device = new_chain1:insert_device_at( 79 | new_device_path, device_count + 1) 80 | device_count = device_count + 1 81 | assert(device_count == #new_chain1.devices) 82 | 83 | local found_device = false 84 | local found_device_path = false 85 | 86 | for _,device in ipairs(new_chain1.devices) do 87 | if device.name == new_device.name then 88 | found_device = true 89 | end 90 | if device.device_path == new_device_path then 91 | found_device_path = true 92 | end 93 | end 94 | 95 | assert(found_device) 96 | assert(found_device_path) 97 | 98 | new_chain1:delete_device_at(#new_chain1.devices) 99 | device_count = device_count - 1 100 | assert(device_count == #new_chain1.devices) 101 | 102 | new_chain1:insert_device_at(new_device_path, 103 | #new_chain1.devices + 1) 104 | new_chain1:insert_device_at(new_device_path, 105 | #new_chain1.devices + 1) 106 | 107 | device_count = device_count + 2 108 | assert(device_count == #new_chain1.devices) 109 | 110 | new_chain1:swap_devices_at( 111 | #new_chain1.devices, 112 | #new_chain1.devices - 1) 113 | 114 | assert(device_count == #new_chain1.devices) 115 | 116 | new_chain1:delete_device_at(#new_chain1.devices) 117 | new_chain1:delete_device_at(#new_chain1.devices) 118 | 119 | device_count = device_count - 2 120 | assert(device_count == #new_chain1.devices) 121 | 122 | 123 | -- preset handing 124 | 125 | local mixer_device = new_chain1.devices[1] 126 | assert(#mixer_device.presets == 1) -- init 127 | 128 | new_chain1:insert_device_at(new_device_path, 129 | #new_chain1.devices + 1) 130 | 131 | local new_device = new_chain1.devices[ 132 | #new_chain1.devices] 133 | 134 | assert(#new_device.presets >= 1) 135 | assert(new_device.active_preset >= 1) 136 | 137 | local new_preset = math.random(#new_device.presets) 138 | new_device.active_preset = new_preset 139 | assert(new_device.active_preset == new_preset) 140 | 141 | assert_error(function() 142 | new_device.active_preset = 0 143 | end) 144 | assert_error(function() 145 | new_device.active_preset = #new_device.presets + 1 146 | end) 147 | end 148 | 149 | 150 | ------------------------------------------------------------------------------ 151 | -- test finalizers 152 | 153 | collectgarbage() 154 | 155 | 156 | --[[-------------------------------------------------------------------------- 157 | --------------------------------------------------------------------------]]-- 158 | -------------------------------------------------------------------------------- /docs/API/renoise/renoise.SampleOperandModulationDevice.md: -------------------------------------------------------------------------------- 1 | # renoise.SampleOperandModulationDevice 2 | 3 | 4 | 5 | 6 | --- 7 | ## Properties 8 | ### name : [`string`](../../API/builtins/string.md) 9 | > **READ-ONLY** Fixed name of the device. 10 | 11 | ### short_name : [`string`](../../API/builtins/string.md) 12 | > **READ-ONLY** 13 | 14 | ### display_name : [`string`](../../API/builtins/string.md) 15 | > Configurable device display name. 16 | 17 | ### display_name_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 18 | > Track changes to document properties or general states by attaching listener 19 | > functions to it. 20 | 21 | ### enabled : [`boolean`](../../API/builtins/boolean.md) 22 | > **Deprecated.** Use `is_active` instead. 23 | 24 | ### enabled_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 25 | > Track changes to document properties or general states by attaching listener 26 | > functions to it. 27 | 28 | ### is_active : [`boolean`](../../API/builtins/boolean.md) 29 | > not active = bypassed 30 | 31 | ### is_active_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 32 | > Track changes to document properties or general states by attaching listener 33 | > functions to it. 34 | 35 | ### is_maximized : [`boolean`](../../API/builtins/boolean.md) 36 | > Maximize state in modulation chain. 37 | 38 | ### is_maximized_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 39 | > Track changes to document properties or general states by attaching listener 40 | > functions to it. 41 | 42 | ### target : [`renoise.SampleModulationDevice.TargetType`](renoise.SampleModulationDevice.md#TargetType) 43 | > **READ-ONLY** Where the modulation gets applied (Volume, 44 | > Pan, Pitch, Cutoff, Resonance). 45 | 46 | ### operator : [`renoise.SampleModulationDevice.OperatorType`](renoise.SampleModulationDevice.md#OperatorType) 47 | > Modulation operator: how the device applies. 48 | 49 | ### operator_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 50 | > Track changes to document properties or general states by attaching listener 51 | > functions to it. 52 | 53 | ### bipolar : [`boolean`](../../API/builtins/boolean.md) 54 | > Modulation polarity: 55 | > when bipolar, the device applies it's values in a -1 to 1 range, 56 | > when unipolar in a 0 to 1 range. 57 | 58 | ### bipolar_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 59 | > Track changes to document properties or general states by attaching listener 60 | > functions to it. 61 | 62 | ### tempo_sync_switching_allowed : [`boolean`](../../API/builtins/boolean.md) 63 | > **READ-ONLY** When true, the device has one of more time parameters, 64 | > which can be switched to operate in synced or unsynced mode. 65 | > see also field tempo_synced. 66 | 67 | ### tempo_synced : [`boolean`](../../API/builtins/boolean.md) 68 | > When true and the device supports sync switching the device operates 69 | > in wall-clock (ms) instead of beat times. 70 | > see also property 'tempo_sync_switching_allowed' 71 | 72 | ### tempo_synced_observable : [`renoise.Document.Observable`](../../API/renoise/renoise.Document.Observable.md) 73 | > Track changes to document properties or general states by attaching listener 74 | > functions to it. 75 | 76 | ### is_active_parameter : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 77 | > **READ-ONLY** Generic access to all parameters of this device. 78 | 79 | ### parameters : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md)[] 80 | > **READ-ONLY** 81 | 82 | ### value : [`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 83 | > Operand value. 84 | 85 | 86 | 87 | --- 88 | ## Functions 89 | ### init([*self*](../../API/builtins/self.md)) 90 | > Reset the device to its default state. 91 | ### copy_from([*self*](../../API/builtins/self.md), other_device : [`renoise.SampleModulationDevice`](../../API/renoise/renoise.SampleModulationDevice.md)) 92 | > Copy a device's state from another device. 'other_device' must be of the 93 | > same type. 94 | ### parameter([*self*](../../API/builtins/self.md), index : [`integer`](../../API/builtins/integer.md)) 95 | `->`[`renoise.DeviceParameter`](../../API/renoise/renoise.DeviceParameter.md) 96 | 97 | > Access to a single parameter by index. Use properties 'parameters' to iterate 98 | > over all parameters and to query the parameter count. 99 | 100 | --------------------------------------------------------------------------------