diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h index 022689e2c6..6f7c869287 100644 --- a/libs/ardour/ardour/lua_api.h +++ b/libs/ardour/ardour/lua_api.h @@ -54,6 +54,14 @@ namespace ARDOUR { namespace LuaAPI { */ int datatype_ctor_midi (lua_State *L); + /** add a new [external] Send to the given Route + * + * @param s Session Handle + * @param r Route to add Send to + * @param p add send before given processor (or \ref nil_processor to add at the end) + */ + boost::shared_ptr new_send (Session* s, boost::shared_ptr r, boost::shared_ptr p); + /** Create a null processor shared pointer * * This is useful for Track:bounce() to indicate no processing. diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc index 0bbeaf5b2b..cab66f0aa9 100644 --- a/libs/ardour/lua_api.cc +++ b/libs/ardour/lua_api.cc @@ -111,6 +111,33 @@ ARDOUR::LuaAPI::new_luaproc (Session *s, const string& name) return boost::shared_ptr (new PluginInsert (*s, p)); } +boost::shared_ptr +ARDOUR::LuaAPI::new_send (Session* s, boost::shared_ptr r, boost::shared_ptr before) +{ + if (!s) { + return boost::shared_ptr (); + } + + boost::shared_ptr send (new Send (*s, r->pannable (), r->mute_master ())); + + /* make an educated guess at the initial number of outputs for the send */ + ChanCount outs = before ? before->input_streams () : r->n_outputs(); + + try { + Glib::Threads::Mutex::Lock lm (AudioEngine::instance ()->process_lock ()); + send->output()->ensure_io (outs, false, r.get()); + } catch (AudioEngine::PortRegistrationFailure& err) { + error << string_compose (_("Cannot set up new send: %1"), err.what ()) << endmsg; + return boost::shared_ptr (); + } + + if (0 == r->add_processor (send, before)) { + return send; + } + + return boost::shared_ptr (); +} + PluginInfoList ARDOUR::LuaAPI::list_plugins () { diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index fc3aca799b..a2e5e21fc4 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -69,6 +69,7 @@ #include "ardour/midi_port.h" #include "ardour/midi_region.h" #include "ardour/midi_source.h" +#include "ardour/monitor_control.h" #include "ardour/panner_shell.h" #include "ardour/phase_control.h" #include "ardour/playlist.h" @@ -1123,6 +1124,7 @@ LuaBindings::common (lua_State* L) .addFunction ("reset_plugin_insert", &Route::reset_plugin_insert) .addFunction ("customize_plugin_insert", &Route::customize_plugin_insert) .addFunction ("add_sidechain", &Route::add_sidechain) + .addFunction ("add_aux_send", &Route::add_aux_send) .addFunction ("remove_sidechain", &Route::remove_sidechain) .addFunction ("main_outs", &Route::main_outs) .addFunction ("muted", &Route::muted) @@ -1133,6 +1135,8 @@ LuaBindings::common (lua_State* L) .addFunction ("set_meter_point", &Route::set_meter_point) .addFunction ("signal_latency", &Route::signal_latency) .addFunction ("playback_latency", &Route::playback_latency) + .addFunction ("monitoring_state", &Route::monitoring_state) + .addFunction ("monitoring_control", &Route::monitoring_control) .endClass () .deriveWSPtrClass ("Playlist") @@ -1519,6 +1523,7 @@ LuaBindings::common (lua_State* L) .addFunction ("get_delay_out", &Send::get_delay_out) .addFunction ("gain_control", &Send::gain_control) .addFunction ("is_foldback", &Send::is_foldback) + .addFunction ("set_remove_on_disconnect", &Send::set_remove_on_disconnect) .endClass () .deriveWSPtrClass ("InternalSend") @@ -1597,6 +1602,7 @@ LuaBindings::common (lua_State* L) .addFunction ("natural_input_streams", &PluginInsert::natural_input_streams) .addFunction ("reset_parameters_to_default", &PluginInsert::reset_parameters_to_default) .addFunction ("has_sidechain", &PluginInsert::has_sidechain) + .addFunction ("sidechain_input", &PluginInsert::sidechain_input) .addFunction ("is_instrument", &PluginInsert::is_instrument) .addFunction ("type", &PluginInsert::type) .addFunction ("signal_latency", &PluginInsert::signal_latency) @@ -1649,6 +1655,10 @@ LuaBindings::common (lua_State* L) .deriveWSPtrClass ("GainControl") .endClass () + .deriveWSPtrClass ("MonitorControl") + .addFunction ("monitoring_choice", &MonitorControl::monitoring_choice) + .endClass () + .deriveWSPtrClass ("SoloControl") .addFunction ("can_solo", &SoloControl::can_solo) .addFunction ("soloed", &SoloControl::soloed) @@ -2053,6 +2063,13 @@ LuaBindings::common (lua_State* L) .addConst ("MonitorCue", ARDOUR::MonitorChoice(MonitorCue)) .endNamespace () + .beginNamespace ("MonitorState") + .addConst ("MonitoringSilence", ARDOUR::MonitorState(MonitoringSilence)) + .addConst ("MonitoringInput", ARDOUR::MonitorState(MonitoringInput)) + .addConst ("MonitoringDisk", ARDOUR::MonitorState(MonitoringDisk)) + .addConst ("MonitoringCue", ARDOUR::MonitorState(MonitoringCue)) + .endNamespace () + .beginNamespace ("NoteMode") .addConst ("Sustained", ARDOUR::NoteMode(Sustained)) .addConst ("Percussive", ARDOUR::NoteMode(Percussive)) @@ -2597,6 +2614,7 @@ LuaBindings::common (lua_State* L) .beginNamespace ("LuaAPI") .addFunction ("nil_proc", ARDOUR::LuaAPI::nil_processor) .addFunction ("new_luaproc", ARDOUR::LuaAPI::new_luaproc) + .addFunction ("new_send", ARDOUR::LuaAPI::new_send) .addFunction ("list_plugins", ARDOUR::LuaAPI::list_plugins) .addFunction ("new_plugin_info", ARDOUR::LuaAPI::new_plugin_info) .addFunction ("new_plugin", ARDOUR::LuaAPI::new_plugin) diff --git a/share/scripts/s_ducks.lua b/share/scripts/s_ducks.lua new file mode 100644 index 0000000000..21b2a253c4 --- /dev/null +++ b/share/scripts/s_ducks.lua @@ -0,0 +1,52 @@ +ardour { ["type"] = "Snippet", name = "Ducks" } + +function factory (params) return function () + + local chan_out = 2 + if not Session:master_out():isnil() then + chan_out = Session:master_out():n_inputs ():n_audio () + end + + -- create two mono tracks + local tl = Session:new_audio_track (1, chan_out, nil, 2, "Ducks", ARDOUR.PresentationInfo.max_order, ARDOUR.TrackMode.Normal, true) + for t in tl:iter() do + t:set_strict_io (true) + -- switch tracks to monitor input + t:monitoring_control():set_value (ARDOUR.MonitorChoice.MonitorInput, PBD.GroupControlDisposition.NoGroup) + end + + local src = tl:front (); + local dst = tl:back (); + + assert (not src:isnil() and not dst:isnil()) + + -- add "ACE Compressor" to target track + local p = ARDOUR.LuaAPI.new_plugin (Session, "urn:ardour:a-comp", ARDOUR.PluginType.LV2, "") + assert (not p:isnil ()) + + dst:add_processor_by_index (p, 0, nil, true) + ARDOUR.LuaAPI.set_processor_param (p, 1, 300) -- 300ms release time + ARDOUR.LuaAPI.set_processor_param (p, 2, 4) -- 4dB Knee + ARDOUR.LuaAPI.set_processor_param (p, 3, 7) -- ratio 1:7 + ARDOUR.LuaAPI.set_processor_param (p, 4, -25) -- threshold -20dBFS + ARDOUR.LuaAPI.set_processor_param (p, 9, 1) -- enable sidechain + + -- add Send to src track before the fader + local s = ARDOUR.LuaAPI.new_send (Session, src, src:amp ()) + assert (not s:isnil ()) + + -- mark as sidechain send + local send = s:to_send() + send:set_remove_on_disconnect (true) + + -- now connect send to plugin's sidechain input + local src_io = send:output() + + -- ACE Compressor already has a sidechain, and sidechain + -- pin connected. Other plugins see "plugin channel-map dev" + -- snippet how to change plugin pinout. + local dst_io = p:to_plugininsert ():sidechain_input () + + src_io:nth(0):connect (dst_io:nth (0):name ()) + +end end