Redesign Session+Route Template Meta Script API
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 0748d418c269a17aea0ad7253ea5c957815e21cb..d3b07badb933a82dca8ad1fb73a67f9af59b9b18 100644 (file)
@@ -2016,16 +2016,6 @@ ARDOUR_UI::open_session ()
        }
 }
 
-void
-ARDOUR_UI::session_add_vca (const string& name_template, uint32_t n)
-{
-       if (!_session) {
-               return;
-       }
-
-       _session->vca_manager().create_vca (n, name_template);
-}
-
 void
 ARDOUR_UI::session_add_mixed_track (
                const ChanCount& input,
@@ -2038,10 +2028,7 @@ ARDOUR_UI::session_add_mixed_track (
                Plugin::PresetRecord* pset,
                ARDOUR::PresentationInfo::order_t order)
 {
-       if (_session == 0) {
-               warning << _("You cannot add a track without a session already loaded.") << endmsg;
-               return;
-       }
+       assert (_session);
 
        if (Profile->get_mixbus ()) {
                strict_io = true;
@@ -2131,10 +2118,7 @@ ARDOUR_UI::session_add_audio_route (
        list<boost::shared_ptr<AudioTrack> > tracks;
        RouteList routes;
 
-       if (_session == 0) {
-               warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
-               return;
-       }
+       assert (_session);
 
        try {
                if (track) {
@@ -3285,44 +3269,14 @@ ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& sess
        BusProfile bus_profile;
 
        if (nsm) {
-
                bus_profile.master_out_channels = 2;
-               bus_profile.input_ac = AutoConnectPhysical;
-               bus_profile.output_ac = AutoConnectMaster;
-               bus_profile.requested_physical_in = 0; // use all available
-               bus_profile.requested_physical_out = 0; // use all available
-
        } else {
-
                /* get settings from advanced section of NSD */
-
-               if (sd.create_master_bus()) {
-                       bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
-               } else {
-                       bus_profile.master_out_channels = 0;
-               }
-
-               if (sd.connect_inputs()) {
-                       bus_profile.input_ac = AutoConnectPhysical;
-               } else {
-                       bus_profile.input_ac = AutoConnectOption (0);
-               }
-
-               bus_profile.output_ac = AutoConnectOption (0);
-
-               if (sd.connect_outputs ()) {
-                       if (sd.connect_outs_to_master()) {
-                               bus_profile.output_ac = AutoConnectMaster;
-                       } else if (sd.connect_outs_to_physical()) {
-                               bus_profile.output_ac = AutoConnectPhysical;
-                       }
-               }
-
-               bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
-               bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
+               bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
        }
 
-       if (build_session (session_path, session_name, bus_profile)) {
+       // NULL profile: no master, no monitor
+       if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
                return -1;
        }
 
@@ -3479,15 +3433,11 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
                                break;
                        default:
                                if (quit_on_cancel) {
-                                       // JE - Currently (July 2014) this section can only get reached if the
-                                       // user quits from the main 'Session Setup' dialog (i.e. reaching this
-                                       // point does NOT indicate an abnormal termination). Therefore, let's
-                                       // behave gracefully (i.e. let's do some cleanup) before we call exit()
-                                       assert (!_session);
+                                       ARDOUR_UI::finish ();
+                                       Gtkmm2ext::Application::instance()->cleanup();
                                        ARDOUR::cleanup ();
                                        pthread_cancel_all ();
-
-                                       exit (1);
+                                       return -1; // caller is responsible to call exit()
                                } else {
                                        return ret;
                                }
@@ -3736,7 +3686,7 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
        }
        catch (SessionException e) {
                MessageDialog msg (string_compose(
-                                          _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
+                                          _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
                                           path, snap_name, e.what()),
                                   true,
                                   Gtk::MESSAGE_INFO,
@@ -3757,7 +3707,7 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
        catch (...) {
 
                MessageDialog msg (string_compose(
-                                          _("Session \"%1 (snapshot %2)\" did not load successfully"),
+                                          _("Session \"%1 (snapshot %2)\" did not load successfully."),
                                           path, snap_name),
                                   true,
                                   Gtk::MESSAGE_INFO,
@@ -3850,7 +3800,7 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 }
 
 int
-ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
+ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
 {
        Session *new_session;
        int x;
@@ -3867,7 +3817,7 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
        _session_is_new = true;
 
        try {
-               new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
+               new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
        }
 
        catch (SessionException e) {
@@ -3927,6 +3877,108 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
        return 0;
 }
 
+
+static void _lua_print (std::string s) {
+#ifndef NDEBUG
+       std::cout << "LuaInstance: " << s << "\n";
+#endif
+       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)
 {
@@ -3935,7 +3987,7 @@ ARDOUR_UI::meta_session_setup (const std::string& script_path)
        }
 
        LuaState lua;
-       lua.Print.connect (&LuaInstance::_lua_print);
+       lua.Print.connect (&_lua_print);
        lua.sandbox (true);
 
        lua_State* L = lua.getState();
@@ -3948,11 +4000,13 @@ 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) { }
+       } catch (luabridge::LuaException const& e) {
+               cerr << "LuaException:" << e.what () << endl;
+       }
 }
 
 void
@@ -4399,6 +4453,11 @@ ARDOUR_UI::add_route ()
 void
 ARDOUR_UI::add_route_dialog_response (int r)
 {
+       if (!_session) {
+               warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
+               return;
+       }
+
        int count;
 
        switch (r) {
@@ -4412,26 +4471,31 @@ ARDOUR_UI::add_route_dialog_response (int r)
                return;
        }
 
+       std::string template_path = add_route_dialog->get_template_path();
+       if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
+               meta_route_setup (template_path.substr (11));
+               return;
+       }
+
        if ((count = add_route_dialog->count()) <= 0) {
                return;
        }
 
        PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
-       string template_path = add_route_dialog->track_template();
+       const string name_template = add_route_dialog->name_template ();
        DisplaySuspender ds;
 
-       if (!template_path.empty()) {
-               if (add_route_dialog->name_template_is_default())  {
-                       _session->new_route_from_template (count, order, template_path, string());
+       if (!template_path.empty ()) {
+               if (add_route_dialog->name_template_is_default ()) {
+                       _session->new_route_from_template (count, order, template_path, string ());
                } else {
-                       _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
+                       _session->new_route_from_template (count, order, template_path, name_template);
                }
                return;
        }
 
        ChanCount input_chan= add_route_dialog->channels ();
        ChanCount output_chan;
-       string name_template = add_route_dialog->name_template ();
        PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
        RouteGroup* route_group = add_route_dialog->route_group ();
        AutoConnectOption oac = Config->get_output_auto_connect();
@@ -4450,22 +4514,22 @@ ARDOUR_UI::add_route_dialog_response (int r)
 
        switch (add_route_dialog->type_wanted()) {
        case AddRouteDialog::AudioTrack:
-               session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
+               session_add_audio_route (true, input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
                break;
        case AddRouteDialog::MidiTrack:
-               session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
+               session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
                break;
        case AddRouteDialog::MixedTrack:
                session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
                break;
        case AddRouteDialog::AudioBus:
-               session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
+               session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
                break;
        case AddRouteDialog::MidiBus:
                session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
                break;
        case AddRouteDialog::VCAMaster:
-               session_add_vca (name_template, count);
+               _session->vca_manager().create_vca (count, name_template);
                break;
        }
 }