Fix merge error.
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 381e9a72efbe72a520af916977831408890bd6a2..bbdb4d759910b55fb546ee772f5403958949e632 100644 (file)
 #include <glib.h>
 #include "pbd/gstdio_compat.h"
 
-#include <gtkmm/messagedialog.h>
 #include <gtkmm/accelmap.h>
+#include <gtkmm/messagedialog.h>
 #include <gtkmm/stock.h>
+#include <gtkmm/uimanager.h>
 
 #include "pbd/error.h"
 #include "pbd/basename.h"
 #include "gtkmm2ext/bindings.h"
 #include "gtkmm2ext/gtk_ui.h"
 #include "gtkmm2ext/utils.h"
-#include "gtkmm2ext/click_box.h"
-#include "gtkmm2ext/fastmeter.h"
-#include "gtkmm2ext/popup.h"
 #include "gtkmm2ext/window_title.h"
 
+#include "widgets/fastmeter.h"
+#include "widgets/prompter.h"
+
 #include "ardour/ardour.h"
 #include "ardour/audio_backend.h"
 #include "ardour/audio_track.h"
@@ -163,7 +164,6 @@ typedef uint64_t microseconds_t;
 #include "opts.h"
 #include "pingback.h"
 #include "processor_box.h"
-#include "prompter.h"
 #include "public_editor.h"
 #include "rc_option_editor.h"
 #include "route_time_axis.h"
@@ -177,6 +177,7 @@ typedef uint64_t microseconds_t;
 #include "speaker_dialog.h"
 #include "splash.h"
 #include "startup.h"
+#include "template_dialog.h"
 #include "time_axis_view_item.h"
 #include "time_info_box.h"
 #include "timers.h"
@@ -192,6 +193,7 @@ using namespace ARDOUR;
 using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Gtkmm2ext;
+using namespace ArdourWidgets;
 using namespace Gtk;
 using namespace std;
 using namespace Editing;
@@ -296,8 +298,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , solo_alert_button (_("Solo"))
        , feedback_alert_button (_("Feedback"))
        , error_alert_button ( ArdourButton::just_led_default_elements )
-       , editor_meter(0)
        , editor_meter_peak_display()
+       , editor_meter(0)
        , _suspend_editor_meter_callbacks (false)
        , _numpad_locate_happening (false)
        , _session_is_new (false)
@@ -865,7 +867,7 @@ ARDOUR_UI::~ARDOUR_UI ()
                delete gui_object_state; gui_object_state = 0;
                delete main_window_visibility;
                FastMeter::flush_pattern_cache ();
-               PixFader::flush_pattern_cache ();
+               ArdourFader::flush_pattern_cache ();
        }
 
 #ifndef NDEBUG
@@ -1284,11 +1286,6 @@ ARDOUR_UI::starting ()
 
        BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
 
-       if (splash) {
-               // in 1 second, hide the splash screen
-               Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
-       }
-
        /* all other dialogs are created conditionally */
 
        return 0;
@@ -1929,10 +1926,6 @@ ARDOUR_UI::open_recent_session ()
 
                can_return = false;
        }
-       if (splash) {
-               // in 1 second, hide the splash screen
-               Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
-       }
 }
 
 bool
@@ -2773,6 +2766,33 @@ ARDOUR_UI::save_session_as ()
                return;
        }
 
+       if (_session->dirty()) {
+               vector<string> actions;
+               actions.push_back (_("Abort save-as"));
+               actions.push_back (_("Don't save now, just save-as"));
+               actions.push_back (_("Save it first"));
+               switch (ask_about_saving_session(actions)) {
+                       case -1:
+                               return;
+                               break;
+                       case 1:
+                               if (save_state_canfail ("")) {
+                                       MessageDialog msg (_main_window,
+                                                       string_compose (_("\
+%1 was unable to save your session.\n\n\
+If you still wish to proceeed, please use the\n\n\
+\"Don't save now\" option."), PROGRAM_NAME));
+                                       pop_back_splash(msg);
+                                       msg.run ();
+                                       return;
+                               }
+                               // no break
+                       case 0:
+                               _session->remove_pending_capture_state ();
+                               break;
+               }
+       }
+
        if (!save_as_dialog) {
                save_as_dialog = new SaveAsDialog;
        }
@@ -2848,7 +2868,6 @@ ARDOUR_UI::save_session_as ()
        if (!sa.include_media && sa.switch_to) {
                unload_session (false);
                load_session (sa.final_session_folder_name, sa.new_name);
-               hide_splash ();
        }
 }
 
@@ -2888,13 +2907,16 @@ ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
                time (&n);
                localtime_r (&n, &local_time);
                strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
+               if (switch_to_it && _session->dirty ()) {
+                       save_state_canfail ("");
+               }
 
                save_state (timebuf, switch_to_it);
 }
 
 
 bool
-ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
+ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
 {
        string snapname;
 
@@ -2940,8 +2962,34 @@ ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool swi
 void
 ARDOUR_UI::snapshot_session (bool switch_to_it)
 {
-       ArdourPrompter prompter (true);
+       if (switch_to_it && _session->dirty()) {
+               vector<string> actions;
+               actions.push_back (_("Abort saving snapshot"));
+               actions.push_back (_("Don't save now, just snapshot"));
+               actions.push_back (_("Save it first"));
+               switch (ask_about_saving_session(actions)) {
+                       case -1:
+                               return;
+                               break;
+                       case 1:
+                               if (save_state_canfail ("")) {
+                                       MessageDialog msg (_main_window,
+                                                       string_compose (_("\
+%1 was unable to save your session.\n\n\
+If you still wish to proceeed, please use the\n\n\
+\"Don't save now\" option."), PROGRAM_NAME));
+                                       pop_back_splash(msg);
+                                       msg.run ();
+                                       return;
+                               }
+                               // no break
+                       case 0:
+                               _session->remove_pending_capture_state ();
+                               break;
+               }
+       }
 
+       Prompter prompter (true);
        prompter.set_name ("Prompter");
        prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
        if (switch_to_it) {
@@ -2985,7 +3033,7 @@ ARDOUR_UI::rename_session ()
                return;
        }
 
-       ArdourPrompter prompter (true);
+       Prompter prompter (true);
        string name;
 
        prompter.set_name ("Prompter");
@@ -3127,7 +3175,7 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff)
 }
 
 bool
-ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
+ARDOUR_UI::process_save_template_prompter (Prompter& prompter)
 {
        string name;
 
@@ -3156,7 +3204,7 @@ ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
 void
 ARDOUR_UI::save_template ()
 {
-       ArdourPrompter prompter (true);
+       Prompter prompter (true);
 
        if (!check_audioengine (_main_window)) {
                return;
@@ -3182,6 +3230,12 @@ ARDOUR_UI::save_template ()
        }
 }
 
+void ARDOUR_UI::manage_templates ()
+{
+       TemplateDialog td;
+       td.run();
+}
+
 void
 ARDOUR_UI::edit_metadata ()
 {
@@ -3231,44 +3285,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;
        }
 
@@ -3425,14 +3449,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()
+                                       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;
                                }
@@ -3557,7 +3578,12 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
                        _session_is_new = true;
                }
 
-               if (likely_new && template_name.empty()) {
+               if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
+
+                       ret = build_session_from_dialog (session_dialog, session_path, session_name);
+                       meta_session_setup (template_name.substr (11));
+
+               } else if (likely_new && template_name.empty()) {
 
                        ret = build_session_from_dialog (session_dialog, session_path, session_name);
 
@@ -3604,10 +3630,6 @@ ARDOUR_UI::close_session()
        if (get_session_parameters (true, false)) {
                exit (1);
        }
-       if (splash && splash->is_visible()) {
-               // in 1 second, hide the splash screen
-               Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
-       }
 }
 
 /** @param snap_name Snapshot name (without .ardour suffix).
@@ -3680,7 +3702,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,
@@ -3701,7 +3723,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,
@@ -3774,12 +3796,27 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 #endif
        retval = 0;
 
+       if (!mix_template.empty ()) {
+               /* if mix_template is given, assume this is a new session */
+               string metascript = Glib::build_filename (mix_template, "template.lua");
+               meta_session_setup (metascript);
+       }
+
+
   out:
+       /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
+        * which is queued by set_session().
+        * If session-loading fails we hide it explicitly.
+        * This covers both cases in a central place.
+        */
+       if (retval) {
+               hide_splash ();
+       }
        return retval;
 }
 
 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;
@@ -3796,7 +3833,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) {
@@ -3856,6 +3893,44 @@ 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;
+}
+
+void
+ARDOUR_UI::meta_session_setup (const std::string& script_path)
+{
+       if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
+               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);
+
+       try {
+               luabridge::LuaRef fn = luabridge::getGlobal (L, "session_setup");
+               if (fn.isFunction()) {
+                       fn ();
+               }
+       } catch (luabridge::LuaException const& e) {
+               cerr << "LuaException:" << e.what () << endl;
+       }
+}
+
 void
 ARDOUR_UI::launch_chat ()
 {
@@ -4313,6 +4388,22 @@ ARDOUR_UI::add_route_dialog_response (int r)
                return;
        }
 
+       std::string template_name = add_route_dialog->get_template_path();
+       if ( !template_name.empty() ) {
+
+               if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
+
+                       //ret = build_session_from_dialog (session_dialog, session_path, session_name);
+                       meta_session_setup (template_name.substr (11));
+                       
+               } else {
+               
+                       //could be a user's track template (from file).  ToDo
+               }
+               
+               return;
+       }
+
        if ((count = add_route_dialog->count()) <= 0) {
                return;
        }
@@ -5202,6 +5293,15 @@ ARDOUR_UI::first_idle ()
                editor->first_idle();
        }
 
+       /* in 1 second, hide the splash screen
+        *
+        * Consider hiding it *now*. If a user opens opens a dialog
+        * during that one second while the splash is still visible,
+        * the dialog will push-back the splash.
+        * Closing the dialog later will pop it back.
+        */
+       Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+
        Keyboard::set_can_save_keybindings (true);
        return false;
 }