if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){ ?> } else { ?> } ?>
This shows you the differences between two versions of the page.
wiki:ardourlua [28.01.2016 23:12] rgareus |
wiki:ardourlua [24.02.2016 00:46] (current) rgareus [LuaSession] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Ardour Lua Scripting ====== | ====== Ardour Lua Scripting ====== | ||
- | ~~DRAFT~~ | + | moved to http://manual.ardour.org/lua-scripting/ |
- | + | ||
- | Lua is a lightweight programming language which lends itself nicely to embedded into other applications. | + | |
- | + | ||
- | In Ardour's case Lua is available: | + | |
- | + | ||
- | * DSP Scripts - audio processor - plugins with access to the session | + | |
- | * Session Scripts - realtime, called at the start of every audio cycle | + | |
- | * Editor Action Scripts - user accessible actions (menu, bindings) | + | |
- | * Editor Hooks - event triggered actions, GUI thread | + | |
- | * Script Console - GUI thread (for development) | + | |
- | + | ||
- | ===== Why Lua? ===== | + | |
- | + | ||
- | small, lean, rt-safe, easily bindable. | + | |
- | + | ||
- | ===== General Concepts ===== | + | |
- | + | ||
- | * Ardour calls Lua (not the other way 'round). | + | |
- | * There are no bound constructors. ie. Lua asks Ardour to create objects (e.g. add a new track), then receives a reference to the object to modify it. | + | |
- | * Scripts, once loaded, are saved with the Session (no reference to external files) | + | |
- | * Lua Scripts are never executed directly. They provide a "factory" method which can have instantiation parameters. | + | |
- | * All Lua interpreters except the DSP-scripts are singleton instances. | + | |
- | * Session Scripts: The process-callback run all //registered// scripts in sequence. Session Script have limited access to the Session (realtime-safe). Scripts are registered/unregistered from Menu -> Session -> Scripting -> Add/Remove Script | + | |
- | * Editor Action Scripts: These are called from the GUI (explicit user action). 10 Slots are available from Menu -> Edit -> Scripted Actions. Editor Action Scripts have complete access to the Session and to the Editor. | + | |
- | * Editor Hooks: They're automatically triggered Action Scripts, connect to signals (block the GUI thread while running). -- currently not implemented | + | |
- | * DSP scripts: are like regular plugins with a generic GUI. The context menu for each Route allows to add them. Using Plugin Controls, these are the only scripts that a user can interact with once they're instantiated. | + | |
- | * ..except the Script Console, which is currently a separate interpreter (Menu > Window > Scripting) which allows to interactively run Lua code. This interpreter is volatile. The state is not saved with the session. | + | |
- | + | ||
- | + | ||
- | ===== Script Layout ===== | + | |
- | + | ||
- | * Descriptor: Name, Author, Description, URL,... | + | |
- | * Factory function: a function which returns the actual script. | + | |
- | * [optional]: list of parameters for the "factory". | + | |
- | + | ||
- | DSP-plugins have additional list of automatable parameters. | + | |
- | + | ||
- | An minimal example script looks like: | + | |
- | + | ||
- | ardour { | + | |
- | ["type"] = "EditorAction", | + | |
- | name = "Rewind", | + | |
- | } | + | |
- | + | ||
- | function factory (params) | + | |
- | return function () | + | |
- | Session:goto_start() | + | |
- | end | + | |
- | end | + | |
- | + | ||
- | + | ||
- | ===== Bindings ===== | + | |
- | Lua has direct access to Ardour internals: C++ classes, methods, data and functions. | + | |
- | So writing elaborate scripts requires some knowledge about Ardour's internal interfaces. | + | |
- | However the vast majority of simple actions can be done nearly self-contained in Lua. | + | |
- | + | ||
- | ==== C++ bindings ==== | + | |
- | + | ||
- | To access methods or data of specific instances, use a colon ":", e.g. Lua ''Session:get_tracks()'' is equivalent to C++ ''_session->get_tracks()''. | + | |
- | + | ||
- | Static variables, static functions, enums or C++ singletons directly access the Object. e.g. Lua: ''ARDOUR.AudioEngine.create()'' calls C++ ''ARDOUR::AudioEngine::create()'' or Lua: ''Editing.ImportDistinctFiles'' refers to the C++ enum ''Editing::ImportDistinctFiles''. | + | |
- | + | ||
- | see also [[http://www.lua.org/pil/16.html|Programming in Lua, Object-Oriented Programming]]. | + | |
- | + | ||
- | + | ||
- | ==== Pass by value/pass by reference ==== | + | |
- | + | ||
- | + | ||
- | ===== Script Specifics ===== | + | |
- | + | ||
- | The common part for all scripts is the "Descriptor". It's a Lua table with the following keys (the keys are case-sensitive) | + | |
- | * **type** (required): one of "DSP", "Session", "EditorHook", "EditorAction" (the type is not case-sensitive) | + | |
- | * **name** (required): Name/Title of the script | + | |
- | * **author**: Your Name | + | |
- | * **license**: The license of the script (e.g. "GPL" or "MIT") | + | |
- | * **description**: A longer text explaining to the user what the script does. | + | |
- | + | ||
- | ==== Session Scripts ==== | + | |
- | + | ||
- | Session scripts have access to the current session via the global variable ''Session''. | + | |
- | + | ||
- | ==== Editor Action Scripts & Hooks ==== | + | |
- | + | ||
- | Editor Actions and Hooks both have access to the Session and Editor via the global variables ''Session'' and ''Editor'' respectively. | + | |
- | + | ||
- | ==== DSP Scripts ==== | + | |
- | + | ||
- | DSP scripts are the odd one out. An approach not unlike other audio-plugin standard API is used for the script. | + | |
- | DSP scripts directly provide functions: | + | |
- | * ''dsp_init(sample_rate)'' (optional) | + | |
- | * ''dsp_params()'' (optional), returns a table of automatable parameters | + | |
- | * ''dsp_ioconfig()'' (required), returns a table of possible I/O port configurations | + | |
- | * ''dsp (bufs, in_map, out_map, n_samples, offset)'' (required), process the given buffers | + | |
- | + | ||
- | The script has access to the current session via the global variable ''Session'', control-port data is currently mapped to the global variable ''CtrlPorts'' (only valid during ''dsp()''). | + | |
- | + | ||
- | The audio-port to buffer-mapping is currently passed to every call to ''dsp()'', via the local in_map, out_map variables, however Ardour's ''ChanCount'' is mapped to the global Lua variables ''InputConfig'' and ''OutputConfig''. | + | |
- | + | ||
===== Console Examples ===== | ===== Console Examples ===== | ||
Line 135: | Line 36: | ||
# called when a new session is loaded: | # called when a new session is loaded: | ||
function new_session (name) print("NEW SESSION:", name) end | function new_session (name) print("NEW SESSION:", name) end | ||
+ | |||
+ | |||
+ | route = Session:route_by_remote_id(1) | ||
+ | processor = route:nth_plugin(0) | ||
+ | plugininsert = processor:to_insert() | ||
+ | |||
+ | plugin = plugininsert:plugin(0) | ||
+ | print (plugin:label()) | ||
+ | print (plugin:parameter_count()) | ||
+ | |||
+ | x = ARDOUR.ParameterDescriptor () | ||
+ | _, t = plugin:get_parameter_descriptor(2, x) -- port #2 | ||
+ | paramdesc = t[2] | ||
+ | print (paramdesc.lower) | ||
+ | |||
+ | ctrl = ARDOUR.EvoralParameter(ARDOUR.AutomationType.PluginAutomation, 0, 2) | ||
+ | ac = plugininsert:automation_control(ctrl, false) | ||
+ | print (ac:get_value ()) | ||
+ | ac:set_value(1.0, PBD.GroupControlDisposition.NoGroup) | ||
===== LuaSession ===== | ===== LuaSession ===== | ||
- | There's a standalone tool ''luasession' which allows to access an Ardour session directly from the commandline. | + | for i,_ in AudioEngine:available_backends():iter() do print (i.name) end |
- | Interaction is limited by the fact that most actions are provided by the Ardour Editor/GUI. | + | backend = AudioEngine:set_backend("ALSA", "", "") |
- | The tool provides only two special functions ''load_session'' and ''close_session''. | + | print (AudioEngine:current_backend_name()) |
- | + | ||
- | A = ARDOUR.AudioEngine.create() | + | |
- | for i,_ in A:available_backends():iter() do print (i.name) end | + | |
- | backend = A:set_backend("ALSA", "", "") | + | |
- | print (A:current_backend_name()) | + | |
for i,_ in backend:enumerate_devices():iter() do print (i.name) end | for i,_ in backend:enumerate_devices():iter() do print (i.name) end | ||
backend:set_input_device_name("HDA Intel PCH") | backend:set_input_device_name("HDA Intel PCH") | ||
backend:set_output_device_name("HDA Intel PCH") | backend:set_output_device_name("HDA Intel PCH") | ||
print (backend:buffer_size()) | print (backend:buffer_size()) | ||
- | print (A:get_last_backend_error()) | + | print (AudioEngine:get_last_backend_error()) |
s = load_session ("/home/rgareus/Documents/ArdourSessions/lua2/", "lua2") | s = load_session ("/home/rgareus/Documents/ArdourSessions/lua2/", "lua2") | ||
Line 157: | Line 71: | ||
print (s:transport_rolling()) | print (s:transport_rolling()) | ||
s:goto_start() | s:goto_start() | ||
- | unload_session() | + | close_session() |