Redesign Session+Route Template Meta Script API
authorRobin Gareus <robin@gareus.org>
Fri, 18 Aug 2017 18:41:35 +0000 (20:41 +0200)
committerRobin Gareus <robin@gareus.org>
Fri, 18 Aug 2017 18:42:55 +0000 (20:42 +0200)
Remove special-cased script types. Allow Action-Scripts to be re-used
for session-setup or route-templates.

14 files changed:
gtk2_ardour/add_route_dialog.cc
gtk2_ardour/add_route_dialog.h
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/session_dialog.cc
libs/ardour/ardour/luascripting.h
libs/ardour/luascripting.cc
libs/backends/coreaudio/coreaudio_backend.cc
scripts/_route_template_example.lua
scripts/_template_band.lua
scripts/_template_example.lua
scripts/_tracks_band.lua
scripts/_tracks_generic_audio.lua
scripts/session_template_advanced.lua

index 4bfaedd4e31b167f9499daf4f1957429860b0de5..b743fbb15b72317608228c4cdd53615b811296f2 100644 (file)
 #include "ardour/session.h"
 #include "ardour/vca.h"
 
-#include "utils.h"
+#include "LuaBridge/LuaBridge.h"
+
 #include "add_route_dialog.h"
+#include "ardour_ui.h"
 #include "route_group_dialog.h"
+#include "utils.h"
+
 #include "pbd/i18n.h"
 
 using namespace Gtk;
@@ -139,6 +143,7 @@ AddRouteDialog::AddRouteDialog ()
 
        /* template_desc is the textview that displays the currently selected template's description */
        trk_template_desc.set_editable (false);
+       trk_template_desc.set_can_focus (false);
        trk_template_desc.set_wrap_mode (Gtk::WRAP_WORD);
        trk_template_desc.set_size_request(400,200);
        trk_template_desc.set_name (X_("TextOnBackground"));
@@ -288,25 +293,94 @@ AddRouteDialog::trk_template_row_selected ()
                trk_template_desc.get_buffer ()->set_text (d);
 
                const string n = (*iter)[track_template_columns.name];
-               if ( n != _("Manual Configuration") ) {
-                       /* template or meta-template */
-                       const string p = (*iter)[track_template_columns.path];
-                       bool meta_template = p.substr (0, 11) == "urn:ardour:";
+               const string p = (*iter)[track_template_columns.path];
+
+               if ( n != _("Manual Configuration") && p.substr (0, 11) == "urn:ardour:") {
+                       /* lua script - meta-template */
+                       const std::map<std::string, std::string> rs (ARDOUR_UI::instance()->route_setup_info (p.substr (11)));
+
+                       trk_template_desc.set_sensitive (true);
+
+                       manual_label.set_sensitive (false);
+                       add_label.set_sensitive (false);
+                       type_label.set_sensitive (false);
+
+                       name_label.set_sensitive (rs.find ("name") != rs.end());
+                       group_label.set_sensitive (rs.find ("group") != rs.end());
+                       strict_io_label.set_sensitive (rs.find ("strict_io") != rs.end());
+                       configuration_label.set_sensitive (rs.find ("channels") != rs.end ());
+                       mode_label.set_sensitive (rs.find ("track_mode") != rs.end ());
+                       instrument_label.set_sensitive (rs.find ("instrument") != rs.end ());
+                       strict_io_label.set_sensitive (rs.find ("strict_io") != rs.end());
+
+                       track_bus_combo.set_sensitive (false);
+                       routes_spinner.set_sensitive (rs.find ("how_many") != rs.end ());
+                       name_template_entry.set_sensitive (rs.find ("name") != rs.end ());
+                       route_group_combo.set_sensitive (rs.find ("group") != rs.end());
+                       channel_combo.set_sensitive (rs.find ("channels") != rs.end ());
+                       mode_combo.set_sensitive (rs.find ("track_mode") != rs.end ());
+                       instrument_combo.set_sensitive (rs.find ("instrument") != rs.end ());
+                       strict_io_combo.set_sensitive (rs.find ("strict_io") != rs.end());
+
+                       std::map<string,string>::const_iterator it;
+
+                       if ((it = rs.find ("name")) != rs.end()) {
+                               name_template_entry.set_text (it->second);
+                       }
+
+                       if ((it = rs.find ("how_many")) != rs.end()) {
+                               routes_adjustment.set_value (atoi (it->second.c_str()));
+                       }
+
+                       if ((it = rs.find ("track_mode")) != rs.end()) {
+                               switch ((ARDOUR::TrackMode) atoi (it->second.c_str())) {
+                                       case ARDOUR::Normal:
+                                               mode_combo.set_active_text (_("Normal"));
+                                               break;
+                                       case ARDOUR::NonLayered:
+                                               mode_combo.set_active_text (_("Nn Layered"));
+                                               break;
+                                       case ARDOUR::Destructive:
+                                               mode_combo.set_active_text (_("Tape"));
+                                               break;
+                               }
+                       }
 
+                       if ((it = rs.find ("strict_io")) != rs.end()) {
+                               if (it->second == X_("true")) {
+                                       strict_io_combo.set_active (1);
+                               } else if (it->second == X_("false")) {
+                                       strict_io_combo.set_active (0);
+                               }
+                       }
+
+                       if ((it = rs.find ("channels")) != rs.end()) {
+                               uint32_t channels = atoi (it->second.c_str());
+                               for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
+                                       if ((*i).channels == channels) {
+                                               channel_combo.set_active_text ((*i).name);
+                                               break;
+                                       }
+                               }
+                       }
+
+               } else if ( n != _("Manual Configuration")) {
+                       /* user-template */
                        trk_template_desc.set_sensitive (true);
 
                        manual_label.set_sensitive (false);
                        add_label.set_sensitive (false);
                        type_label.set_sensitive (false);
-                       name_label.set_sensitive (!meta_template);
+                       name_label.set_sensitive (true);
                        group_label.set_sensitive (false);
                        strict_io_label.set_sensitive (false);
                        configuration_label.set_sensitive (false);
                        mode_label.set_sensitive (false);
+                       instrument_label.set_sensitive (false);
 
-                       routes_spinner.set_sensitive (!meta_template);
+                       routes_spinner.set_sensitive (true);
                        track_bus_combo.set_sensitive (false);
-                       name_template_entry.set_sensitive (!meta_template);
+                       name_template_entry.set_sensitive (true);
                        channel_combo.set_sensitive (false);
                        mode_combo.set_sensitive (false);
                        instrument_combo.set_sensitive (false);
@@ -314,7 +388,7 @@ AddRouteDialog::trk_template_row_selected ()
                        route_group_combo.set_sensitive (false);
 
                } else {
-
+                       /* all manual mode */
                        trk_template_desc.set_sensitive (false);
 
                        manual_label.set_sensitive (true);
@@ -564,21 +638,26 @@ AddRouteDialog::mode ()
        return ARDOUR::Normal;
 }
 
+uint32_t
+AddRouteDialog::channel_count ()
+{
+       string str = channel_combo.get_active_text();
+       for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
+               if (str == (*i).name) {
+                       return (*i).channels;
+               }
+       }
+       return 0;
+}
+
 ChanCount
 AddRouteDialog::channels ()
 {
        ChanCount ret;
-       string str;
        switch (type_wanted()) {
        case AudioTrack:
        case AudioBus:
-               str = channel_combo.get_active_text();
-               for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
-                       if (str == (*i).name) {
-                               ret.set (DataType::AUDIO, (*i).channels);
-                               break;
-                       }
-               }
+               ret.set (DataType::MIDI, channel_count ());
                ret.set (DataType::MIDI, 0);
                break;
 
@@ -589,13 +668,7 @@ AddRouteDialog::channels ()
                break;
 
        case MixedTrack:
-               str = channel_combo.get_active_text();
-               for (ChannelSetups::iterator i = channel_setups.begin(); i != channel_setups.end(); ++i) {
-                       if (str == (*i).name) {
-                               ret.set (DataType::AUDIO, (*i).channels);
-                               break;
-                       }
-               }
+               ret.set (DataType::MIDI, channel_count ());
                ret.set (DataType::MIDI, 1);
                break;
        default:
@@ -676,8 +749,11 @@ AddRouteDialog::refill_channel_setups ()
        trk_template_model->clear();
 
        /* Add any Lua scripts (factory templates) found in the scripts folder */
-       LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::TrackSetup));
+       LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction));
        for (LuaScriptList::const_iterator s = ms.begin(); s != ms.end(); ++s) {
+               if (!((*s)->subtype & LuaScriptInfo::RouteSetup)) {
+                       continue;
+               }
                TreeModel::Row row;
                if ( (*s)->name == "Add tracks") {  //somewhat-special, most-used template
                        row = *(trk_template_model->prepend ());
index 920113f275dfee283f1d0df43f4078301478944c..c49e1a1692ef30df0fec4db4c99edfc9145ee50e 100644 (file)
@@ -71,6 +71,7 @@ public:
        TypeWanted type_wanted() const;
 
        ARDOUR::ChanCount channels ();
+       uint32_t channel_count ();
        int count ();
 
        std::string name_template () const;
index 95a97d2829fe6d8dc8a516bbd36ab53762a4b766..d3b07badb933a82dca8ad1fb73a67f9af59b9b18 100644 (file)
@@ -3885,6 +3885,100 @@ static void _lua_print (std::string s) {
        PBD::info << "LuaInstance: " << s << endmsg;
 }
 
+std::map<std::string, std::string>
+ARDOUR_UI::route_setup_info (const std::string& script_path)
+{
+       std::map<std::string, std::string> rv;
+
+       if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
+               return rv;
+       }
+
+       LuaState lua;
+       lua.Print.connect (&_lua_print);
+       lua.sandbox (true);
+
+       lua_State* L = lua.getState();
+       LuaInstance::register_classes (L);
+       LuaBindings::set_session (L, _session);
+       luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
+       lua_setglobal (L, "Editor");
+
+       lua.do_command ("function ardour () end");
+       lua.do_file (script_path);
+
+       try {
+               luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
+               if (!fn.isFunction ()) {
+                       return rv;
+               }
+               luabridge::LuaRef rs = fn ();
+               if (!rs.isTable ()) {
+                       return rv;
+               }
+               for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
+                       if (!i.key().isString()) {
+                               continue;
+                       }
+                       std::string key = i.key().tostring();
+                       if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
+                               rv[key] = i.value().tostring();
+                       }
+               }
+       } catch (luabridge::LuaException const& e) {
+               cerr << "LuaException:" << e.what () << endl;
+               return rv;
+       }
+       return rv;
+}
+
+void
+ARDOUR_UI::meta_route_setup (const std::string& script_path)
+{
+       if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
+               return;
+       }
+       assert (add_route_dialog);
+
+       int count;
+       if ((count = add_route_dialog->count()) <= 0) {
+               return;
+       }
+
+       LuaState lua;
+       lua.Print.connect (&_lua_print);
+       lua.sandbox (true);
+
+       lua_State* L = lua.getState();
+       LuaInstance::register_classes (L);
+       LuaBindings::set_session (L, _session);
+       luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
+       lua_setglobal (L, "Editor");
+
+       lua.do_command ("function ardour () end");
+       lua.do_file (script_path);
+
+       luabridge::LuaRef args (luabridge::newTable (L));
+
+       args["name"]       = add_route_dialog->name_template ();
+       args["insert_at"]  = translate_order (add_route_dialog->insert_at());
+       args["group"]      = add_route_dialog->route_group ();
+       args["strict_io"]  = add_route_dialog->use_strict_io ();
+       args["instrument"] = add_route_dialog->requested_instrument ();
+       args["track_mode"] = add_route_dialog->mode ();
+       args["channels"]   = add_route_dialog->channel_count ();
+       args["how_many"]   = count;
+
+       try {
+               luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
+               if (fn.isFunction()) {
+                       fn (args)();
+               }
+       } catch (luabridge::LuaException const& e) {
+               cerr << "LuaException:" << e.what () << endl;
+       }
+}
+
 void
 ARDOUR_UI::meta_session_setup (const std::string& script_path)
 {
@@ -3906,9 +4000,9 @@ ARDOUR_UI::meta_session_setup (const std::string& script_path)
        lua.do_file (script_path);
 
        try {
-               luabridge::LuaRef fn = luabridge::getGlobal (L, "session_setup");
+               luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
                if (fn.isFunction()) {
-                       fn ();
+                       fn ()();
                }
        } catch (luabridge::LuaException const& e) {
                cerr << "LuaException:" << e.what () << endl;
@@ -4379,7 +4473,7 @@ ARDOUR_UI::add_route_dialog_response (int r)
 
        std::string template_path = add_route_dialog->get_template_path();
        if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
-               meta_session_setup (template_path.substr (11));
+               meta_route_setup (template_path.substr (11));
                return;
        }
 
index ae1cd9c1320a5f050490c4f657f77c07dc0bf17b..de1b598b3c3d9f5218d20e7f423c9d0481a392d3 100644 (file)
@@ -67,6 +67,8 @@
 #include "ardour/session_handle.h"
 #include "ardour/system_exec.h"
 
+#include "LuaBridge/LuaBridge.h"
+
 #include "video_timeline.h"
 
 #include "widgets/ardour_button.h"
@@ -347,6 +349,8 @@ public:
 
        ARDOUR::PresentationInfo::order_t translate_order (RouteDialogs::InsertAt);
 
+       std::map<std::string, std::string> route_setup_info (const std::string& script_path);
+
 protected:
        friend class PublicEditor;
 
@@ -624,6 +628,7 @@ private:
        void manage_templates ();
 
        void meta_session_setup (const std::string& script_path);
+       void meta_route_setup (const std::string& script_path);
 
        void edit_metadata ();
        void import_metadata ();
index 2337d985c38d8a02574575ec9c63c0813c9bd41c..a41078c49a1a83e0d5396dad3efbac26e83d6520 100644 (file)
@@ -237,7 +237,7 @@ SessionDialog::meta_master_bus_profile (std::string script_path) const
        }
 
        LuaScriptInfo::ScriptType type = LuaScriptInfo::str2type (nfo["type"].cast<std::string>());
-       if (type != LuaScriptInfo::SessionSetup) {
+       if (type != LuaScriptInfo::SessionInit) {
                return UINT32_MAX;
        }
 
@@ -562,10 +562,22 @@ SessionDialog::populate_session_templates ()
        template_model->clear ();
 
        //Add any Lua scripts (factory templates) found in the scripts folder
-       LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::SessionSetup));
+       LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::SessionInit));
        for (LuaScriptList::const_iterator s = ms.begin(); s != ms.end(); ++s) {
-               TreeModel::Row row;
-               row = *(template_model->append ());
+               TreeModel::Row row = *(template_model->append ());
+               row[session_template_columns.name] = "Meta: " + (*s)->name;
+               row[session_template_columns.path] = "urn:ardour:" + (*s)->path;
+               row[session_template_columns.description] = (*s)->description;
+               row[session_template_columns.created_with_short] = _("{Factory Template}");
+               row[session_template_columns.created_with_long] = _("{Factory Template}");
+       }
+
+       LuaScriptList& as (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction));
+       for (LuaScriptList::const_iterator s = as.begin(); s != as.end(); ++s) {
+               if (!((*s)->subtype & LuaScriptInfo::SessionSetup)) {
+                       continue;
+               }
+               TreeModel::Row row = *(template_model->append ());
                row[session_template_columns.name] = "Meta: " + (*s)->name;
                row[session_template_columns.path] = "urn:ardour:" + (*s)->path;
                row[session_template_columns.description] = (*s)->description;
index 7ea26a339a2d9553659479627fca898c46c903dc..a184c4058b91cd7d989b954e85c5e35e8fc868ec 100644 (file)
@@ -38,8 +38,14 @@ class LIBARDOUR_API LuaScriptInfo {
                EditorHook,
                EditorAction,
                Snippet,
-               SessionSetup,
-               TrackSetup,
+               SessionInit,
+       };
+
+       /* binary flags, valid for ActionScripts */
+       enum ScriptSubType {
+               None          = 0x00,
+               RouteSetup    = 0x01,
+               SessionSetup  = 0x02,
        };
 
        static std::string type2str (const ScriptType t);
@@ -47,6 +53,7 @@ class LIBARDOUR_API LuaScriptInfo {
 
        LuaScriptInfo (ScriptType t, const std::string &n, const std::string &p, const std::string &uid)
        : type (t)
+       , subtype (0)
        , name (n)
        , path (p)
        , unique_id (uid)
@@ -55,6 +62,8 @@ class LIBARDOUR_API LuaScriptInfo {
        virtual ~LuaScriptInfo () { }
 
        ScriptType type;
+       uint32_t   subtype;
+
        std::string name;
        std::string path;
        std::string unique_id;
index 31437fcf6eaae5a9c1e47013432db4646dee987e..e2fc9d49f109a5c2572cf7648e771c6ed3430dc0 100644 (file)
@@ -158,12 +158,9 @@ LuaScripting::scan ()
                        case LuaScriptInfo::Snippet:
                                _sl_snippet->push_back(lsi);
                                break;
-                       case LuaScriptInfo::SessionSetup:
+                       case LuaScriptInfo::SessionInit:
                                _sl_setup->push_back(lsi);
                                break;
-                       case LuaScriptInfo::TrackSetup:
-                               _sl_tracks->push_back(lsi);
-                               break;
                        default:
                                break;
                }
@@ -286,6 +283,24 @@ LuaScripting::scan_script (const std::string &fn, const std::string &sc)
                if (key == "description") { lsi->description = val; }
                if (key == "category") { lsi->category = val; }
        }
+
+
+       if (type == LuaScriptInfo::EditorAction) {
+
+               luabridge::LuaRef lua_rs = luabridge::getGlobal (L, "route_setup");
+               if (lua_rs.isFunction ()) {
+                       lsi->subtype |= LuaScriptInfo::RouteSetup;
+               }
+
+               luabridge::LuaRef lua_ss = luabridge::getGlobal (L, "session_setup");
+               if (lua_ss.isFunction ()) {
+                       if (lua_ss () == true) {
+                               lsi->subtype |= LuaScriptInfo::SessionSetup;
+                       }
+               }
+
+       }
+
        return lsi;
 }
 
@@ -312,12 +327,9 @@ LuaScripting::scripts (LuaScriptInfo::ScriptType type) {
                case LuaScriptInfo::Snippet:
                        return *_sl_snippet;
                        break;
-               case LuaScriptInfo::SessionSetup:
+               case LuaScriptInfo::SessionInit:
                        return *_sl_setup;
                        break;
-               case LuaScriptInfo::TrackSetup:
-                       return *_sl_tracks;
-                       break;
                default:
                        break;
        }
@@ -333,8 +345,7 @@ LuaScriptInfo::type2str (const ScriptType t) {
                case LuaScriptInfo::EditorHook: return "EditorHook";
                case LuaScriptInfo::EditorAction: return "EditorAction";
                case LuaScriptInfo::Snippet: return "Snippet";
-               case LuaScriptInfo::SessionSetup: return "SessionSetup";
-               case LuaScriptInfo::TrackSetup: return "TrackSetup";
+               case LuaScriptInfo::SessionInit: return "SessionInit";
                default: return "Invalid";
        }
 }
@@ -347,8 +358,7 @@ LuaScriptInfo::str2type (const std::string& str) {
        if (!strcasecmp (type, "EditorHook")) {return LuaScriptInfo::EditorHook;}
        if (!strcasecmp (type, "EditorAction")) {return LuaScriptInfo::EditorAction;}
        if (!strcasecmp (type, "Snippet")) {return LuaScriptInfo::Snippet;}
-       if (!strcasecmp (type, "SessionSetup")) {return LuaScriptInfo::SessionSetup;}
-       if (!strcasecmp (type, "TrackSetup")) {return LuaScriptInfo::TrackSetup;}
+       if (!strcasecmp (type, "SessionInit")) {return LuaScriptInfo::SessionInit;}
        return LuaScriptInfo::Invalid;
 }
 
index 66f184ec63f95fc8716030dcc001625f17fc8c04..f9dd15ea8dee9d5be9878cf20abaa2a96f8c2811 100644 (file)
@@ -338,7 +338,7 @@ CoreAudioBackend::set_buffer_size (uint32_t bs)
        for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i) {
                coreaudio_set_realtime_policy (*i);
        }
-       engine.buffer_size_change (bs);
+       //engine.buffer_size_change (bs);
        return 0;
 }
 
index 9018fc0ddaa60f2b6aaf063ec05929b455d0bb1b..0f460de25c6d76990939d5aa11de9abed5973418 100644 (file)
@@ -1,11 +1,52 @@
 ardour {
-       ["type"]    = "TrackSetup",
-       name        = "Route Test",
-       description = [[ FOR TESTING AND PROTOTYING ONLY ]]
+       ["type"]    = "EditorAction",
+       name        = "Generic Audio Track",
+       description = [[Example ]]
 }
 
--- DON'T COUNT ON THIS TO REMAIN AS IS.
--- This may turn into a factory method, re-usable as ActionScript.
-function session_setup ()
-       Session:new_audio_track (1, 1, nil, 1, "Hello",  ARDOUR.PresentationInfo.max_order, ARDOUR.TrackMode.Normal)
+-- If a route_setup function is present in an Editor Action Script
+-- the script is also listed in the "add track/bus" dialog as meta-template
+--
+-- The function is expected to return a Lua table. The table may be empty.
+function route_setup ()
+       local e = Session:engine()
+       local _, t = e:get_backend_ports ("", ARDOUR.DataType("audio"), ARDOUR.PortFlags.IsOutput | ARDOUR.PortFlags.IsPhysical, C.StringVector())
+       return
+       {
+               -- keys control which AddRouteDialog controls are made sensitive.
+               -- The following keys accept a default value to pre-seed the dialog
+               ['how_many'] = t[4]:size(),
+               ['name'] = 'Audio',
+               ['channels'] = 2,
+               -- these keys just need to be set (to something other than nil)
+               ['insert_at'] = ARDOUR.PresentationInfo.max_order,
+               ['group'] = false,
+               --[[
+               ['track_mode'] = ARDOUR.TrackMode.Normal,
+               ['strict_io'] = true,
+               --]]
+       }
 end
+
+-- The Script can be used as EditorAction in which case it can
+-- optionally provide instantiation parmaters
+function action_params ()
+       return
+       {
+               ['how_many'] = { title = "How Many tracks to add", default = "1" },
+               ["name"]     = { title = "Track Name Prefix", default = "Audio" },
+       }
+end
+
+
+function factory (params) return function ()
+       local p         = params or route_setup ()
+       local name      = p["name"] or 'Audio'
+       local how_many  = p["how_many"] or 1
+       local channels  = p["channels"] or 1
+       local insert_at = p["insert_at"] or ARDOUR.PresentationInfo.max_order;
+       local group     = p["group"] or nil
+
+       Session:new_audio_track (channels, channels, group, how_many, name, insert_at, ARDOUR.TrackMode.Normal)
+
+end end
index bf7326121731b9e2cb349dbf8ecdb4ce7c808cb6..ccfb26d7c633c3523e2e180fd03d9adb40c2882f 100644 (file)
@@ -1,5 +1,5 @@
 ardour {
-       ["type"]    = "SessionSetup",
+       ["type"]    = "SessionInit",
        name        = "Live Band Recording Session",
        description = [[
 This template helps create the tracks for a typical pop/rock band.
@@ -10,7 +10,7 @@ Each track comes with its pre-assigned grouping, routing, EQ and plugins.
 ]]
 }
 
-function session_setup ()
+function factory () return function ()
 
        --prompt the user for the tracks they'd like to instantiate
        local dialog_options = {
@@ -92,4 +92,4 @@ function session_setup ()
        Editor:access_action("Editor","fit_all_tracks")
 
        Session:save_state("");
-end
+end end
index bf895dccf24a599238cd72864fc0e9cbf40a32bc..9656fd14735dad044fd14ff0f68594f589987e24 100644 (file)
@@ -1,5 +1,5 @@
 ardour {
-       ["type"]    = "SessionSetup",
+       ["type"]    = "SessionInit",
        name        = "Recording Session",
        description = [[Add as many mono tracks to the new session as there are physical audio inputs and optionally record-arm them.]]
 }
@@ -7,21 +7,28 @@ ardour {
 ---- For use with templates: Session Template setup-hook
 --
 -- If a script named 'template.lua' exists in a session-template folder
--- the `session_setup` function of the script is called after
--- creating the session from the template.
+-- the function produced by the 'factory' function of the script is called
+-- once after creating the session from the template.
 --
 -- (e.g. ~/.config/ardour5/templates/Template-Name/template.lua)
 --
 --
----- For use as meta-session
+---- For use as meta-session (specic session-setup scripts)
 --
--- Every Lua script in the script-folder of type "SessionSetup"
+-- Every Lua script in the script-folder of type "SessionInit"
 -- is listed as implicit template in the new-session dialog.
--- The scripts 'session_setup' function  is called once after
--- creating a new, empty session.
+-- The function produced by the scripts `factory` function is called
+-- once after creating a new, empty session.
 --
+---- For use as meta-session (general purpose Actions)
+--
+-- In some cases normal action scripts can also serve as session-setup
+-- To include those ActionScripts in the template-list the script needs
+-- to implement an additional function
+--      function session_setup () return true end;
+-- The script's factory will be called without any parameters
 
-function session_setup ()
+function factory () return function ()
        local e = Session:engine()
        -- from the engine's POV readable/capture ports are "outputs"
        local _, t = e:get_backend_ports ("", ARDOUR.DataType("audio"), ARDOUR.PortFlags.IsOutput | ARDOUR.PortFlags.IsPhysical, C.StringVector())
@@ -50,4 +57,4 @@ function session_setup ()
        end
 
        Session:save_state("");
-end
+end end
index 346a17cd9b278ba6c120150e81189dfca91bed28..e7b9084d35b18cf24a59887ae1f67e7ad028467d 100644 (file)
@@ -1,5 +1,5 @@
 ardour {
-       ["type"]    = "TrackSetup",
+       ["type"]    = "EditorAction",
        name        = "Live Band Recording Session",
        description = [[
 This template helps create the tracks for a typical pop/rock band.
@@ -11,10 +11,12 @@ Each track will be pre-assigned with a color.
 Optionally, tracks may be assigned to sensible Groups ( vocals, guitars, drums )
 
 Optionally, tracks may be assigned Gates and other plugins.
-    ]]
+]]
 }
 
-function session_setup ()
+function route_setup () return {} end
+
+function factory () return function ()
 
     --prompt the user for the tracks they'd like to instantiate
        local dialog_options = {
@@ -334,4 +336,4 @@ function session_setup ()
     Editor:access_action("Editor","fit_all_tracks")
 
        Session:save_state("");
-end
+end end
index 96034647b7b76bb05cb5e0145d35834fdf4505ae..28d174ae8b748729312b28357de38eb1ab0ca367 100644 (file)
@@ -1,5 +1,5 @@
 ardour {
-       ["type"]    = "TrackSetup",
+       ["type"]    = "EditorAction",
        name        = "Add tracks",
        description = [[
 This template creates audio tracks.
@@ -12,7 +12,17 @@ You will be prompted for:
 ]]
 }
 
-function session_setup ()
+function route_setup ()
+       return
+       {
+               ['Insert_at'] = ARDOUR.PresentationInfo.max_order;
+       }
+end
+
+function factory (params) return function ()
+       local p         = params or route_setup ()
+       local insert_at = p["insert_at"] or ARDOUR.PresentationInfo.max_order;
+
        local e = Session:engine()
        -- from the engine's POV readable/capture ports are "outputs"
        local _, t = e:get_backend_ports ("", ARDOUR.DataType("audio"), ARDOUR.PortFlags.IsOutput | ARDOUR.PortFlags.IsPhysical, C.StringVector())
@@ -31,11 +41,11 @@ function session_setup ()
        end
 
        -- create tracks
-       local tl = Session:new_audio_track (1, 1, nil, rv['tracks'], "",  ARDOUR.PresentationInfo.max_order, ARDOUR.TrackMode.Normal)
+       local tl = Session:new_audio_track (1, 1, nil, rv['tracks'], "", insert_at, ARDOUR.TrackMode.Normal)
        -- and optionally record-arm them
        if rv['recarm'] then
                for track in tl:iter() do
                        track:rec_enable_control ():set_value (1, PBD.GroupControlDisposition.NoGroup)
                end
        end
-end
+end end
index 3e8d95f5b2b5a34a0bb841978db9f039b9c9bb46..d9f0a03ed2df88f1dbace5d821640cdae46a3b11 100644 (file)
@@ -1,11 +1,11 @@
 ardour {
-       ["type"]    = "SessionSetup",
+       ["type"]    = "SessionInit",
        name        = "Advanced Session",
        description = [[Allows to configure master-bus and autoconnect]],
        master_bus  = 0
 }
 
-function session_setup ()
+function factory () return function ()
 
        local auto_connect_in = {
                [0] = "Manually",
@@ -56,4 +56,4 @@ function session_setup ()
        ARDOUR.config():set_output_auto_connect (rv['ac_output'])
 
        Session:save_state("");
-end
+end end